opencvを学ぶ-選択的な検索オブジェクト検出(C ++ / Python)



Learn Opencv Selective Search Object Detection



参照:
1、 https://github.com/spmallick/learnopencv
二、 https://github.com/opencv/


このチュートリアルでは、オブジェクト検出における「選択的検索」と呼ばれる重要な概念を理解します。また、C ++とPythonでOpenCVコードを共有します。




物体検出と物体認識

オブジェクト認識アルゴリズムは、画像に存在するオブジェクトを認識します。画像全体を入力として受け取り、画像に存在するオブジェクトのクラスラベルとクラス確率を出力します。たとえば、クラスラベルは「犬」であり、関連するクラス確率は97%である可能性があります。

一方、オブジェクト検出アルゴリズムは、画像内に存在するオブジェクトを通知するだけでなく、画像内のオブジェクトの位置を示す境界ボックス(x、y、幅、高さ)も出力します。



すべてのオブジェクト検出アルゴリズムの中核は、オブジェクト認識アルゴリズムです。画像パッチ内の犬を認識するオブジェクト認識モデルをトレーニングしたとします。このモデルは、画像に犬が含まれているかどうかを示します。オブジェクトがどこにあるかはわかりません。

オブジェクトをローカライズするには、画像のサブ領域(パッチ)を選択してから、これらの画像パッチにオブジェクト認識アルゴリズムを適用する必要があります。オブジェクトの位置は、オブジェクト認識アルゴリズムによって返される高いクラス確率を持つ画像ブロックの位置によって与えられます。
画像

より小さなサブ領域(パッチ)を生成する最も簡単な方法は、スライディングウィンドウ法です。ただし、スライディングウィンドウ方式にはいくつかの制限があります。これらの制限は、「エリア提案」アルゴリズムと呼ばれるアルゴリズムのクラスによって克服されます。選択的検索は、最も人気のあるエリア提案アルゴリズムの1つです。




スライディングウィンドウアルゴリズム

スライディングウィンドウ方式では、画像上でボックスまたはウィンドウをスライドさせてパッチを選択し、オブジェクト認識モデルを使用して、ウィンドウで覆われている各画像パッチを分類します。これは、画像全体の徹底的な検索です。画像内のすべての可能な位置を検索する必要があるだけでなく、さまざまなスケールで検索する必要もあります。これは、オブジェクト認識モデルは通常、特定のスケール(またはスケール範囲)でトレーニングされるためです。これにより、何千もの画像ブロックが分類されます。

問題はここで終わらない。スライディングウィンドウ方式は、人間の顔や歩行者など、アスペクト比が固定されたオブジェクトに適しています。画像は3Dオブジェクトの2D投影です。アスペクト比や形状などのオブジェクトの特性は、キャプチャした画像の角度によって大きく異なります。スライディングウィンドウ法は、複数のアスペクト比を検索する場合、計算コストが非常に高くなります。


エリア提案アルゴリズム

これまでに説明した問題は、領域提案アルゴリズムを使用することで解決できます。これらのメソッドは、オブジェクトである可能性が最も高い画像内のすべてのパッチに対応する入力および出力境界ボックスとして画像を使用します。これらの領域の提案は、ノイズが多く、重複している可能性があり、オブジェクトが完全に含まれていない可能性がありますが、これらの領域の提案には、画像内の実際のオブジェクトに非常に近い提案があります。次に、オブジェクト認識モデルを使用してこれらの提案を分類できます。確率スコアの高いエリア提案が対象物の位置です。

青いボックス:誤検知緑色のボックス:真陽性
青いボックス:誤検知緑色のボックス:真陽性

領域提案アルゴリズムは、セグメンテーションを使用して、画像内の予想されるオブジェクトを識別します。セグメンテーションでは、いくつかの基準(色、テクスチャなど)に従って隣接する領域をグループ化します。すべてのピクセル位置とすべてのスケールでオブジェクトを見つけるスライディングウィンドウ法とは異なり、領域提案アルゴリズムはピクセルをより少ないフラグメントにグループ化します。したがって、生成される提案の最終的な数は、スライディングウィンドウ方式よりも何倍も少なくなります。これにより、分類する必要のある画像パッチの数が減ります。これらの生成された地域提案には、さまざまなスケールとアスペクト比があります。

