0

我正在使用 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,我会让 rgb 视频在 openCV 窗口中运行,但最终会因为内存不足而崩溃。

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

4

2 回答 2

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; 
}
于 2011-08-12T14:47:50.957 回答
1

刚刚解决了这个问题。

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

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

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

于 2011-08-16T23:41:03.340 回答