Tutorial OpenCV: Deteksi Objek Real-time Menggunakan MSER di iOS

Diterbitkan: 2022-03-11

Selama beberapa tahun terakhir, rata-rata kinerja ponsel meningkat secara signifikan. Baik itu untuk tenaga kuda CPU atau kapasitas RAM, sekarang lebih mudah untuk melakukan tugas komputasi yang berat pada perangkat keras seluler. Meskipun teknologi seluler ini menuju ke arah yang benar, masih banyak yang harus dilakukan pada platform seluler, terutama dengan munculnya augmented reality, virtual reality, dan kecerdasan buatan.

Tantangan utama dalam visi komputer adalah untuk mendeteksi objek yang menarik dalam gambar. Mata dan otak manusia melakukan pekerjaan yang luar biasa, dan mereplikasi ini dalam mesin masih merupakan mimpi. Selama beberapa dekade terakhir, pendekatan telah dikembangkan untuk meniru ini di mesin, dan itu menjadi lebih baik.

Dalam tutorial ini, kita akan mengeksplorasi algoritma yang digunakan dalam mendeteksi gumpalan pada gambar. Kami juga akan menggunakan algoritme, dari perpustakaan sumber terbuka, OpenCV, untuk mengimplementasikan prototipe aplikasi iPhone yang menggunakan kamera belakang untuk memperoleh gambar dan mendeteksi objek di dalamnya.

Tutorial OpenCV

OpenCV adalah perpustakaan sumber terbuka yang menyediakan implementasi visi komputer utama dan algoritma pembelajaran mesin. Jika Anda ingin menerapkan aplikasi untuk mendeteksi wajah, bermain kartu di meja poker, atau bahkan aplikasi sederhana untuk menambahkan efek pada gambar yang berubah-ubah, maka OpenCV adalah pilihan yang tepat.

OpenCV ditulis dalam C/C++, dan memiliki pustaka pembungkus untuk semua platform utama. Ini membuatnya sangat mudah digunakan dalam lingkungan iOS. Untuk menggunakannya dalam aplikasi Objective-C iOS, unduh OpenCV iOS Framework dari situs web resmi. Harap pastikan bahwa Anda menggunakan OpenCV versi 2.4.11 untuk iOS (yang diasumsikan oleh artikel ini Anda gunakan), karena versi terbaru, 3.0, memiliki beberapa perubahan yang merusak kompatibilitas dalam cara mengatur file header. Informasi terperinci tentang cara menginstalnya didokumentasikan di situs webnya.

MSER

MSER, kependekan dari Maximally Stable Extremal Regions, adalah salah satu dari banyak metode yang tersedia untuk deteksi gumpalan dalam gambar. Dengan kata sederhana, algoritme mengidentifikasi kumpulan piksel yang berdekatan yang intensitas piksel batas luarnya lebih tinggi (dengan ambang yang diberikan) daripada intensitas piksel batas dalam. Daerah seperti itu dikatakan stabil maksimal jika tidak banyak berubah pada jumlah intensitas yang bervariasi.

Meskipun sejumlah algoritma pendeteksi gumpalan lain ada, MSER dipilih di sini karena memiliki kompleksitas run-time yang cukup ringan dari O(n log(log(n))) di mana n adalah jumlah total piksel pada gambar. Algoritme ini juga kuat untuk mengaburkan dan menskalakan, yang menguntungkan saat memproses gambar yang diperoleh melalui sumber waktu nyata, seperti kamera ponsel.

Untuk tujuan tutorial ini, kami akan merancang aplikasi untuk mendeteksi logo Toptal. Simbol itu memiliki sudut yang tajam, dan itu mungkin membuat orang berpikir tentang seberapa efektif algoritma pendeteksian sudut dalam mendeteksi logo Toptal. Bagaimanapun, algoritme semacam itu mudah digunakan dan dipahami. Meskipun metode berbasis sudut mungkin memiliki tingkat keberhasilan yang tinggi dalam hal mendeteksi objek yang secara jelas terpisah dari latar belakang (seperti objek hitam pada latar belakang putih), akan sulit untuk mencapai deteksi real-time logo Toptal di dunia nyata. gambar, di mana algoritme akan terus mendeteksi ratusan sudut.

