2011-08-11 40 views
0

我使用cvSetData得到RGB幀到一個我可以使用OpenCV的。 我稍微修改了SkeletalViewer以產生rgb流。內存問題與cvShowImage和Kinect SDK:骨骼瀏覽器

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視頻,但最終會因爲內存不足而崩潰。

我應該如何正確釋放的形象呢?

回答

1

剛剛解決了這個問題。

一堆使用斷點調試偵探後,它看起來好像問題已經與cvSetData使用指針做。我最好的猜測是在調用cvReleaseImage之前,Nui_GotVideoAlert()更新pBuffer指向的地址。另外,cvSetData從不會複製這個地址的字節。

那麼會發生什麼情況是,cvReleaseImage被稱爲對已不存在的地址。

我通過在NuiImpl.cpp的頂部聲明瞭kinectColorImage,調用:: Nui_GotVideoAlert()中的cvSetData,並且只在Nui_Uninit()方法中調用cvReleaseImage來解決這個問題。這樣,kinectColorImage只會更新,而不是在每次調用Nui_GotVideoAlert()時創建一個新的IplImage。

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; 
}