テンプレート画像を与え 入力画像からそのテンプレート画像にマッチングした領域を探すことを テンプレートマッチングといいます。
OpenCvでは ImgprocクラスのmatchTemplateメソッドで この テンプレートマッチングを行います。
static void matchTemplate(Mat image, Mat templ, Mat result,int method)
Mat image : テンプレートの探索対象となる画像.8ビットまたは32ビットの浮動小数点型。
Mat templ : 探索されるテンプレート.探索対象となる画像以下のサイズで,同じデータ型でなければいけません。
Mat result : 比較結果のマップ.シングルチャンネル,32ビット,浮動小数点型。
image が(W,H) で, templ が(w,h) とすると result は(W-w+1,H-h+1) となります。
int method : 比較手法の指定 Imgprocクラスの定数を指定します。
TM_SQDIFF、TM_SQDIFF_NORMED、TM_CCORR、TM_CCORR_NORMED、TM_CCOEFF、TM_CCOEFF_NORMED
詳しくは OpenCv2.2 C++リファレンスを参照してください。数式だらけで何のコッチャ(笑い)
この関数による比較の後、Coreクラスの関数 minMaxLoc() を用いて,大域的最小値( CV_TM_SQDIFF の場合)あるいは大域的最大値( CV_TM_CCORR や CV_TM_CCOEFF の場合)を検出することでベストマッチを得ることができます。
static Core.MinMaxLocResult minMaxLoc(Mat src)
static Core.MinMaxLocResult minMaxLoc(Mat src, Mat mask)
実行結果 |
//入力画像 Bitmap src = BitmapFactory.decodeFile(path); Bitmap src1 = src.copy(Bitmap.Config.ARGB_8888, true); Mat image = android.BitmapToMat(src1); //テンプレート画像 src = BitmapFactory.decodeFile(path2); Bitmap src2 = src.copy(Bitmap.Config.ARGB_8888, true); Mat templ = android.BitmapToMat(src2); //テンプレートマッチング Mat result = new Mat(); Imgproc.matchTemplate(image, templ, result, Imgproc.TM_CCOEFF_NORMED); Core.MinMaxLocResult maxr = Core.minMaxLoc(result); //マッチング結果の表示 Point maxp = maxr.maxLoc; Point pt2 = new Point(maxp.x + templ.width(), maxp.y + templ.height()); Mat dst = image.clone(); Core.rectangle(dst, maxp, pt2, new Scalar(255,0,0), 2);
実行結果は下図
上段:入力画像
中段:テンプレート画像
下段:マッチング結果
Imgproc.matchTemplate(image, templ, result, Imgproc.TM_CCOEFF_NORMED);のmethodを変えてみました。
TM_CCOEFF : TM_CCOEFF_NORMEDと全く同じ結果
TM_SQDIFF、TM_SQDIFF_NORMED :
Point maxp = maxr.maxLoc; を Point maxp = maxr.minLoc; とすることでTM_CCOEFF_NORMEDと全く同じ結果
TM_CCORR、TM_CCORR_NORMED :
TM_CCOEFF_NORMEDと全く同じ結果をどうすれば得られるかはわかりませんでした。
by Android2.2 with OpenCv 2.3.1 for Android |
コメント
ありがとう。
参考になりました。ありがとうございます。