Object Detection: Membuat Classifier Anda Sendiri
Pendahuluan
Pada tutorial sebelumnya, kita sudah belajar bagaimana mendeteksi obyek mobil dengan Haarcascade Classifier. Pada tulisan ini, kita akan belajar bagaimana membuat classifier kita sendiri dengan kasus "Deteksi Compact Disk". Diharapkan setelah mempelajari tutorial ini, anda dapat menentukan sendiri obyek apapun yang akan anda deteksi.
Persiapan
Pada tutorial sebelumnya, kita sudah belajar bagaimana mendeteksi obyek mobil dengan Haarcascade Classifier. Pada tulisan ini, kita akan belajar bagaimana membuat classifier kita sendiri dengan kasus "Deteksi Compact Disk". Diharapkan setelah mempelajari tutorial ini, anda dapat menentukan sendiri obyek apapun yang akan anda deteksi.
Persiapan
Software yang saya gunakan adalah:
- Visual Studio 2010
- library OpenCV 2.4.11.
- ObjectMarker
- Cascade2xml
Langkah-langkah:
Berikut adalah langkah-langkah pembuatan classifier. Sesuaikan sendiri dengan path direktori anda.
1. Step: Pembuatan list negatif
Buat list foto background (negatif) yang sudah dalam format JPG dan greyscale dengan perintah: dir /b > negatif.txt dan jangan lupa bersihkan file negatif.txt dari dirinya sendiri (karena kata "negatif.txt" ada di dalamnya). Pastikan isi negatif.txt hanya daftar JPG gambar negatif anda. Lihat pada Gambar 1 berikut:
Gambar 1: Proses pembuatan list gambar negatif
2. Step: Pemberian fullpath gambar negatif
Berikan FullPath untuk setiap foto negatif yang sudah dibuat (gunakan file list_neg.bat) dengan perintah:
(for /F "delims=" %%L in (neg.txt) do @echo D:\DataJati\belajar_image_processing\negatif\jpg\%%L)>> negNew.txt
Edit lebih dulu dan sesuaikan folder path anda. Pada contoh gambar 2, saya meletakkan file background (negatif) di path: D:\DataJati\belajar_image_processing\negatif\jpg. Sesuaikan dengan path anda masing-masing.
(for /F "delims=" %%L in (neg.txt) do @echo D:\DataJati\belajar_image_processing\negatif\jpg\%%L)>> negNew.txt
Edit lebih dulu dan sesuaikan folder path anda. Pada contoh gambar 2, saya meletakkan file background (negatif) di path: D:\DataJati\belajar_image_processing\negatif\jpg. Sesuaikan dengan path anda masing-masing.
Gambar 2: Proses pemberian fullpath gambar negatif
3. Step: Pembentukan file negNew.txt
Gambar 3 menunjukkan isi file negatif yang lengkap dengan fullpath-nya
Gambar 3: File negNew.txt
4. Step: Persiapan file positif
File positif adalah file yang nantinya menjadi acuan pendeteksian obyek. Kita sebenarnya akan melatih sistem untuk mengenali obyek seperti obyek yang terlihat di file positif ini. Pindahkan file positif anda ke direktori rawdata dengan mengubah format menjadi BMP. Path image rawdata saya ada di D:\DataJati\belajar_image_processing\CD_Tracking\img\rawdata\. Proses pemindahan ke folder rawdata ini wajib karena aplikasi objectmarker.exe di langkah 5 membutuhkannya.
Gambar 4: File positif dalam format BMP
5. Step: Pembuatan object info
Gambar 5: Aplikasi objectmarker
Saat aplikasi objectmarker dijalankan, anda akan diminta untuk "menandai" sebuah area yang merupakan obyek terdeteksi. Perhatikan gambar 5a. Pada gambar 5a, saya menandai CD di tangan saya, yang otomatis dicatat rawdata area tersebut (gambar 5b).
Gambar 5a: Proses pembuatan rawdata (1)
Gambar 5b: Proses pembuatan rawdata (2)
6. Step: Terbentuk file info.txt
File info.txt ini berisi rawdata dari sample yang berasal dari gambar positif dari proses tahap 5. Gambar 6 menunjukkan isi rawdata dan bisa berbeda dengan rawdata anda.
Gambar 6: File info.txt yang berisi rawdata gambar positif
7. Step: Replace karakter
Ganti slash (/) menjadi backslash (\) mengikuti format direktori di Sistem Operasi Windows.
Gambar 7: Replace karakter / menjadi \
8. Step: Full Path untuk file info.txt (rawdata)
Proses ini diperlukan untuk memberikan fullpath di file info.txt anda menjadi file positif.txt
Gambar 8a: Proses pemberian full path untuk setiap rawdata
File positif ditunjukkan pada Gambar 8b sebagai berikut:
9. Step: Pembuatan file vector (*.vec)
Buat file VEC menggunakan create_sample_command.bat. Sesuaikan parameter num sesuai jumlah file positif anda (lihat langkah 8). Yang perlu menjadi perhatian adalah parameter lebar dan tinggi (w dan h) disesuaikan dengan langkah 13. Perhatikan gambar 9a. Gambar 9b menunjukkan proses eksekusi createsample.
Gambar 9a: Pembuatan file vector
Proses eksekusinya ditunjukkan pada Gambar 9b sebagai berikut:
Gambar 9b: Proses pembentukan file vector
10. Step: Terbentuk file vector
Gambar 10 menunjukkan telah terbentuk file samples.vec
Gambar 10: File samples.vec
11. Step: Pembuatan classifier
Gambar 11a: Pembuatan tempat penampungan (direktori) classifier
Kemudian kita buat perintah untuk membuat classifier. Perhatikan gambar 11b
Gambar 11b: Perintah haartraining
Pada gambar 11b, saya menulisnya dengan enter agar tidak terlalu panjang saja. :)
Proses training-nya ditunjukkan pada gambar 11c sebagai berikut:
Gambar 11c: Proses Training
12. Step: Terbentuk training cascade
Pada tahap ini telah terbentuk file cascade yang berada di direktori classifier
Gambar 12: Training Cascade
13. Step: Penyatuan file cascade menjadi cascade classifier lengkap
Pada tahap ini, kita akan menyatukan training cascade di langkah 12 supaya menjadi cascade classifier lengkap yang nantinya akan kita panggil di source code. Saya menggunakan tools convert cascade2xml yang dapat didownload di sini.
Pertama kita pindahkan dulu isi classifier kita ke direktori data di aplikasi cascade2xml seperti pada gambar 13a.
Gambar 13a: Pemindahan classifier ke data
Gambar 13b menunjukkan perintah konversi cascade2xml (perhatikan parameter h dan w-nya). Sesuaikan dengan langkah 9. Data merupakan direktori tempat classifier yang sudah kita pindahkan.
Gambar 13b: Proses penyatuan
Output dari cascade2xml adalah output.xml seperti ditunjukkan gambar 13a. File output inilah yang nanti dipanggil pada source pendeteksian obyek anda.
Implementasi
Setelah file classifier sudah kita dapatkan, berikut adalah source code pendeteksian obyek dalam file CPP.
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
void deteksi_tampilkan( Mat frame );
String cascade_name = "E:\\cascade2xml\\output.xml";
CascadeClassifier cd_cascade;
string window_name = "Tampilkan - Deteksi Obyek";
int main( )
{
CvCapture* ambilVideo;
Mat frame;
//-- 1. Panggil cascade
if( !cd_cascade.load( cascade_name ) ){ printf("--(!)Error loading\n"); system("PAUSE"); return -1; };
//-- 2. Baca video
ambilVideo = cvCaptureFromCAM( 0 );
if (!ambilVideo) {
printf("Tidak dapat memanggil Kamera");
}
else
{
printf("Panggil Camera Sukses");
}
if( ambilVideo )
{
while( true )
{
frame = cvQueryFrame( ambilVideo );
//-- 3. Terapkan classifier ke Frame Video
if( !frame.empty() )
{ deteksi_tampilkan( frame ); }
else
{ printf(" --(!) Tidak ada Frame -- Berhenti!"); break; }
int c = waitKey(10);
if( (char)c == 'c' ) { break; }
}
}
return 0;
}
//-- Fungsi deteksi_tampilkan
void deteksi_tampilkan( Mat frame )
{
std::vector<Rect> obyek;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
//-- Deteksi obyek
cd_cascade.detectMultiScale( frame_gray, obyek, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( size_t i = 0; i < obyek.size(); i++ )
{
Point center( obyek[i].x + obyek[i].width*0.5, obyek[i].y + obyek[i].height*0.5 );
ellipse( frame, center, Size( obyek[i].width*0.5, obyek[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
}
//-- Tampilkan Pendeteksian
imshow( window_name, frame );
}
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
void deteksi_tampilkan( Mat frame );
String cascade_name = "E:\\cascade2xml\\output.xml";
CascadeClassifier cd_cascade;
string window_name = "Tampilkan - Deteksi Obyek";
int main( )
{
CvCapture* ambilVideo;
Mat frame;
//-- 1. Panggil cascade
if( !cd_cascade.load( cascade_name ) ){ printf("--(!)Error loading\n"); system("PAUSE"); return -1; };
//-- 2. Baca video
ambilVideo = cvCaptureFromCAM( 0 );
if (!ambilVideo) {
printf("Tidak dapat memanggil Kamera");
}
else
{
printf("Panggil Camera Sukses");
}
if( ambilVideo )
{
while( true )
{
frame = cvQueryFrame( ambilVideo );
//-- 3. Terapkan classifier ke Frame Video
if( !frame.empty() )
{ deteksi_tampilkan( frame ); }
else
{ printf(" --(!) Tidak ada Frame -- Berhenti!"); break; }
int c = waitKey(10);
if( (char)c == 'c' ) { break; }
}
}
return 0;
}
//-- Fungsi deteksi_tampilkan
void deteksi_tampilkan( Mat frame )
{
std::vector<Rect> obyek;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
//-- Deteksi obyek
cd_cascade.detectMultiScale( frame_gray, obyek, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( size_t i = 0; i < obyek.size(); i++ )
{
Point center( obyek[i].x + obyek[i].width*0.5, obyek[i].y + obyek[i].height*0.5 );
ellipse( frame, center, Size( obyek[i].width*0.5, obyek[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
}
//-- Tampilkan Pendeteksian
imshow( window_name, frame );
}
Hasil
Note:
Penting untuk menjadi perhatian, banyaknya file positif, negatif dan jumlah stage dalam proses training akan sangat berpengaruh pada ketepatan pendeteksian obyek yang anda lakukan. Permasalahannya, semakin banyak file positif, negatif dan jumlah stage akan memperpanjang waktu yang diperlukan untuk melakukan haartraining. Jadi siapkan cemilan dan tempat duduk yang nyaman saat melakukan haartraining.
Referensi
https://www.cs.auckland.ac.nz/~m.rezaei/Tutorials/Creating_a_Cascade_of_Haar-Like_Classifiers_Step_by_Step.pdf
Selamat mencoba
mas pada proses haartraining -nstages 10 maksudnya apa ya? kalau saya punya positive 94 negative 200 -nstages yg dimasukan berapa?
Thanks a lot Mr. Haruno
You're welcome. Sami-sami.
mas haruno, saya bisa minta bantuan teori facedetection serta buku2 yang mendukung untuk daftar pustaka step by step, alamat email oktakurniawan.mail@gmail.com, untuk keperluan skripsi. saya akan beli mas tenang tidak gratisan.
saya sekarang pake PHP dan openCV php extension, deteksi wajah (haar cascade)
trimakasih.
-Ubuntu Server
-OpenCV 2
-PHP Extension OpenCV
mas isi gambar file negatif (bg) spt apa?
assalamualikum pa, maaf sebelumnya disini bapa menggunkan sample negatif dan positif sudah berbentuk gambar, bagaimana langkah-langkahnyanya apabila filenya berbentuk video, terimakasih
Assalamualaikum mas....untuk kasusku, yang akan di deteksi berapa banyak objek yang mengalir dalam aliran sungai (ranting, sampah dan buih) yang akan dijadikan indikator peringatan dini banjir bandang. jika ada 3 objek seperti itu, boleh petunjuknya bagaimana membuat training negatif dan positi