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

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

ただいまの
回答率

90.48%

  • C++

    4505questions

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

  • OpenCV

    1552questions

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

opencvでのエラー

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 5,023

yamata

score 28

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

動作環境は、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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

0

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 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(&copy_frameImage);
    cvReleaseImage(&output);
    cvReleaseImage(&img);
    cvReleaseImage(&temp);
    cvReleaseImage(&grey_img);
    cvReleaseImage(&grey_temp);
    cvReleaseImage(&dst);
    cvDestroyWindow("windowNameTemplate");
    cvReleaseCapture(&capture);

    キャンセル

  • 2016/06/30 14:44

    > cvDestroyWindow("windowNameTemplate");
    > cvReleaseCapture(&capture);

    この二つはループの終わりに書いてはいけません。ウィンドウもcaptureもループに入る前に作っているので、ループを抜けた先で書くべきです。というか、最初からそうなっていますよね。そっちが正解です。

    エラーの原因は、`cvReleaseCapture(&capture)`をループの終わりでやってしまったため、二回目のループ先頭で`cvQueryFrame`関数が失敗し、`frameImage`が無効なデータとなって`cvCloneImage`も失敗したのだと思います。

    ループの終わりで開放する領域は、必ずループの中で確保したものだけにしてください。さらに細かく言うと、ifブロックの中で確保しているものについては、そのブロックの終わりで解放するようにしてください。

    キャンセル

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/29 15:48

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

    opencvを64bitに変更できるのですか?

    キャンセル

  • 2016/06/29 15:52

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

    キャンセル

  • 2016/06/29 15:54

    > opencvを64bitに変更できるのですか?

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

    キャンセル

  • 2016/06/29 16:23

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

    キャンセル

0

こんにちは。

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

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


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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/30 13:38

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

    キャンセル

  • 2016/06/30 14:21

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

    キャンセル

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/30 13:56

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

    キャンセル

  • 2016/06/30 14:00

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

    キャンセル

同じタグがついた質問を見る

  • C++

    4505questions

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

  • OpenCV

    1552questions

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