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

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

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

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

C++

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

解決済

OpenCV4.5.4 での画素を用いた2画像の比較方法について

teru99
teru99

総合スコア10

OpenCV

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

C++

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

1回答

0評価

0クリップ

262閲覧

投稿2022/05/24 16:55

編集2022/05/25 20:24

解決したいこと

Visual Studio 2022, OpenCV 4.5.4, C++開発環境での画素毎の比較方法について質問です。

初学者なりに調べたり書き直したりしたのですが、類似の情報を見つけることができず質問させていただいた次第です。
類似の質問が既にありましたら申し訳ありません。

現在のプログラムの概要

現在Mat img1 と Mat img2にそれぞれ保存されている画像を全画素比較し、
結果を Mat img3に保存するプログラムを作成しています。

① img1 と img2 の縦横のピクセル数を求め、小さいほうのサイズに合わせた img3を作成する。

② forループで img1 と img2 で異なる画素を持つピクセルを見つけ、同じ座標にある img3のピクセルを赤色にする。
(img1 と img2のサイズが異なったら小さいほうのサイズ分のみ for ループを走らせる)

③ 差分である赤色のピクセル数を変数に保存し、最後にパーセンテージとして相似度を示す。

この②の段階でエラーが生じています。
(ビルドは成功しています。)

作成したコード

C++

#include <iostream> #include <string> #include <opencv2/opencv.hpp> #include <opencv2/highgui.hpp> using namespace std; using namespace cv; int main() { //読み込みたい画像のパス string f1 = "C:\\Users\\user\\Desktop\\TEST\\90.jpg"; string f2 = "C:\\Users\\user\\Desktop\\TEST\\91.jpg"; //保存した画像用のパス string f3 = "C:\\Users\\user\\Desktop\\画像処理テスト用画像\\100002_TEST\\2.jpg"; //画像の読み込み, 保存 Mat img1 = imread(f1, IMREAD_UNCHANGED); Mat img2 = imread(f2, IMREAD_UNCHANGED); //img1の縦横のピクセル数を代入 int pix1[2] = { img1.cols, img1.rows, }; //img2の縦横のピクセル数の代入 int pix2[2] = { img2.cols, img2.rows, }; //img1, img2の小さいほうの縦横を代入 int min_pix[2]; min_pix[0] = pix1[0] >= pix2[0] ? pix2[0] : pix1[0]; min_pix[1] = pix1[1] >= pix2[1] ? pix2[1] : pix1[1]; //min_pix[]をもとに img3 を作成する Mat img3 = Mat::zeros(min_pix[1], min_pix[0], CV_8UC3); //差分のピクセル数を保存する変数 int count_red = 0; //for ループ. xで横を、yで縦を管理する for (int x = 0; x < min_pix[0]; x++) { for (int y = 0; y < min_pix[1]; y++) { //座標(x,y)の画素が異なったら img3 の (x,y) の画素を赤色 Vec3b(0,0,255) にする if ((img1.at<Vec3b>(y, x)) != (img2.at<Vec3b>(y, x))) { img3.at<Vec3b>(y, x) = Vec3b(0, 0, 255); count_red++; //カウントを進める } } } //得られた img3 を保存する imwrite(f3, img3); //得られた情報を表示する cout << "合計ピクセル数: " << min_pix[0] * min_pix[1] << endl << "異なったピクセル数 : " << count_red; return 0; }

実行結果

ソースコード内の "int count_red = 0;" までは意図通り動いているが、それ以降でエラーが生じている状態です。
forループ内を

C++

//for ループ. xで横を、yで縦を管理する for (int x = 0; x < min_pix[0]; x++) { for (int y = 0; y < min_pix[1]; y++) { //座標(x,y)における画素をVec3bに代入する Vec3b vec1 = img1.at<Vec3b>(y, x); Vec3b vec2 = img2.at<Vec3b>(y, x); //画素が同じかどうかの判定用 bool isSame = true; //各色の要素毎に比較する for (int i = 0; i < 3; i++) { if (vec1[i] != vec2[i]) { isSame = false; //比較した結果異なったら isSame に false を代入 } } //isSame が false であったら img3 の座標(x,y)の画素を赤色にする if (isSame == false) { img3.at<Vec3b>(y, x) = Vec3b(0, 0, 255); count_red++; //カウントを進める } } }

