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

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

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

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

C++

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

Q&A

解決済

4回答

11205閲覧

opencvでのエラー

yamata

総合スコア36

OpenCV

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

C++

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

0グッド

0クリップ

投稿2016/06/29 06:16

編集2016/06/30 04:37

自作でプログラムを組み、遊んでいたところ次のエラーが出て
実行できなくなりました。
メモリー不足が原因なのでしょうか?

動作環境は、VC++2010Express、opencv2.4.9です。

以下にエラー画像をのせます。

よろしくお願いします。

多くの意見ありがとうございました。

全プログラムをのせます。
アドバイスをいただけたらと思います。
よろしくお願いします。

プログラムとしては、キーを押したら画像を保存して
マッチングを行うことを繰り返すものです。

//静止画像をマッチング改良版(カメラ使用) int main( int argc , char** argv) { int key;//キー入力用の変数 CvCapture *capture;//カメラキャプチャ用の構造体 IplImage *frameImage = NULL;//キャプチャ画像用IplImage char windowNameCapture[] = "Capture";//キャプチャした画像を表示するウィンドウの名前 #define LINE_THICKNESS 1 #define LINE_TYPE 8 #define SHIFT 0 IplImage * temp = NULL; IplImage * dst = NULL; IplImage * img = NULL; IplImage * grey_img = NULL; IplImage * grey_temp = NULL; IplImage * output =NULL; IplImage * copy_frameImage = NULL; CvRect rect; double max_inter1inkage=0; double min_inter1inkage=0; CvPoint max_point; CvPoint min_point; //カメラを初期化する if ( ( capture = cvCreateCameraCapture( -1 ) ) == NULL ) { //カメラが見つからなかった場合 printf( "カメラが見つかりません\n" ); return -1; } //Windowの生成 //cvNamedWindow("Capture", CV_WINDOW_AUTOSIZE); //カメラ・デバイスから画像を取得 frameImage=cvQueryFrame(capture); //メインループ while ( 1 ) { //カメラからの入力画像1フレームをframeImageに格納する(画像加工不可) frameImage = cvQueryFrame( capture ); //frameImageをコピー copy_frameImage=cvCloneImage(frameImage); //ROIを用いて短形切り出し //IplImage* image = cvLoadImage("sign.bmp"); //画面中央にROI rect.x = cvRound(copy_frameImage->width * 0.25); rect.y = cvRound(copy_frameImage->height * 0.25); rect.width = cvRound(copy_frameImage->width * 0.2); rect.height = cvRound(copy_frameImage->height * 0.11); //ROI指定 cvSetImageROI(copy_frameImage, rect); //出力先指定 cvCloneImageでROIまるごとコピー output=cvCloneImage(copy_frameImage); //cvSaveImage("test.bmp", frameImage); //ROIを保存 output=cvCloneImage(copy_frameImage); //元の画像をコピー //ROIを表示 cvNamedWindow("Capture",CV_WINDOW_AUTOSIZE); cvShowImage("Capture",output); //画像を表示する //cvShowImage( windowNameCapture, frameImage ); //'q'キーが入力されたらループを抜ける key = cvWaitKey( 1 ); if ( key == 'q' ) { break; } else if( key == 'c') { int64 start = cv::getTickCount();//所要時間計測 cvSaveImage("sign.bmp", output ); //キーを押して保存 //cvNamedWindow("window picture",CV_WINDOW_AUTOSIZE); //cvShowImage("window picture",frameImage); //--------原画像を読み込む--------- img=cvLoadImage("sign.bmp",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); //カラー読み込み //---------テンプレート画像を読み込む------- temp=cvLoadImage("temp8.png",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); //カラー読み込み //テンプレート・マッチングに用いる相関値データを格納する画像の領域確保 //グレー・スケール画像用に領域確保 grey_img=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1); //1チャンネル8ビットのIplImage作成(元画像) grey_temp=cvCreateImage(cvGetSize(temp),IPL_DEPTH_8U,1); //1チャンネル8ビットのIplImage作成(元画像) dst =cvCreateImage(cvSize(img->width-temp->width+1,img->height-temp->height+1),IPL_DEPTH_32F,1); //領域確保 //グレー・スケールに変換して格納 cvCvtColor(img,grey_img,CV_BGR2GRAY); cvCvtColor(temp,grey_temp,CV_BGR2GRAY); //-------テンプレートマッチングを取る----- cvMatchTemplate(grey_img,grey_temp,dst,CV_TM_CCOEFF_NORMED); //-----------マッチング点を求める--------- cvMinMaxLoc(dst,&min_inter1inkage,&max_inter1inkage,&min_point,&max_point,NULL); //------マッチングを表示する----- //相関値0.75以下ならばLostを表示して次に行く if(max_inter1inkage>0.5) { //マッチング箇所を四角で描画 cvRectangle(img,min_point,cvPoint(min_point.x+temp->width,min_point.y+temp->height),CV_RGB(255,0,0),LINE_THICKNESS,LINE_TYPE,SHIFT); //画像を表示 cvNamedWindow("windowNameTemplate",CV_WINDOW_AUTOSIZE); cvShowImage("windowNameTemplate",img); //類似度表示 printf("Detection %lf\n",max_inter1inkage); } else { printf("Lost %lf\n",max_inter1inkage); } //タイマー終了 int64 end = cv::getTickCount(); double elapsedMsec = ( end - start )*1000/cv::getTickFrequency(); //タイマー表示 std::cout << elapsedMsec <<"ms" <<std::endl; } } //メモリ開放 cvReleaseCapture(&capture); cvDestroyWindow("windowNameCapture"); return 0; }

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

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

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

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

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

guest

回答4

0

