• image01

    Face

    Recognition

  • image02

    Object

    Recognition

  • image03

    Face

    Identification

  • image04

    Hand Gesture

    Recognition

  • image05

    QR & Barcode

    Scanner

Friday, April 24, 2015

Tutorial OpenCV 5: Sensor Gerak dengan Metode Background Subtraction

   Kalau dalam Fisika, gerak diartikan sebagai perpindahan benda dari satu titik ke titik lainnya. Nah, kalau dalam pengolahan citra tentunya kita tidak bisa mengatakan titik-titik warnanya berpindah tempat bukan? Yang terjadi adalah warna yang hampir sama ditampilkan oleh piksel-piksel yang bersebelahan secara bergantian. Kalau dilihat dengan mata, kita mudah sekali membedakan benda bergerak dan benda diam. Namun, bagaimana caranya komputer dapat mengenal gerak?
   Nah, dalam tutorial kali ini kita akan belajar membuat sebuah sensor gerak sederhana menggunakan webcam. Metode yang kita gunakan adalah background subtraction Gaussian Mixture Model (GMM). Kalau di OpenCV metode ini dikenal dengan fungsi BackgroundSubtractorMOG2(). Selain yang MOG2 kita juga bisa gunakan yang MOG saja. Bedanya yang MOG2 katanya lebih cepat dan akurat. Oh iya, MOG itu singkatan dari Mixture of Gaussian. Kalau mau tahu teorinya yang lebih lengkap cari aja GMM di internet.
   Pertama, buat project baru dari template OpenCV, beri nama projectnya “sonsorgerak”. Seperti biasa buat tombol “Mulai” dan “Berhenti” serta sebuah PictureBox. Biar lebih menarik, tambahkan pula ProgressBar. Setelah itu, klik 2 kali tombol “Mulai” dan juga tombol “Berhenti” lalu masukkan kode berwarna merah berikut:
int tutup;
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
                 VideoCapture webcam;
                 webcam.open(0);
                 Mat asli,mask;
                 tutup=0;
                 Ptr<BackgroundSubtractor> MOG2;
                 MOG2 = new BackgroundSubtractorMOG2();
                 float alfa=0.1;
                 cv::Scalar mean, stdev;
                 namedWindow("tes",0);
                 namedWindow("asli",0);
                 while(tutup==0)
                 {
                                 webcam>>asli;
                                 MOG2->operator()(asli, mask, alfa);
                                 imshow("tes",mask);
                                 meanStdDev(mask,mean,stdev);
                                 double stddev=*stdev.val/1.2;
                                 if(stddev<100)
                                                 progressBar1->Value=stddev;
                                 else progressBar1->Value=100;
                                 cvtColor(mask,mask,CV_GRAY2BGR);
                                 MatIterator_<Vec3b> it, end;
                                 for( it = mask.begin<Vec3b>(), end = mask.end<Vec3b>(); it != end; ++it)
                                 {
                                                 if((*it)[2]>0)
                                                 {
                                                                 (*it)[0]=0;
                                                                 (*it)[2]=0;
                                                 }
                                 }
                                 addWeighted(asli,1,mask,0.9,0.0,asli);
                                 imshow("asli",asli);
                                 Mat img1 = asli;
                                 System::Drawing::Graphics^ graphics1 = pictureBox1->CreateGraphics();
                                 System::IntPtr ptr1(img1.ptr());
                                 System::Drawing::Bitmap^ b1 = gcnew System::Drawing::Bitmap(img1.cols,
                                                 img1.rows, img1.step, System::Drawing::Imaging::PixelFormat::Format24bppRgb, ptr1);
                                 System::Drawing::RectangleF rect1(0, 0, pictureBox1->Width, pictureBox1->Height);
                                 graphics1->DrawImage(b1, rect1);
                                 waitKey(1);
                 }
 }
private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
                 tutup=1;
                 destroyAllWindows();
 }
   Lalu, jangan lupa menambah event FormClosing (baca tutorial 3 atau 4) dan masukkan kode:
          tutup=1;
   Bagaimana hasilnya? Kalau sukses maka kita akan melihat ProgressBar yang berubah-ubah nilainya saat ada yang bergerak di depan webcam. Semakin banyak gerakan yang terjadi maka nilai pada ProgressBar juga akan semakin besar. Nah, bagaimana sistematika penjelasannya?
