OpenCV Eğitimi: iOS'ta MSER Kullanarak Gerçek Zamanlı Nesne Algılama

Yayınlanan: 2022-03-11

Son birkaç yılda, ortalama cep telefonu performansı önemli ölçüde arttı. İster saf CPU beygir gücü ister RAM kapasitesi olsun, mobil donanımda hesaplama ağırlıklı görevleri yapmak artık daha kolay. Bu mobil teknolojiler doğru yönde ilerlese de, özellikle artırılmış gerçeklik, sanal gerçeklik ve yapay zekanın ortaya çıkmasıyla birlikte mobil platformlarda hala yapılacak çok şey var.

Bilgisayarlı görüdeki en büyük zorluk, görüntülerdeki ilgi çekici nesneleri tespit etmektir. İnsan gözü ve beyni olağanüstü bir iş çıkarıyor ve bunu makinelerde kopyalamak hala bir hayal. Son yıllarda, bunu makinelerde taklit etmek için yaklaşımlar geliştirildi ve daha iyi hale geliyor.

Bu öğreticide, görüntülerdeki blobları algılamada kullanılan bir algoritmayı keşfedeceğiz. Açık kaynak kitaplığı OpenCV'den alınan algoritmayı, görüntüleri almak ve içlerindeki nesneleri algılamak için arka kamerayı kullanan bir prototip iPhone uygulamasını uygulamak için de kullanacağız.

OpenCV Eğitimi

OpenCV, büyük bilgisayarlı görme ve makine öğrenimi algoritmalarının uygulamalarını sağlayan açık kaynaklı bir kitaplıktır. Yüzleri, poker masasında iskambil kağıtlarını veya hatta rastgele bir görüntüye efekt eklemek için basit bir uygulamayı algılamak için bir uygulama uygulamak istiyorsanız, OpenCV harika bir seçimdir.

OpenCV, C/C++ ile yazılmıştır ve tüm büyük platformlar için sarmalayıcı kitaplıklarına sahiptir. Bu, özellikle iOS ortamında kullanımı kolaylaştırır. Bir Objective-C iOS uygulamasında kullanmak için resmi web sitesinden OpenCV iOS Framework'ü indirin. Lütfen, iOS için OpenCV'nin 2.4.11 sürümünü kullandığınızdan emin olun (bu makale sizin kullandığınızı varsaymaktadır), çünkü en son sürüm olan 3.0, başlık dosyalarının düzenlenmesinde uyumluluğu bozan bazı değişikliklere sahiptir. Nasıl kurulacağına dair ayrıntılı bilgi web sitesinde belgelenmiştir.

MSER

Maximally Stable Extremal Regions'un kısaltması olan MSER, görüntülerde blob tespiti için kullanılabilen birçok yöntemden biridir. Basit bir deyişle, algoritma, dış sınır piksel yoğunlukları (belirli bir eşik tarafından) iç sınır piksel yoğunluklarından daha yüksek olan bitişik piksel kümelerini tanımlar. Bu tür bölgelerin, değişen yoğunluklarda çok fazla değişmezlerse azami kararlı oldukları söylenir.

Bir dizi başka blob algılama algoritması mevcut olmasına rağmen, MSER burada seçilmiştir, çünkü n görüntü üzerindeki toplam piksel sayısı olmak üzere O(n log(log(n))) oldukça hafif bir çalışma zamanı karmaşıklığına sahiptir. Algoritma, aynı zamanda, bir cep telefonunun kamerası gibi gerçek zamanlı kaynaklar aracılığıyla elde edilen görüntülerin işlenmesi söz konusu olduğunda avantajlı olan, bulanıklaştırma ve ölçeklendirme açısından da sağlamdır.

Bu eğitimin amacı doğrultusunda, Toptal'ın logosunu algılayacak uygulamayı tasarlayacağız. Sembolün keskin köşeleri vardır ve bu, Toptal'ın logosunu tespit etmede köşe algılama algoritmalarının ne kadar etkili olabileceğini düşündürebilir. Sonuçta, böyle bir algoritmanın kullanımı ve anlaşılması hem basittir. Köşe tabanlı yöntemler, arka plandan belirgin şekilde ayrı olan nesneleri (beyaz arka plan üzerindeki siyah nesneler gibi) tespit etme konusunda yüksek bir başarı oranına sahip olsa da, Toptal'ın logosunun gerçek dünyada gerçek zamanlı olarak tespit edilmesini sağlamak zor olacaktır. Algoritmanın sürekli olarak yüzlerce köşeyi algılayacağı görüntüler.

