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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C++

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

Q&A

解決済

2回答

1345閲覧

なぜエラーが出るのかわかりません

aiueokakiku

総合スコア1

C++

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

0グッド

0クリップ

投稿2021/11/08 16:56

編集2021/11/08 17:53

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
(例)PHP(CakePHP)で●●なシステムを作っています。
■■な機能を実装中に以下のエラーメッセージが発生しました。
cv::matchTemplateを使わずにテンプレートマッチング(SSD)を実装したい.

発生している問題・エラーメッセージ

エラーメッセージ OpenCV(4.5.1) Error: Assertion failed ((unsigned)i0 < (unsigned)size.p[0]) in cv::Mat::at, file C:\opencv\build\include\opencv2\core\mat.inl.hpp, line 871 OpenCV: terminate handler is called! The last OpenCV error is: OpenCV(4.5.1) Error: Assertion failed ((unsigned)i0 < (unsigned)size.p[0]) in cv::Mat::at, file C:\opencv\build\include\opencv2\core\mat.inl.hpp, line 871

該当のソースコード

コード #include <stdio.h> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main(void) { int i, j, k, l, hiku, count, smallest, ssd, x, y, smallx, smally; smallest = 10000000; smallx = 0; smally = 0; Mat gray_src, gray_temp; Mat src = imread("C:\Users\Owner\Pictures\あ\src.jpeg"); Mat temp = imread("C:\Users\Owner\Pictures\あ\temp.png"); cvtColor(src, gray_src, COLOR_BGR2GRAY); cvtColor(temp, gray_temp, COLOR_BGR2GRAY); printf("aaaa\n"); for (k = 0; k < src.rows - temp.rows; k++) { printf("aaa\n"); for (l = 0; l < src.cols - temp.cols;l++) { printf("%d\n", l); ssd = 0; printf("aa\n"); for (i = k; i < temp.rows + k; i++) {//y for (j = l; j < temp.cols + l; j++) {//x hiku = gray_src.at<unsigned char>(j, i) - gray_temp.at<unsigned char>(j, i); ssd = ssd + hiku * hiku; printf("%d\n", j); x= l; y = k; } } if (ssd < smallest) { smallest = ssd; smallx = x; smally = y; } } } Rect roi_rect(0, 0, temp.cols, temp.rows); roi_rect.x = smallx; roi_rect.y = smally; cv::rectangle(src, roi_rect, cv::Scalar(0, 255, 255), 3);//一番類似度の高い場所を矩形で囲む cv::imshow("src", src); waitKey(); return 0; }
c++ ソースコード

試したこと

ここに問題に対して試したことを記載してください。
printfでどこまで動くのかを試しました.j=72までは表示されて,それから先がエラーになります.

補足情報(FW/ツールのバージョンなど)

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

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

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

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

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

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

y_waiwai

2021/11/08 17:19

このままではコードが読みづらいので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください また、エラーが出たなら、エラーメッセージを提示しましょう エラーメッセージは、いらぬ翻訳省略しないで、出たそのママをコピペで提示してください
aiueokakiku

2021/11/08 17:51

修正しました. 提示するべきエラーメッセージも間違えていました. ご指摘ありがとうございます.
guest

回答2

0

ベストアンサー

エラーの意味自体は他の方が指摘している通りの範囲外エラーです.

ここ↓のループ範囲はどういう考えでこのようになっているのでしょう?
もっと言えば,「i とか j とかって何を示す値なのでしょう?」というあたりに混乱があるのではないでしょうか?

C++

1for (i = k; i < temp.rows + k; i++) {//y 2 for (j = l; j < temp.cols + l; j++) {//x 3 hiku = gray_src.at<unsigned char>(j, i) - gray_temp.at<unsigned char>(j, i);

「いずれかの画像の画素位置を示すindex」という意味合いの値であれば,そうと分かる名前を付けるとよいでしょう.
それだけで混乱しにくくなります.

例えば,この内側のループを「テンプレート画像の画素位置」に関するループだとするならば,

C++

1//まぁ,あまり良い変数名じゃないかもしれないけども,テンプレートの画素位置だよ,っていう名前のつもり. 2for( int temp_y=0; temp_y<temp.rows; ++temp_y ) 3 for( int temp_x=0; temp_x<temp.cols; ++temp_x )

とか.
とにかく
【この変数は「テンプレート画像の画素位置」を示すのだ】
【このループは「テンプレート画像の画素位置」に関するループだ】
といったような明確な意思を持って書けば,

  • ループ範囲は自明となるでしょう.
  • temp_x や temp_y を他の画像(gray_src)の画素位置を指す値として誤用したりすることもなくなるでしょう.

すなわち,【「テンプレート画像の画素位置(temp_x,temp_y)」と比較すべき「元画像(gray_src)側の画素位置」とはどこなのか?】という話が自然と湧いて出てくるので,それを実装することになるでしょう.

投稿2021/11/09 01:59

fana

総合スコア11996

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

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

fana

2021/11/09 02:03 編集

挙げた例えが,質問者の考えと一致しているかどうかはわからない. (質問者のコードにおける内側のループの位置づけは テンプレート画像の画素位置に関するループ ではないのかもしれない.) あくまでも「例え」である.(「コードをこの形に修正せよ」とか言っているわけではない) i,j,k,l のような変数が入り乱れて何か座標を計算するようなコードは「いかにもミスりやすい」と「思う」ので, もっと強い意志を持って,各変数の役割を表現した方がよいのではないかな,と.
fana

2021/11/09 02:11 編集

外側のループの k と l も同様に,「何の値なのか」を表現したほうがいい. 元画像上でのSSDを計算する範囲の「左上」なのか「真ん中」なのかそれ以外の何かなのか? それによってループの範囲は違ってくるかもしれないし,内側での kやらl の使い方も異なってくる. ※あと,「SSDを計算する範囲」が元画像の範囲外にはみ出す場合をどう扱うのか? という点に対応が必要となるが,質問コードにはそれも無い(ように見える).
aiueokakiku

2021/11/09 03:30

解答ありがとうございます. 指摘してくださったことを考えてみたら,確かに参照する画素が範囲外で,他の画像の画素位置を指す値として誤用していました. また,なぜそうなってしまったのかと言う点についても,変数の名前を適当に決めてしまったことが大きく,指摘の通りです. これからは変数名をもっと工夫しようと思います. SSDの範囲は絶対に元の画像の範囲外にはみ出さないようになっているはずです.(端は検出できないようになっているということです,そこの部分も間違っていなければ) 本当にご丁寧にありがとうございます.
guest

0

openCVはあまり得意ではないですが。

エラーメッセージは「Matのサイズを超えたところにMat::atでアクセスしようとしたからエラーにした」と言っているようですね。
Mat gray_src, gray_temp;
でデフォルトコンストラクタでMatを作っていますが、ここを他の画像にあわせたサイズ/タイプで作成するようにしたらいかがでしょう。

投稿2021/11/08 22:57

thkana

総合スコア7703

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

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

fana

2021/11/09 01:37

gray_src と gray_temp の領域は > cvtColor(src, gray_src, COLOR_BGR2GRAY); > cvtColor(temp, gray_temp, COLOR_BGR2GRAY); によって生成されます.
fana

2021/11/09 01:44

よって, gray_temp のサイズは temp と同じになっているハズなんだけども, > for (i = k; i < temp.rows + k; i++) {//y のあたりで,tempのサイズを超えた範囲でループしており, > gray_temp.at<unsigned char>(j, i); で,ご指摘通りのエラーが発生しているのだと見えます.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問