解決したいこと
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 が原因のようですがわかりませんでした。
実行結果について
これも原因がわからないのですが、同一のコピーした画像を読み込ませた時に成功する場合と上記のエラーを起こしてしない場合があります。
また、コピー画像同士を比較させて実行に成功しても出力画像が殆ど赤色になってしまいます。
最後に、
これらの情報を示すのを失念しており申し訳ありませんでした。
まだ回答がついていません
会員登録して回答してみよう