OpenCV 教程:在 iOS 中使用 MSER 進行實時對象檢測

已發表: 2022-03-11

在過去幾年中,手機的平均性能顯著提高。 無論是純粹的 CPU 馬力還是 RAM 容量,現在在移動硬件上執行計算繁重的任務變得更加容易。 儘管這些移動技術正朝著正確的方向發展,但在移動平台上仍有很多工作要做,尤其是隨著增強現實、虛擬現實和人工智能的出現。

計算機視覺的一個主要挑戰是檢測圖像中感興趣的對象。 人眼和大腦做得非常出色,在機器上複製它仍然是一個夢想。 近幾十年來,已經開發出一些方法來在機器中模仿這一點,而且它正在變得越來越好。

在本教程中,我們將探索一種用於檢測圖像中的斑點的算法。 我們還將使用開源庫 OpenCV 中的算法來實現一個原型 iPhone 應用程序,該應用程序使用後置攝像頭獲取圖像並檢測其中的對象。

OpenCV 教程

OpenCV 是一個開源庫,提供主要計算機視覺和機器學習算法的實現。 如果您想實現一個應用程序來檢測人臉、撲克桌上的撲克牌,甚至是一個簡單的應用程序來為任意圖像添加效果,那麼 OpenCV 是一個不錯的選擇。

OpenCV 是用 C/C++ 編寫的,並且具有適用於所有主要平台的包裝庫。 這使得它在 iOS 環境中特別容易使用。 要在 Objective-C iOS 應用程序中使用它,請從官方網站下載 OpenCV iOS 框架。 請確保您使用的是 OpenCV for iOS 的 2.4.11 版本(本文假設您正在使用),因為最新版本 3.0 在頭文件的組織方式上有一些破壞兼容性的變化。 有關如何安裝它的詳細信息記錄在其網站上。

質譜儀

MSER 是Maximally Stable Extremal Regions 的縮寫,是可用於圖像內斑點檢測的眾多方法之一。 簡而言之,該算法識別其外邊界像素強度高於(給定閾值)內邊界像素強度的連續像素集。 如果這些區域在不同強度的情況下變化不大,則稱它們是最大穩定的。

儘管存在許多其他 blob 檢測算法,但這裡選擇了 MSER,因為它的運行時間複雜度相當低,為 O(n log(log(n))),其中 n 是圖像上的像素總數。 該算法還對模糊和縮放具有魯棒性,這在處理通過實時源(例如手機的攝像頭)獲取的圖像時具有優勢。

出於本教程的目的,我們將設計應用程序來檢測 Toptal 的徽標。 該符號有尖角,這可能會導致人們思考角檢測算法在檢測 Toptal 徽標方面的有效性。 畢竟,這樣的算法既易於使用又易於理解。 雖然基於角點的方法在檢測與背景明顯分離的物體(例如白色背景上的黑色物體)時可能具有很高的成功率,但在現實世界中很難實現對 Toptal 徽標的實時檢測圖像,算法將不斷檢測數百個角落。

戰略

機器學習和opencv

對於應用程序通過相機獲取的每一幀圖像,首先將其轉換為灰度。 灰度圖像只有一個顏色通道,但徽標仍然可見。 這使算法更容易處理圖像,並顯著減少算法必須處理的數據量,而幾乎沒有額外收益。

接下來,我們將使用 OpenCV 的實現算法來提取所有 MSER。 接下來,每個 MSER 將通過將其最小邊界矩形轉換為正方形來進行歸一化。 這一步很重要,因為可以從不同的角度和距離獲取徽標,這將增加透視失真的容差。

此外,為每個 MSER 計算了許多屬性:

  • 孔數
  • MSER 的面積與其凸包面積之比
  • MSER 的面積與其最小面積矩形的面積之比
  • MSER 骨架長度與 MSER 面積之比
  • MSER 的面積與其最大輪廓面積之比

ios應用和機器學習

為了檢測圖像中的 Toptal 徽標,所有 MSER 的屬性都與已經學習的 Toptal 徽標屬性進行比較。 出於本教程的目的,根據經驗選擇每個屬性的最大允許差異。

最後,選​​擇最相似的區域作為結果。

iOS 應用程序