Dalam tutorial ini kita menggunakan fungsi MOG2. Pada fungsi ini nilai piksel gambar terbaru (foreground, FG) akan dikurangkan dengan nilai piksel gambar acuan (background, BG). BG bisa dibuat statis atau dinamis, misalnya BG adalah gambar pertama saja, gabungan 10 gambar sebelum FG, atau gambar tepat sebelum FG. Banyaknya gambar yang dijadikan BG ditentukan dengan variabel alfa. Perhitungannya adalah:
log 0,9 / log (1-alfa) = n frame
   Jadi misalkan kita menggunakan alfa 0,001 maka BG terdiri dari campuran 105 gambar sebelum FG. Kalau misalkan webcam bekerja maksimal (30 fps) maka waktunya kira-kira 3,5 detik. Artinya jika kamu diam di depan webcam selama 3,5 detik maka program tidak lagi menganggap kamu sebagai benda asing/bergerak. Namun, jika kamera bekerja minimal (6 fps) maka dibutuhkan waktu + 7,5 detik. Oh iya, biasanya prosesor saya cuma bisa 22 fps jika tidak menggunakan CUDA.
   Gambar hasil BG subtraction (disebut mask) kemudian dicari nilai standar deviasinya (SD) dengan fungsi meanStdDev(). Jika ukuran gambar dari webcam adalah 640x480 piksel maka nilai SD ini memiliki nilai maksimal sekitar 127,5. Nilai maksimal ini tercapai jika gambar mask memiliki piksel putih dan hitam berjumlah sama. Nilai SD ini sebanding dengan banyaknya piksel putih. Simpelnya semakin besar gerakan yang terjadi, maka ProgressBar akan semakin penuh. Nilai SD ini bisa diakses dari variabel stdev atau stddev (stddev=stdev/1,2).
   Selanjutnya gambar mask dikonversi dari GRAY ke BGR dengan fungsi cvtColor() dan diambil hanya warna hijaunya sebagai indikator piksel-piksel yang menunjukkan pergerakan. Jika ingin menggunakan warna lain kita bisa mengubah kode:
     (*it)[0]=0;
        (*it)[2]=0;
Kode [0] adalah komponen warna merah, [1] hijau, dan [2] merah. sedangkan nilai setelah tanda “=” adalah intensitas warna-warna tersebut dengan nilai maksimal 255. Misalkan kita ingin menggunakan warna oranye maka kita ganti kodenya dengan:
       (*it)[0]=0;
       (*it)[1]=150;
       (*it)[2]=255;
Nah, selanjutnya gambar mask tersebut dibaurkan dengan gambar asli sehingga tercipta kesan warna hijau/oranye pada piksel yang mendeteksi gerakan. Penggabungan kedua gambar ini dilakukan dengan fungsi addWeighted(), di mana intensitas kedua gambar dapat diatur. Pada tutorial ini intensitas gambar mask diatur pada 0,9.
Ingat bahwa tutorial ini sifatnya masih simpel. Untuk aplikasi nyatanya kita bisa menggunakannya untuk menghitung barang/orang yang melewati webcam, sistem parkir, webcam keamanan, atau juga mengukur periode bandul. Sedikit bocoran, kita bisa menggunakan prinsip kontur (baca tutorial 4) untuk melakukannya. Nah, selamat ngoding...

4 comments:

  1. kenapa tutorialnya nggak dilanjutin lagi mas? Padahal blognya bagus..

    ReplyDelete
  2. permisi gan, saya kebetulan sedang mencari referensi untuk membuat program mendeteksi gerak menggunakan opencv dan kemudian ketemu dengan thread agan. tetapi saat saya coba codingnya, kenapa error ya gan? karena saya belum paham betul soal opencv, makanya saya hanya mensalin semua coding yang agan tulis di sini dan saya paste ke visualstudionya. kira-kira kenapa ya gan? barangkali bisa membantu. terimakasih.

    ReplyDelete
  3. Bagus banget penjelasan nya om...
    izin baca artikel selanjutnya
    thanks

    ReplyDelete
  4. Permisi kak, penjelasan mengenai standar deviasinya saya kurang paham. Untuk rumusnya bagaimana ya? Terima kasih kak.

    ReplyDelete

Populer

Kategori

Jumlah Pemirsa

Powered by Blogger.
Tutorial OpenCV © 2018 Supported by Best Blogger Templates and Premium Blog Templates

This Template is Customized by: HDQ Basith Studio ©2018