地域提案手法の重要な特徴は、再現率が高いことです。これは、私たちが見るオブジェクトを含むエリアがエリア提案のリストに含まれている必要があるという独特の声明です。この目標を達成するために、地域提案のリストには、最終的にはオブジェクトを含まない多くの地域が含まれる可能性があります。言い換えると、領域提案アルゴリズムは、すべての真陽性をキャプチャできる限り、多数の偽陽性を生成できます。これらの誤検知のほとんどは、オブジェクト認識アルゴリズムによって拒否されます。誤検知が多く、精度に影響が出ると、検出にかかる時間が長くなります。ただし、実際のオブジェクトを含む領域の選択が不足していると、検出率に深刻な影響を与える可能性があるため、再現率を高くすることをお勧めします。

次のようないくつかの地域の推奨事項が提案されています。
1.客観性
2.最小カット、自動オブジェクトセグメンテーションの制約パラメータ
3.カテゴリに依存しないオブジェクトの提案
4.ランダムプリム
5.選択的検索

これらすべてのエリア提案方法の中で、選択的検索は高速で再現率が高いため、最も一般的に使用されます。


物体認識のための選択的検索


選択的検索とは何ですか?

選択的検索は、オブジェクト検出のための領域提案アルゴリズムです。再現率が非常に高くなるように設計されています。これは、色、テクスチャ、サイズ、および形状の互換性に基づいて、類似した領域の階層グループを計算することに基づいています。

選択的検索は、FelzenszwalbとHuttenlocherのグラフベースのセグメンテーション方法を使用して開始され、ピクセルの強度に基づいて画像をオーバーセグメント化します。アルゴリズムの出力を以下に示します。右側の画像には、単色で表されたセグメント化された領域が含まれています。
画像

この画像の一部のセグメントは地域の提案ですか?答えはいいえだ。これができない理由は2つあります。
1.元の画像のほとんどの実際のオブジェクトには、2つ以上のセグメント化されたパーツが含まれています
2.この方法を使用すると、カップで覆われたプレートやコーヒーで満たされたカップなど、閉じたオブジェクトの領域の提案を生成できません。

隣接する領域をさらにマージして最初の問題を解決しようとすると、2つのオブジェクトをカバーするセグメント化された領域になります。

完璧なセグメンテーションは私たちの目標ではありません。多くの地域で推奨事項を予測したいだけですが、その一部は実際のターゲットとの重複が大きい​​はずです。

選択的検索では、最初のシードとしてFelzenszwalbとHuttenlocherの方法を使用します。外向的な画像は次のようになります。

選択的検索アルゴリズムは、これらの外因性を初期入力として受け取り、次の手順を実行します

1.分割された部分に対応するすべての境界ボックスを地域入札リストに追加します
2.類似性に基づいて隣接するセグメントをグループ化します
3.ステップ1に進みます

各反復で、より大きなフラグメントが形成され、地域の提案のリストに追加されます。したがって、ボトムアップアプローチを使用して、小さな部分から大きな部分への地域提案を作成します。これは、「レベル」の分割を計算するためのFelzenszwalbとHuttenlocherのルールの使用と呼ばれるものです。
画像

この図は、階層的セグメンテーションプロセスの最初、中間、および最後のステップを示しています。


同様

2つの領域間の類似性を計算する方法について詳しく学びましょう。

選択的検索では、色、テクスチャ、サイズ、および形状の互換性に基づいて4つの類似性指標を使用します。

色の類似性

画像の各チャネルの25領域のカラーヒストグラムを計算し、すべてのチャネルのヒストグラムを接続してカラー記述子を取得し、25×3 = 75次元のカラー記述子を取得します。

2つの領域の色の類似性は、ヒストグラムの交点に基づいており、次のように計算できます。
画像

c カラー記述子にあります th ビンのヒストグラム値

テクスチャの類似性

テクスチャの特徴は、チャネルごとに8方向のガウス導関数を抽出することによって計算されます。各方向および各カラーチャネルについて、10個のヒストグラムが計算され、10×8×3 = 240次元の特徴記述子が取得されます。

2つの領域のテクスチャの類似性も、ヒストグラムの交点を使用して計算されます。
画像