從 iOS 使用 OpenCV 很容易。 如果您還沒有這樣做,這裡簡要介紹了設置 Xcode 以創建 iOS 應用程序並在其中使用 OpenCV 所涉及的步驟:

  1. 創建一個新項目名稱“SuperCool Logo Detector”。 作為語言,選擇 Objective-C。

  2. 添加一個新的 Prefix Header (.pch) 文件並將其命名為 PrefixHeader.pch

  3. 進入項目“SuperCool Logo Detector”構建目標,在“構建設置”選項卡中,找到“前綴標題”設置。 您可以在 LLVM 語言部分找到它,或使用搜索功能。

  4. 將“PrefixHeader.pch”添加到前綴標題設置

  5. 此時,如果您尚未安裝 OpenCV for iOS 2.4.11,請立即安裝。

  6. 將下載的框架拖放到項目中。 在 Target Settings 中選中“Linked Frameworks and Libraries”。 (它應該是自動添加的,但最好是安全的。)

  7. 此外,鏈接以下框架:

    • AV基金會
    • 資產庫
    • 核心媒體
  8. 打開“PrefixHeader.pch”並添加以下 3 行:

     #ifdef __cplusplus #include <opencv2/opencv.hpp> #endif”
  9. 將自動創建的代碼文件的擴展名從“ .m”更改為“ .mm”。 OpenCV 是用 C++ 編寫的,使用 *.mm 表示您將使用 Objective-C++。

  10. 在 ViewController.h 中導入“opencv2/highgui/cap_ios.h”並更改 ViewController 以符合協議 CvVideoCameraDelegate:

     #import <opencv2/highgui/cap_ios.h>
  11. 打開 Main.storyboard 並將 UIImageView 放在初始視圖控制器上。

  12. 為 ViewController.mm 創建一個名為“imageView”的出口

  13. 創建一個變量“CvVideoCamera *camera;” 在 ViewController.h 或 ViewController.mm 中,並使用對後置攝像頭的引用對其進行初始化:

     camera = [[CvVideoCamera alloc] initWithParentView: _imageView]; camera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack; camera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset640x480; camera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait; camera.defaultFPS = 30; camera.grayscaleMode = NO; camera.delegate = self;
  14. 如果你現在構建項目,Xcode 會警告你沒有從 CvVideoCameraDelegate 實現“processImage”方法。 現在,為了簡單起見,我們將只從相機獲取圖像並用簡單的文本覆蓋它們:

    • 在“viewDidAppear”中添加一行:
     [camera start];
    • 現在,如果您運行該應用程序,它會詢問您訪問相機的權限。 然後你應該看到來自相機的視頻。

    • 在“processImage”方法中添加以下兩行:

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

差不多就是這樣。 現在您有一個非常簡單的應用程序,它可以在來自相機的圖像上繪製文本“Toptal”。 我們現在可以從這個更簡單的應用程序中構建目標徽標檢測應用程序。 為簡潔起見,在本文中,我們將僅討論對理解應用程序整體工作方式至關重要的少數代碼段。 GitHub 上的代碼有相當多的註釋來解釋每個部分的作用。

由於該應用程序只有一個目的,即檢測 Toptal 的徽標,因此一旦啟動,就會從給定的模板圖像中提取 MSER 特徵,並將值存儲在內存中:

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

該應用程序只有一個帶有開始/停止按鈕的屏幕,所有必要的信息,如 FPS 和檢測到的 MSER 的數量,都會自動繪製在圖像上。 只要應用程序沒有停止,對於相機中的每一幀圖像,都會調用以下 processImage 方法:

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

這種方法本質上是創建原始圖像的灰度副本。 它識別所有 MSER 並提取它們的相關特徵,對每個 MSER 與模板的相似度進行評分並挑選出最佳的。 最後,它在最佳 MSER 周圍繪製綠色邊界,並用元信息覆蓋圖像。

以下是此應用程序中幾個重要類及其方法的定義。 他們的目的在評論中描述。

幾何工具.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

將所有內容連接在一起後,使用此應用程序,您應該能夠使用 iOS 設備的攝像頭從不同角度和方向檢測 Toptal 的徽標。

垂直檢測圖像(Toptal 徽標)。

檢測襯衫上的對角線圖像(Toptal 標誌)。

增強現實應用程序從理解圖像開始,這就是你可以做到的。
鳴叫

結論

在本文中,我們展示了使用 OpenCV 從圖像中檢測簡單對像是多麼容易。 整個代碼可在 GitHub 上找到。 隨意分叉和發送推送請求,因為歡迎貢獻。

與任何機器學習問題一樣,通過使用不同的特徵集和不同的對象分類方法,可以提高此應用程序中徽標檢測的成功率。 但是,我希望本文能幫助您開始使用 MSER 進行對象檢測和計算機視覺技術的應用。

延伸閱讀

  • J. Matas、O. Chum、M. Urban 和 T. Pajdla。 “來自最大穩定極值區域的穩健寬基線立體聲。”
  • 諾伊曼,盧卡斯; 馬塔斯,吉里(2011)。 “一種在現實世界圖像中進行文本定位和識別的方法”
相關:介紹性機器人編程教程