while-loop 内で (cvReleaseImageによって)解放しなければいけないイメージがあるんじゃないですか?
たとえば cvLoadImage(...) で得られたIplImage* は解放しなくていいんですか?

投稿2016/06/30 04:51

episteme

総合スコア16614

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

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

yamata

2016/06/30 04:56

ありがとうございます!試したいと思います。
episteme

2016/06/30 05:00

C++ interface 使えばほとんどの後始末は自動的にやってくれるのに...
guest

0

ベストアンサー

「メモリ不足」を示すエラーが出た場合、それはメモリが足りないのではなく「メモリリーク」が原因であることがほとんどです。

確保した領域を解放し忘れたりしていませんか? 特にループの中で画像データを作ったまま解放せずにループを繰り返して次々と新しい画像データを作ったりしていませんか?

投稿2016/06/29 08:44

catsforepaw

総合スコア5938

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

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

yamata

2016/06/30 04:38

プログラムをのせました。 アドバイスをいただけたらと思います。
catsforepaw

2016/06/30 04:50

予想的中 メインループ内で作成/複製した画像を解放せずにループを回しているので、思いっきりメモリリークしていますね。 `cvLoadImage`,`cvCreateImage`,`cvCloneImage`はいずれも内部でメモリを確保して画像データを保持しているので、使い終わったら`cvReleaseImage`関数で領域を解放してやる必要があります。
yamata

2016/06/30 04:55

ありがとうございます!メインループ内で全て解放する必要があるのですね! 試したいと思います。
yamata

2016/06/30 05:23

試してみました。メインループの終わりに以下のプログラムを入れてみました。 すると、cvCloneImageのヘッダーの引数のエラーがでました。 以下のプログラムを省略すると、でなくなるのですが、プログラムにミスはありますか? cvReleaseImage(&copy_frameImage); cvReleaseImage(&output); cvReleaseImage(&img); cvReleaseImage(&temp); cvReleaseImage(&grey_img); cvReleaseImage(&grey_temp); cvReleaseImage(&dst); cvDestroyWindow("windowNameTemplate"); cvReleaseCapture(&capture);
catsforepaw

2016/06/30 05:44

> cvDestroyWindow("windowNameTemplate"); > cvReleaseCapture(&capture); この二つはループの終わりに書いてはいけません。ウィンドウもcaptureもループに入る前に作っているので、ループを抜けた先で書くべきです。というか、最初からそうなっていますよね。そっちが正解です。 エラーの原因は、`cvReleaseCapture(&capture)`をループの終わりでやってしまったため、二回目のループ先頭で`cvQueryFrame`関数が失敗し、`frameImage`が無効なデータとなって`cvCloneImage`も失敗したのだと思います。 ループの終わりで開放する領域は、必ずループの中で確保したものだけにしてください。さらに細かく言うと、ifブロックの中で確保しているものについては、そのブロックの終わりで解放するようにしてください。
guest

0

こんにちは。

Windowsは仮想メモリをサポートしているので、私自身はメモリ不足エラーを経験したことはないのですが、メモリ空間を使い切るとメモリ不足エラーがでるそうです。
32ビット・ビルドでユーザメモリを2GBytesを越えて確保しようとするとそのようなエラーが出る筈です。また、64ビット・ビルドでも同様に巨大メモリ空間を消費すると発生するそうです。
メモリ獲得失敗に対応できていることのテスト、どうしてますか?にてcatsforepawさんから回答を頂きました。

以上の話は物理メモリ・サイズの影響を事実上受けません。例えば1GBytesしかメモリを搭載していないPCの32bit Windowsでも2GBytesまではメモリ確保可能です。(仮想メモリが自動的に用いられるため、スワップアウト/インが発生し、システムの応答が極端に遅くなります。)


【追記】
メモリ獲得し開放しないというリソース・リークと呼ばれる不具合があり、1分程でメモリ空間を全て消費していると思います。
高々1分程度で2GBytes以上を消費してしまうということは、獲得したメモリを開放していない可能性が高いです。
newしてdeleteしていないものがないか確認下さい。

投稿2016/06/29 06:48

編集2016/06/29 09:51
Chironian

総合スコア23272

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

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

yamata

2016/06/30 04:38

プログラムをのせました。 アドバイスをいただけたらと思います。
Chironian

2016/06/30 05:21

ざっとみたところ、cvCreateImage()後、解放していませんね。そのため、メモリ・リークします。 ↓のようにcvCreateImage()で確保したものは、cvReleaseImage()で解放して下さい。 http://opencv.jp/sample/initialization.html 獲得と解放は必ずセットになるようご注意下さい。
guest

0

メッセージが正しいのなら、文字どおりメモリ不足でしょう。
32bit-app.でメモリ足りないなら64bitでre-buildすれば解決するかも、です。
(もちろん64bit-OSで、たっぷりメモリ積んでいれば、ですが)

投稿2016/06/29 06:41

episteme

総合スコア16614

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

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

yamata

2016/06/29 06:48

実行してから、1分くらいたつと上のエラーがでます。 プログラムに問題があるということにはならないのでしょうか? opencvを64bitに変更できるのですか?
episteme

2016/06/29 06:52

必要なメモリ解放を忘れているなら、じわじわとメモリを食いつぶしていずれ枯渇します。
episteme

2016/06/29 06:54

> opencvを64bitに変更できるのですか? OpenCVにはコンパイル済の64bitライブラリは同梱されてないんですか? ソース公開されているなら64bitでライブラリをre-buildできるんじゃないかと。
episteme

2016/06/29 07:23

OpenCV 3.1 には Visal Studio 2013(vc12),2015(vc14) の 32/64bit ライブラリが入ってますね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問