BAB III PERANCANGAN DAN PEMBUATAN SISTEM Pada bab III ini akan dijelaskan mengenai perancangan dan desain sistem yang dikerjakan dalam proyek akhir ini. Desain sistem ditujukan agar sistem yang dihasilkan mudah digunakan dan mudah dikembangkan, sehingga dapat menjadi aplikasi yang serba guna. 3.1 PERANCANGAN SISTEM Berdasarkan penjelasan dari bagian sebelumnya, penelitian tugas akhir ini bertujuan untuk melakukan pengenalan menampilkan gambar diatom dengan jarak kemiripan terdekat dengan gambar query. Desain sistem yang dibuat dalam penelitian ini merupakan aplikasi yang menerapkan CBIR (Content Based Image Retrieval). Permasalahan yang akan diselesaikan dalam penelitian ini adalah : - Pembentukan database fitur dan jenis diatom. - Pembentukan database gambar diatom. - Ekstraksi fitur dari gambar diatom yang berupa fitur tekstur. - Image Matching, untuk mencari nilai kedekatan fitur gambar. Dalam menyelesaikan permasalahan tersebut diatas, dalam mengembangkan desain sistem ini penulis merencanakan beberapa tahapan dalam membangun sistem ini, diagram sistem dapat dilihat pada gambar , yaitu : • Data pendukung (Data Preparing) Dalam penelitian ini dibutuhkan beberapa data diantaranya : Database taksonomi diatom dan database gambar diatom. • Ekstraksi fitur gambar (Feature Extraction) Dalam aplikasi CBIR proses ekstraksi fitur gambar merupakan bagian yang terpenting. Dalam penelitian ini fitur yang direpresentasikan adalah fitur tekstur. Dalam merepresentasikan fitur tekstur digunakan metode multi-resolution filtering, yaitu Filter Gabor. • Pengukuran Kemiripan (Similarity Measurement) Nilai dari fitur gambar query yang dihasilkan dan nilai dari masing – masing fitur gambar training yang telah disimpan dalam database akan dicari nilai kemiripannya. Nilai kemiripan ini akan dihitung dengan menggunakan metode Euclidean Distance.
15
Gambar 3.1 Diagram alur dari desain sistem Ekstraksi Fitur Tekstur Diatom. 3.2 PEMBUATAN SISTEM 3.2.1 FILTERING
Sistem yang dikembangkan penulis di sini merupakan penerapan ekstraksi fitur gambar, fitur yang digunakan adalah fitur tekstur. Ekstraksi fitur sendiri memegang peranan terpenting dalam pembangunan sistem ini. Ekstraksi fitur tekstur dilakukan dengan metode filter gabor. Pada bagian berikut akan dijelaskan bagamana penggunaan ekstraksi fitur tesebut. 3.2.1.1 Filter Gabor
Diatom memiliki tekstur unik yang dapat digunakan sebagai pembeda antara diatom yang satu dengan diatom yang lain. Selain itu tekstur diatom dapat juga digunakan untuk mengidentifikasi tergolong genus apakah diatom tersebut. Untuk dapat menggunakan keseluruhan tekstur diatom, digunakan filter gabor dengan delapan arah sudut orientasi, yaitu ο ο o o o o o o Nilai 0 , 22. 5 , 45 , 67 .5 , 90 , 112 .5 ,135 , 157 .5 . yang digunakan dari fungsi Gabor adalah nilai real yang kemudian diubah ke dalam bentuk filter spasial berupa kernel Gabor. Ukuran kernel yang digunakan dalam tugas akhir ini adalah 17 x 17. Persamaan Gabor yang digunakan yaitu: 16
G x,y,f,θ =exp
{ [
]}
−1 x' 2 y' 2 cos 2π fx' 2 δ 2 δ2 x y
(3.1)
x '=x sin θ+y cos θ ,
(3.2)
y'=x cos θ − y sin θ ,
(3.3)
Nilai f diperoleh dari rata-rata frekuensi ridge (1/K) dimana K adalah rata-rata jarak antar ridge. δx dan δy secara empiris ditetapkan dengan nilai bekisar setengah dari rata-rata jarak antar ridge. Untuk θ merupakan sudut orientasi seperti yang disebutkan diatas. Langkah berikut ini untuk inisialisasi variabel sebelum digunakan pada fungsi GaborMask: 1. Lakukan inisialisasi nilai rata-rata jarak antar ridge. 2. Lakukan inisialisasi sudut orientasi. 3. Lakukan inisialisasi lebar kernel. 4. Lakukan inisialisasi frekuensi. 5. Lakukan inisialisasi luas spasial dan bandwidth dari filter. 6. Panggil fungsi masking dengan filter gabor. Implementasi dari penjelasan diatas dalam sistem ini dapat dilihat pada source code berikut: public GaborFilter(float sudut, int wSize, float K){ this.K = K;//inisialisasi nilai rata-rata jarak antar ridge this.sudut = sudut;//inisialisasi sudut orientasi this.wSize = wSize;//inisialisasi lebar kernel
filter
gabor }
this.F = (float)1/K;//inisialisasi frekuensi //inisialisasi luas spasial dan bandwidth dari this.S_x = (float)0.5*K; this.S_y = (float)0.5*K; GaborMask();//memanggil fungsi masking dengan filter
Gambar 3.2 Fungsi GaborFilter
Setelah kita mendefinisikan nilai frekuensi F dan mendapatkan nilai setengah dari rata-rata jarak antar ridge yaitu S_y dan S_x, Selanjutnya kita akan mencari nilai koordinat garis lurus yang dirotasi x1 dan y1, cara memperoleh koefisien ini dijelaskan dalam kode 17
program pada gambar 3.6, method getX1(float x, float y, float sudut), dan method getY1(float x, float y, float sudut) masing – masing dipanggil untuk mendapatkan nilai koordinat garis x1 dan y1. Langkah berikut digunakan untuk mengambil nilai koordinat garis lurus yang dirotasi: 1. Untuk mendapatkan koordinat garis lurus yang dirotasi x1, kerjakan nomor 2 – 4. 2. Lakukan inisialisasi nilai sudut derajat ke radian. 3. Hitung nilai koordinat garis lurus yang dirotasi x1 dengan menghitung hasil kali x dengan sin theta. Kemudian hasilnya ditambah dengan perkalian y dengan cos theta. 4. Kembalikan nilai koordinat garis lurus x1 yang dirotasi pada fungsi yang memanggilnya. 5. Untuk mendapatkan koordinat garis lurus yang dirotasi y1, kerjakan nomor 6 – 8. 6. Lakukan inisialisasi nilai sudut derajat ke radian. 7. Hitung nilai koordinat garis lurus yang dirotasi y1 dengan menghitung hasil kali x dengan cos theta. Kemudian hasilnya dikurangi dengan perkalian y dengan sin theta. 8. Kembalikan nilai koordinat garis lurus y1 yang dirotasi pada fungsi yang memanggilnya. Potongan program berikut ini merupakan penerapan dari langkah di atas : private float getX1(float x, float y, float sudut){ double theta = Math.toRadians((double)sudut);//inisialisasi nilai sudut derajat ke radian return (float) (x*Math.sin(theta) + y*Math.cos(theta));//mengembalikan nilai koordinat garis lurus yang dirotasi x1 } private float getY1(float x, float y, float sudut){ double theta = Math.toRadians((double)sudut);//inisialisasi nilai sudut derajat ke radian return (float) (x*Math.cos(theta) y*Math.sin(theta));//mengembalikan nilai koordinat garis lurus yang dirotasi y1 }
Gambar 3.3 Fungsi getX1 dan getX2
Dengan langkah-langkah berikut ini, dapat dihitung nilai gabor real dan gabor imaginer : 1. Untuk menghitung gabor real kerjakan nomor 2 - 6. 18
2.
Hitung perkalian x1 dengan x1, kemudian dibagi dengan hasil kali S-x dikali dengan S_x. 3. Hitung perkalian y1 dengan y1, kemudian dibagi dengan hasil kali S-y dikali dengan S_y. 4. Jumlahkan hasil nomor 1 dan 2, kemudian kalikan dengan -0.5. 5. Lakukan perhitungan nilai cosinus dari 2 dikali phi dikali F dikali x1. 6. Selanjutnya kalikan hasil perhitungan nomor 4 dan 5, maka didapat nilai gabor real. 7. Untuk menghitung nilai gabor imaginer, kerjakan nomor 8 – 12. 8. Hitung perkalian x1 dengan x1, kemudian dibagi dengan hasil kali S-x dikali dengan S_x. 9. Hitung perkalian y1 dengan y1, kemudian dibagi dengan hasil kali S-y dikali dengan S_y. 10. Jumlahkan hasil nomor 8 dan 9, kemudian kalikan dengan -0.5. 11. Lakukan perhitungan nilai sinus dari 2 dikali phi dikali F dikali x1. 12. Selanjutnya kalikan hasil perhitungan nomor 10 dan 11, maka didapat nilai gabor imaginer. Koefisien kernel fungsi Gabor diperoleh dengan mengimplementasikan langkah di atas dan persamaan 3.1 ke dalam potongan program berikut : private float GaborReal(float x1, float y1, float S_x, float S_y, float F){ return (float) (Math.exp(-0.5*(((x1*x1)/(S_x*S_x))+((y1*y1)/ (S_y*S_y))))*Math.cos(2*this.PI*F*x1));//mengembalikan nilai gabor real } private float GaborImaginer(float x1, float y1, float S_x, float S_y, float F){ return (float) (Math.exp(-0.5*(((x1*x1)/(S_x*S_x))+((y1*y1)/ (S_y*S_y))))*Math.sin(2*this.PI*F*x1));//mengembalikan nilai gabor imaginer }
Gambar 3.4 Fungsi GaborReal dan GaborImaginer
Akhirnya nilai – nilai koefesien kernel dari fungsi gabor ini dapat diperoleh dengan langkah berikut ini: 1. Lakukan inisialisasi nilai size, yaitu setengah lebar kernel. 2. Lakukan inisialisasi nilai koordinat garis lurus yang dirotasi x1 dan y1. 19
3. 4. 5. 6. 7.
Lakukan inisialisasi x dan y. Lakukan inisialisasi gabor real dan gabor imaginer. Lakukan inisialisasi n dan k menjadi 0. Inisialisasi nilai tengah dengan setengah lebar kernel. Lakukan looping mulai dari -nilai tengah sampai dengan nilai tengah, kerjakan nomor 8-. 8. Tentukan nilai y ke-n dengan nilai i dan nilai x ke-n dengan j. 9. Jumlahkan nilai n dengan 1. 10. Lakukan looping sebanyak size. 11. Panggil fungsi untuk membangkitkan nilai x1 dan y1. 12. Panggil fungsi GaborReal untuk mendapatkan nilai gabor real dan GaborImaginer untuk mendapatkan nilai gabor imaginer. Potongan program berikut ini merupakan penerapan dari langkahlangkah di atas : private void GaborMask(){ int size = this.wSize*this.wSize;//inisialisasi nilai size float[] x1= new float[size];//inisialisasi nilai koordinat garis lurus yang dirotasi float[] y1= new float[size];//inisialisasi nilai koordinat garis lurus yang dirotasi float[] x = new float[size];//inisialisasi x float[] y = new float[size];//inisialisasi y float[] gmask_real= new float[size];//inisialisasi gabor real float[] gmask_imajiner= new float[size];//inisialisasi gabor imaginer int n=0;//inisialisasi nilai n=0 int k=0;//inisialisasi nilai k=0 int nilaiTengah = (int)this.wSize/2;//inisialisasi nilai tengah for(int i=-1*nilaiTengah ;i<=nilaiTengah ; i++) {//looping sebanyak -nilai tengah sampai dengan nilai tengah for(int j=-1*nilaiTengah; j<=nilaiTengah ; j++) {//looping sebanyak -nilai tengah sampai dengan nilai tengah y[n]=(float)i;//set nilai y ke-n = i x[n]=(float)j;//set nilai x ke-n = j n++;//tambah 1 nilai n } }
Gambar 3.5.1 Fungsi menghitung GaborReal dan GaborImaginer
20
private void GaborMask(){ int size = this.wSize*this.wSize;//inisialisasi nilai size float[] x1= new float[size];//inisialisasi nilai koordinat garis lurus yang dirotasi float[] y1= new float[size];//inisialisasi nilai koordinat garis lurus yang dirotasi float[] x = new float[size];//inisialisasi x float[] y = new float[size];//inisialisasi y float[] gmask_real= new float[size];//inisialisasi gabor real float[] gmask_imajiner= new float[size];//inisialisasi gabor imaginer int n=0;//inisialisasi nilai n=0 int k=0;//inisialisasi nilai k=0 int nilaiTengah = (int)this.wSize/2;//inisialisasi nilai tengah for(int i=-1*nilaiTengah ;i<=nilaiTengah ; i++) {//looping sebanyak -nilai tengah sampai dengan nilai tengah for(int j=-1*nilaiTengah; j<=nilaiTengah ; j++) {//looping sebanyak -nilai tengah sampai dengan nilai tengah y[n]=(float)i;//set nilai y ke-n = i x[n]=(float)j;//set nilai x ke-n = j n++;//tambah 1 nilai n } }
x1 ke-i y1 ke-i
for(int i=0; i<size ; i++){//looping sebanyak size x1[i]= getX1(x[i],y[i],sudut);//mengambil nilai y1[i]= getY1(x[i],y[i],sudut);//mengambil nilai
gmask_real[i] = GaborReal(x1[i], y1[i], this.S_x, this.S_y, this.F);//memanggil fungsi GaborReal untuk mendapatkan nilai gabor gmask_imajiner[i] = GaborImaginer(x1[i], y1[i], this.S_x, this.S_y, this.F);//memanggil fungsi GaborImajiner untuk mendapatkan nilai imajiner gabor. } }
Gambar 3.5.2 Fungsi menghitung GaborReal dan GaborImaginer 3.2.2 Konvolusi
Hasil pembangkitan berbagai fungsi filter tersebut diatas kemudian akan kita lakukan konvolusi terhadap gambar. Dengan langkah berikut ini dapat dilakukan konvolusi pada gambar dengan kernel yang sebelumnya dibangkitkan : 21
1.
Kirimkan kernel yang telah dibangkitkan ke fungsi convolution. 2. Pada fungsi convolution deklarasikan variabel op yang merupakan operator BufferedImageOp. 3. Inisialisasikan op dengan operator ConvolveOp dengan parameter kernel yang diterima. 4. Lakukan konvolusi pada image dengan menggunakan operator op.filter menggunakan parameter gambar sumber image dan parameter lain null. 5. Kembalikan image hasil konvolusi pada fungsi yang memanggilnya. Kode dibawah menjelaskan bagaimana proses konvolusi kernel – kernel tersebut terhadap gambar, dalam implementasinya dalam sistem ini. public BufferedImage getImageFiltered(){ convolution(this.kernel);//memanggil fungsi untuk menkonvolusi image return this.image;//mengembalikan image yang telah dikonvolusi } private void convolution(Kernel kernel){ BufferedImageOp op = new ConvolveOp(kernel);//inisialisasi op sebagai pengkonvolusi dengan kernel gabor this.image = op.filter(this.image, null);//lakukan konvolusi pada image }
Gambar 3.6 Fungsi getImageFiltered dan convolution 3.2.3 Ekstraksi Fitur
3.2.3.1 Mean Langkah – langkah dalam mendapatkan dari gambar query dan gambar training adalah sebagai berikut : 1. Tentukan nilai Mean mean[jmlSudut]. 2. Tentukan x=lebar gambar dan y=tinggi gambar. 3. Untuk k=0 sampai k=jmlSudut, kerjakan langkah nomor 4. 4. tentukan nilai mean ke-k =0. 5. Untuk i=0 sampai i=x, kerjakan langkah nomor 6. 6. Untuk j=0 sampai j=y, kerjakan langkah nomor 7. 7. Jumlahkan nilai mean ke-k dengan nilai pixel gambar hasil extraksi pada pixel ke-[i][j].
22
8.
Setelah keluar dari iterasi i dan j, tentukan nilai mean ke-k sebagai hasil bagi nilai mean ke-k dengan jumlah pixel observasi. Potongan program berikut menunjukan bagaimana algoritma tersebut di atas diimplementasikan dalam pemograman java. public double[] getMean() { double[] dArray = new double[1];//deklarasi dArray x = image[0].getWidth();//tentukan x sebagai lebar image y = image[0].getHeight();//tentukan y sebagai tinggi image mul = x * y;//tentukan mul sebagai hasil kali lebar & tinggi int xy[] = new int[jmlSudut];//deklarasi xy avg = new double[jmlSudut];inisialisasi avg for (int k = 0; k < jmlSudut; k++) {//looping sebanyak jmlSudut xy[k] = 0;//inisialisasi xy ke-k for (int i = 0; i < x; i++) {//looping sebanyak lebar image for (int j = 0; j < y; j++) {//looping sebanyak tinggi image image[k].getData().getPixel(i, j, dArray);//dapatkan nilai pixel image pada index ke-ij xy[k] += dArray[0];//tentukan xy ke-k = xy ditambah nilai pixel ke-ij } } avg[k] = (double) xy[k] / mul;//tentukan avg kek sebagai xy ke-k dibagi hasil kali lebar & tinggi image } return avg;//kembalikan nilai avg }
Gambar 3.7 Fungsi getMean
3.2.3.2 Standard Deviasi Standard Deviasi merupakan pengukuran penyebaran dari kumpulan data. Dalam sistem ini, Standard Deviasi dihitung dengan langkah-langkah sebagai berikut: 1. Tentukan nilai Standard Deviasi stdDev[jmlSudut]. 2. Tentukan x=lebar gambar dan y=tinggi gambar. 3. Tentukan xy[jmlSudut] sebagai variabel penampung nilai pixel sementara. 4. Untuk k=0 sampai k=jmlSudut, kerjakan langkah nomor 5. 5. tentukan nilai xy ke-k =0. 6. Untuk i=0 sampai i=x, kerjakan langkah nomor 7. 23
7. 8.
Untuk j=0 sampai j=y, kerjakan langkah nomor 8. Jumlahkan nilai xy ke-k dengan nilai pixel gambar hasil extraksi pada pixel ke-[i][j] dikurangi nilai mean ke-[k] kemudian dikuadratkan. 9. Setelah keluar dari iterasi i dan j, tentukan nilai stdDev ke-k sebagai akar kuadrat xy ke-[k] kemudian dibagi jumlah pixel observasi. Potongan program berikut menunjukan bagaimana algoritma penghitungan Standard Deviasi di atas diimplementasikan dalam pemograman java: public double[] getStdDev() { double[] dArray = new double[1];//deklarasi dArray double xy[] = new double[jmlSudut];//deklarasi xy stdDev = new double[jmlSudut];//inisialisasi stdDev for (int k = 0; k < jmlSudut; k++) {//looping sebanyak jumlah sudut xy[k] = 0;//tentukan xy ke-k = 0 for (int i = 0; i < x; i++) {//looping sebanyak lebar image for (int j = 0; j < y; j++) {//looping sebanyak tinggi image image[k].getData().getPixel(i, j, dArray);//ambil nilai pixel ke-ij xy[k] += Math.pow(dArray[0] - avg[k], 2);//tentukan xy ke-k = xy ditambah nilai pixel ke-ij } } stdDev[k] = (double) Math.sqrt(xy[k]) / mul;//tentukan nilai stdDev ke-k sebagai hasil akar xy ke-k dibagi luas image } return stdDev;//kembalikan nilai stdDev } }
Gambar 3.8 Fungsi getStdDev 3.2.4 Pengukuran Kemiripan
Pengukuran Kemiripan gambar merupakan langkah akhir dalam kaitannya dengan ekstraksi fitur di sistem ini. Pengukuran kemiripan ini menghitung kedekatan fitur gambar query dengan gambar training. Kedekatan fitur dihitung dengan menggunakan euclidean distance dengan membandingkan nilai mean dan standart deviasi gambar query dan gambar training.
24
3.2.4.1 Euclidean Distance Berdasarkan pada persamaan Mean dan Standard Deviasi, dalam sistem ini, Euclidean Distance dihitung dengan langkah-langkah sebagai berikut: 1. Jika operasi mean kerjakan nomor 2 sampai dengan nomor 7. 2. Lakukan looping sebanyak jumlah image. 3. Hitung nilai tmpAvg dari pengurangan mean gambar query dengan mean gambar training ke-i. 4. Kuadratkan tmpAvg. 5. Hitung nilai tmpStdDev dari pengurangan mean standard deviasi gambar query dengan mean standard deviasi gambar training ke-i. 6. Kuadratkan tmpStdDev. 7. Hitung nilai jarakEuclidean ke-i dari akar kuadrat hasil penjumlahan tmpAvg dan tmpStdDev. 8. Jika operasi adalah avgEuclidean kerjakan nomor 9 sampai dengan 12. 9. Lakukan looping sebanyak jumlah image, kerjakan nomor 1012. 10. Lakukan looping sebanyak jumlah sudut, kerjakan nomor 11. 11. Tentukan nilai tampung ke-i dijumlah dengan euclideanDistance ke-ij. 12. Tentukan nilai tampung ke-i dibagi dengan jumlah sudut. 13. Jika operasi adalah theta, kerjakan nomor 14 sampai dengan 19. 14. Lakukan looping sebanyak jumlah image, kerjakan nomor 1516. 15. inisialisasi nilai tampung ke-i dengan 10000 16. Lakukan looping sebanyak jumlah sudut, kerjakan nomor 16. 17. Periksa apakah tampung ke-i lebih besar dari euclideanDistance ke-i, kerjakan nomor 18 jika ya. 18. Tentukan nilai tampung ke-i dengan euclideanDistance ke-i. 19. Tentukan nilai tampung ke-i dengan tampung ke-i dibagi jumlah sudut. Berikut ini merupakan potongan program algoritma di atas.
25
private void initialize() { //deklarasi tmpAvg & tmpStdDev utk euclidean dng average double tmpAvg, tmpStdDev; //deklarasi avgTmp utk euclidean dng theta dan stdDevTmp double[] avgTmp = new double[sudut.length], stdDevTmp = new double[sudut.length]; if (operasi.equals("mean")) {//jika operasi adalah mean
jarakEuclidean = new double[indexImg];//inisialisasi jarakEuclidean for (int i = 0; i < indexImg; i++) {//looping sebanyak image tmpAvg = meanAvg – db_meanAvg[i];//tentukan tmpAvg = mean gambar query – mean gambar training ke-i tmpAvg = Math.pow(tmpAvg, 2);//tentukan tmpAvg = kuadrat tmpAvg tmpStdDev = meanStdDev db_meanStdDev[i];//tentukan tmpStdDev = mean gambar query – mean gambar training ke-i tmpStdDev = Math.pow(tmpStdDev, 2);//tentukan tmpStdDev = kuadrat tmpStdDev jarakEuclidean[i] = Math.sqrt(tmpAvg + tmpStdDev);//tentukan jarakEuclidean ke-i = akar dari penjumlahan tmpAvg dan tmpStdDev } tampung = new double[indexImg];//inisialisasi tampung if (operasi.equals("avgEuclidean")) {//jika operasi adalah avgEuclidean for (int i = 0; i < indexImg; i++) {//looping sebanyak image tampung[i] = 0;//inisialisasi tampung kei dengan 0 for (int j = 0; j < sudut.length; j++) {//looping sebanyak jumlah sudut tampung[i] += euclideanDistance[i] [j];//tentukan tampung ke-i ditambah dengan euclideanDistance ke-i } tampung[i] = (double) tampung[i] / sudut.length;//tentukan tampung ke-i sebagai tampung ke-i dibagi jumlah sudut } }
Gambar 3.9.1 Fungsi initialize
26
adalah theta
if (operasi.equals("theta")) {//jika operasi
for (int i = 0; i < indexImg; i++) {//looping sebanyak jumlah image tampung[i] = (double) 10000;//inisialisasi tampung ke-i dengan 10000 for (int j = 0; j < sudut.length; j++) {//looping sebanyak jumlah sudut untuk mencari nilai euclideanDistance terkecil if (tampung[i] > euclideanDistance[i][j]) {//jika tampung ke-i lebih besar dari euclideanDistance ke-i tampung[i] = euclideanDistance[i][j];//tentukan nilai tampung ke-i dengan nilai euclideanDistance ke-i } } } } } }
Gambar 3.9.2 Fungsi initialize
3.2.5 Pengurutan gambar Dalam sistem Ekstraksi Fitur Tekstur Image Diatom Dengan Menggunakan Filter Gabor ini, penulis menggunakan bubble sort untuk mengurutkan Euclidean Distance yang telah didapat sebelumnya. Dalam pengurutan ini, yang diurutkan bukan hanya Euclidean Distance. Nama file, nama spesies, jenis spesies, nama genus, mean & standard deviasi juga ikut diurutkan, namun demikian pengurutan tetap berdasarkan Euclidean Distance. Pengurutan gambar dikerjakan dengan urutan berikut ini. 1. Lakukan looping sebanyak jumlah image, kerjakan nomor 2-9. 2. Lakukan looping sebanyak jumlah image-1, kerjakan nomor 3. 3. Jika jarak euclidean ke-i lebih besar dari jarak euclidean ke-j, kerjakan nomor 4-9. 4. Tukar nilai rata-rata ke-i dengan rata-rata ke-j. 5. Tukar nilai standard deviasi ke-i dengan standard deviasi ke-j. 6. Tukar nama file ke-i dengan nama file ke-j. 7. Tukar nama spesies ke-i dengan nama spesies ke-j. 8. Tukar genus ke-i dengan genus ke-j. 9. Tukar image ke-i dengan image ke-j. Dengan algoritma yang telah dikembangkan dan diterapkan pada potongan program di bawah ini, kita dapat mengurutkan Euclidean Distance. 27
private void bruteForce() { double tD;//deklarasi tD double[] tDArr = new double[indexImg];//deklarasi tDarr tDArr = jarakEuclidean;//tentukan nilai tDarr adalah jarakEuclidean double temp[] = new double[sudut.length];//deklarasi temp String tmpString;deklarasi tmpString int tmpInd;//deklarasi tmpInd if (operasi.equals("mean")) {//jika operasi adalah mean for (int i = 0; i < indexImg; i++) {//looping sebanyak jumlah image for (int j = i + 1; j < indexImg; j++) {//looping sebanyak jumlah image-1 if (jarakEuclidean[i] > jarakEuclidean[j]) {//jika jarakEuclidean ke-i lebih besar daripada jarakEuclidean ke-j //tukar nilai jarakEuclidean ke-i dengan nilai jarakEuclidean ke-j tD = jarakEuclidean[i]; jarakEuclidean[i] = jarakEuclidean[j]; jarakEuclidean[j] = tD;//sorting index //tukar nilai db_avg ke-i dengan nilai db_avg ke-j temp = db_avg[i]; db_avg[i] = db_avg[j]; db_avg[j] = temp; //tukar nilai db_stdDev ke-i dengan nilai db_stdDev ke-j temp = db_stdDev[i]; db_stdDev[i] = db_stdDev[j]; db_stdDev[j] = temp; //tukar nilai db_avg ke-i dengan nilai db_namaFile ke-j tmpString = db_namaFile[i]; db_namaFile[i] = db_namaFile[j]; db_namaFile[j] = tmpString; //tukar isi db_namaSpesies ke-i dengan isi db_namaSpesies ke-j tmpString = db_namaSpesies[i]; db_namaSpesies[i] = db_namaSpesies[j]; db_namaSpesies[j] = tmpString;
Gambar 3.10.1 Fungsi bruteForce
28
//tukar isi db_genus ke-i dengan
isi db_genus ke-j
tmpString = db_genus[i] db_genus[j] //tukar isi isi db_spesies ke-j
} }
db_genus[i]; = db_genus[j]; = tmpString; db_spesies ke-i dengan
tmpString = db_spesies[i]; db_spesies[i] = db_spesies[j]; db_spesies[j] = tmpString; }
}
for (int i = 0; i < indexImg; i++) {//looping sebanyak jumlah image for (int j = i + 1; j < indexImg; j++) {//looping sebanyak jumlah image-1 if (tampung[i] > tampung[j]) {//jika tampung ke-i lebih besar daripada tampung ke-j //tukar nilai tampung ke-i dengan nilai tampung ke-j tD = tampung[i]; tampung[i] = tampung[j]; tampung[j] = tD; //tukar nilai db_namaFile ke-i dengan nilai db_namaFile ke-j tmpString = db_namaFile[i]; db_namaFile[i] = db_namaFile[j]; db_namaFile[j] = tmpString; //tukar nilai db_namaSpesies ke-i dengan nilai db_namaSpesies ke-j tmpString = db_namaSpesies[i]; db_namaSpesies[i] = db_namaSpesies[j]; db_namaSpesies[j] = tmpString; //tukar isi db_namaFile ke-i dengan isi db_namaFile ke-j tmpString = db_namaFile[i]; db_namaFile[i] = db_namaFile[j]; db_namaFile[j] = tmpString; //tukar isi db_namaSpesies ke-i dengan isi db_namaSpesies ke-j tmpString = db_namaSpesies[i]; db_namaSpesies[i] = db_namaSpesies[j]; db_namaSpesies[j] = tmpString;
Gambar 3.10.2 Fungsi bruteForce
29
//tukar isi db_genus ke-i dengan
isi db_genus ke-j
tmpString = db_genus[i]; db_genus[i] = db_genus[j]; db_genus[j] = tmpString; //tukar isi db_spesies ke-i dengan
isi db_spesies ke-j
} }
tmpString = db_spesies[i]; db_spesies[i] = db_spesies[j]; db_spesies[j] = tmpString;
}
} for (int i = 0; i < indexImg; i++) {//looping sebanyak jumlah image for (int j = i + 1; j < indexImg; j++) {//looping sebanyak jumlah image-1 if (tampung[i] > tampung[j]) {//jika tampung ke-i lebih besar daripada tampung ke-j //tukar nilai tampung ke-i dengan nilai tampung ke-j tD = tampung[i]; tampung[i] = tampung[j]; tampung[j] = tD; isi db_namaFile ke-j
//tukar isi db_namaFile ke-i dengan tmpString = db_namaFile[i]; db_namaFile[i] = db_namaFile[j]; db_namaFile[j] = tmpString;
//tukar isi db_namaSpesies ke-i dengan isi db_namaSpesies ke-j tmpString = db_namaSpesies[i]; db_namaSpesies[i] = db_namaSpesies[j]; db_namaSpesies[j] = tmpString; //tukar isi db_genus ke-i dengan isi db_genus ke-j
tmpString = db_genus[i]; db_genus[i] = db_genus[j]; db_genus[j] = tmpString;
Gambar 3.10.3 Fungsi bruteForce
30
//tukar isi db_spesies ke-i dengan
isi db_spesies ke-j
tmpString = db_spesies[i]; db_spesies[i] = db_spesies[j]; db_spesies[j] = tmpString; //tukar nilai db_avg ke-i dengan
nilai db_avg ke-j
temp = db_avg[i]; db_avg[i] = db_avg[j]; db_avg[j] = temp; //tukar nilai db_stdDev ke-i dengan
nilai db_stdDev ke-j
} }
temp = db_stdDev[i]; db_stdDev[i] = db_stdDev[j]; db_stdDev[j] = temp;
Gambar 3.10.4 Fungsi bruteForce
3.2.6 Seaching Image Setelah Euclidean Distance beserta fitur-fitur lain diurutkan, dilakukan pencarian image / gambar, agar bisa ditampilkan hasil setelah dilakukan pengurutan. Pencarian image di sini dilakukan berdasarkan nama file. Nama file dipilih karena antara file satu dengan file yang lain memiliki nama yang unik, sehingga nama file dapat dijadikan acuan untuk pencarian. Dengan langkah berikut ini, dapat dicari gambar setelah diurutkan. 1. Lakukan perulangan selama gambar terurut yang ditemukan kurang dari 8. 2. Untuk exception error, lakukan pemeriksaan apakah indeks pencarian pertama telah mencapai jumlah maksimal gambar, jika ya kerjakan nomor 3. 3. Kembalikan indeks pencarian ke 0. 4. Lakukan pemeriksaan apakah nama file ke-i sudah sama dengan nama file terurut ke-i, jika ya kerjakan nomor 5. 5. Simpan indeks file terurut. 6. Tambahkan jumlah gambar terurut yang ditemukan, kembalikan indeks pencarian pertama dan ke dua ke 0. Potongan program di bawah ini merupakan penerapan dari algoritma pencarian gambar di atas.
31
private void searchImg() { int j = 0, i = 0, k = 0;//deklarasi j,i,k sortedIndex = new int[8];//inisialisasi sortedIndex while (k < 8) {//selama k kurang dari 8 if (j == 162) {//jika j mencapai jumlah image maksimal j = 0;//tentukan j = 0 } if (db_namaFile[i].equals(allImageFileName[j])) {//jika nama file gambar database ke-i sama dengan nama gambar pada file ke-j sortedIndex[k] = j;//tentukan sortedIndex ke-k = j i++;//nilai i tambah 1 k++;//nilai k tambah 1 j = 0;//tentukan j = 0 } j++;//nilai j tambah 1 } }
Gambar 3.11 Fungsi searchImg
3.2.7 Generating Chart Langkah terakhir dalam sistem ini adalah membangkitkan chart / grafik. Yang ditampilkan dalam grafik ini adalah nilai mean dan standard deviasi 8 gambar training yang memiliki kemiripan terdekat dengan gambar query, sehingga dari grafik dapat diketahui seberapa kedekatan fitur antar gambar training dan gambar query. Di sini untuk membangkitkan grafik, digunakan library JfreeChart. 3.3
PERANCANGAN DATABASE Pada sistem ini menggunakan database management system mysql untuk menyimpan fitur gambar dan jenis gambar. Pada database yang digunakan, terdiri dari beberapa tabel sebagai berikut: 3.3.1 Tabel tabel_spesies Tabel ini menyimpan spesifikasi spesies diatom, yaitu nama spesies, genus dan species.
32
Tabel 3.1 Menyimpan spesifikasi diatom
3.3.2 Tabel tabel_fitur Tabel ini menyimpan fitur diatom, yaitu mean dan standard deviasi. Tabel 3.2 Menyimpan fitur diatom
3.3.3 Relasi antar tabel Berikut ini merupakan relasi antar tabel_spesies dan tabel_fitur. Di mana nama_file pada tabel_spesies merupakan primary key. Pada tabel_fitur, nama_file dan theta merupakan primary key, di mana nama_file merupakan reference dari tabel_spesies. nama_file nama_spesies genus spesies nama_file theta
mean std_dev
Gambar 3.12 Relasi antar tabel
33
3.4
ANTAR MUKA APLIKASI Dalam pembuatan antarmuka sistem ini mengunakan antarmuka swing dengan JAVA JDK 1.6, Secara umum antarmuka dari sistem ini terdiri dari panel untuk tombol, panel untuk gambar hasil, panel untuk menu, panel untuk keterangan gambar query.
Gambar 3.13 Welcome screen Ekstraksi Fitur Tekstur Image Diatom dengan Filter Gabor.
Gambar 3.14 Antarmuka sistem Ekstraksi Fitur Tekstur Image Diatom dengan Filter Gabor.
34
Gambar 3.15 Panel – panel dalam antar muka aplikasi.
35