cvShowImage和Kinect SDK的内存问题:骨架查看器

时间:2011-08-11 00:44:15

标签: memory opencv kinect

我正在使用cvSetData将rgb帧转换为可用于openCV的帧。 我稍微修改了SkeletalViewer以生成rgb流。

void CSkeletalViewerApp::Nui_GotVideoAlert( )
{
    const NUI_IMAGE_FRAME * pImageFrame = NULL;

    IplImage* kinectColorImage = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U, 4);

    HRESULT hr = NuiImageStreamGetNextFrame(
        m_pVideoStreamHandle,
        0,
        &pImageFrame );
    if( FAILED( hr ) )
    {
        return;
    }

    NuiImageBuffer * pTexture = pImageFrame->pFrameTexture;
    KINECT_LOCKED_RECT LockedRect;
    pTexture->LockRect( 0, &LockedRect, NULL, 0 );
    if( LockedRect.Pitch != 0 )
    {
        BYTE * pBuffer = (BYTE*) LockedRect.pBits;

        m_DrawVideo.DrawFrame( (BYTE*) pBuffer );

        cvSetData(kinectColorImage, (BYTE*) pBuffer,kinectColorImage->widthStep);

        cvShowImage("Color Image", kinectColorImage);
        //cvReleaseImage( &kinectColorImage );
        cvWaitKey(10);

    }
    else
    {
        OutputDebugString( L"Buffer length of received texture is bogus\r\n" );
    }

    cvReleaseImage(&kinectColorImage);
    NuiImageStreamReleaseFrame( m_pVideoStreamHandle, pImageFrame );

}

使用cvReleaseImage,我会收到cvException错误。不确定哪一个没有指定。如果没有cvReleaseImage,我会在openCV窗口中运行rgb视频,但最终会因为内存不足而崩溃。

我应该如何正确发布图像?

2 个答案:

答案 0 :(得分:1)

这很奇怪。据我所知,cvReleaseImage发布了图像头和图像数据。我做了下面的代码,在这个特定的例子中,cvReleaseImage 没有释放包含数据的缓冲区。在那里我没有使用cvSetData,但我刚刚更新了指向图像数据的指针。如果取消注释注释行并对每个注释行进行注释,程序仍会运行,但会出现内存泄漏。我使用的是OpenCV 2.2(这是传统的界面)。

#include <opencv/cv.h>
#include <stdlib.h>
#define NLOOPS 1000
int main(void){
  int i,j

  char *buff = (char *) malloc( sizeof(char) * 3 * 640 * 480 );
  for( i = 0; i < 640 * 480 * 3; i++ ) buff[i] = 128;
  j = 0;
  while( j++< NLOOPS ){

      IplImage *im = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U, 3); 
      //cvSetData(im, buff, im->widthStep);  ---> If you use that version you'll get memory  leaks. Comment line below.
      im->imageData = buff;
      cvWaitKey(4);
      cvShowImage("kk", im);
      //cvReleaseImageHeader(&im);           ---> If you use that version you'll get memory leaks. Comment line below.
      cvReleaseImage(&im);

      free(im);
  }

  free(buff);
  return 0; 
}

答案 1 :(得分:1)

刚刚解决了这个问题。

在使用断点和调试进行一系列调查后,似乎问题与cvSetData中使用的指针有关。我最好的猜测是,在调用cvReleaseImage之前,Nui_GotVideoAlert()会更新pBuffer指向的地址。此外,cvSetData似乎永远不会从该地址复制字节。

然后会发生的是在不再存在的地址上调用cvReleaseImage。

我通过在NuiImpl.cpp的顶部声明kinectColorImage,在:: Nui_GotVideoAlert()中调用cvSetData,并且仅在Nui_Uninit()方法中调用cvReleaseImage来修复此问题。这样,kinectColorImage将在每次调用Nui_GotVideoAlert()时更新而不是创建新的IplImage。