strateji

makine öğrenimi ve opencv

Uygulamanın kamera aracılığıyla aldığı her görüntü karesi için, önce gri tonlamaya dönüştürülür. Gri tonlamalı görüntülerin yalnızca bir renk kanalı vardır, ancak yine de logo görünür olacaktır. Bu, algoritmanın görüntüyle ilgilenmesini kolaylaştırır ve algoritmanın işlemesi gereken veri miktarını çok az veya hiç ekstra kazanç olmadan önemli ölçüde azaltır.

Daha sonra, tüm MSER'leri çıkarmak için OpenCV'nin algoritmasını kullanacağız. Daha sonra, her MSER, minimum sınırlayıcı dikdörtgeni bir kareye dönüştürerek normalize edilecektir. Bu adım önemlidir çünkü logo farklı açılardan ve mesafelerden alınabilir ve bu perspektif bozulma toleransını artıracaktır.

Ayrıca, her MSER için bir dizi özellik hesaplanır:

  • Delik sayısı
  • MSER alanının dışbükey gövdesinin alanına oranı
  • MSER alanının minimum alan dikdörtgeninin alanına oranı
  • MSER iskeletinin uzunluğunun MSER alanına oranı
  • MSER alanının en büyük kontur alanına oranı

ios uygulamaları ve makine öğrenimi

Bir görüntüde Toptal'ın logosunu tespit etmek için, tüm MSER'lerin özellikleri önceden öğrenilmiş Toptal logo özellikleriyle karşılaştırılır. Bu öğreticinin amacı doğrultusunda, her bir özellik için izin verilen maksimum farklar deneysel olarak seçilmiştir.

Son olarak, sonuç olarak en benzer bölge seçilir.

iOS Uygulaması

OpenCV'yi iOS'tan kullanmak kolaydır. Henüz yapmadıysanız, bir iOS uygulaması oluşturmak ve içinde OpenCV kullanmak için Xcode'u kurmayla ilgili adımların kısa bir özeti aşağıda verilmiştir:

  1. “SuperCool Logo Detector” adlı yeni bir proje adı oluşturun. Dil olarak Objective-C'yi seçili bırakın.

  2. Yeni bir Prefix Header (.pch) dosyası ekleyin ve PrefixHeader.pch olarak adlandırın

  3. “SuperCool Logo Detector” Yapı Hedefi projesine gidin ve Yapı Ayarları sekmesinde “Önek Başlıkları” ayarını bulun. LLVM Dili bölümünde bulabilir veya arama özelliğini kullanabilirsiniz.

  4. Önek Başlıkları ayarına “PrefixHeader.pch” ekleyin

  5. Bu noktada, iOS 2.4.11 için OpenCV yüklemediyseniz, şimdi yapın.

  6. İndirilen çerçeveyi projeye sürükleyip bırakın. Hedef Ayarlarınızda “Bağlantılı Çerçeveler ve Kitaplıklar”ı kontrol edin. (Otomatik olarak eklenmelidir, ancak güvenli olması daha iyidir.)

  7. Ek olarak, aşağıdaki çerçeveleri bağlayın:

    • AVFoundation
    • VarlıklarKütüphanesi
    • ÇekirdekMedya
  8. “PrefixHeader.pch” dosyasını açın ve aşağıdaki 3 satırı ekleyin:

     #ifdef __cplusplus #include <opencv2/opencv.hpp> #endif”
  9. Otomatik olarak oluşturulan kod dosyalarının uzantılarını “ .m”den “ .mm”ye değiştirin. OpenCV, C++ ile yazılmıştır ve *.mm ile Objective-C++ kullanacağınızı söylüyorsunuz.

  10. ViewController.h'de “opencv2/highgui/cap_ios.h” dosyasını içe aktarın ve ViewController'ı CvVideoCameraDelegate protokolüne uyacak şekilde değiştirin:

     #import <opencv2/highgui/cap_ios.h>
  11. Main.storyboard'u açın ve ilk görünüm denetleyicisine bir UIImageView koyun.

  12. “imageView” adlı ViewController.mm'ye bir çıkış yapın

  13. “CvVideoCamera *kamera” değişkeni oluşturun; ViewController.h veya ViewController.mm'de ve arka kamera referansıyla başlatın:

     camera = [[CvVideoCamera alloc] initWithParentView: _imageView]; camera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack; camera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset640x480; camera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait; camera.defaultFPS = 30; camera.grayscaleMode = NO; camera.delegate = self;
  14. Projeyi şimdi oluşturursanız, Xcode sizi CvVideoCameraDelegate'in “processImage” yöntemini uygulamadığınız konusunda uyaracaktır. Şimdilik ve basitlik adına, sadece kameradan görüntüleri alıp basit bir metinle üst üste koyacağız:

    • “viewDidAppear”a tek bir satır ekleyin:
     [camera start];
    • Şimdi, uygulamayı çalıştırırsanız, kameraya erişmek için sizden izin isteyecektir. Ve sonra kameradan video görmelisiniz.

    • “processImage” yönteminde aşağıdaki iki satırı ekleyin:

     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));