t テクスチャ記述子のk番目の{bin}のヒストグラム値です

同様のサイズ

サイズの類似性は、より小さな領域の早期統合を促進します。これにより、すべての地域の推奨事項が画像のすべての部分で形成されます。この類似性の尺度が考慮されていない場合、単一の領域がすべての小さな隣接領域を1つずつ飲み込むため、複数のスケールの地域提案はこの場所でのみ生成できます。サイズの類似性は次のように定義されます。

画像

sです((m)。 画像のサイズ(ピクセル単位)です

形状の互換性

形状の互換性は2つの領域を測定します( r rj )相互適合の程度。万一に備えて r に適し rj 、ギャップを埋めるためにそれらをマージしたいのですが、互いに接触していなければ、マージしないでください。

形状の互換性は次のように定義されます。
画像

sです((BBj)。 周りにあります r rj バウンディングボックス

最終的な類似性

2つの領域間の最終的な類似性は、上記の4つの類似性の線形結合として定義されます。

画像

その中で r rj 画像内に2つの領域またはセグメントがありますか? 01 類似性測度を使用するかどうかを示します。


結果

OpenCVでの選択的検索の実装により、何千もの地域提案をオブジェクトの順序で配置できます。わかりやすくするために、結果を共有し、画像に200〜250個のボックスを描画しています。一般的に言って、1000-1200の提案は、すべての正しい地域の提案を得るのに十分です。

画像


選択的検索コード

OpenCVに実装されている選択的検索ベースのセグメンテーションの使用方法を見てみましょう。


選択的検索:C ++

次のコードは、OpenCVを使用した選択的検索のためのC ++チュートリアルです。コードを理解するためにコメントを読んでください。

#include 'opencv2/ximgproc/segmentation.hpp' #include 'opencv2/highgui.hpp' #include 'opencv2/core.hpp' #include 'opencv2/imgproc.hpp' #include #include using namespace cv using namespace cv::ximgproc::segmentation //Program execution command: ./ssearch input_image (f|q) static void help() q)' << std::endl << 'f=fast, q=quality' << std::endl << 'Use l to display less rects, m to display more rects, q to quit' << std::endl int main(int argc, char** argv) { // If image path and f/q is not passed as command // line arguments, quit and display help message //I did not enter the command as required if (argc <3) { help() return -1 } // speed-up using multithreads // Speed ​​up the use of multithreading setUseOptimized(true) setNumThreads(4) // read image read image Mat im = imread(argv[1]) // resize image adjust size int newHeight = 200 int newWidth = im.cols*newHeight/im.rows resize(im, im, Size(newWidth, newHeight)) // create Selective Search Segmentation Object using default parameters // Create selective search segmentation object with default parameters Ptr ss = createSelectiveSearchSegmentation() // set input image on which we will run segmentation // Set the input image we will run the segmentation ss->setBaseImage(im) // Switch to fast but low recall Selective Search method // Switch to fast but low call rate selective search method if (argv[2][0] == 'f') { ss->switchToSelectiveSearchFast() } // Switch to high recall but slow Selective Search method //Switch to high call rate, but slow selective search method else if (argv[2][0] == 'q') { ss->switchToSelectiveSearchQuality() } // if argument is neither f nor q print help message // If the last parameter is neither f nor q print help information else { help() return -2 } // run selective search segmentation on input image // Run selective search segmentation on the input image std::vector rects ss->process(rects) std::cout << 'Total Number of Region Proposals: ' << rects.size() << std::endl // number of region proposals to show // Show the suggested number of areas int numShowRects = 100 // increment to increase/decrease total number // of reason proposals to be shown // Increase/decrease the total number of reason suggestions to be displayed int increment = 50 while(1) { // create a copy of original image // Create a copy of the original image Mat imOut = im.clone() // itereate over all the region proposals // Iterate through all the suggestions of regions for(int i = 0 i if (i 0, 255, 0)) } else { break } } // show output // display output imshow('Output', imOut) // record key press // record key press int k = waitKey() // m is pressed // m is pressed if (k == 109) { // increase total number of rectangles to show by increment // Increase the total number of rectangles to display in increments numShowRects += increment } // l is pressed // l is pressed else if (k == 108 && numShowRects > increment) { // decrease total number of rectangles to show by increment // Reduce the total number of rectangle display increments numShowRects -= increment } // q is pressed // press q to exit else if (k == 113) { break } } return 0 }

注意:
不足しているモジュールximgprocは行くことができます
https://github.com/opencv/opencv_contrib ダウンロードとインストール

コンパイルリファレンス: http://blog.csdn.net/wc781708249/article/details/78273241


選択的検索:Python

次のコードは、OpenCV3.3を使用した選択的検索のためのPythonチュートリアルです。コードブロックの後に記載されているOpenCV3.2エラーアラートに注意してください。コードを理解するためにコメントを読んでください。

#!/usr/bin/env python # -*- coding: UTF-8 -*- ''' Usage: ./ssearch.py input_image (f|q) f=fast, q=quality Use 'l' to display less rects, 'm' to display more rects, 'q' to quit. ''' import sys import cv2 if __name__ == '__main__': # If image path and f/q is not passed as command # line arguments, quit and display help message if len(sys.argv) <3: print(__doc__) sys.exit(1) # speed-up using multithreads # Use multi-threaded acceleration cv2.setUseOptimized(True) cv2.setNumThreads(4) # read image im = cv2.imread(sys.argv[1]) # resize image newHeight = 200 newWidth = int(im.shape[1]*200/im.shape[0]) im = cv2.resize(im, (newWidth, newHeight)) # create Selective Search Segmentation Object using default parameters # Use default parameters to create selective search segment objects ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation() # set input image on which we will run segmentation # Set the input image we will run segmentation ss.setBaseImage(im) # Switch to fast but low recall Selective Search method # Switch to fast but low callback selective search method if (sys.argv[2] == 'f'): ss.switchToSelectiveSearchFast() # Switch to high recall but slow Selective Search method # Switch to high callback, but slow selective search method elif (sys.argv[2] == 'q'): ss.switchToSelectiveSearchQuality() # if argument is neither f nor q print help message # If the parameter is neither f nor q print help information else: print(__doc__) sys.exit(1) # run selective search segmentation on input image # Run selective search segmentation on the input image rects = ss.process() print('Total Number of Region Proposals: {}'.format(len(rects))) # number of region proposals to show # Show the number of regional recommendations numShowRects = 100 # increment to increase/decrease total number # of reason proposals to be shown # Increase/decrease the total number of reason suggestions to be displayed increment = 50 while True: # create a copy of original image # Create a copy of the original image imOut = im.copy() # itereate over all the region proposals # Iterate over suggestions for all regions for i, rect in enumerate(rects): # draw rectangle for region proposal till numShowRects # Propose drawing a rectangle for the area until numShowRects if (i 0, 255, 0), 1, cv2.LINE_AA) else: break # show output cv2.imshow('Output', imOut) # record key press k = cv2.waitKey(0) & 0xFF # m is pressed if k == 109: # increase total number of rectangles to show by increment # Increase the total number of rectangles to display in increments numShowRects += increment # l is pressed elif k == 108 and numShowRects > increment: # decrease total number of rectangles to show by increment # Reduce the total number of rectangle display increments numShowRects -= increment # q is pressed elif k == 113: break # close image show window cv2.destroyAllWindows()

バグ警告:選択的検索用のPythonバインディングのバグは、この送信で修正されています。したがって、PythonコードはOpenCV 3.3.0には使用できますが、OpenCV3.2.0には使用できません。

OpenCV 3.3.0をコンパイルせず、OpenCV 3.2.0のビルドフォルダーを以前にコンパイルしたことがある場合は、このバグを修正することもできます。
Githubの提出物を見ると、これはほんの小さな変更です。ファイルの239行目を変更する必要があります

opencv_contrib-3.2.0 / modules / ximgproc / include / opencv2 / ximgproc / segmentation.hpp

// from CV_WRAP virtual void process(std::vector& rects) = 0 // to CV_WRAP virtual void process(CV_OUT std::vector& rects) = 0

ここで、OpenCV3.2.0を再度コンパイルします。以前にOpenCVをコンパイルしたビルドフォルダーがある場合、makeコマンドを実行するとモジュールがコンパイルされます。