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

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

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

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

Q&A

1回答

2226閲覧

動画像処理のつなぎ合わせ方

uuuuuu

総合スコア10

C++

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

0グッド

0クリップ

投稿2018/11/14 16:26

前提・実現したいこと

駐車場を15分おきに撮影した画像をつなぎ合わせた動画から、駐車エリアの”空/埋”を自動で判別するためのプログラムを作っています。
現在、
・透視変換プログラム
・HSV情報での差分による15分前との変化点の抽出プログラム
・透視変換動画&差分動画を一つのウインドウに配置させるプログラム
以上が完成しているのですが、つなぎ合わせるとエラーが発生してしまいます。
プログラム初心者ですがご教授いただければ幸いです。
よろしくお願いします。
※実際に使用している画像と添付画像が違うためピクセル値は添付画像に対応しておりません。

入力画像から出力したい画像のイメージは添付画像の通りです。
イメージ説明
イメージ説明
イメージ説明

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

OpenCV(3.4.1) Error: Assertion failed ((unsigned)i0 < (unsigned)size.p[0]) in cv::Mat::at, file c:\opencv3.4.1\build\include\opencv2\core\mat.inl.hpp, line 1106

該当のソースコード

int main(int argc, const char* argv[]) { // 動画ファイルを開くための準備を行う cv::VideoCapture cap("撮影した画像をつなぎ合わせた動画.AVI"); // 動画プロパティ取得 int W = cap.get(CV_CAP_PROP_FRAME_WIDTH); // 幅 int H = cap.get(CV_CAP_PROP_FRAME_HEIGHT); // 高さ int count = cap.get(CV_CAP_PROP_FRAME_COUNT); // 総フレーム数 int fps = cap.get(CV_CAP_PROP_FPS); // fps // (3)動画ファイルが正しく開けているかをチェックする(正しく開けていなければエラー終了する) if (!cap.isOpened()) return -1; // (4) 動画プロパティ表示 printf("%d\n", W); printf("%d\n", H); printf("%d\n", count); printf("%d\n", fps); // 画像表示用のウィンドウを生成する cv::namedWindow("image1", cv::WINDOW_AUTOSIZE);//原画像 // 画像データを格納するための変数を宣言する cv::Mat pic0_bef; cv::Mat pic0_aft; cv::Mat pic1_bef; cv::Mat pic1_aft; cv::Mat pic2_bef; cv::Mat pic2_aft; cv::Mat frame1; cv::Mat frame2; cv::Mat frame3; cap >> pic0_aft ; pic1_aft = pic0_aft.clone(); pic2_aft = pic0_aft.clone(); for (int nowf = 1; nowf < count; nowf++) { // (3)動画ファイルから1フレーム分の画像データを取得して、変数frameに格納する pic0_bef = pic0_aft.clone(); pic1_bef = pic1_aft.clone(); pic2_bef = pic2_aft.clone(); using namespace cv; const int WIDTH = 880; const int HEIGHT = 800; Mat pic1_aft = Mat::zeros(HEIGHT, WIDTH, CV_8UC3); // 変換前の画像での座標 const Point2f pic0_aft_pt[] = { Point2f(420,330), Point2f(390,700), Point2f(800,310), Point2f(1300,650) }; // 変換後の画像での座標 const Point2f pic1_aft_pt[] = { Point2f(50,50), Point2f(50,50 + HEIGHT - 1), Point2f(50 + WIDTH - 1,50), Point2f(50 + WIDTH - 1,50 + HEIGHT - 1) }; // homography 行列を計算 const Mat homography_matrix = getPerspectiveTransform(pic0_aft_pt, pic1_aft_pt); // 透視変換 warpPerspective(pic0_aft, pic1_aft, homography_matrix, pic1_aft.size()); //HSV差分 using namespace cv; int width = pic1_aft.cols; int height = pic1_aft.rows; Mat hsv_image1; cvtColor(pic1_aft, hsv_image1, CV_BGR2HSV); uchar hue1, sat1, val1; int width1 = pic2_aft.cols; int height1 = pic2_aft.rows; Mat hsv_image2; cvtColor(pic2_aft, hsv_image2, CV_BGR2HSV); uchar hue2, sat2, val2; Mat pic_dif = Mat(Size(width, height), CV_8UC1); for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { hue1 = hsv_image1.at<Vec3b>(y, x)[0]; sat1 = hsv_image1.at<Vec3b>(y, x)[1]; val1 = hsv_image1.at<Vec3b>(y, x)[2]; hue2 = hsv_image2.at<Vec3b>(y, x)[0]; sat2 = hsv_image2.at<Vec3b>(y, x)[1]; val2 = hsv_image2.at<Vec3b>(y, x)[2]; int dif = 0 * abs(hue1 - hue2) + 0 * abs(sat1 - sat2) + 2 * abs(val1 - val2); if (dif > 100) pic_dif.at<uchar>(y, x) = 0; else pic_dif.at<uchar>(y, x) = 255; } frame3 = pic_dif; if (frame3.empty()) { break; } // 3つの画像を横に並べた大きさのMat型を作成する Mat base(Size(2640, 800), CV_8UC3); // frame1を張り付ける領域をあらわすMat型を作成する Mat roi1(base, Rect(0, 0, 880, 800)); // frame1をroi1にコピーする pic1_bef.copyTo(roi1); // frame2を張り付ける領域をあらわすMat型を作成する Mat roi2(base, Rect(880, 0, 880, 800)); // frame2をroi2にコピーする pic1_aft.copyTo(roi2); // frame3を張り付ける領域をあらわすMat型を作成する Mat roi3(base, Rect(1760, 0, 880, 800)); // frame3をroi3にコピーする frame3.copyTo(roi3); namedWindow("image1", CV_WINDOW_AUTOSIZE); imshow("image1", base); pic2_aft = pic1_bef.clone(); if (pic1_aft.empty()) { break; } cvWaitKey(200); } return 0; }

試したこと

ループ?させる位置を変更したりしましたがうまくいきませんでした

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

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

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

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

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

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

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

tiitoi

2018/11/15 15:58

動画がないので、こちらで動かして確認することはできないです。エラーはどの箇所で起きているのでしょうか?print() 文を入れるなどして、まずエラーが起きている関数の呼び出しを特定してください。
guest

回答1

0

cv::Mat::atの呼び出しで、行列のサイズを超えてアクセスしたために発生したエラーのようです。
動画ファイルからキャプチャしたpic2_aftが**pic1_aft(サイズ880x800?)**より小さかったりしませんか?

投稿2018/11/18 16:52

TaroToyotomi

総合スコア1430

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問