と改めてもエラーが生じてしまいます。
どういった方法であれば画素毎に正しく比較が行えるのかをご教示いただけると幸いです。

駄文で失礼いたしました。

追記

エラー内容と実行結果について追記いたします。

エラー内容

コンソール画面には以下のように表示されました。

C++

OpenCV(4.5.5) Error: Assertion failed ((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels())) in cv::Mat::at, file C:\OpenCV454\opencv\build\include\opencv2\core\mat.inl.hpp, line 899 OpenCV: terminate handler is called! The last OpenCV error is: OpenCV(4.5.5) Error: Assertion failed ((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels())) in cv::Mat::at, file C:\OpenCV454\opencv\build\include\opencv2\core\mat.inl.hpp, line 899

Mat::at が原因のようですがわかりませんでした。

実行結果について

これも原因がわからないのですが、同一のコピーした画像を読み込ませた時に成功する場合と上記のエラーを起こしてしない場合があります。

また、コピー画像同士を比較させて実行に成功しても出力画像が殆ど赤色になってしまいます。

最後に、
これらの情報を示すのを失念しており申し訳ありませんでした。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

YOshim

2022/05/24 23:07

エラー内容を教えてもらえませんか。
yominet

2022/05/25 02:44

すでに指摘されてるように、期待してない結果なのか処理が途中でとまるエラーかどうかなどの情報がないのでほぼ雑談レベルになりますが・・・ 比較対象がJPGなのが気になる。 JPGは圧縮時に色が荒れるので、見た目では同じにみえても、デジタルデータとして細かくみていったら一致するほうが珍しい。
jbpb0

2022/05/25 10:02 編集

質問の最初の方のコードで、画像ファイルのパスだけ変えて、他はそのままでコンパイルして実行したら、正常に実行でき、下記が表示されました 合計ピクセル数: 数値 異なったピクセル数 : 数値 ちなみに、画像ファイルのパスを存在しないものにわざと間違えても、forループが終わるところまでは実行されました 当方の環境は下記の通り Windows 10 Visual Studio 2017 OpenCV 4.5.2
teru99

2022/05/25 10:08

実行結果・エラー内容未記載の件失念しており申し訳ありませんでした。編集いたします。 画像の拡張子に関しましては盲点でした。拡張子を変えて試させていただきます。 正常に動いたとの情報ありがとうございます。当方もパスを変えて試させていただきます。
jbpb0

2022/05/25 10:23 編集

> コピー画像同士を比較させて実行に成功しても出力画像が殆ど赤色になってしまいます。 当方での実行では、 ・同一の画像間の比較 (f1, f2を全く同じパスに) ・別のディレクトリにコピーした画像間の比較 (もともとは同じ画像ファイル) のどちらの場合も、何回実行しても、結果の画像(f3)は常に真っ黒になりました (同じ画像だから差は無いので、それが正常)
jbpb0

2022/05/25 10:30

「C:\\Users\\user\\Desktop」が、もしかしたらonedrive上だったりしませんか? 画像を置く場所を変えてみるとか (「Desktop」と「Documents」と「Pictures」以外のどこか)
teru99

2022/05/25 10:38

何度も情報提供ありがとうございます。パスの場所に関しては試してみましたが成功しませんでした。 ですがjbpb0様の環境では無事動いたとのことでしたので、とりあえず一安心です。 どうやら私の環境構築に問題があるようですのでOpenCVを入れ直し、プロジェクトを立ち上げ直して検証したいと思います
teru99

2022/05/25 11:01

環境を再構築して実行しなおしたところ、正常に作動しました。 原因はわかりませんでしたが、情報提供していただいた皆様ありがとうございました
yominet

2022/05/25 11:24

質問タイトルと、質問最初の1行だと >Visual Studio 2022, OpenCV 4.5.4, C++開発環境での画素毎の比較方法について質問です。 バージョンが、4.5.4になっていますが、エラーは >OpenCV(4.5.5) Error: と4.5.5になっているようです(でも指定されてるソースファイルは4.5.4?) 4.5.4と4.5.5の環境が混じっていて、読み込まれるDLLがおかしいのかもしれません。 #debug,release版の違いも注意

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

OpenCV

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

C++

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