マッチング
■ テンプレートマッチング
テンプレート画像呼ばれる探索対象となるオブジェクト等の画像と, 探索領域となる(その一部にオブジェクト等の探索対象を含む)画像を入力と する. テンプレート画像を少しずつずらしながら,探索領域内の対象領域との比較を 行う.比較に用いられる相関関数には,計算量を考慮して,分散や平均を仮定し た近似式が用いられることが多い.サンプル
テンプレートマッチング cvMatchTemplate
探索画像からテンプレートの位置を探す
サンプルコード
#include <cv.h>
#include <highgui.h>
int
main (int argc, char **argv)
{
double min_val, max_val;
CvPoint min_loc, max_loc;
CvSize dst_size;
IplImage *src_img, *tmp_img, *dst_img;
if (argc != 3 ||
(src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR)) == 0 ||
(tmp_img = cvLoadImage (argv[2], CV_LOAD_IMAGE_COLOR)) == 0)
return -1;
// (1)探索画像全体に対して,テンプレートのマッチング値(指定した手法に依存)を計算
dst_size = cvSize (src_img->width - tmp_img->width + 1, src_img->height - tmp_img->height + 1);
dst_img = cvCreateImage (dst_size, IPL_DEPTH_32F, 1);
cvMatchTemplate (src_img, tmp_img, dst_img, CV_TM_CCOEFF_NORMED);
cvMinMaxLoc (dst_img, &min_val, &max_val, &min_loc, &max_loc, NULL);
// (2)テンプレートに対応する位置に矩形を描画
cvRectangle (src_img, max_loc,
cvPoint (max_loc.x + tmp_img->width, max_loc.y + tmp_img->height), CV_RGB (255, 0, 0), 3);
cvNamedWindow ("Image", 1);
cvShowImage ("Image", src_img);
cvWaitKey (0);
cvDestroyWindow ("Image");
cvReleaseImage (&src_img);
cvReleaseImage (&tmp_img);
cvReleaseImage (&dst_img);
return 0;
}
// (1)探索画像全体に対して,テンプレートのマッチング値(指定した手法に依存)を計算
読み込まれた探索画像とテンプレート画像を用いて,テンプレートマッチングを行う.
マッチングに利用する相関関数には,CV_TM_SQDIFF,CV_TM_SQDIFF_NORMED,
CV_TM_CCORR,CV_TM_CCORR_NORMED,CV_TM_CCOEFF,CV_TM_CCOEFF_NORMED,
が指定可能である.今回は,CV_TM_CCOEFF_NORMEDを指定している.これは,
各比較領域の輝度値の平均が等しいと仮定した場合の相関演算式の近似である.
詳しくは,リファレンスを参照すること.
マッチングは,関数cvCalcBackProjectionPatch()と似ているが,あらかじめヒストグラムを
計算するような前処理は必要ではない.
画像中の値の最大,最小値,およびその位置は,関数cvMinMaxLoc()によって取り出す.
CV_TM_CCOEFF_NORMEDを指定した場合には,最大値の座標がマッチング位置になる.
また,CV_TM_SQDIFF(SSDとも呼ばれる),CV_TM_SQDIFF_NORMEDを指定した場
合には,最小値の座標がマッチング位置になる.
// (2)テンプレートに対応する位置に矩形を描画
探索画像中の求められた座標位置に矩形を描画する.その画像を表示し,何かキーが押されるまで待つ.
実行結果例
以下の例では,探索画像の一部を切り出したものをテンプレート画像として扱っ
ている(探索画像に直接ROIを設定しても同様の事が可能である)ので,完全に正しい結果が得られている.
従って,探索領域とテンプレート画像とで画像が変化するような場合は,常に正しい位置にマッチングするとは限らない.
入力画像 | テンプレート画像 | 結果画像 |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
■ 形状マッチング
二つの形状(輪郭データ,あるいはグレースケール画像)を入力とする. OpenCVの関数cvMatchShapes()では,形状の比較にHuモーメントを用いるため, 回転,スケーリング,反転に対して不変である.サンプル
形状のマッチング cvMatchShapes
二つの入力画像に対して,3種類の手法で形状比較を行う
サンプルコード
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
int
main (int argc, char **argv)
{
char text[16];
int i;
double result[3];
CvFont font;
IplImage *src_img1, *src_img2;
IplImage *dst_img[3];
if (argc != 3 ||
(src_img1 = cvLoadImage (argv[1], CV_LOAD_IMAGE_GRAYSCALE)) == 0 ||
(src_img2 = cvLoadImage (argv[2], CV_LOAD_IMAGE_GRAYSCALE)) == 0)
return -1;
for (i = 0; i < 3; i++) {
dst_img[i] = (IplImage *) cvClone (src_img2);
}
// (1)3種類の手法で形状を比較
result[0] = cvMatchShapes (src_img1, src_img2, CV_CONTOURS_MATCH_I1, 0);
result[1] = cvMatchShapes (src_img1, src_img2, CV_CONTOURS_MATCH_I2, 0);
result[2] = cvMatchShapes (src_img1, src_img2, CV_CONTOURS_MATCH_I3, 0);
// (2)形状マッチングの結果を画像に描画
for (i = 0; i < 3; i++) {
snprintf (text, 16, "%.5f", result[i]);
cvInitFont (&font, CV_FONT_HERSHEY_SIMPLEX, 1.0, 1.0, 0, 4, 8);
cvPutText (dst_img[i], text, cvPoint (10, dst_img[i]->height - 10), &font, cvScalarAll (0));
}
// (3)入力画像1と3種類の値が書き込まれた入力画像2を表示し,何かキーが押されるまで待つ
cvNamedWindow ("Image1", CV_WINDOW_AUTOSIZE);
cvNamedWindow ("Image2a", CV_WINDOW_AUTOSIZE);
cvNamedWindow ("Image2b", CV_WINDOW_AUTOSIZE);
cvNamedWindow ("Image2c", CV_WINDOW_AUTOSIZE);
cvShowImage ("Image1", src_img1);
cvShowImage ("Image2a", dst_img[0]);
cvShowImage ("Image2b", dst_img[1]);
cvShowImage ("Image2c", dst_img[2]);
cvWaitKey (0);
cvDestroyWindow ("Image1");
cvDestroyWindow ("Image2a");
cvDestroyWindow ("Image2b");
cvDestroyWindow ("Image2c");
cvReleaseImage (&src_img1);
cvReleaseImage (&src_img2);
cvReleaseImage (&dst_img[0]);
cvReleaseImage (&dst_img[1]);
cvReleaseImage (&dst_img[2]);
return 0;
}
// (1)3種類の手法で形状を比較
関数cvMatchShapes()によって,二つの入力画像に対して形状マッチングを行う.ここで,3番目の引数が比較手法を表す.
また,4番目の引数は,現在のところ利用されていない.
// (2)形状マッチングの結果を画像に描画
比較結果を,画像に文字列として描画する.小さい値であるほど二つの画像
の形状が近い(0の場合は同じ形状)という事になる.
// (3)入力画像1と3種類の値が書き込まれた入力画像2を表示
結果の画像を表示し,何かキーが押されるまで待つ.
実行結果例
入力画像 | 比較画像1 | 比較画像2 | 比較画像3 | 比較画像4 | |
![]() |
![]() |
![]() |
![]() |
![]() |
CV_CONTOURS_MATCH_I1 |
![]() |
![]() |
![]() |
![]() |
CV_CONTOURS_MATCH_I2 | |
![]() |
![]() |
![]() |
![]() |
CV_CONTOURS_MATCH_I3 |
入力画像 | 比較画像1 | 比較画像2 | 比較画像3 | 比較画像4 | |
![]() |
![]() |
![]() |
![]() |
![]() |
CV_CONTOURS_MATCH_I1 |
![]() |
![]() |
![]() |
![]() |
CV_CONTOURS_MATCH_I2 | |
![]() |
![]() |
![]() |
![]() |
CV_CONTOURS_MATCH_I3 |