BAB II DASAR TEORI
4.2 Coding Program Pengenalan Alat Bengkel Motor
4.2.4 Program Ekstraksi Ciri Discrete Cosine Transform ....................... 47-48
int ConvertToDct(const cv::Mat &src, cv::Mat &dst) {
if (src.data == 0) return ErrorCode::ARG_ZERO_SIZED_IMAGE;
if (src.rows != src.cols) return ErrorCode::ARG_IMAGE_NOT_SQUARE;
cv::Mat tmp1, tmp2;
src.convertTo(tmp1, CV_32FC1, 1.0/255); // , 1.0/255 cv::dct(tmp1, tmp2);
tmp2.convertTo(dst, CV_8UC1, 255);
return 0;
}
int InverseDct(const cv::Mat &src, cv::Mat &dst) {
if (src.data == 0) return ErrorCode::ARG_ZERO_SIZED_IMAGE;
if (src.rows != src.cols) return ErrorCode::ARG_IMAGE_NOT_SQUARE;
cv::Mat tmp1, tmp2;
src.convertTo(tmp1, CV_32FC1); // , 1.0/255 cv::idct(tmp1, tmp2);
tmp2.convertTo(dst, CV_8UC1);
return 0;
}
// TO_DO: optimize this
const cv::Mat GenerateDctMatrix(unsigned int order) { // TO_DO: make sure order is the power of 2 cv::Mat kernel(order, order, CV_64F);
double valRow0 = sqrt(1.0 / static_cast<double>(order));
double alpha = sqrt(2.0 / static_cast<double>(order));
double denominator = static_cast<double>(2*order);
for (unsigned int j = 0; j < order; j++) { kernel.at<double>(0, j) = valRow0;
for (unsigned int i = 1; i < order; i++) {
double numerator = CV_PI * static_cast<double>(i * (2*j + 1));
kernel.at<double>(i, j) = alpha * cos(numerator / denominator);
} }
return kernel;
}
int FastDct(const cv::Mat &src, cv::Mat &dst) {
if (src.data == 0) return ErrorCode::ARG_ZERO_SIZED_IMAGE;
if (src.rows != src.cols) return ErrorCode::ARG_IMAGE_NOT_SQUARE;
// TO_DO: make sure order is the power of 2 cv::Mat tmp1;
src.convertTo(tmp1, CV_64F);
cv::Mat kernel = GenerateDctMatrix(src.rows);
dst = kernel * tmp1 * kernel.t();
return 0;
}
int FastInverseDct(const cv::Mat &src, cv::Mat &dst) {
if (src.data == 0) return ErrorCode::ARG_ZERO_SIZED_IMAGE;
if (src.rows != src.cols) return ErrorCode::ARG_IMAGE_NOT_SQUARE;
if (src.type() != CV_64F) return ErrorCode::ARG_IMAGE_HAS_INVALID_TYPE;
// TO_DO: make sure order is the power of 2 cv::Mat tmp1;
src.convertTo(tmp1, CV_64F);
cv::Mat kernel = GenerateDctMatrix(src.rows);
cv::Mat tmp2 = kernel.t() * tmp1 * kernel;
tmp2.convertTo(dst, CV_8U);
return 0;
}
Zig Zag Scanning
int zigzag(const cv::Mat &src, cv::Mat &dst) {
if (src.data == 0) return ErrorCode::ARG_ZERO_SIZED_IMAGE;
if (src.rows != src.cols) return ErrorCode::ARG_IMAGE_NOT_SQUARE;
unsigned int size = src.rows;
unsigned int totalData = size * size;
dst = cv::Mat(1, totalData, src.type());
unsigned int i, j, n;
for (i = n = 0; i < size * 2; i++) {
for (j = ((i < size) ? 0 : i-size+1); j <= i && j < size; j++) { int idx = (i&1)? j*(size-1)+i : (i-j)*size+j;
//s[idx] = n++;
int row = idx / size;
int col = idx % size;
dst.at<double>(0, n++) = src.at<double>(row, col);
//s[n++] = static_cast<unsigned int>(m.at<unsigned char>(row, col));
} }
return 0;
}
4.2.5 Fungsi Similaritas Kosinus
double CheckSimilarity(const cv::Mat &m1, const cv::Mat &m2, unsigned int persentase){
cv::Mat z1, z2;
unsigned int size;
if (persentase <= 0 || persentase >= 100) { pixelscanning(m1, z1);
pixelscanning(m2, z2);
size = z1.cols;
unsigned int size = z1.cols;
} else {
cv::Mat t1, t2;
pixelscanning(m1, t1);
pixelscanning(m2, t2);
size = t1.cols * persentase/100;
cv::Rect window(t1.cols - size - 1 ,0, size, 1);
z1 = t1(window);
z2 = t2(window);
}
double magnitude1 = 0.0;
double magnitude2 = 0.0;
//double dotProduct = 0.0;
for (unsigned int i = 0; i < size; i++) { double v1 = z1.at<double>(0, i);
double v2 = z2.at<double>(0, i);
magnitude1 += v1*v1;
magnitude2 += v2*v2;
//dotProduct += v1*v2;
}
cv::Mat dot = z1 * z2.t();
double numerator = dot.at<double>(0, 0);
double denumerator = sqrt(magnitude1) * sqrt(magnitude2);
//std::cout << "dot, num, denum " << numerator // << "\t" << dotProduct
// << "\t" << magnitude1 // << "\t" << magnitude2 // << "\t" << denumerator // << "\n";
return numerator / denumerator;
} };
4.2.6 Tanpa Ekstraksi Ciri
// TEMPLATE MATCHING std::string ok = "[N] ";
cv::Mat chkTemplate;
#if 1
cv::matchTemplate(fTemplate, test1, chkTemplate, CV_TM_CCOEFF_NORMED);
double minval, maxval, threshold = 0.6;
cv::Point minloc, maxloc;
cv::minMaxLoc(chkTemplate, &minval, &maxval, &minloc, &maxloc);
if(maxval >= threshold) { ok = "[Y] ";
}
#else
int match_method = 0;
cv::matchTemplate(fTemplate, test1, chkTemplate, match_method);
//cv::normalize( chkTemplate, chkTemplate, 0, 1, cv::NORM_MINMAX, -1, cv::Mat() );
/// Localizing the best match with minMaxLoc
double minVal; double maxVal; cv::Point minLoc; cv::Point maxLoc;
cv::minMaxLoc( chkTemplate, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() );
//cv::Point matchLoc;
//matchLoc = ( match_method == CV_TM_SQDIFF || match_method==
CV_TM_SQDIFF_NORMED ) // ? minLoc : maxLoc;
// TO_DO: check how to get this if (minVal < 255) {
ok = "[Y] ";
}
#endif
4.3 Pengujian Software Aplikasi Pengenalan Peralatan Bengkel Motor Secara Real Time
Sebelum memulai pengetesan, terlebih dahulu menentukan nilai “batas” dan nilai persentase windowing. Nilai batas dipakai untuk menentukan nilai atas dan bawah hasil DCT dan Tanpa Ekstraksi Cirihasil pengetesan terhadap data training. Sedangkan nilai persentase windowing adalah untuk menentukan area windowing yang ingin dipakai. Nilai 100% pada nilai persentase windowing mempunyai arti bahwa scanning yang dilakukan adalah untuk setiap pixel. Windowing 100% memiliki waktu eksekusi program lebih lama daripada persentase dibawahnya. Setelah persiapan selesai, maka selanjutnya masuk ke pendeteksian alat. Deteksi alat ini akan memunculkan hasil berupa text pengenalan DCT dan Template Matching.
std::cout << "Config tidak bisa dibaca." << "\n";
return -1;
if (training.data == 0) {
std::cout << "Database untuk alat '" << db.Data()[i].namaAlat << "' tidak bisa dibaca." << "\n"
<< "Pastikan gambar '" << db.Data()[i].lokasiGambar << "' tersedia."
<< "\n";
return -1;
}
cv::Mat dTrain;
int res = dct::FastDct(training, dTrain);
templates.emplace_back(dTrain);
}
for (unsigned int i = 0; i < cfg.pathTestCases.size(); i++) {
cv::Mat test1 = cv::imread(cfg.pathTestCases[i],CV_LOAD_IMAGE_GRAYSCALE);
double nilaiKemiripanMaksimal = -2.0;
unsigned int indexMirip = 0;
cv::Mat d2;
int res = dct::FastDct(test1 , d2);
for (unsigned int j = 0; j < templates.size(); j++) {
double cs = dct::CheckSimilarity(templates[j], d2, db.Persentase());
if (cs < db.Data()[j].batasMinimum) continue;
if (cs > nilaiKemiripanMaksimal) { nilaiKemiripanMaksimal = cs;
indexMirip = j;
} }
if (nilaiKemiripanMaksimal > 0.0f) {
std::cout << "Gambar '" << cfg.pathTestCases[i] << "' kemungkinan adalah '"
<< db.Data()[indexMirip].namaAlat << "' dengan tingkat kimiripan: "
<< nilaiKemiripanMaksimal << "\n";
} else {
std::cout << "Gambar '" << cfg.pathTestCases[i] << "' tidak dikenali" <<
"\n";
Testing 1 Testing 2 Testing 3 Testing 4 Testing 5
A B A B A B A B A B
Kunci Ring 0º 1 1 1 1 1 1 1 0 0 0
Kunci Ring 90º 1 1 1 0 1 1 1 1 0 0
Kunci Ring 180º 1 1 1 0 1 1 1 0 0 0
Kunci Ring 270º 1 1 0 0 1 1 0 0 0 0
Palu 0º 1 1 1 1 1 1 1 0 0 0
Palu 90º 1 1 1 1 1 1 1 1 0 0
Palu 180º 1 1 1 0 1 1 1 0 0 0
Palu 270º 1 1 1 1 1 1 1 0 0 0
Senter 0º 1 1 1 0 1 1 1 1 0 0
Senter 90º 1 1 1 1 1 0 1 1 0 0
Senter 180º 1 1 1 1 1 1 1 0 0 0
Senter 270º 1 1 1 1 1 1 1 1 0 0
Kunci L 0º 1 1 1 1 1 1 1 1 1 1
Kunci L 90º 0 0 0 0 0 0 0 0 0 0
Kunci L 180º 1 1 1 0 1 1 0 0 1 1
Kunci L 270º 1 1 1 1 1 1 1 1 1 1
Kunci soket 0º 1 1 1 0 1 1 1 0 0 0
Kunci soket 90º 1 1 1 1 1 1 1 1 0 0
Kunci soket 180º 1 1 1 1 1 1 1 0 0 0
Kunci soket 270º 1 1 1 1 1 1 1 0 0 0
Obeng Plus 0º 1 1 1 1 1 1 1 0 1 1
Obeng Plus 90º 1 1 1 0 1 1 1 0 1 0
Obeng Plus 180º 1 1 1 0 1 1 1 0 1 0
Obeng Plus 270º 1 1 1 0 1 0 1 0 1 0
Tang 0º 1 1 1 0 1 0 1 0 0 0
Tang 90º 1 1 1 0 1 0 1 0 0 0
Tang 180º 1 1 1 1 1 0 1 0 1 0
Tang 270º 1 1 1 0 1 0 0 0 0 0
Kunci pas 0º 1 1 1 0 1 1 0 0 0 0
Kunci pas 90º 1 1 0 0 1 0 0 0 0 0
Kunci pas 180º 1 1 1 0 1 1 1 0 1 0
Kunci pas 270º 1 1 1 0 1 0 0 0 0 0
Kunci inggris 0º 1 1 1 0 1 0 1 0 0 0
Kunci inggris 90º 1 1 1 0 1 0 1 0 0 0
Kunci inggris 180º 1 1 1 0 1 0 1 0 0 0
Kunci inggris 270º 1 1 1 0 1 0 1 0 0 0
Penggaris 0º 1 1 1 1 1 1 1 1 0 0
Penggaris 90º 1 1 1 1 1 1 1 1 0 0
Penggaris 180º 1 1 1 1 1 1 1 0 0 0
Penggaris 270º 1 1 1 1 1 1 1 1 0 0
SUM 39 39 37 18 39 27 33 11 9 4
PERSEN 97,5% 97,5% 92,5% 45,0% 97,5% 67,5% 82,5% 27,5% 22,5% 10,0%
Ekstraksi Ciri 79%
Tanpa Ekstraksi Ciri 50%
Tabel 4.8 Tabel Validasi Testing
Keterangan:
A : Hasil percobaan “dengan” menggunakan Ekstraksi Ciri B : Hasil percobaan “tanpa” menggunakan Ekstraksi Ciri Angka 1 : Alat dikenali
Angka 0 : Alat tidak dikenali
Testing 1 : Posisi alat sama “testing” dengan “training”
Testing 2 : Posisi alat dirotasi 20 derajat
Testing 3 : Posisi alat digeser jarak sampai dengan “1 cm” keatas dan kebawah Testing 4 : Posisi alat digeser jarak sampai dengan “1 cm” dan dirotasi 20 derajat Testing 5 : Posisi alat jarak lebih dari “1 cm” dan rotasi 50 derajat
4.3.2 Hasil Testing
Testing 1 : (10 alat bengkel dan dirotasi 0º - 270º ) mendapat hasil yang sama nilai Ekstraksi Ciri 97.5% dan Tanpa Ekstraksi Ciri 97.5% (Ekstraksi Ciri = Tanpa Ekstraksi Ciri)
Testing 2 : (10 alat bengkel dan dirotasi 0º - 270º ) mendapat hasil lebih besar nilai Ekstraksi Ciri 95 % dan Tanpa Ekstraksi Ciri) 25% (Ekstraksi Ciri >
Tanpa Ekstraksi Ciri)
Testing 3 : (10 alat bengkel dan dirotasi 0º - 270º ) mendapat hasil lebih besar nilai Tanpa Ekstraksi Ciri 85% dan Ekstraksi Ciri 97 % (Tanpa Ekstraksi Ciri >
Ekstraksi Ciri)
Testing 4 : (10 alat bengkel dan dirotasi 0º - 270º ) mendapat hasil lebih besar nilai Ekstraksi Ciri 72.5 % dan Tanpa Ekstraksi Ciri 25% (Ekstraksi Ciri >
Tanpa Ekstraksi Ciri)
Testing 5 : (10 alat bengkel dan dirotasi 0º - 270º ) mendapat hasil lebih besar nilai Ekstraksi Ciri 10% dan Tanpa Ekstraksi 7.5% (Ekstraksi Ciri > Tanpa Ekstraksi Ciri)
Total Testing : (10 alat bengkel dan dirotasi 0º - 270º ) mendapat hasil lebih besar nilai Ekstaksi Ciri 70% dan Tanpa Ekstraksi Ciri 50% (Ekstaksi Ciri >
Tanpa Ekstraksi Ciri)
Ekstraksi Ciri DCT dan Similaritas Kosinus merupakan salah satu metode yang sudah umum digunakan sebagai metode pengenalan citra. Sebagai pembanding, penulis menggunakan metode pengenalan citra “Tanpa Ekstraksi Ciri”. Penulis memilih metode klasifikasi Tanpa Ekstraksi Ciripada metode pengenalan citra “Tanpa Ekstraksi Ciri”.
Tanpa Ekstraksi Ciri dipilih penulis sebagai metode pembanding karena Tanpa Ekstraksi Cirimerupakan metode yang paling sederhana yang sering digunakan sebagai metode klasifikasi. Perbedaan mendasar antara metode pengenalan citra dengan Ekstraksi Ciri Tanpa Ekstraksi Ciri adalah sebagai berikut :
Metode pengenalan citra dengan Ekstraksi Ciri menggunakan DCT sebagai Feature Ekstraction dan fungsi Similaritas kosinus.
Metode pengenalan citra tanpa Ekstraksi Ciri menggunakan Tanpa Ekstraksi Ciri sebagai metode klasifikasi
Dari tabel diatas, diketahui bahwa pengenalan dengan Ekstraksi Ciri memiliki persentase tingkat keberhasilan yang lebih tinggi daripada metode Tanpa Ekstraksi Ciri. Hal ini membuktikan bahwa metode dengan Ekstraksi Ciri jauh lebih robust / tahan. Metode dengan Ekstraksi Ciri lebih tahan terhadap rotasi dan pergeseran. Semakin jauh pergeseran dan rotasi yang di tes, metode Tanpa Ekstraksi Ciri semakin tidak dapat mengenali “tools”
dengan benar.
56
BAB V KESIMPULAN
Dari percobaan dan pengujian sistem pengenalan alat bengkel disimpulkan sebagai berikut :
1. Implementasi dari sistem pengenalan alat bengkel pada dasarnya dapat bekerja sesuai dengan perancangan. Program pengenalan alat bengkel sudah mampu untuk mengenali alat bengkel dari penulis meliputi tang dan sebagainya.
2. Penentuan nilai ambang batas 0.5 dan windowing 100% adalah untuk menguji kestabilan metode Ekstraksi Ciri bila dibandingkan dengan metode Tanpa Ekstraksi Ciri.
Karena pada kondisi yang ideal (misal batas ambang “0.5” dan windowing
“100” %) hasil Ekstraksi Ciri dan Tanpa Ekstraksi Ciri saling mendekati.
3. Pembagian data ke dalam ukuran data yang lebih kecil dengan mengurangi jumlah koefisien elemen ekstraksi ciri, akan mempercepat proses Ekstraksi Ciri dan Tanpa Ekstraksi Ciri.
4. Berdasarakan tabel hasil validasi, hasil testing Ekstraksi Ciri mendapat nilai 79 % dan Tanpa Ekstraksi Ciri 50 %. Jadi metode DCT lebih unggul dibandingkan Tanpa Ekstraksi Ciri.
SARAN
Beberapa saran untuk pengembangan Aplikasi Pengenalan Alat Bengkel dari penulis adalah sebagai berikut:
1. Metode DCT dapat mengenali tools / alat bengkel untuk semua posisi (rotasi dan pergeseran) tanpa perlu menggunakan modul.
2. Pengenalan alat bengkel dapat dilakukan pada kondisi lingkungan (penerangan) apapun.
57
DAFTAR PUSTAKA
[1] Anonim, 2010, Perbedaan Discrete Cosine Transform dan Discrete Wavelet Transform
http://anoa5.wordpress.com/2010/05/08/perbedaan-discrete-cosine-
transform-dct-dan discrete-wavelet-transform-dwt/ diakses 12 September 2014.
[2] Anonim, Tanpa Tahun, Modul KLT,
http://www.planetsourcecode.com/ diakses 16 Juni 2014.
[3] Anonim, Tanpa Tahun, Discrete Cosine Transform,
http://en.wikipedia.org/wiki/Discrete_cosine_transform/ diakses 28 September 2014.
[4] Munir, Rinaldi, Tanpa Tahun, Pengenalan Pola ,
http://informatika.stei.itb.ac.id/rinaldi.munir/Buku/Pengolahan/Bab-15_Pengenalan Pola.pdf/ diakses 20 Juni 2015.
[5] Laksmito, B., 2010, Pengertian Webcam dan Jenis-Jenisnya,
http://en.wikipedia.org/wiki/Pengertian Webcam dan Jenis-Jenisnya/ diakses 28 September 2014
[6] Putra, R. The Best Source Code Visual Basic. Jakarta: PT Gramedia. 2006.
[7] Sumarno, Linggo. Pengenalan Nada Pianika Menggunakan Jendela Gaussian DCT dan Jarak Kosinus. Program Studi Teknik Elektro Fakultas Teknik Universitas Sanata Dharma. Yogyakarta. 2013; SIGMA, Vol.17(1): 8-10.
[8] Novariyanto, Irwan. Pengenalan Nada Alat Musik Belira secara Real Time dengan Ekstraksi Ciri DCT dan Similaritas Kosinus. Skripsi. Yogyakarta : Universitas Sanata Dharma; 2014.
58
[9] Wardhana, Wisnu A, Yudi P. Penggunaan Metode Templete Matching
untuk Identifikasi Kecacatan pada PCB. Seminar Nasional Aplikasi Teknologi Informasi.
Yogyakarta; 2008.
[10] Putra, Dharma. Pengolahan Citra Digital. Yogyakarta: Andi Offset. 2010.
[11] Kadir A, Susanto A. Teori dan Aplikasi Pengolahan Citra.
Yogyakarta: Andi Offset. 2013.
[12] Alfatah, Hanif. Konversi Format Citra RGB ke Graysacle Menggunakan Visual Basic. Thesis. Yogyakarta: STMIK AMIKOM; 2007.
[13] Mesran. Visual Basic. Jakarta: Mitra Wacana Media. 2009.
[14] Pearson, Don. Editors. Image Processing. New York: McGraw- Hill. 1991.
[15] Sklar, Bernard, 1988, Digital Communications Fundamental and Application, New Jersey: P T R Prentice Hall.
[16] Sumarno, Linggo. Pengenalan Huruf Tulisan Tangan Berderau Dan Terskala Berbasis Ekstraksi Ciri DCT Dengan Menggunakan Jaringan Syaraf Probabilistik. Program Studi Teknik Elektro Fakultas Teknik Universitas Sanata Dharma. Yogyakarta. 2007; SIGMA,Vol.10(2): 185-197.
[17] Banks, Stephen. Signal Processing, Image Processing, and Pattern Recognition.
New York: Prentice Hall. 1990.
[18] Bow, S. Pattern Recognition and Image Processing. Basel: Marcel Dekker, Inc.
2002.
[19] Andrew, R.Webb. Statistical Pattern Recognition. Second Edition. West Susse:
JohnWiley and Sons, Ltd. 2002.
[20] Gonzales, Rafael C., Woods, Richard E., 2004.Digital Image Processing. Third Edition. New Jersey: Pearson Education, Inc. 2008.
[21] Schalkoff, J. Robert. Digital Image Processing and Computer Vision. New York:
John Wiley and Sons, Inc. 1989.
[22] Kadir, Abdul. Pemampatan Data Citra Menggunakan Alihragam Gelombang Singkat . Thesis. Yogyakarta: Universitas Gajah Mada; 1998.
59
[23] J. Xiao-Yuan, D. Zhang. A Face and Palmprint Recognition Approach Based
on Discriminant DCT Feature Extraction. IEEE Transactions On Systems Man Cybern B.December 2004; VOL. 34(6).
[24] https://en.wikipedia.org/wiki/JPEG#Discrete_cosine_transform
[25] http://stackoverflow.com/questions/7013309/visual-studio-debugger-error-unable- to-start-program-specified-file-cannot-be-f
[26] https://en.wikipedia.org/wiki/JPEG#Discrete_cosine_transform
[27] http://stackoverflow.com/questions/7013309/visual-studio-debugger-error-unable- to- start-program-specified-file-cannot-be-f
[28] http://stackoverflow.com/questions/5864520/error-while-trying-to-run-project- unable- to-start-program-cannot-find-the-file\
LAMPIRAN I
Coding Testing
// test.cpp : Defines the entry point for the console application.
//
//Just to test DCT & IDCT int TestDctIDct() {
int res = ErrorCode::NATIVE_UNEXPECTED_EXCEPTION;
cv::Mat src = cv::imread("D:\TA\20160210\sample\\f_double.png", CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat d1, d2;
//res = dct::ConvertToDct(src, d1);
//res = dct::InverseDct(d1, d2);
res = dct::FastDct(src, d1);
res = dct::FastInverseDct(d1, d2);
cv::Mat debug(src.rows * 2, src.cols * 2, CV_8U, cv::Scalar(0));
cv::Rect window(0, 0, src.rows, src.cols);
cv::Mat w1 = debug(window);
src.copyTo(w1);
window = cv::Rect(src.rows, 0, src.rows, src.cols);
w1 = debug(window);
cv::Mat plot;
d1.convertTo(plot, CV_8U);
plot.copyTo(w1);
window = cv::Rect(0, src.cols, src.rows, src.cols);
w1 = debug(window);
int res = ErrorCode::NATIVE_UNEXPECTED_EXCEPTION;
config cfg("..\\..\\sample\\dct.xml");
cv::Mat training = cv::imread(cfg.pathTraining, CV_LOAD_IMAGE_GRAYSCALE);
if (training.data == 0) {
std:: cout << "Gambar tidak ada! cari dahulu " << cfg.pathTraining << "\n";
return -1;
}
cv::Mat dTrain;
if (cfg.toApply) { cv::Mat temp;
if (cfg.method == 0) {
cv::threshold(training, temp, cfg.param1, 225, CV_THRESH_BINARY);
} else {
cv::threshold(training, temp, 0, 225, CV_THRESH_BINARY| CV_THRESH_OTSU);
}
res = dct::FastDct(temp, dTrain);
} else {
res = dct::FastDct(training, dTrain);
}
cv::Mat fTemplate = cv::imread(cfg.pathTemplate, CV_LOAD_IMAGE_GRAYSCALE);
cv::Matdebug(training.rows * cfg.pathTestCases.size(), training.cols * 2, CV_8U, cv::Scalar(0));
int topLeft = 0;
for (unsigned int i = 0; i < cfg.pathTestCases.size(); i++) { cv::Mat test1 = cv::imread(cfg.pathTestCases[i], CV_LOAD_IMAGE_GRAYSCALE);
if (test1.data == 0) {
std:: cout << "Gambar tidak ada! cari dahulu " << cfg.pathTestCases[i] <<
"\n";
cv::threshold(test1, bin, cfg.param1, 400, CV_THRESH_BINARY);
} else {
cv::threshold(test1, bin, 0, 400, CV_THRESH_BINARY| CV_THRESH_OTSU);
} } else {
bin = test1;
}
res = dct::FastDct(bin, d2);
double cs = dct::CheckSimilarity(dTrain, d2, static_cast<unsigned int>(cfg.persentase));
cv::Rect window(0, topLeft, test1.rows, test1.cols);
topLeft += test1.cols;
cv::Mat crop = debug(window);
bin.copyTo(crop);
// TEMPLATE MATCHING std::string ok = "[N] ";
cv::Mat chkTemplate;
#if 1
cv::matchTemplate(fTemplate, test1, chkTemplate, CV_TM_CCOEFF_NORMED);
double minval, maxval, threshold = 0.6;
cv::Point minloc, maxloc;
cv::minMaxLoc(chkTemplate, &minval, &maxval, &minloc, &maxloc);
if(maxval >= threshold) { ok = "[Y] ";
}
#else
int match_method = 0;
cv::matchTemplate(fTemplate, test1, chkTemplate, match_method);
//cv::normalize( chkTemplate, chkTemplate, 0, 1, cv::NORM_MINMAX, -1, cv::Mat() );
/// Localizing the best match with minMaxLoc
double minVal; double maxVal; cv::Point minLoc; cv::Point maxLoc;
cv::minMaxLoc( chkTemplate, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() );
//cv::Point matchLoc;
//matchLoc = ( match_method == CV_TM_SQDIFF || match_method ==
CV_TM_SQDIFF_NORMED )
// ? minLoc : maxLoc;
// TO_DO: check how to get this if (minVal < 255) {
ok = "[Y] ";
}
#endif
// TULIS HASIL
cv::putText(debug, ok + std::to_string(cs)
, cv::Point( (test1.cols + 10), (topLeft-test1.rows/2) ) , CV_FONT_HERSHEY_PLAIN, 1, cv::Scalar(255));
}cv::imwrite(cfg.pathResult, debug);
return 0;
}
// This function should be called just once; to help creating the config file int CreateConfig() {
fs << "test_cases" << sampleCases;
fs << "training" << "..\\samples\\f_training.png";
fs << "training" << "..\\samples\\f_training.png";
fs << "template" << "..\\samples\\f_template.png";
fs << "result" << "..\\samples\\f_result.png";
fs << "toApply" << true;
fs << "method" << CV_THRESH_BINARY;
fs << "param1" << 127;
return 0;
}
static void onMouse( int event, int x, int y, int flag, void *data ) { if( event != CV_EVENT_LBUTTONDOWN )
return;
if (data == 0) return;
int length = 256;
int panel = 200;
int margin = 10;
int thickness = 23;
if ( (length+margin) > x || x > (length+panel-margin)) return;
if ( (margin) > y || y > (panel-margin)) return;
unsigned char temp = 0;
if ( (margin) <= y && y <= (thickness+margin)) { temp = 67; // "C"
}
if (temp == 0) return;
unsigned char *sel;
try {
sel = static_cast<unsigned char *>(data);
} catch(...) { return;
}*sel = temp;
}
int TestCroppedStreaming() {
int idCamera = -1; // cek di aplikasi camera (index mulai dari 0 config cfg("..\\..\\sample\\dct.xml");
// TO_DO: get cameraid idCamera = 1;
cv::VideoCapture vc(idCamera);
std::string nameWindow = "DCT - CS";
cv::namedWindow( nameWindow, cv::WINDOW_AUTOSIZE );
cv::Mat frame;
cv::Rect crop(0,0 // ujung kiri atas , 479, 479); // ukuran crop unsigned char key = 0;
unsigned char mouse = 0;
detection det(cfg);
cv::setMouseCallback( nameWindow, onMouse, static_cast<void *>(&mouse) );
unsigned int i = 0;
int length = 256;
int panel = 200;
int margin = 10;
int thickness = 23;
cv::Mat canvas(cv::Size(length+panel, length), CV_8UC1, cv::Scalar(200));
std::vector<cv::Point> tombol;
tombol.emplace_back(cv::Point(length+margin, margin));
tombol.emplace_back(cv::Point(length+panel-margin, margin));
tombol.emplace_back(cv::Point(length+panel-margin, margin+thickness));
tombol.emplace_back(cv::Point(length+margin, margin+thickness));
cv::polylines(canvas, tombol, true, cv::Scalar(50), 1);
cv::putText(canvas, "deteksi alat", cv::Point(length+margin+30, margin+13), CV_FONT_NORMAL, 0.5, cv::Scalar(0), 1);
std::vector<cv::Point> blank;
blank.emplace_back(cv::Point(length+margin, margin+thickness+1));
blank.emplace_back(cv::Point(length+panel-margin, margin+thickness+1));
blank.emplace_back(cv::Point(length+panel-margin, length-margin));
blank.emplace_back(cv::Point(length+margin, length-margin));
std::vector< std::vector<cv::Point> > blanks;
blanks.push_back(blank);
cv::Rect viewPort(0,0 , length, length);
while (key != 27) {
HWND hwnd = (HWND)cvGetWindowHandle(nameWindow.c_str());
key = cv::waitKey(50);
if (hwnd == 0 || !IsWindowVisible(hwnd)) { key = 27;
break;
}
vc >> frame;
cv::Mat bin = frame(crop);
cv::cvtColor(bin, bin, CV_RGB2GRAY);
cv::resize(bin, bin, cv::Size(length, length));
cv::Mat feed = canvas(viewPort);
bin.copyTo(feed);
cv::imwrite("..\\..\\sample\\" + std::to_string(i++) +".png", bin);
break;
case 67: // (C)heck
{ hasil res = det.cek(bin);
cv::fillPoly(canvas, blanks, cv::Scalar(200));
int posY = margin + 2*thickness;
int posX = length+margin;
cv::putText(canvas, "Kosinus:", cv::Point(posX, posY), CV_FONT_NORMAL, 0.5, cv::Scalar(0), 1);
posY += thickness;
if (res.alatKosinus.length() == 0) {
cv::putText(canvas, "TIDAK DIKENALI", cv::Point(posX, posY), CV_FONT_NORMAL, 0.5, cv::Scalar(0), 1);
posY += thickness;
} else {
cv::putText(canvas, res.alatKosinus, cv::Point(posX, posY), CV_FONT_NORMAL, 0.5, cv::Scalar(0), 1);
posY += thickness;
cv::putText(canvas, "nilai: " +
patch::to_string(res.nilaiKosinus), cv::Point(posX, posY), CV_FONT_NORMAL, 0.5, cv::Scalar(0), 1);
}posY += thickness;
cv::putText(canvas, "Template Matching:", cv::Point(posX, posY), CV_FONT_NORMAL, 0.5, cv::Scalar(0), 1);
posY += thickness;
if (res.alatTemplate.length() == 0) {
cv::putText(canvas, "TIDAK DIKENALI", cv::Point(posX, posY), CV_FONT_NORMAL, 0.5, cv::Scalar(0), 1);
posY += thickness;
} else {
cv::putText(canvas, res.alatTemplate, cv::Point(posX, posY), CV_FONT_NORMAL, 0.5, cv::Scalar(0), 1);
posY += thickness;
cv::putText(canvas, "nilai: " +
patch::to_string(res.nilaiTemplate), cv::Point(posX, posY), CV_FONT_NORMAL, 0.5, cv::Scalar(0), 1);
std::cout << "Config tidak bisa dibaca." << "\n";
return -1;
}
std::vector<cv::Mat> templates;
for (unsigned int i = 0; i < db.Data().size(); i++) {
cv::Mat training = cv::imread(db.Data()[i].lokasiGambar, CV_LOAD_IMAGE_GRAYSCALE);
if (training.data == 0) {
std::cout << "Database untuk alat '" << db.Data()[i].namaAlat << "' tidak bisa dibaca." << "\n"
<< "Pastikan gambar '" << db.Data()[i].lokasiGambar << "' tersedia."
<< "\n";
return -1;
}cv::Mat dTrain;
int res = dct::FastDct(training, dTrain);
templates.emplace_back(dTrain);
}
for (unsigned int i = 0; i < cfg.pathTestCases.size(); i++) { cv::Mat test1 = cv::imread(cfg.pathTestCases[i], CV_LOAD_IMAGE_GRAYSCALE);
double nilaiKemiripanMaksimal = -2.0;
unsigned int indexMirip = 0;
cv::Mat d2;
int res = dct::FastDct(test1 , d2);
for (unsigned int j = 0; j < templates.size(); j++) {
double cs = dct::CheckSimilarity(templates[j], d2, db.Persentase());
if (cs < db.Data()[j].batasMinimum) continue;
if (cs > nilaiKemiripanMaksimal) { nilaiKemiripanMaksimal = cs;
indexMirip = j;
}
}if (nilaiKemiripanMaksimal > 0.0f) {
std::cout << "Gambar '" << cfg.pathTestCases[i] << "' kemungkinan adalah '"
<< db.Data()[indexMirip].namaAlat << "' dengan tingkat kimiripan: "
<< nilaiKemiripanMaksimal << "\n";
} else {
std::cout << "Gambar '" << cfg.pathTestCases[i] << "' tidak dikenali" <<
"\n";
} }
return 0;
}
int _tmain(int argc, _TCHAR* argv[]) { return TestCroppedStreaming();
//CreateConfig();
//return 0;
int keyStroke = 49;
{
std::cout << "Please select what you intend to do:\n";
std::cout << "\t<1> Get Sample\n";
std::cout << "\t<2> Test\n";
std::cout << "\t<3> Perbandingan\n";
std::cout << "\t<Esc> Forget about it, let me out\n";
bool noValidInput = true;
while (noValidInput) { keyStroke = _getch();
switch (keyStroke) { case 27: return 0;
case 49: noValidInput = false; break; // 1 case 50: noValidInput = false; break; // 2 case 51: noValidInput = false; break; // 3 default: break;
} }
}switch (keyStroke) {
case 49: TestCroppedStreaming(); break;// buat ambil sample case 50: TestCosineSimilarity(); break;// buat testing
case 51: DeteksiAlat(); break;// aplikasi akhir jadi kaya gini?
}
std::cout << "Selesai\n";
_getch();
return 0;
}