自作でプログラムを組み、遊んでいたところ次のエラーが出て
実行できなくなりました。
メモリー不足が原因なのでしょうか?
動作環境は、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;
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
「メモリ不足」を示すエラーが出た場合、それはメモリが足りないのではなく「メモリリーク」が原因であることがほとんどです。
確保した領域を解放し忘れたりしていませんか? 特にループの中で画像データを作ったまま解放せずにループを繰り返して次々と新しい画像データを作ったりしていませんか?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
メッセージが正しいのなら、文字どおりメモリ不足でしょう。
32bit-app.でメモリ足りないなら64bitでre-buildすれば解決するかも、です。
(もちろん64bit-OSで、たっぷりメモリ積んでいれば、ですが)
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
こんにちは。
Windowsは仮想メモリをサポートしているので、私自身はメモリ不足エラーを経験したことはないのですが、メモリ空間を使い切るとメモリ不足エラーがでるそうです。
32ビット・ビルドでユーザメモリを2GBytesを越えて確保しようとするとそのようなエラーが出る筈です。また、64ビット・ビルドでも同様に巨大メモリ空間を消費すると発生するそうです。
メモリ獲得失敗に対応できていることのテスト、どうしてますか?にてcatsforepawさんから回答を頂きました。
以上の話は物理メモリ・サイズの影響を事実上受けません。例えば1GBytesしかメモリを搭載していないPCの32bit Windowsでも2GBytesまではメモリ確保可能です。(仮想メモリが自動的に用いられるため、スワップアウト/インが発生し、システムの応答が極端に遅くなります。)
【追記】
メモリ獲得し開放しないというリソース・リークと呼ばれる不具合があり、1分程でメモリ空間を全て消費していると思います。
高々1分程度で2GBytes以上を消費してしまうということは、獲得したメモリを開放していない可能性が高いです。
newしてdeleteしていないものがないか確認下さい。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
while-loop 内で (cvReleaseImageによって)解放しなければいけないイメージがあるんじゃないですか?
たとえば cvLoadImage(...) で得られたIplImage* は解放しなくていいんですか?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.36%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/06/30 13:38
アドバイスをいただけたらと思います。
2016/06/30 13:50
メインループ内で作成/複製した画像を解放せずにループを回しているので、思いっきりメモリリークしていますね。
`cvLoadImage`,`cvCreateImage`,`cvCloneImage`はいずれも内部でメモリを確保して画像データを保持しているので、使い終わったら`cvReleaseImage`関数で領域を解放してやる必要があります。
2016/06/30 13:55
試したいと思います。
2016/06/30 14:23
すると、cvCloneImageのヘッダーの引数のエラーがでました。
以下のプログラムを省略すると、でなくなるのですが、プログラムにミスはありますか?
cvReleaseImage(©_frameImage);
cvReleaseImage(&output);
cvReleaseImage(&img);
cvReleaseImage(&temp);
cvReleaseImage(&grey_img);
cvReleaseImage(&grey_temp);
cvReleaseImage(&dst);
cvDestroyWindow("windowNameTemplate");
cvReleaseCapture(&capture);
2016/06/30 14:44
> cvReleaseCapture(&capture);
この二つはループの終わりに書いてはいけません。ウィンドウもcaptureもループに入る前に作っているので、ループを抜けた先で書くべきです。というか、最初からそうなっていますよね。そっちが正解です。
エラーの原因は、`cvReleaseCapture(&capture)`をループの終わりでやってしまったため、二回目のループ先頭で`cvQueryFrame`関数が失敗し、`frameImage`が無効なデータとなって`cvCloneImage`も失敗したのだと思います。
ループの終わりで開放する領域は、必ずループの中で確保したものだけにしてください。さらに細かく言うと、ifブロックの中で確保しているものについては、そのブロックの終わりで解放するようにしてください。