0

このコードはcamからキャプチャするために使用され、各フレームでHSV画像に変換し、カラーセグメンテーションを適用して赤、緑、青のオブジェクトを見つけ、それぞれの輪郭を見つけてCVSeqに保存します.

cvClearMemStorage()コードは正常に動作していますが、問題は、メモリを解放するために使用したにもかかわらず、新しい輪郭にメモリを割り当てることができないため、10 分後に実行時例外がスローされることです。

#include <cv.h>
#include <highgui.h>

CvSeq *contours;
IplImage* frame=0;
CvMemStorage* g_storage;

//This function threshold the HSV image and create a binary image
IplImage* GetThresholdedRedImage(IplImage* imgHSV)
{
       IplImage* imgThresh = cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
       cvInRangeS(imgHSV, cvScalar(160,160,60), cvScalar(180,256,256), imgThresh);

       //CvMemStorage* g_storage = cvCreateMemStorage(0);
       cvFindContours( cvCloneImage(imgThresh), g_storage, &contours );
       if( contours )
       {
           cvDrawContours(frame, contours, cvScalar(0, 255, 0), cvScalarAll(255), 100);
           cvClearSeq(contours);

       }

       cvClearMemStorage(g_storage);

       return imgThresh;
}

IplImage* GetThresholdedGreenImage(IplImage* imgHSV)
{
       IplImage* imgThresh=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
       cvInRangeS(imgHSV, cvScalar(38,160,60), cvScalar(75,256,256), imgThresh);

       //CvMemStorage* g_storage = cvCreateMemStorage(0);
       cvFindContours( cvCloneImage(imgThresh), g_storage, &contours );
       if( contours )
       {
           cvDrawContours(frame, contours, cvScalar(0, 255, 255), cvScalarAll(255), 100);
           cvClearSeq(contours);
       }

       cvClearMemStorage(g_storage);

       return imgThresh;
}

IplImage* GetThresholdedBlueImage(IplImage* imgHSV)
{
       IplImage* imgThresh=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
       cvInRangeS(imgHSV, cvScalar(75,160,60), cvScalar(130,256,256), imgThresh);

       //CvMemStorage* g_storage = cvCreateMemStorage(0);
       cvFindContours( cvCloneImage(imgThresh), g_storage, &contours );
       if( contours )
       {
           cvDrawContours(frame, contours, cvScalarAll(255), cvScalarAll(255), 100);
           cvClearSeq(contours);
       }

       cvClearMemStorage(g_storage);

       return imgThresh;
}

int main()
{
      CvCapture* capture =0;

      capture = cvCaptureFromCAM(0);
      if(!capture)
      {
        printf("Capture failure\n");
        return -1;
      }

      //IplImage* frame=0;

      cvNamedWindow("Video");
      cvNamedWindow("Red");
      //cvNamedWindow("Yellow");
      //cvNamedWindow("Orange");
      cvNamedWindow("Green");
      cvNamedWindow("Blue");
      //cvNamedWindow("Violet");
      g_storage = cvCreateMemStorage(0);

      //iterate through each frames of the video
      while(true)
      {

            frame = cvQueryFrame(capture);
            if(!frame) break;

            frame = cvCloneImage(frame);
            cvSmooth(frame, frame, CV_GAUSSIAN,3,3); //smooth the original image using Gaussian kernel

            IplImage* imgHSV = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
            cvCvtColor(frame, imgHSV, CV_BGR2HSV); //Change the color format from BGR to HSV

            IplImage* redImgThresh = GetThresholdedRedImage(imgHSV);
            IplImage* blueImgThresh = GetThresholdedBlueImage(imgHSV);
            IplImage* greenImgThresh = GetThresholdedGreenImage(imgHSV);

            //cvClearSeq(contours);

            cvSmooth(redImgThresh, redImgThresh, CV_GAUSSIAN,3,3); //smooth the binary image using Gaussian kernel
            cvSmooth(blueImgThresh, blueImgThresh, CV_GAUSSIAN,3,3);
            cvSmooth(greenImgThresh, greenImgThresh, CV_GAUSSIAN,3,3);

            cvShowImage("Red", redImgThresh);
            cvShowImage("blue", blueImgThresh);
            cvShowImage("green", greenImgThresh);
            cvShowImage("Video", frame);

            //Clean up used images
            cvReleaseImage(&imgHSV);
            cvReleaseImage(&redImgThresh);
            cvReleaseImage(&blueImgThresh);
            cvReleaseImage(&greenImgThresh);
            cvReleaseImage(&frame);

            //Wait 50mS
            int c = cvWaitKey(10);
            //If 'ESC' is pressed, break the loop
            if((char)c==27 ) break;
      }

      cvDestroyAllWindows() ;
      cvReleaseCapture(&capture);

      return 0;
}
4

