Monday, April 21, 2014

Penggunaan FXML dalam membentuk GUI dengan javaFX

Dalam kesempatan kali ini saya memberikan sedikit contoh penggunaan FXML dalam membentuk GUI di javaFX. FXML sendiri merupakan penarapan konsep MVC di java yakni dengan menggunakan bantuan java reflection. Terdapat beberapa tag yang cukup penting dalam javaFX. Yakni fx:include dan fx:root. Tutorial ini mencoba memberikan proof of concept mengenai tag yang kedua. Tag fx:root digunakan untuk melompati pendefenisian controller pada  file fxml. Jadi dengan tag ini maka class controller yang digunakan di-inisialisasi selama runtime.  Untuk maksud ini, maka terdapat  menu option pada javaFX scenebuilder yang bisa digunakan  yang bisa dilihat pada gambar berikut

:

Sehingga file fxml yang  sebelumnya berbentuk: <!--xml version="1.0" encoding="UTF-8"?--> <!--import java.lang.*?--> <!--import java.util.*?--> <!--import javafx.scene.*?--> <!--import javafx.scene.control.*?--> <!--import javafx.scene.layout.*?--> <AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="fjr.example.mediaplayer.playlist.PlayerController"> <children> <StackPane layoutX="49.0" layoutY="14.0" prefHeight="150.0" prefWidth="200.0" /> </children> </AnchorPane> akan berubah menjadi <!--xml version="1.0" encoding="UTF-8"?--> <!--import java.lang.*?--> <!--import java.util.*?--> <!--import javafx.scene.*?--> <!--import javafx.scene.control.*?--> <!--import javafx.scene.layout.*?--> <fx:root type="javafx.scene.layout.AnchorPane" id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2"> <children> <StackPane layoutX="49.0" layoutY="14.0" prefHeight="150.0" prefWidth="200.0" /> </children> </fx:root> Nah agar properti dari file fxml tersebut bisa diakses, maka dalam kelas controller kita harus defenisikan root-nya yang contohnya bisa dilihat pada potongan berikut:
    public PlayerController(Group root) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Player.fxml"));
        loader.setController(this);
        loader.setRoot(this);
        loader.load();
        root.getChildren().add(this);
        this.root = root;
        this.mainStage = (Stage) root.getScene().getWindow();
    }
Untuk melengkapi tutorial kali ini, saya memberikan sebuah proyek kecil yakni membuat sebuah media player dengan playlist dengan menggunakan javaFX. Playlist yang dimaksud dapat digunakan layaknya playlist di media player yang biasa kita kenal (semacam winamp, jet audio atau lain-lain) yakni dapat di-repeat kembali ke daftar pertama ketika lagu terakhir selesai. Bagi pembaca yang tertarik mencoba, dapat meng-clone source code-nya di github: https://github.com/gunungloli666/example-media-player-with-playlist/tree/master/src/fjr/example/mediaplayer/playlist

Thursday, April 17, 2014

Benchmarking operasi matriks pengganti loop di MATLAB

Dalam tulisan ini saya hanya sedikit mengulangi kembali beberapa hal yang saya peroleh dari pengalaman selama menggunakan MATLAB. Khususnya berkaitan dengan filosofi dari MATLAB itu sendiri yang merupakan laboratorium  matriks (matrix laboratory). Seperti kita ketahui dalam MATLAB semua operasi pemgrograman ditekankan dalam skema matriks. Jadi bagi pengguna yang terbiasa dengan bahasa lain, maka ada baiknya mempelajari beberapa operasi-operasi dasar dalam manipulasi matriks di MATLAB.

Sebenarnya tulisan ini hanya sekedar mengulangi apa yang sudah saya singgung di tulisan sebelum-nya mengenai seberapa besar pengaruh penggunaan operasi matriks dalam mereduksi waktu komputasi di MATLAB. Namun dalam tulisan ini saya lebih menekankan pada proses benchmarking-nya. Untuk membuktikan perbedaan besar antara menggunakan operasi matriks dengan menggunakan standar pemrograman biasa  (loop: for, while, dll) di MATLAB maka anda bisa mengetes potongan script berikut:
clear all ;
clc; 

% buat matriks M ukuran 5000 x 5000 yang elemennya bilangan bulat acak dari 1 sampai 10
M = randi(10,5000,5000);
% buat matriks N yang ukuran dan nilai elemennya sama dengan matriks M
% ingat, tanda  '='  di MATLAB bukan menandakan pointer kalo merujuk
% pada matriks. Jadi operasi pada elemen M tidak akan berpengaruh pada elemen N. 
N = M; 

[a,b] = size(M);
tic; 
for i=1:a,
    for j=1:b,
        if M(i,j) > 5
            M(i,j) = 20000; 
        end
    end
end
disp(['lama pake loop = ', num2str(toc)]);

tic; 
N(N>5) = 20000;
disp(['lama pake indeks = ', num2str(toc)]);

% cek apakah elemen kedua matriks sama... 
% tanda '==' pada MATLAB bukan menandakan cek objek, tapi cek elemen
if M==N,
    disp('yes..'); 
end
Hasil eksekusinya untuk situasi komputer saya (core i3 dengan ram 4 giga) adalah operasi matriks mampu mereduksi waktu komputasi hingga 5 kali lipat.


