LAMPIRAN A
DATA SAMPEL
1. Data Latih
No
Citra (.jpg)
No
Citra (.jpg)
No
Citra (.jpg)
No
Citra (.jpg)
1
2
3
4
Palmprint_April (1) Palmprint_April (2) Palmprint_April (3) Palmprint_April (4)
5
6
7
8
Palmprint_April (5) Palmprint_April (6) Palmprint_April
(7) Palmprint_April (8)
9
10
11
12
Palmprint_April (9)
Palmprint_April (10)
Palmprint_April (11)
Palmprint_April (12)
13
14
15
16
Palmprint_April (13) Palmprint_April (14) Palmprint_April (15)
Palmprint_April (16)
17
18
19
20
Palmprint_April (17) Palmprint_April (18)
Palmprint_April (19)
Palmprint_April (20)
21
22
23
24
Palmprint_Bobby (1)
Palmprint_Bobby (2)
Palmprint_Bobby (3)
47
Palmprint_Bobby (12)
Palmprint_Bobby (16)
2. Data uji tanpa
noise
No
Citra (.jpg)
No
Citra (.jpg)
No
Citra (.jpg)
No
Citra (.jpg)
1
2
3
4
A (1)
A (2)
A (3)
A (4)
5
6
7
8
A (5)
A (6)
B (1)
B (2)
9
10
11
12
B (3)
B (4)
B (5)
B (6)
13
14
15
16
C (1)
C (2)
C (3)
C (4)
17
18
19
20
C (5)
C (6)
I (1)
I (2)
21
22
23
24
I (3)
I (4)
I (5)
I (6)
25
26
27
28
IW (1)
IW (2)
IW (3)
IW (4)
29
30
31
32
53
No
Citra (.jpg)
No
Citra (.jpg)
No
Citra (.jpg)
No
Citra (.jpg)
33
34
35
36
R (3)
R (4)
R (5)
R (6)
37
38
39
40
V (1)
V (2)
V (3)
V (4)
41
42
43
44
V (5)
V (6)
Y (1)
Y (2)
45
46
47
48
Y (3)
Y (4)
Y (5)
Y (6)
3. Data uji memiliki
noise
No
Citra (.jpg)
No
Citra (.jpg)
No
Citra (.jpg)
No
Citra (.jpg)
49
50
51
52
A (7)
A (8)
A (9)
A (10)
53
54
55
56
B (7)
B (8)
B (9)
B (10)
57
58
59
60
No
Citra (.jpg)
No
Citra (.jpg)
No
Citra (.jpg)
No
Citra (.jpg)
61
62
63
64
I (7)
I (8)
I (9)
I (10)
65
66
67
68
IW (7)
IW (8)
IW (9)
IW (10)
69
70
71
72
R (7)
R (8)
R (9)
R (10)
73
74
75
76
V (7)
V (8)
V (9)
V (10)
77
78
79
80
LAMPIRAN B
LISTING PROGRAM
1. Modul Filter Gambar
import java.io.File;
import javax.swing.filechooser.FileFilter;
//class yang digunakan untuk menyaring format citra hanya .jpg saja
public class filterGambar extends FileFilter {
public filterGambar()
{}
public boolean accept (File f)
{
if(f.isDirectory())
{
return true;
}
//pengubahan String dari nama citra menjadi huruf kapital
String file = f.getName().toUpperCase();
if(file.endsWith(".JPG")) //kondisi jika file citra/image memiliki ekstensi .jpg
{
return true;
}
return false;
}
public String getDescription(){
return "Image File";
}
2. Modul pelatihan (grayscale, deteksi tepi, dan binerisasi)
public class formUtama3 extends javax.swing.JFrame {
filterGambar filter = new filterGambar();
BufferedImage originalImage;
BufferedImage grayscaleImage, normalisasiIntensitasImage, edgeImage;
JFileChooser fc = new JFileChooser();
/*1. Method RGB2GS : mengubah citra RGB menjadi grayscale*/
public void RGB2GS(BufferedImage grayscaleImage){
int alpha, r, g, b;
/*variable width : mengambil nilai lebar dari citra
* variable height : mengambil nilai tinggi dari citra*/
int width = originalImage.getWidth();
int height = originalImage.getHeight();
//Membuat Buffered image untuk image grayscale
BufferedImage im = new BufferedImage
(width,height,BufferedImage.TYPE_BYTE_GRAY);
for(int i=0; i < width; i++){
for(int j=0; j < height; j++){
//mendapatkan nilai RGB dari originalImage
alpha = originalImage.getRGB(i,j);
r = (alpha & 0x00ff0000) >> 16; //mendapatkan nilai red (merah)
g = (alpha & 0x0000ff00) >> 8; //mendapatkan nilai green (hijau)
b = alpha & 0x000000ff; //mendapatkan nilai blue (biru)
//menghitung nilai gray image
float gray = (float) (0.3 * r + 0.59 * g + 0.11 * b);
}
}
// membuat dan menyimpan citra grayscale ke dalam folder
ImageIO.write(im,"JPG",new File
("3. Citra Hasil Latih/1. Grayscale/newGrayLatih.jpg"));
}
/*2. method setCannyEdgeDetector untuk mengubah citra grayscale menjadi citra deteksi tepi*/
public void setCannyEdgeDetector(BufferedImage edges){
//file image grayscale untuk dibentuk citra deteksi tepi
57
BufferedImage frame = ImageIO.read(file);
//membuat sebuah objek bernama detector dari Class CannyEdge Detector
CannyEdgeDetector detector = new CannyEdgeDetector();
//tetapkan low dan high threshold
detector.setLowThreshold(0.5f);
detector.setHighThreshold(1.0f);
//proses pendeteksian tepi
detector.setSourceImage(frame); //pengambilan sumber image
detector.process(); //method proses deteksi tepi
edges = detector.getEdgesImage();
// membuat dan menyimpan citra deteksi tepi ke dalam folder
ImageIO.write(edges,"PNG",new File
("3. Citra Hasil Latih/2. Deteksi Tepi/newEdgeLatih.png"));
}
/*3. Method setBinerisasi untuk mengubah citra deteksi tepi menjadi citra biner*/
public void setBinerisasi(){
File file = new File("3. Citra Hasil Latih/2. Deteksi Tepi/newEdgeLatih.png");
BufferedImage imageBiner = ImageIO.read(file);
int lebar = imageBiner.getWidth();
int tinggi = imageBiner.getHeight();
int threshold = 150; //nilai threshold yang ditetapkan
BufferedImage im = new BufferedImage
(lebar,tinggi,BufferedImage.TYPE_BYTE_GRAY);
for(int i = 0; i < lebar; i++){
for (int j=0; j < tinggi; j++){
//kondisi jika nilai image lebih besar dari nilai threshold
if(image.getRGB(j,i) >= threshold)
{
image.getRGB(j,i) = 255;
}
//kondisi jika nilai image lebih kecil dari nilai threshold
{
image.getRGB(j,i)= 0;
}
}
}
// membuat dan menyimpan citra biner ke dalam folder
ImageIO.write(im,"PNG",new File
("3. Citra Hasil Latih/3. Biner/newBinerLatih.png"));
}
//method setEkstraksi untuk mendapatkan nilai fitur dari citra yang diproses
public void setEkstraksi(){
File file = new File("3. Citra Hasil Latih/3. Biner/newBinerLatih.png"); //mengambil file yang dihitung
fiturnya
BufferedImage image = ImageIO.read(file);
int lebar = image.getWidth();
int tinggi = image.getHeight();
int[][] gambar = new int[tinggi][lebar]; //membuat array 2 dimensi dengan nama
//variable gambar
for (int row = 0; row < tinggi; row++) { //perulangan untuk membaca piksel baris
//dan kolom dari citra
for (int col = 0; col < lebar; col++) {
gambar[row][col] = image.getRGB(col, row);
//kondisi saat image memiliki nilai biner -16777216 (hitam) set menjadi nilai biner
if(gambar[row][col] == -16777216)
gambar[row][col] = 1;
//kondisi saat image memiliki nilai biner -1(putih) set menjadi nilai biner 0
else if(gambar[row][col] == -1)
gambar[row][col] = 0;
}
}
//inisialisasi variable untuk perhitungan pixel dan blok
int index_i , index_j, nilai_pixel, jlh_pixel, kolom, hasil_index, temp_hasil = 0;
int total_block = 10; //jumlah blok 10x10 blok
59
double[] hasil = new double[100]; //array dengan variable hasil yang memiliki
//panjang array 100
for(int h=0; h < total_block; h++) //perulangan pada kolom blok
{
for(int i= 0; i < total_block; i++) //perulangan pada baris blok
{
nilai_pixel = 0;
jlh_pixel = 0;
index_i = h * max_pixel_block;
temp_hasil = 0;
for(int j = index_i; j<index_i + max_pixel_block; j++)
{
index_j = i * max_pixel_block;
for(int k = index_j; k < index_j + max_pixel_block; k++)
{
temp_hasil += gambar[k][j];
}
}
// array hasil utk menyimpan nilai fitur rata-rata
hasil[hasil_index] = (double) temp_hasil / 400;
//menampilkan hasil index di textArea variable txtRataRata
txtRataRata.setText(txtRataRata.getText()+""+hasil[hasil_index]+"\n");
hasil_index++; //melanjutkan nilai hasil dengan index berikutnya
kolom++; //perhitungan blok di kolom berikutnya
}
}
}
}
Class: CannyEdgeDetector.java
public class CannyEdgeDetector {
private final static float GAUSSIAN_CUT_OFF = 0.005f;
private final static float MAGNITUDE_SCALE = 100F;
private final static int MAGNITUDE_MAX = (int) (MAGNITUDE_SCALE * MAGNITUDE_LIMIT);
private int height;
private int width;
private int picsize;
private int[] data;
private int[] magnitude;
private BufferedImage sourceImage;
private BufferedImage edgesImage;
private float gaussianKernelRadius;
private float lowThreshold;
private float highThreshold;
private int gaussianKernelWidth;
private boolean contrastNormalized;
private float[] xConv;
private float[] yConv;
private float[] xGradient;
private float[] yGradient;
public CannyEdgeDetector() {
lowThreshold = 2.5f;
highThreshold = 7.5f;
gaussianKernelRadius = 2f;
gaussianKernelWidth = 16;
contrastNormalized = false;
}
/*method process berisi proses yang dilakukan untuk mencari deteksi tepi*/
public void process() {
width = sourceImage.getWidth();
height = sourceImage.getHeight();
picsize = width * height;
initArrays(); //komponen yang terdapat didalamnya
//proses-proses untuk mendapatkan citra deteksi tepi
61
int low = Math.round(lowThreshold * MAGNITUDE_SCALE);
int high = Math.round(highThreshold * MAGNITUDE_SCALE);
performHysteresis(low, high); //proses hysteresis menghilangkan tepi yang rusak
thresholdEdges();
writeEdges(data);
}
private void initArrays() {
if (data == null || picsize != data.length) {
data = new int[picsize];
magnitude = new int[picsize];
xConv = new float[picsize];
yConv = new float[picsize];
xGradient = new float[picsize];
yGradient = new float[picsize];
}
}
// memproses penerapan filter gaussian
private void computeGradients(float kernelRadius, int kernelWidth) {
//perhitungan dengan matriks konvolusi Gaussian
float kernel[] = new float[kernelWidth];
float diffKernel[] = new float[kernelWidth];
int kwidth;
for (kwidth = 0; kwidth < kernelWidth; kwidth++) {
float g1 = gaussian(kwidth, kernelRadius);
if (g1 <= GAUSSIAN_CUT_OFF && kwidth >= 2) break;
float g2 = gaussian(kwidth - 0.5f, kernelRadius);
float g3 = gaussian(kwidth + 0.5f, kernelRadius);
kernel[kwidth] = (g1 + g2 + g3) / 3f / (2f * (float) Math.PI * kernelRadius * kernelRadius);
diffKernel[kwidth] = g3 - g2;
}
int initX = kwidth - 1;
int maxX = width - (kwidth - 1);
int initY = width * (kwidth - 1);
int maxY = width * (height - (kwidth - 1));
for (int x = initX; x < maxX; x++) {
for (int y = initY; y < maxY; y += width) {
int index = x + y;
float sumX = data[index] * kernel[0];
float sumY = sumX;
int xOffset = 1;
int yOffset = width;
for(; xOffset < kwidth ;) {
sumY += kernel[xOffset] * (data[index - yOffset] +
data[index + yOffset]);
sumX += kernel[xOffset] * (data[index - xOffset] +
data[index + xOffset]);
yOffset += width;
xOffset++;
}
yConv[index] = sumY;
xConv[index] = sumX;
}
}
for (int x = initX; x < maxX; x++) {
for (int y = initY; y < maxY; y += width) {
float sum = 0f;
int index = x + y;
for (int i = 1; i < kwidth; i++)
sum += diffKernel[i] * (yConv[index - i] - yConv[index + i]);
xGradient[index] = sum;
}
}
for (int x = kwidth; x < width - kwidth; x++) {
for (int y = initY; y < maxY; y += width) {
float sum = 0.0f;
int index = x + y;
int yOffset = width;
for (int i = 1; i < kwidth; i++) {
sum += diffKernel[i] * (xConv[index - yOffset] - xConv[index + yOffset]);
yOffset += width;
}
63
}
}
initX = kwidth;
maxX = width - kwidth;
initY = width * kwidth;
maxY = width * (height - kwidth);
/*perulangan untuk menghubungkan arah tepi (North, South, West, East, dst)*/
for (int x = initX; x < maxX; x++) {
for (int y = initY; y < maxY; y += width) {
int index = x + y;
int indexN = index - width;
int indexS = index + width;
int indexW = index - 1;
int indexE = index + 1;
int indexNW = indexN - 1;
int indexNE = indexN + 1;
int indexSW = indexS - 1;
int indexSE = indexS + 1;
float xGrad = xGradient[index];
float yGrad = yGradient[index];
float gradMag = hypot(xGrad, yGrad);
// non-maximal suppression : penelusuran tepi yang ada di dalam arah tepi
float nMag = hypot(xGradient[indexN], yGradient[indexN]);
float sMag = hypot(xGradient[indexS], yGradient[indexS]);
float wMag = hypot(xGradient[indexW], yGradient[indexW]);
float eMag = hypot(xGradient[indexE], yGradient[indexE]);
float neMag = hypot(xGradient[indexNE], yGradient[indexNE]);
float seMag = hypot(xGradient[indexSE], yGradient[indexSE]);
float swMag = hypot(xGradient[indexSW], yGradient[indexSW]);
float nwMag = hypot(xGradient[indexNW], yGradient[indexNW]);
float tmp;
if (xGrad * yGrad <= (float) 0 /*(1)*/
? Math.abs(xGrad) >= Math.abs(yGrad) /*(2)*/
? (tmp = Math.abs(xGrad * gradMag)) >= Math.abs(yGrad * neMag - (xGrad + yGrad) * eMag) /*(3)*/
: (tmp = Math.abs(yGrad * gradMag)) >= Math.abs(xGrad * neMag - (yGrad + xGrad) *
nMag) /*(3)*/
&& tmp > Math.abs(xGrad * swMag - (yGrad + xGrad) * sMag) /*(4)*/
: Math.abs(xGrad) >= Math.abs(yGrad) /*(2)*/
? (tmp = Math.abs(xGrad * gradMag)) >= Math.abs(yGrad * seMag + (xGrad - yGrad) *
eMag) /*(3)*/
&& tmp > Math.abs(yGrad * nwMag + (xGrad - yGrad) * wMag) /*(4)*/
: (tmp = Math.abs(yGrad * gradMag)) >= Math.abs(xGrad * seMag + (yGrad - xGrad) *
sMag) /*(3)*/
&& tmp > Math.abs(xGrad * nwMag + (yGrad - xGrad) * nMag) /*(4)*/
)
{
magnitude[index] = gradMag >= MAGNITUDE_LIMIT ? MAGNITUDE_MAX : (int)
(MAGNITUDE_SCALE * gradMag);
}
else
{
magnitude[index] = 0;
}
}
}
private float hypot(float x, float y) {
return (float) Math.hypot(x, y);
}
private float gaussian(float x, float sigma) { //rumus untuk filter Gaussian
return (float) Math.exp(-(x * x) / (2f * sigma * sigma));
}
/*proses hysteresis
private void performHysteresis(int low, int high) {
Arrays.fill(data, 0);
int offset = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (data[offset] == 0 && magnitude[offset] >= high) {
65
offset++;
}
}
}
private void follow(int x1, int y1, int i1, int threshold) {
int x0 = x1 == 0 ? x1 : x1 - 1;
int x2 = x1 == width - 1 ? x1 : x1 + 1;
int y0 = y1 == 0 ? y1 : y1 - 1;
int y2 = y1 == height -1 ? y1 : y1 + 1;
data[i1] = magnitude[i1];
for (int x = x0; x <= x2; x++) {
for (int y = y0; y <= y2; y++) {
int i2 = x + y * width;
if ((y != y1 || x != x1)
&& data[i2] == 0
&& magnitude[i2] >= threshold) {
follow(x, y, i2, threshold);
return;
}
}
}
}
//penentuan nilai threshold dalam menetapkan tepi atau tidak
private void thresholdEdges() {
for (int i = 0; i < picsize; i++) {
data[i] = data[i] > 0 ? -1 : 0xff000000;
}
}
//membuat edge /tepi citra
private void writeEdges(int pixels[]) {
if (edgesImage == null) {
edgesImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
}
3. Modul Pengujian
Modul untuk proses pengolahan citra sama dengan modul pelatihan hanya berbeda pada folder target
penyimpanan. Semua citra hasil pengujian akan disimpan di dalam folder hasil citra uji.
//method untuk mencari jarak Euclidean ternormalisasi
public void cariJarak(){
String nilaiUji = ambilFiturUji();
String[] potongUji = nilaiUji.split("; ");
Double[] u = new Double[potongUji.length];
Double uNorm = 0.0;
double min;
double d = 0.0;
/* array untuk menyimpan nilai jarak yang akan diuji*/
Double[] arrayD = new Double[160];
int h;
for( h=0; h < potongUji.length; h++) //perulangan saat pengambilan fitur citra uji {
u[h] = Double.parseDouble(potongUji[h]);
uNorm += (double) u[h] * u[h]; //sigma uh2 (hitung sigma uNorm)
}
uNorm = (double) Math.sqrt(uNorm); //(sigma (uh2))1/2
/* perulangan untuk mengambil fitur yang telah dilatih dalam database (sebanyak 160 fitur) */
for(int i=0; i < arrayD.length; i++) {
String nilaiLatih = ambilFiturLatih(i+1); //nilai fitur latih yang diambil
//mulai dari nomor indeks-1
String[] potongLatih = nilaiLatih.split("; ");
/*membuat array v dengan panjang sebesar fitur latih yaitu 100*/
Double[] v = new Double[potongLatih.length]; Double vNorm =
0.0;
for(int j=0; j < v.length; j++) //perulangan untuk menghitung sigma vNorm
{
v[j] = Double.parseDouble(potongLatih[j]);
vNorm += (double) v[j] * v[j]; // sigma vj2 (hitung sigma vNorm)
67
vNorm = (double) Math.sqrt(vNorm); //(sigma (vj 2
))1/2
/*perulangan menghitung nilai jarak Euclidean ternormalisasi*/
for(int j=0; j < u.length; j++)
{
//hitung jarak (d)
d += (double) (u[j]/uNorm-v[j]/vNorm)*(u[j]/uNorm-v[j]/vNorm);
d = (double) Math.sqrt(d);
}
arrayD[i] = (double) d; //menyimpan nilai setiap indeks arrayD dengan nilai
//hasil jarak (d)
System.out.println(arrayD[i]); //cetak nilai semua indeks dalam arrayD
}
/*kondisi pencarian nilai jarak (d) minimum*/
min = arrayD[0]; //inisialisasi nilai min = nilai indeks ke-0 arrayD
for (int k=1; k <arrayD.length; k++){ // pengecekan disetiap indeks arrayD
if(arrayD[k] < min){ //kondisi saat nilai arrayD lebih kecil dari nilai min
min = arrayD[k];
}
}