我正在使用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视频,但最终会因为内存不足而崩溃。
我应该如何正确发布图像?
答案 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。