前提・実現したいこと
カラー画像のテンプレートマッチングを行いたいです。
テンプレート画像は抵抗のひょうたん部分です。
環境
OS: Mac OS
Xcode
発生している問題・エラーメッセージ
画像の通り違う場所が格子で囲まれてしまいます。 ![イメージ説明](763c0e22ac4818e055388101bca730c0.png)
該当のソースコード
C++
1#include "opencv2/opencv.hpp" 2 3using namespace std; 4using namespace cv; 5 6Mat pyr(Mat, int); // 画像ピラミッド生成 7void sad(Mat, Mat); // 高速テンプレートマッチング 8 9int main() 10{ 11 Mat src_img =imread("/Users/i-am-kaito/Downloads/IMG_4238.png",1); 12 Mat tmp_img = imread("/Users/i-am-kaito/Downloads/IMG_4236.png",1); // テンプレート画像 13 14 sad(src_img, tmp_img); 15 16 waitKey(0); 17 18 return 0; 19} 20 21Mat pyr(Mat src, int n) //(入力画像,出力画像の大きさ[1/(2^n)]) 22 { 23 Mat dst = src; 24 25 for (int i = 0; i < n; i++) pyrDown(dst, dst); // pyrDownは元画像の半分の画像を生成する標準関数 26 27 return dst; 28} 29 30void sad(Mat src, Mat tmp) 31{ 32 int sad_min = INT_MAX; 33 int sad_x = 0; 34 int sad_y = 0; 35 36 // 第一段階 37 Mat src1_4 = pyr(src, 2); // 4分の1の入力画像 38 Mat tmp1_4 = pyr(tmp, 2); // 4分の1のテンプレート画像 39 for (int y = 0; y < src1_4.rows - tmp1_4.rows; y++){ 40 for (int x = 0; x < src1_4.cols - tmp1_4.cols; x++){ 41 int sad = 0; 42 for (int j = 0; j < tmp1_4.rows; j++){ 43 for (int i = 0; i < tmp1_4.cols; i++){ 44 sad += abs((int)src1_4.at<uchar>(y + j, x + i) - (int)tmp1_4.at<uchar>(j, i)); 45 if (sad > sad_min) goto SSDA_loop1; 46 } 47 } 48 sad_min = sad; 49 sad_x = x; 50 sad_y = y; 51 SSDA_loop1:; 52 } 53 } 54 55 // 第二段階 56 Mat src1_2 = pyr(src, 1); // 2分の1の入力画像 57 Mat tmp1_2 = pyr(tmp, 1); // 2分の1のテンプレート画像 58 sad_min = INT_MAX; 59 int yyy = sad_y * 2; // 画像が2倍の大きさになるので2倍 60 int xxx = sad_x * 2; 61 // テンプレート画像サイズの周囲±1ピクセルの範囲を探索 62 for (int y = yyy - 1; y <= yyy + 1 && y < src1_2.rows - tmp1_2.rows; y++){ 63 for (int x = xxx - 1; x <= xxx + 1 && x < src1_2.cols - tmp1_2.cols; x++){ 64 int sad = 0; 65 for (int j = 0; j < tmp1_2.rows; j++){ 66 for (int i = 0; i < tmp1_2.cols; i++){ 67 sad += abs((int)src1_2.at<uchar>(y + j, x + i) - (int)tmp1_2.at<uchar>(j, i)); 68 if (sad > sad_min) goto SSDA_loop2; 69 } 70 } 71 sad_min = sad; 72 sad_x = x; 73 sad_y = y; 74 SSDA_loop2:; 75 } 76 } 77 78 // 第三段階 79 Mat src1_1 = src.clone(); // 元画像と同じ大きさの入力画像 80 Mat tmp1_1 = tmp.clone(); // 元画像と同じ大きさのテンプレート画像 81 sad_min = INT_MAX; 82 int yy = sad_y * 2; // 画像が2倍の大きさになるので2倍 83 int xx = sad_x * 2; 84 // テンプレート画像サイズの周囲±1ピクセルの範囲を探索 85 for (int y = yy - 1; y <= yy + 1 && y < src1_1.rows - tmp1_1.rows; y++){ 86 for (int x = xx - 1; x <= xx + 1 && x < src1_1.cols - tmp1_1.cols; x++){ 87 int sad = 0; 88 for (int j = 0; j < tmp1_1.rows; j++){ 89 for (int i = 0; i < tmp1_1.cols; i++){ 90 sad += abs((int)src1_1.at<uchar>(y + j, x + i) - (int)tmp1_1.at<uchar>(j, i)); 91 if (sad > sad_min) goto SSDA_loop3; 92 } 93 } 94 sad_min = sad; 95 sad_x = x; 96 sad_y = y; 97 SSDA_loop3:; 98 } 99 } 100 101 // テンプレートマッチング位置を四角で囲む 102 Mat rect = src.clone(); 103 rectangle(rect, Point(sad_x, sad_y), Point(sad_x + tmp.cols, sad_y + tmp.rows), Scalar(0, 0, 200), 3, 4); 104 namedWindow("Rectangle", WINDOW_AUTOSIZE); // ウィンドウ表示の準備 105 imshow("Rectangle", rect); // ウィンドウで表示 106 imwrite("build.jpg", rect); // 画像として出力 107 108 cout << "3段階SAD法" << endl; 109 // マッチした座標(左上)とそのときのsad値を表示 110 cout << "(" << sad_x << ", " << sad_y << ") " << sad_min << endl; 111} 112
試したこと
グレースケールでは正常にマッチングできました。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
使った画像も添付してください
回答1件
あなたの回答
tips
プレビュー