2012-09-25 6 views
1

pictureBox에서 강도 측정기를 만들었습니다. 이 강도 미터를 만들기 위해 저는 Dialer (Dialer.bmp)와 같은 그림을 사용했고 선을 사용하여 바늘을 만들었습니다. openCV를 사용하여이 작업을 수행하고 있습니다. 바늘 포인터를 바꾸면 폼로드시 쓰레드가 생성됩니다. 코드는 다음과 같습니다.cvLoadImage 함수에서 메모리 누수가 발생했습니다.

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; 

} 

이 코드는 제대로 동작하고 제 요구 사항에 따라 출력을 제공합니다. 하지만 유일한 문제는 폼을 열 때 메모리 누수가 발생한다는 것입니다. 작업 관리자에서 보았으며 인텔 Vtune 프로파일 러도 사용했습니다. 이 프로파일은 다음 줄에 일치하지 않는 할당/해제을 보여주고있다

우리가 이미지에 선을 그리는 바늘 포인터가 변경되면 그것은 걸기를 필요로하기 때문에 우리는이 이미지를 다시로드해야 IplImage *Background =cvLoadImage("Dialer.bmp", 1);

바늘없는 이미지.

아무도 나에게이 메모리 누출 문제를 해결하기위한 해결책을 제안 할 수 있습니까?

도움이 될 것입니다.

+0

: 당신이 전역 변수를 확인하고 그것이 main() 방법에로드하거나 그것을 drawImageMeter()의 매개 변수를 만들 수 있습니다 그렇게하려면? 필요한 단계처럼 들린다 – Sam

+0

@vasile 답장을 보내 주셔서 감사합니다. cvReleaseImage (& Background)를 사용할 때 pictureBox에서 Dialer Image를 볼 수 없어 갑자기 응용 프로그램이 닫힙니다. – geeta

+1

bmp로 압축 된 데이터를 사용하는 동안 이미지를 릴리스하기 때문입니다. 따라서 몇 가지 단계를 거쳐 일반적인 프로그래밍 문제, 포인터 및 메모리 관리에 대한 강의를 듣는 것이 좋습니다. 개인적으로 받아들이지는 말고 정말로 필요합니다. – Sam

답변

2

drawImageMeter()이 두 번 이상 호출 된 것 같습니다. 문제는 cvLoadImage()이 실행될 때마다 픽셀에 대해 HEAP에 공간을 할당한다는 것입니다. 따라서 이미지를 표시 한 후에는 cvReleaseImage()으로 해제해야 데이터가 해제됩니다.

신속하고 더러운 (끔찍한) 수정 make the variablestatic하는 것입니다 :

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

하지만 당신이 정말로 그것을 한 번만 할당 그래서 Background 응용 프로그램의 디자인을 변경 한다. 무엇 cvReleaseImage (배경)에 대해

System::Drawing::Bitmap^ drawImageMeter(IplImage* Background, float intensity_value) 
{ 
    // code 
} 
+0

+1; 내 javacpp opencv 응용 프로그램에서 누출 된 메모리의 원인을 알아 내려고 애 쓰고 있습니다. 결국, 나는 커리큘럼 이미지의 커다란 디렉토리에서 반복적으로 호출되는'cvLoadImage() '를 포함하는 첫 줄까지 모든 코드를 주석 처리하기 시작했다. 그때 나는 올바른 단어를 봤고 여기에서 끝났다. 고맙습니다. – SND

+0

@SND 당신이 그것을 발견했기 때문에 기쁘게 생각합니다! – karlphillip

관련 문제