Mungkin ada yang menduga jangan-jangan ini dikarenakan waktu pertama running saja. Artinya andaikan operasi ini dilakukan berulang-ulang dalam waktu yang lama, maka hasilnya hampir mirip antara loop dengan operasi matriks. Anda bisa melakukan sedikit modifikasi pada script di atas yakni sebagai berikut:
clear all ;
clc; 
lama_loop = 0; 
lama_indeks = 0;
iter = 0; 
while iter < 23
    M = randi(10,5000,5000);
    N = M; 
    [a,b] = size(M);
    tic; 
    for i=1:a,
        for j=1:b,
            if M(i,j) > 5
                M(i,j) = 20000; 
            end
        end
    end
    lama_loop = lama_loop + toc; 
    tic; 
    N(N>5) = 20000;
    lama_indeks = lama_indeks + toc; 
    iter = iter + 1; 
end

disp(['lama operasi loop untuk 100 iterasi = ', num2str(lama_loop)]);
disp(['lama operasi matriks untuk 100 iterasi = ', num2str(lama_indeks)]);
Hasilnya kurang lebih sama.


Baru satu logika if dan satu loop sudah sekian waktu yang bisa dihemat dengan mengganti loop dengan operasi matriks. Sementara pada kenyataannya dalam suatu proyek komputasi ada banyak loop-loop yang sebenarnya tidak perlu dilakukan karena bisa diganti dengan operasi matriks. 

Intinya operasi matriks ini sangat berfungsi dalam kasus modifikasi elemen-elemen pada matriks. Bahkan hampir semua algoritma yang berhubungan  dengan operasi pada elemen-elemen matriks bisa dinotasikan ke dalam operasi matriks. 

Sunday, April 13, 2014

Menghitung luas area yang gelap pada image di MATLAB



Pada tulisan kali ini saya akan memberikan sedikit tutorial mengenai bagaimana menentukan persentase area pada gambar yang nilai pixel RGB-nya memilik karakter warna tertentu (misalnya gelap atau hitam). Tanpa perlu berbasa-basi saya langsung saja membagikan script disertai komentar seperlunya yang bisa saudara coba di MATLAB.
clc;
clear all ;
[a,b] = imread('polpot.jpg'); 
[m,n,o] = size(a);
% pertama akan ditentukan apakah nilai RGB pada koordinat seragam. Misalnya
% kita ambil sampel koordinat dari 10 baris pertama dan 10 kolom pertama. 
HJ = (a(1:10,1:10,1) == a(1:10,1:10,3) ) & ((a(1:10,1:10,1) == a(1:10,1:10,2) )) ;
HJ
%% 
% yang ternyata elemen matriks HJ  semua 1 yang menandakan semua nilai RGB piksel seragam.
% Untuk  membuktikan, coba kita Print 
% nilai elemen pada baris dan kolom tersebut
a(1:10,1:10,:)
%%
% sekarang karena outputnya seragam maka otomatis nilai sum terhadap
% seluruh matriks HJ akan sama dengan penjumlahan terhadap seluruh matrix
% 'ones' yang ukurannya sama dengan HJ. Jika logika ini kita perumum, akan bisa digunakan pada
% kasus matrik HH yang mencakup seluruh area dari image, yang  akan kita
% peroleh adalah
HH = (a(:,:,1) == a(:,:,2)) & (a(:,:,1) == a(:,:,3)); 
if sum(sum(HH)) == sum(sum(ones(m,n)))
    M  = a(:,:,1) <10;
    disp(['persen area yang nilai pixel-nya di bawah 10 (nilai 0 berarti hitam): ',... 
    num2str(sum(sum(M))/sum(sum(ones(m,n)))*100), ' persen']);
else 
    disp('nilai pixel tidak seragam')
    % karena nilai pixel tidak seragam, maka kita bisa gunakan asumsi bahwa
    % nilai pixel yang mendekati warna gelap itu yang nilai pixel-nya
    % kurang dari 5 untuk R, 5 untuk G, dan 5 untuk B. Memang nilai pixel
    % yang benar-benar hitam adalah R = 0, G = 0, dan B = 0. Akan tetapi
    % kita hanya mendapat sedikit porsi dari area image  untuk nilai tersebut. 
    % Jadi kita gunakan pendekatan tadi. 
    M = (a(:,:,1) < 5) & (a(:,:,2) < 5) & (a(:,:,3) < 5); 
    disp(['persen area yang nilai pixel untuk R < 5; G  < 5, dan B < 5: ',... 
    num2str(sum(sum(M))/sum(sum(ones(m,n)))*100), ' persen']);
end
%% 
% Kita juga bisa menentukan pada baris dan kolom mana saja yang nilai pixel
% R, G, B tidak seragam
logic = (a(:,:,1)== a(:,:, 2)) & (a(:,:,1)== a(:,:,3)); 
[x1,x2,x3] = ind2sub(size(a),find(~logic)); 
disp('10 baris pertama dan 10 kolom pertama yang pikselnya tidak seragam: '); 
x1(1:10)'
x2(1:10)'
disp('nilai RGB pada baris dan kolom tersebut: '); 
a(x1(1:10),x2(1:10),:)