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

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

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

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

C++

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

Q&A

1回答

1829閲覧

OpenCVを用いた背景差分および物体の輪郭の検出

17546

総合スコア1

OpenCV

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

C++

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

0グッド

0クリップ

投稿2021/10/21 01:57

前提・実現したいこと

vectorのソースファイル内でエラーが起きます。
エラーの場所は以下の通りです。

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

[[noreturn]] static void _Xrange() { _Xout_of_range("invalid vector subscript"); } ハンドルされない例外が 0x00007FFF0CB24ED9 で発生しました (sotsuken.exe 内): Microsoft C++ の例外: std::out_of_range (メモリの場所 0x000000A53759DC60)。

該当のソースコード

#include <opencv2/highgui/highgui.hpp> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/opencv.hpp> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <vector> using namespace std; //閾値(threshold)の設定 static const int th = 50; int main(void) { //カメラを開く cv::VideoCapture video1(0); //動画の読み込み //変数の準備 cv::Mat im1, im2, frame1; cv::Mat diff; cv::Mat immask, mask; cv::Mat image; cv::Mat contours; cv::Mat immask1, immask2; video1.read(image); //cv::Mat image = cv::imread("C:/Users/s17546/Desktop/3.jpg"); //if (image.empty() == true) { // 画像の中身が空なら終了する // return 0; //} //ウィンドウを3枚生成 cv::namedWindow("in"); cv::namedWindow("out1"); cv::namedWindow("out2"); cv::cvtColor(image, im1, cv::COLOR_BGR2GRAY); while (1) { video1.read(frame1); cv::cvtColor(frame1, im2, cv::COLOR_BGR2GRAY); cv::absdiff(im2, im1, diff); //差分diffのうち、閾値thを超えている部分を1、それ以外を0としてmaskに出力 cv::threshold(diff, mask, th, 1, cv::THRESH_BINARY); //マスクmaskのうち、1(True)の部分を白(0)に、0(False)の部分を黒(255)にしてim_maskに出力 cv::threshold(mask, immask, 0, 255, cv::THRESH_BINARY); //メディアンフィルタを使った平滑化によってゴマ塩ノイズを除去、アパーチャサイズ9 cv::medianBlur(immask, immask, 9); immask1 = cv::Mat(immask, cv::Rect(0, 0, 671, 376)); immask2 = cv::Mat(immask, cv::Rect(672, 0, 671, 376)); vector<vector<cv::Point> > contours; cv::findContours(immask1, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); double max_area = 0; int max_area_contour = -1; for (int j = 0; j < contours.size(); j++) { double area = cv::contourArea(contours.at(j)); if (max_area < area) { max_area = area; max_area_contour=j; } } int count = contours.at(max_area_contour).size(); double x = 0; double y = 0; for (int k = 0; k < count; k++) { x += contours.at(max_area_contour).at(k).x; y += contours.at(max_area_contour).at(k).y; } x /= count; y /= count; cv::circle(immask1, cv::Point(x, y), 50, cv::Scalar(0, 0, 255), 3, 4); vector<vector<cv::Point>>contours_subset; contours_subset.push_back(contours.at(max_area_contour)); cv::drawContours(immask1, contours_subset, -1, cv::Scalar(0, 255, 0), 4); //ウィンドウ2枚にそれぞれ入力画像、差分画像を表示 cv::imshow("in", im2); cv::imshow("out1", immask1); cv::imshow("out2", immask2); //ウィンドウ上でEscキーが押されたらプログラム終了 if (cv::waitKey(27) >= 0) { cv::destroyAllWindows(); break; } } }

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

Windows10
OpenCV ver4.5.3
visualstudio2019

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

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

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

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

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

guest

回答1

0

とりあえずコードを見た感じ,contours が空になり得ることを全く考慮していないように見える.

投稿2021/10/21 02:13

fana

総合スコア11996

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

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

17546

2021/10/21 04:37

最初に輪郭を抽出する物体がある状態で始めるとうまくいくことから,輪郭がない状態のときに例外処理が必要ということがわかりましたが,どのようにすればよろしいでしょうか。 contourに中身があるときはそのまま動作して,ないときはスキップするようにしたいです。 よろしくお願いします。
fana

2021/10/21 05:15

> ないときはスキップする ようにするにあたって,何が障害となっているのか? がこちらにはわかりませんが…… 「輪郭情報を用いた処理は,輪郭情報が存在する場合にのみ行う」という話で良いのであれば, 至極単純には if( !contours.empty() ) //空じゃないとき {//輪郭情報を用いる処理 double max_area = 0; ... cv::drawContours(immask1, contours_subset, -1, cv::Scalar(0, 255, 0), 4); } //ifおわり とか何とかすれば良いのではないかと思いますが…?
17546

2021/10/21 06:30

ありがとうございます。 試したら動作するようになりました。
fana

2021/10/21 07:47

解決したのであれば,適切に質問を閉じてください. ・この話で十分だということであれば,これをベストアンサーに選ぶ. ・これだけだと不十分で,何らかの補足事項があるとか,修正後の具体コードを示さないと話が通じないような話なのであれば,自己解決の形をとる.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問