2 に答える 2

0

これをコンパイルするためにMSVCを使用している場合...

main()エントリ ポイントを含む同じファイルに次のコード行を含めます。

#if _DEBUG
#   define _CRTDBG_MAP_ALLOC
#   include <stdlib.h>
#   include <crtdbg.h>
#endif

main()次に、関数の一番上に以下を含めます。

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

これにより、アプリケーションのリソース リークを動的に監視するように VC ランタイムに指示されます。
アプリケーションをコンパイルして実行し、数秒後に終了します。

出力ウィンドウを見ると、次のような行が表示されるはずです。

Detected memory leaks!
Dumping objects ->
{18} normal block at 0x00780E80, 64 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

ここで注目すべき点{18} normal blockは、メモリ割り当て数とブロック タイプです。リストの最初の割り当て番号を見て、それをコピーします。

ここで、関数で記述した場所のすぐ下に_CrtSetDbgFlag()main()次を貼り付けます。

_CrtSetBreakAlloc(18); // Where `18` is the memory allocation number

コンパイルして再度実行すると、そのメモリ ブロックが割り当てられた時点でプロジェクトが壊れるはずです。コードの不明なセクションで問題が発生した場合は、[コール スタック] ウィンドウをチェックして、記述したコードまでさかのぼることができます。

この情報を使用して、どのオブジェクトの割り当てを解除する必要があるかを把握し、どこでそれを行うべきかを把握する必要があります。漏れが検出されなくなるまで、このプロセスを繰り返すだけです。

このすべての情報とその他の情報は、MSDN のメモリ リークの検出と分離を介して見つけることができます。

UNIX 用にコンパイルする場合...

詳細については、このスレッドを確認してください。

さて、割り当てを解除する方法に関する限り...

まあ、それは実際に割り当てられたもの (および正確にどのように) に依存します。
の場合、これは (一見)が呼び出されるCvSeqまで OpenCV によって管理されるため、通常はまったく割り当てを解除する必要はありません。cvReleaseMemStorageあなたが投稿したコード内のどこにもこのメソッドへの呼び出しが見られないので、これがあなたのリソースリークに貢献している可能性があります...

したがって、上記の手順に従って、コードが壊れるかどうかを自分で判断することをお勧めしますcvCreateMemStorage。その場合は、cvReleaseMemStorage使用が終わったら必ず への呼び出しを含めてください。

一方、cvClearMemStorageは次のように記述されています。
「この関数は、ストレージの先頭 (空き領域境界) を最初にリセットします。この関数はメモリの割り当てを解除しません。ストレージに親がある場合、関数はすべてのブロックをに戻します。親。"

これら 2 つの機能を混同していた可能性はありますか?

于 2013-05-24T04:29:46.367 に答える
0

私が気に入らないコードの一部は次のとおりです。

frame = cvCloneImage(frame);
...
cvReleaseImage(&frame);

以来、からhighgui.h

 /* Just a combination of cvGrabFrame and cvRetrieveFrame
 !!!DO NOT RELEASE or MODIFY the retrieved frame!!!      */
 CVAPI(IplImage*) cvQueryFrame( CvCapture* capture );

別のポインターを使用して画像を取得し、このポインターに複製することをお勧めします。

IplImage* tempFrame = cvCloneImage(frame);
frame = cvCloneImage(tempFrame);
...
cvReleaseImage(&frame);

また、お読みください:OpenCVの紹介

ビデオ シーケンスの操作セクションを参照してください。

于 2013-02-21T21:19:06.447 に答える