1

私はpictureBoxで強度メーターを作成しました。この強度計を作るために、私はダイヤラ(Dialer.bmp)として写真を使用し、線を使用して針を作成しました。私はopenCVを使用してこれを行っています。そして、ニードルポインタを変更して、フォームのロード時にスレッドを作成しました。そして、コードは次のとおりです

private: System::Void FocusExposure_Load(System::Object^  sender, System::EventArgs^  e) {
 if(ExposureThreadStatus)
                     th->Abort();
                 th = gcnew Thread(gcnew ThreadStart(this,&FocusExposure::UpdateIntensity)); 
                th->Start();
                ExposureThreadStatus = true;
                }


void UpdateIntensity()
{
Intensity_Values data;
 while(1)
 {

 data = ReadImage(focusBuffer);
    System::Drawing::Bitmap ^bmp=drawImageMeter(data.Max);
     this->pictureBox1->Image =this->pictureBox1->Image->FromHbitmap(bmp->GetHbitmap());
     delete bmp;
     Sleep(1000);                   
 }
}

 System::Drawing::Bitmap^ drawImageMeter(float intensity_value)
{
        IplImage  *Background =cvLoadImage("Dialer.bmp", 1);
        int width,height;
        if(counter==1)
        {
        width=Background->width;
           height=Background->height;
            counter++;
        needle_center.x=width/2;
        needle_center.y=height/2;
        needle_top.x=needle_center.x;
        needle_top.y=needle_center.y-140;
        }
            double const PI = 3.14159265358979323;
           int x1 = needle_top.x; 
           int y1 = needle_top.y;
           int x0=needle_center.x;
           int y0=needle_center.y;
           float angle;
            CurrIntensity = intensity_value;
            angle = CurrIntensity-PreIntensity;
            angle= 0.0703125f * angle;
           // degrees, not radians
           float radians = angle * (PI / 180.0f);   // convert degrees to radians

           if (current_max==1)
            {
                current_max++;
                int N1x1 = needle_top.x; 
                int N1y1 = needle_top.y;
                needle1_top.x = ((N1x1-x0) * cos(radians)) - ((N1y1-y0) * sin(radians)) + x0; 
                needle1_top.y = ((N1x1-x0) * sin(radians)) + ((N1y1-y0) * cos(radians)) + y0;
            }
           needle_top.x = ((x1-x0) * cos(radians)) - ((y1-y0) * sin(radians)) + x0; 
           needle_top.y = ((x1-x0) * sin(radians)) + ((y1-y0) * cos(radians)) + y0;

           cvLine(Background, needle_center, needle1_top, CV_RGB(0, 0, 255), 1, 4, 0);
           cvLine(Background, needle_center, needle_top, CV_RGB(255, 0, 0), 1, 4, 0);
         System::Drawing::Bitmap ^bmp = gcnew System::Drawing::Bitmap(Background->width,Background->height,Background->widthStep,System::Drawing::Imaging::PixelFormat::Format24bppRgb,(System::IntPtr)Background->imageData);
         PreIntensity = CurrIntensity;
         return bmp;

}

このコードは正常に機能しており、要件に従って出力を提供します。しかし、唯一の問題は、フォームを開いているときにメモリリークが発生していることです。私はタスクマネージャーで見たことがあり、IntelVtuneプロファイラーも使用しました。このプロファイラーは、次の行で不一致の割り当て/割り当て解除を示しています

IplImage *Background =cvLoadImage("Dialer.bmp", 1);

画像に線を引いているため、この画像をリロードする必要があります。針ポインタが変更された場合は、針のないダイヤラ画像が必要です。

誰かがこのメモリリークの問題を解決するための解決策を私に提案できますか?

どんな助けでもありがたいです。

4

1 に答える 1

3

drawImageMeter()何度も呼ばれているようです。問題は、cvLoadImage()実行されるたびに、HEAPにピクセル用のスペースが割り当てられることです。したがって、画像を表示した後cvReleaseImage()、データを解放するために画像を解放する必要があります。

迅速で汚い(そして恐ろしい)修正はvariable静的にすることです:

static IplImage* Background =cvLoadImage("Dialer.bmp", 1);

ただし、アプリケーションの設計を実際に変更して、Background割り当てが1回だけになるようにする必要があります。これを行うには、グローバル変数にしてメソッドにロードするか、次main()のパラメーターにすることができますdrawImageMeter()

System::Drawing::Bitmap^ drawImageMeter(IplImage* Background, float intensity_value)
{
   // code
}
于 2012-09-25T17:52:47.347 に答える