Bu oldukça fazla. Artık kameradan alınan görüntülere “Toptal” yazısını çizen çok basit bir uygulamanız var. Artık bu daha basit olandan hedef logo algılama uygulamamızı oluşturabiliriz. Kısaca, bu makalede, uygulamanın genel olarak nasıl çalıştığını anlamak için kritik olan yalnızca bir avuç kod bölümünü tartışacağız. GitHub'daki kod, her bir bölümün ne yaptığını açıklamak için oldukça fazla yorum içeriyor.

Uygulamanın tek bir amacı olduğundan, Toptal'ın logosunu algılamak, başlatılır başlatılmaz, verilen şablon görüntüsünden MSER özellikleri çıkarılır ve değerler hafızada saklanır:

 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];

Uygulamanın Başlat/Durdur butonlu tek ekranı vardır ve FPS ve tespit edilen MSER sayısı gibi gerekli tüm bilgiler otomatik olarak görüntü üzerine çizilir. Uygulama durdurulmadığı sürece kameradaki her görüntü çerçevesi için aşağıdaki processImage yöntemi çağrılır:

 -(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]; }

Bu yöntem, özünde, orijinal görüntünün gri tonlamalı bir kopyasını oluşturur. Tüm MSER'leri tanımlar ve ilgili özelliklerini çıkarır, her MSER'yi şablonla benzerlik açısından puanlar ve en iyisini seçer. Son olarak, en iyi MSER'in etrafına yeşil bir sınır çizer ve görüntüyü meta bilgilerle kaplar.

Aşağıda, bu uygulamada birkaç önemli sınıfın tanımları ve yöntemleri bulunmaktadır. Amaçları yorumlarda açıklanmıştır.

GeometriUtil.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

Her şey birbirine bağlandıktan sonra, bu uygulama ile, Toptal'ın logosunu farklı açılardan ve yönlerden algılamak için iOS cihazınızın kamerasını kullanabilmelisiniz.

Bir görüntüyü (Toptal logosu) dikey olarak algılama.

Bir gömlek üzerinde çapraz olarak bir görüntü (Toptal logosu) algılama.

Artırılmış gerçeklik uygulamaları görüntüleri anlamakla başlar ve bunu bu şekilde yapabilirsiniz.
Cıvıldamak

Çözüm

Bu yazıda OpenCV kullanarak bir görüntüden basit nesneleri algılamanın ne kadar kolay olduğunu gösterdik. Kodun tamamı GitHub'da mevcuttur. Katkıları memnuniyetle karşılayacağından, istekte bulunmaktan çekinmeyin.

Herhangi bir makine öğrenimi probleminde olduğu gibi, bu uygulamada logo tespitinin başarı oranı, farklı bir dizi özellik ve nesne sınıflandırması için farklı yöntemler kullanılarak arttırılabilir. Ancak, bu makalenin genel olarak MSER kullanarak nesne algılama ve bilgisayarla görme teknikleri uygulamalarına başlamanıza yardımcı olacağını umuyorum.

Daha fazla okuma

  • J. Matas, O. Chum, M. Urban ve T. Pajdla. "Maksimum düzeyde kararlı uç bölgelerden gelen sağlam geniş taban çizgisi stereo."
  • Neumann, Lukas; Matas, Jiri (2011). “Gerçek Dünya Görüntülerinde Metin Yerelleştirme ve Tanıma Yöntemi”
İlgili: Bir Giriş Robotu Programlama Eğitimi