質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

684閲覧

Opencv カラー画像テンプレートマッチング

taeyang_88

総合スコア10

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/12/05 01:52

前提・実現したいこと

カラー画像のテンプレートマッチングを行いたいです。
テンプレート画像は抵抗のひょうたん部分です。
環境
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/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki23

2019/12/05 02:31

使った画像も添付してください
guest

回答1

0

ベストアンサー

sad += abs((int)src1_4.at<uchar>(y + j, x + i) - (int)tmp1_4.at<uchar>(j, i));
等の箇所の記述がグレースケール画像を前提とした実装になっているからでしょう.
カラー(複数ch)画像に対してat<uchar>を用いているので,想定とは異なるbyte間の比較が成されてしまっていると思います.

例えば画像が3chである場合,at< cv::Vec3b > 等で画素値を取得して比較するべきです.

投稿2019/12/05 03:55

編集2019/12/05 03:57
fana

総合スコア11632

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問