Strategi

pembelajaran mesin dan opencv

Untuk setiap bingkai gambar yang diperoleh aplikasi melalui kamera, itu diubah terlebih dahulu menjadi skala abu-abu. Gambar skala abu-abu hanya memiliki satu saluran warna, tetapi logo akan tetap terlihat. Ini memudahkan algoritme untuk menangani gambar dan secara signifikan mengurangi jumlah data yang harus diproses oleh algoritme dengan sedikit atau tanpa perolehan tambahan.

Selanjutnya, kita akan menggunakan algoritma implementasi OpenCV untuk mengekstrak semua MSER. Selanjutnya, setiap MSER akan dinormalisasi dengan mentransformasikan minimum bounding rectangle menjadi persegi. Langkah ini penting karena logo dapat diperoleh dari sudut dan jarak yang berbeda dan ini akan meningkatkan toleransi distorsi perspektif.

Selanjutnya, sejumlah properti dihitung untuk setiap MSER:

  • Jumlah lubang
  • Rasio luas MSER dengan luas lambung cembungnya
  • Rasio luas MSER dengan luas persegi panjang minimumnya
  • Rasio panjang kerangka MSER dengan luas MSER
  • Rasio luas MSER dengan luas kontur terbesarnya

aplikasi ios dan pembelajaran mesin

Untuk mendeteksi logo Toptal dalam sebuah gambar, properti dari semua MSER dibandingkan dengan properti logo Toptal yang sudah dipelajari. Untuk tujuan tutorial ini, perbedaan maksimum yang diperbolehkan untuk setiap properti dipilih secara empiris.

Akhirnya, wilayah yang paling mirip dipilih sebagai hasilnya.

Aplikasi iOS

Menggunakan OpenCV dari iOS itu mudah. Jika Anda belum melakukannya, berikut adalah garis besar langkah-langkah yang terlibat dalam menyiapkan Xcode untuk membuat aplikasi iOS dan menggunakan OpenCV di dalamnya:

  1. Buat nama proyek baru "Detektor Logo SuperCool." Sebagai bahasa, biarkan Objective-C dipilih.

  2. Tambahkan file Prefix Header (.pch) baru dan beri nama PrefixHeader.pch

  3. Masuk ke proyek "SuperCool Logo Detector" Build Target dan di tab Build Settings, temukan pengaturan "Prefix Headers". Anda dapat menemukannya di bagian LLVM Language, atau menggunakan fitur pencarian.

  4. Tambahkan "PrefixHeader.pch" ke pengaturan Header Awalan

  5. Pada titik ini, jika Anda belum menginstal OpenCV untuk iOS 2.4.11, lakukan sekarang.

  6. Seret dan lepas kerangka kerja yang diunduh ke dalam proyek. Periksa "Kerangka dan Perpustakaan Tertaut" di Pengaturan Target Anda. (Ini harus ditambahkan secara otomatis, tetapi lebih baik aman.)

  7. Selain itu, tautkan kerangka kerja berikut:

    • Yayasan AV
    • AsetPerpustakaan
    • CoreMedia
  8. Buka “PrefixHeader.pch” dan tambahkan 3 baris berikut:

     #ifdef __cplusplus #include <opencv2/opencv.hpp> #endif”
  9. Ubah ekstensi file kode yang dibuat secara otomatis dari “ .m” menjadi “ .mm”. OpenCV ditulis dalam C++ dan dengan *.mm Anda mengatakan bahwa Anda akan menggunakan Objective-C++.

  10. Impor “opencv2/highgui/cap_ios.h” di ViewController.h dan ubah ViewController agar sesuai dengan protokol CvVideoCameraDelegate:

     #import <opencv2/highgui/cap_ios.h>
  11. Buka Main.storyboard dan letakkan UIImageView pada pengontrol tampilan awal.

  12. Buat outlet ke ViewController.mm bernama "imageView"

  13. Buat variabel “CvVideoCamera *camera;” di ViewController.h atau ViewController.mm, dan inisialisasi dengan referensi ke kamera belakang:

     camera = [[CvVideoCamera alloc] initWithParentView: _imageView]; camera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack; camera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset640x480; camera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait; camera.defaultFPS = 30; camera.grayscaleMode = NO; camera.delegate = self;
  14. Jika Anda membangun proyek sekarang, Xcode akan memperingatkan Anda bahwa Anda tidak mengimplementasikan metode "processImage" dari CvVideoCameraDelegate. Untuk saat ini, dan demi kesederhanaan, kita hanya akan memperoleh gambar dari kamera dan melapisinya dengan teks sederhana:

    • Tambahkan satu baris ke "viewDidAppear":
     [camera start];
    • Sekarang, jika Anda menjalankan aplikasi, itu akan meminta izin Anda untuk mengakses kamera. Dan kemudian Anda akan melihat video dari kamera.

    • Dalam metode "processImage" tambahkan dua baris berikut:

     const char* str = [@"Toptal" cStringUsingEncoding: NSUTF8StringEncoding]; cv::putText(image, str, cv::Point(100, 100), CV_FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 0, 255));

