Deteksi Objek Menggunakan OpenCV dan Swift
Diterbitkan: 2022-03-11Swift telah bersama kami untuk sementara waktu sekarang, dan melalui iterasinya, ia telah memberi kami semua fitur bahasa pemrograman berorientasi objek modern. Ini termasuk opsional, generik, tupel, struct yang mendukung metode, ekstensi dan protokol, dan banyak lagi. Tetapi jika aplikasi Anda bergantung pada pustaka yang ditulis menggunakan C++ maka Anda tidak dapat mengandalkan Swift lagi. Untungnya Objective-C++ ada di sini untuk membantu kami.
Sejak diperkenalkan, Swift telah memiliki interoperabilitas yang hebat dengan Objective-C dan kami akan menggunakan Objective-C untuk menjembatani Swift dengan C++. Objective-C++ tidak lebih dari Objective-C dengan kemampuan untuk menautkan dengan kode C++, dan menggunakannya, dalam posting blog ini, kami akan membuat aplikasi sederhana yang akan mengenali logo Toptal di dalam gambar menggunakan OpenCV. Ketika kami mendeteksi logo itu, kami akan membuka beranda Toptal.
Seperti yang dinyatakan di halaman web OpenCV:
"OpenCV dirancang untuk efisiensi komputasi dan dengan fokus yang kuat pada aplikasi waktu nyata. Ditulis dalam C/C++ yang dioptimalkan, perpustakaan dapat memanfaatkan pemrosesan multi-core."
Ini adalah solusi yang bagus jika Anda ingin visi komputer yang cepat berkembang dan andal.
Membuat Pembungkus Objective-C++ OpenCV
Dalam tutorial ini, kami akan mendesain aplikasi yang akan mencocokkan logo Toptal di dalam gambar dan membuka halaman web Toptal. Untuk memulai, buat proyek Xcode baru dan atur CocoaPods menggunakan pod init
. Tambahkan OpenCV ke Podfile pod 'OpenCV
dan jalankan pod install
di Terminal. Pastikan untuk membatalkan komentar use_frameworks
! pernyataan di dalam Podfile.
Sekarang, ketika kita memiliki OpenCV di dalam proyek Xcode, kita harus menghubungkannya dengan Swift. Berikut adalah garis besar langkah-langkah yang terlibat:
Langkah 1: Buat kelas Objective-C baru OpenCVWrapper
. Ketika Xcode bertanya kepada Anda “ Apakah Anda ingin mengonfigurasi header penghubung Objective-C? ” pilih “ Buat tajuk penghubung .” Header penghubung adalah tempat Anda mengimpor kelas Objective-C, dan kemudian kelas tersebut terlihat di dalam Swift.
Langkah 2: Untuk menggunakan C++ di dalam Objective-C, kita harus mengubah ekstensi file dari OpenCVWrapper.m
menjadi OpenCVWrapper.mm
. Anda dapat melakukannya hanya dengan mengganti nama file di dalam navigator proyek Xcode. Menambahkan .mm
sebagai ekstensi akan mengubah jenis file dari Objective-C ke Objective-C++.
Langkah 3: Impor OpenCV ke OpenCVWrapper.mm
menggunakan impor berikut. Penting untuk menulis impor yang diberikan di atas #import "OpenCVWrapper.h"
karena dengan cara ini kita menghindari konflik BOOL yang terkenal. OpenCV berisi enum yang memiliki nilai NO
yang menyebabkan konflik dengan nilai Objective-C BOOL NO
. Jika Anda tidak memerlukan kelas yang menggunakan enum seperti itu, maka ini adalah cara paling sederhana. Jika tidak, Anda harus membatalkan definisi BOOL sebelum mengimpor OpenCV.
#ifdef __cplusplus #import <opencv2/opencv.hpp> #import <opencv2/imgcodecs/ios.h> #import <opencv2/videoio/cap_ios.h> #endif
Langkah 4: Tambahkan #import "OpenCVWrapper.h"
ke header penghubung Anda.
Buka OpenCVWrapper.mm
dan buat antarmuka pribadi tempat kami akan mendeklarasikan properti pribadi:
@interface OpenCVWrapper() <CvVideoCameraDelegate> @property (strong, nonatomic) CvVideoCamera *videoCamera; @property (assign, nonatomic) cv::Mat logoSample; @end
Untuk membuat CvVideoCamera
, kita harus meneruskan UIImageView
ke sana, dan kita akan melakukannya melalui penginisialisasi designator kita.
- (instancetype)initWithParentView:(UIImageView *)parentView delegate:(id<OpenCVWrapperDelegate>)delegate { if (self = [super init]) { self.delegate = delegate; parentView.contentMode = UIViewContentModeScaleAspectFill; self.videoCamera = [[CvVideoCamera alloc] initWithParentView:parentView]; self.videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack; self.videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPresetHigh; self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait; self.videoCamera.defaultFPS = 30; self.videoCamera.grayscaleMode = [NSNumber numberWithInt:0].boolValue; self.videoCamera.delegate = self; // Convert UIImage to Mat and store greyscale version UIImage *templateImage = [UIImage imageNamed:@"toptal"]; cv::Mat templateMat; UIImageToMat(templateImage, templateMat); cv::Mat grayscaleMat; cv::cvtColor(templateMat, grayscaleMat, CV_RGB2GRAY); self.logoSample = grayscaleMat; [self.videoCamera start]; } return self; }
Di dalamnya, kami mengonfigurasi CvVideoCamera
yang membuat video di dalam parentView
yang diberikan dan melalui delegasi mengirimkan gambar cv::Mat
kepada kami untuk dianalisis.

processImage:
metode berasal dari protokol CvVideoCameraDelegate
, dan di dalamnya, kita akan melakukan pencocokan template.
- (void)processImage:(cv::Mat&)image { cv::Mat gimg; // Convert incoming img to greyscale to match template cv::cvtColor(image, gimg, CV_BGR2GRAY); // Get matching cv::Mat res(image.rows-self.logoSample.rows+1, self.logoSample.cols-self.logoSample.cols+1, CV_32FC1); cv::matchTemplate(gimg, self.logoSample, res, CV_TM_CCOEFF_NORMED); cv::threshold(res, res, 0.5, 1., CV_THRESH_TOZERO); double minval, maxval, threshold = 0.9; cv::Point minloc, maxloc; cv::minMaxLoc(res, &minval, &maxval, &minloc, &maxloc); // Call delegate if match is good enough if (maxval >= threshold) { // Draw a rectangle for confirmation cv::rectangle(image, maxloc, cv::Point(maxloc.x + self.logoSample.cols, maxloc.y + self.logoSample.rows), CV_RGB(0,255,0), 2); cv::floodFill(res, maxloc, cv::Scalar(0), 0, cv::Scalar(.1), cv::Scalar(1.)); [self.delegate openCVWrapperDidMatchImage:self]; } }
Pertama, kami mengonversi gambar yang diberikan menjadi gambar skala abu-abu karena di dalam metode init kami mengubah gambar pencocokan template logo Toptal menjadi skala abu-abu. Langkah selanjutnya adalah memeriksa kecocokan dengan ambang tertentu yang akan membantu kami dengan penskalaan dan sudut. Kami harus memeriksa sudut karena Anda dapat mengambil foto di berbagai sudut di mana kami masih ingin mendeteksi logo. Setelah mencapai ambang batas yang diberikan, kami akan memanggil delegasi dan membuka halaman web Toptal.
Jangan lupa untuk menambahkan NSCameraUsageDescription
ke Info.plist Anda jika tidak, aplikasi Anda akan crash setelah memanggil [self.videoCamera start];
.
Sekarang Akhirnya Cepat
Sejauh ini kami fokus pada Objective-C++ karena semua logika dilakukan di dalamnya. Kode Swift kami akan cukup sederhana:
- Di dalam
ViewController.swift
, buatUIImageView
tempatCvVideoCamera
akan merender konten. - Buat instance
OpenCVWrapper
dan teruskan instanceUIImageView
ke sana. - Menerapkan protokol
OpenCVWrapperDelegate
untuk membuka halaman web Toptal ketika kami mendeteksi logo.
class ViewController: UIViewController { var wrapper: OpenCVWrapper! @IBOutlet var imageView: UIImageView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. wrapper = OpenCVWrapper.init(parentView: imageView, delegate: self) } } extension ViewController: OpenCVWrapperDelegate { //MARK: - OpenCVWrapperDelegate func openCVWrapperDidMatchImage(_ wrapper: OpenCVWrapper) { UIApplication.shared.open(URL.init(string: "https://toptal.com")!, options: [:], completionHandler: nil) } }
OpenCV Swift beraksi
Pada artikel ini, kami telah menunjukkan bagaimana Anda dapat mengintegrasikan kode C++ dengan Swift dan membuat kelas pembungkus yang ada di sini untuk menjembatani kode C++ dengan Swift. Sekarang, ketika kami mendeteksi Logo Toptal melalui kamera, kami membuka halaman utama Toptal.
Untuk pembaruan di masa mendatang, Anda mungkin ingin menjalankan pencocokan template CV di utas latar belakang. Dengan cara ini, Anda tidak akan memblokir utas utama dan UI akan tetap responsif. Karena ini adalah contoh sederhana OpenCV, pencocokan template mungkin tidak terlalu berhasil, tetapi tujuan artikel ini adalah untuk menunjukkan kepada Anda bagaimana Anda dapat mulai menggunakannya.
Jika Anda masih tertarik untuk mempelajari OpenCV dan penggunaannya yang lebih kompleks di iOS, saya merekomendasikan Deteksi Objek Real-time Menggunakan MSER di iOS , yang memandu Anda melalui deteksi gambar menggunakan kamera belakang iPhone.