過去数年間で、携帯電話の平均パフォーマンスは大幅に向上しました。 CPUの処理能力やRAMの容量が非常に大きい場合でも、モバイルハードウェアで計算量の多いタスクを実行するのが簡単になりました。これらのモバイルテクノロジーは正しい方向に向かっていますが、特に拡張現実、仮想現実、人工知能の出現により、モバイルプラットフォームでやるべきことはまだたくさんあります。
コンピュータビジョンの主な課題は、画像内の関心のあるオブジェクトを検出することです。人間の目と脳は並外れた仕事をし、そして これをマシンで複製する まだ夢です。ここ数十年にわたって、マシンでこれを模倣するためのアプローチが開発され、それはますます良くなっています。
このチュートリアルでは、画像内のブロブの検出に使用されるアルゴリズムについて説明します。また、オープンソースライブラリであるOpenCVのアルゴリズムを使用して実装します プロトタイプのiPhoneアプリケーション リアカメラを使用して画像を取得し、その中のオブジェクトを検出します。
OpenCV は、主要なコンピュータビジョンと機械学習アルゴリズムの実装を提供するオープンソースライブラリです。顔、ポーカーテーブルのトランプ、または任意の画像に効果を追加するための単純なアプリケーションを検出するアプリケーションを実装する場合は、OpenCVが最適です。
OpenCVはC / C ++で記述されており、すべての主要なプラットフォーム用のラッパーライブラリがあります。これにより、特に簡単に使用できます。 iOS環境 。 Objective-C内で使用するには iOSアプリケーション 、ダウンロード 公式ウェブサイトからのOpenCViOSフレームワーク 。 iOS用OpenCVのバージョン2.4.11(この記事では使用していることを前提としています)を使用していることを確認してください。最新バージョンの3.0では、ヘッダーファイルの編成方法に互換性を損なう変更がいくつかあります。インストール方法の詳細情報は そのウェブサイトに文書化 。
MSER は、Maximally Stable Extremal Regionsの略で、画像内のブロブ検出に使用できる多くの方法の1つです。簡単に言うと、アルゴリズムは、外側の境界ピクセルの強度が内側の境界のピクセル強度よりも高い(指定されたしきい値だけ)連続したピクセルのセットを識別します。そのような領域は、さまざまな量の強度にわたってあまり変化しない場合、最大に安定していると言われます。
他の多くの ブロブ検出アルゴリズム 存在する場合、MSERが選択されたのは、実行時の複雑さがO(n log(log(n)))とかなり軽いためです。ここで、nは画像上のピクセルの総数です。このアルゴリズムは、ぼかしや拡大縮小にも堅牢であり、携帯電話のカメラなどのリアルタイムソースから取得した画像を処理する場合に有利です。
このチュートリアルの目的のために、 応用 ApeeScapeのロゴを検出します。シンボルには鋭い角があり、それはApeeScapeのロゴを検出するのにどれほど効果的な角検出アルゴリズムがあるかを考えるように導くかもしれません。結局のところ、このようなアルゴリズムは使いやすく、理解しやすいものです。コーナーベースの方法は、背景から明確に分離されたオブジェクト(白い背景上の黒いオブジェクトなど)の検出に関しては高い成功率を示す可能性がありますが、ApeeScapeのリアルタイム検出を実現することは困難です。 ロゴ アルゴリズムが常に数百のコーナーを検出する実世界の画像。
DiscordMobileでボットを作成する方法
アプリケーションがカメラを介して取得する画像のフレームごとに、最初にグレースケールに変換されます。グレースケール画像の色のチャネルは1つだけですが、それでもロゴは表示されます。これにより、アルゴリズムが画像を処理しやすくなり、アルゴリズムが処理する必要のあるデータの量が大幅に削減され、追加のゲインがほとんどまたはまったくなくなります。
次に、OpenCVの実装アルゴリズムを使用して、すべてのMSERを抽出します。次に、各MSERは、最小の境界矩形を正方形に変換することによって正規化されます。ロゴはさまざまな角度や距離から取得される可能性があり、これにより遠近法による歪みの許容度が高まるため、この手順は重要です。
さらに、MSERごとにいくつかのプロパティが計算されます。
画像内のApeeScapeのロゴを検出するために、すべてのMSERのプロパティが、すでに学習されているApeeScapeのロゴプロパティと比較されます。このチュートリアルの目的のために、各プロパティの最大許容差は経験的に選択されました。
レスポンシブデザインのためのメディアクエリ
最後に、最も類似した領域が結果として選択されます。
iOSからOpenCVを使用するのは簡単です。まだ行っていない場合は、iOSアプリケーションを作成してOpenCVを使用するためのXcodeのセットアップに関連する手順の概要を以下に示します。
新しいプロジェクト名「SuperCoolLogoDetector」を作成します。言語として、Objective-Cを選択したままにします。
新しいプレフィックスヘッダー(.pch)ファイルを追加し、PrefixHeader.pchという名前を付けます
プロジェクト「SuperCoolLogoDetector」ビルドターゲットに移動し、「ビルド設定」タブで「プレフィックスヘッダー」設定を見つけます。 LLVM言語セクションで見つけるか、検索機能を使用できます。
「PrefixHeader.pch」をプレフィックスヘッダー設定に追加します
この時点で、インストールしていない場合 iOS用OpenCV 2.4.11、今それをしなさい。
ダウンロードしたフレームワークをプロジェクトにドラッグアンドドロップします。ターゲット設定の「リンクされたフレームワークとライブラリ」をチェックします。 (自動的に追加する必要がありますが、安全のために追加することをお勧めします。)
さらに、次のフレームワークをリンクします。
「PrefixHeader.pch」を開き、次の3行を追加します。
nodejsは安らかなAPIを表現します
#ifdef __cplusplus #include #endif”
自動作成されたコードファイルの拡張子を「 .m」から「 。んん'。 OpenCVはC ++で書かれており、*。mmを使用すると、Objective-C ++を使用することになります。
ViewController.hに「opencv2 / highgui / cap_ios.h」をインポートし、プロトコルCvVideoCameraDelegateに準拠するようにViewControllerを変更します。
#import
Main.storyboardを開き、UIImageViewを最初のViewControllerに配置します。
「imageView」という名前のViewController.mmへのアウトレットを作成します
変数「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;
今すぐプロジェクトをビルドすると、Xcodeは、CvVideoCameraDelegateの「processImage」メソッドを実装していないことを警告します。今のところ、簡単にするために、カメラから画像を取得し、簡単なテキストでオーバーレイします。
[camera start];
これで、アプリケーションを実行すると、カメラにアクセスするための許可を求められます。そして、あなたはカメラからのビデオを見るはずです。
「processImage」メソッドに、次の2行を追加します。
CFOの仕事は何ですか
const char* str = [@'ApeeScape' cStringUsingEncoding: NSUTF8StringEncoding]; cv::putText(image, str, cv::Point(100, 100), CV_FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 0, 255));
それはほとんどそれです。これで、カメラからの画像に「ApeeScape」というテキストを描画する非常に単純なアプリケーションができました。これで、この単純なアプリケーションからターゲットロゴ検出アプリケーションを構築できます。簡潔にするために、この記事では、アプリケーションが全体的にどのように機能するかを理解するために重要な、ほんの一握りのコードセグメントについてのみ説明します。 GitHubのコードには、各セグメントの機能を説明するためのかなりの量のコメントがあります。
迅速なプロトコル指向プログラミング
アプリケーションの目的はApeeScapeのロゴを検出することだけなので、起動するとすぐに、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 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 normalizedMser = [ImageUtils maxMser: &normalizedImage]; //remember the template self.logoTemplate = [[MSERManager sharedInstance] extractFeature: &normalizedMser]; //store the feature [self storeTemplate];
アプリケーションには、開始/停止ボタンのある画面が1つだけあり、FPSや検出されたMSERの数など、必要なすべての情報が画像に自動的に描画されます。アプリケーションが停止していない限り、カメラ内のすべての画像フレームに対して、次のprocessImageメソッドが呼び出されます。
-(void)processImage:(cv::Mat &)image { cv::Mat gray; cvtColor(image, gray, CV_BGRA2GRAY); std::vector msers; [[MSERManager sharedInstance] detectRegions: gray intoVector: msers]; if (msers.size() == 0) { return; }; std::vector *bestMser = nil; double bestPoint = 10.0; std::for_each(msers.begin(), msers.end(), [&] (std::vector &mser) { MSERFeature *feature = [[MSERManager sharedInstance] extractFeature: &mser]; if(feature != nil) { if([[MLManager sharedInstance] isApeeScapeLogo: 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の周囲に緑色の境界線を描画し、画像にメタ情報をオーバーレイします。
以下は、このアプリケーションにおけるいくつかの重要なクラスの定義とそのメソッドです。それらの目的はコメント内に記述されています。
/* 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
/* 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 &) vector; /* Extracts feature from the mser. For some MSERs feature can be NULL !!! */ - (MSERFeature *) extractFeature: (std::vector *) mser; @end
/* 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) isApeeScapeLogo: (MSERFeature *) feature; @end
このアプリケーションを使用すると、すべてが相互に接続された後、iOSデバイスのカメラを使用して、さまざまな角度と方向からApeeScapeのロゴを検出できるようになります。
この記事では、OpenCVを使用して画像から単純なオブジェクトを検出することがいかに簡単であるかを示しました。コード全体は GitHubで入手可能 。貢献を歓迎するので、気軽にフォークしてプッシュリクエストを送信してください。
機械学習の問題に当てはまるように、このアプリケーションでのロゴ検出の成功率は、オブジェクト分類にさまざまな機能セットとさまざまな方法を使用することで向上する可能性があります。ただし、この記事が、MSERを使用したオブジェクト検出と一般的なコンピュータービジョン技術のアプリケーションを開始するのに役立つことを願っています。