Itu cukup banyak. Sekarang Anda memiliki aplikasi yang sangat sederhana yang menggambar teks "Toptal" pada gambar dari kamera. Kami sekarang dapat membangun aplikasi pendeteksi logo target kami dari yang lebih sederhana ini. Untuk singkatnya, dalam artikel ini kita hanya akan membahas beberapa segmen kode yang penting untuk memahami cara kerja aplikasi secara keseluruhan. Kode di GitHub memiliki cukup banyak komentar untuk menjelaskan apa yang dilakukan setiap segmen.

Karena aplikasi hanya memiliki satu tujuan, untuk mendeteksi logo Toptal, segera setelah diluncurkan, fitur MSER diekstraksi dari gambar template yang diberikan dan nilainya disimpan dalam memori:

 cv::Mat logo = [ImageUtils cvMatFromUIImage: templateImage]; //get gray image cv::Mat gray; cvtColor(logo, gray, CV_BGRA2GRAY); //mser with maximum area is std::vector<cv::Point> maxMser = [ImageUtils maxMser: &gray]; //get 4 vertices of the maxMSER minrect cv::RotatedRect rect = cv::minAreaRect(maxMser); cv::Point2f points[4]; rect.points(points); //normalize image cv::Mat M = [GeometryUtil getPerspectiveMatrix: points toSize: rect.size]; cv::Mat normalizedImage = [GeometryUtil normalizeImage: &gray withTranformationMatrix: &M withSize: rect.size.width]; //get maxMser from normalized image std::vector<cv::Point> normalizedMser = [ImageUtils maxMser: &normalizedImage]; //remember the template self.logoTemplate = [[MSERManager sharedInstance] extractFeature: &normalizedMser]; //store the feature [self storeTemplate];

