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.
Gambar 3.1 Diagram alur dari desain sistem Ekstraksi Fitur Tekstur
Diatom.
3.2 PEMBUATAN SISTEM
3.2.1 FILTERINGSistem 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
0
ο, 22. 5
ο, 45
o, 67 .5
o, 90
o, 112 .5
o,135
o, 157 .5
o. Nilai
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:
G
x,y,f,θ
=exp
{
−1
2
[
x'
2δ
x2
y'
2δ
2y]
}
cos
2π fx'
(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. δ
xdan δ
ysecara 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
this.F = (float)1/K;//inisialisasi frekuensi //inisialisasi luas spasial dan bandwidth dari filter
this.S_x = (float)0.5*K; this.S_y = (float)0.5*K;
GaborMask();//memanggil fungsi masking dengan filter gabor
}
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
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 :
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
3. Lakukan inisialisasi x dan y.
4. Lakukan inisialisasi gabor real dan gabor imaginer.
5. Lakukan inisialisasi n dan k menjadi 0.
6. Inisialisasi nilai tengah dengan setengah lebar kernel.
7. 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
langkah-langkah 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
} }
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
} }
for(int i=0; i<size ; i++){//looping sebanyak size x1[i]= getX1(x[i],y[i],sudut);//mengambil nilai x1 ke-i
y1[i]= getY1(x[i],y[i],sudut);//mengambil nilai y1 ke-i
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 :
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].
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 ke-k sebagai xy ke-ke-ke-k dibagi hasil ke-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.
7. Untuk j=0 sampai j=y, kerjakan langkah nomor 8.
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.
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
meankerjakan 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
avgEuclideankerjakan nomor 9 sampai
dengan 12.
9. Lakukan looping sebanyak jumlah image, kerjakan nomor
10-12.
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
15-16.
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.
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 ke-i 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
} }
if (operasi.equals("theta")) {//jika operasi adalah theta
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.
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;
//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;
//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;
//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;
//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; //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; //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.
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.
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
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.