Aplikasi hanya memiliki satu layar dengan tombol Start/Stop, dan semua informasi yang diperlukan, seperti FPS dan jumlah MSER yang terdeteksi, digambar secara otomatis pada gambar. Selama aplikasi tidak dihentikan, untuk setiap bingkai gambar di kamera, metode processImage berikut dipanggil:

 -(void)processImage:(cv::Mat &)image { cv::Mat gray; cvtColor(image, gray, CV_BGRA2GRAY); std::vector<std::vector<cv::Point>> msers; [[MSERManager sharedInstance] detectRegions: gray intoVector: msers]; if (msers.size() == 0) { return; }; std::vector<cv::Point> *bestMser = nil; double bestPoint = 10.0; std::for_each(msers.begin(), msers.end(), [&] (std::vector<cv::Point> &mser) { MSERFeature *feature = [[MSERManager sharedInstance] extractFeature: &mser]; if(feature != nil) { if([[MLManager sharedInstance] isToptalLogo: feature] ) { double tmp = [[MLManager sharedInstance] distance: feature ]; if ( bestPoint > tmp ) { bestPoint = tmp; bestMser = &mser; } } } }); if (bestMser) { NSLog(@"minDist: %f", bestPoint); cv::Rect bound = cv::boundingRect(*bestMser); cv::rectangle(image, bound, GREEN, 3); } else { cv::rectangle(image, cv::Rect(0, 0, W, H), RED, 3); } // Omitted debug code [FPS draw: image]; }

Metode ini, pada dasarnya, membuat salinan skala abu-abu dari gambar asli. Ini mengidentifikasi semua MSER dan mengekstrak fitur yang relevan, menilai setiap MSER untuk kesamaan dengan template dan memilih yang terbaik. Terakhir, ia menggambar batas hijau di sekitar MSER terbaik dan melapisi gambar dengan informasi meta.

Di bawah ini adalah definisi dari beberapa kelas penting, dan metodenya, dalam aplikasi ini. Tujuan mereka dijelaskan dalam komentar.

GeometryUtil.h

 /* This static class provides perspective transformation function */ @interface GeometryUtil : NSObject /* Return perspective transformation matrix for given points to square with origin [0,0] and with size (size.width, size.width) */ + (cv::Mat) getPerspectiveMatrix: (cv::Point2f[]) points toSize: (cv::Size2f) size; /* Returns new perspecivly transformed image with given size */ + (cv::Mat) normalizeImage: (cv::Mat *) image withTranformationMatrix: (cv::Mat *) M withSize: (float) size; @end

MSERManager.h

 /* Singelton class providing function related to msers */ @interface MSERManager : NSObject + (MSERManager *) sharedInstance; /* Extracts all msers into provided vector */ - (void) detectRegions: (cv::Mat &) gray intoVector: (std::vector<std::vector<cv::Point>> &) vector; /* Extracts feature from the mser. For some MSERs feature can be NULL !!! */ - (MSERFeature *) extractFeature: (std::vector<cv::Point> *) mser; @end

mlmanager.h

 /* This singleton class wraps object recognition function */ @interface MLManager : NSObject + (MLManager *) sharedInstance; /* Stores feature from the biggest MSER in the templateImage */ - (void) learn: (UIImage *) templateImage; /* Sum of the differences between logo feature and given feature */ - (double) distance: (MSERFeature *) feature; /* Returns true if the given feature is similar to the one learned from the template */ - (BOOL) isToptalLogo: (MSERFeature *) feature; @end

Setelah semuanya terhubung, dengan aplikasi ini, Anda seharusnya dapat menggunakan kamera perangkat iOS Anda untuk mendeteksi logo Toptal dari berbagai sudut dan orientasi.

Mendeteksi gambar (logo Toptal) secara vertikal.

Mendeteksi gambar (logo Toptal) secara diagonal pada kemeja.

Aplikasi augmented reality dimulai dengan memahami gambar, dan beginilah cara Anda melakukannya.
Menciak

Kesimpulan

Pada artikel ini kami telah menunjukkan betapa mudahnya mendeteksi objek sederhana dari sebuah gambar menggunakan OpenCV. Seluruh kode tersedia di GitHub. Jangan ragu untuk melakukan fork dan mengirim permintaan push, karena kontribusi dipersilakan.

Seperti halnya masalah pembelajaran mesin apa pun, tingkat keberhasilan deteksi logo dalam aplikasi ini dapat ditingkatkan dengan menggunakan serangkaian fitur yang berbeda dan metode yang berbeda untuk klasifikasi objek. Namun, saya berharap artikel ini akan membantu Anda memulai pendeteksian objek menggunakan MSER dan aplikasi teknik computer vision secara umum.

Bacaan lebih lanjut

  • J. Matas, O. Chum, M. Urban, dan T. Pajdla. “Stereo baseline lebar yang kuat dari daerah ekstrem yang stabil secara maksimal.”
  • Neumann, Lukas; Matas, Jiri (2011). “Metode Lokalisasi dan Pengenalan Teks dalam Gambar Dunia Nyata”
Terkait: Tutorial Pemrograman Robot Pengantar