2011-05-14 124 views
0

我使用從源代碼編譯而成的OpenCV 2.2 for iOS。我用這個blog post作爲指導。iOS + OpenCV - Mat內存泄漏

我已經玩弄了一些東西來工作,如使圖像灰度,模糊他們,甚至運行FAST。然而,我的問題是,我的代碼泄漏內存,這很快就會導致應用程序在設備上運行時被終止。

從博客帖子上面我用下面的代碼把一個UIImage到的IplImage

+ (IplImage *)IplImageFromUIImage:(UIImage *)image 
{ 
    // NOTE you SHOULD cvReleaseImage() for the return value when end of the code. 
    CGImageRef imageRef = image.CGImage; 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    IplImage *iplimage = cvCreateImage(cvSize(image.size.width, image.size.height), IPL_DEPTH_8U, 4); 
    CGContextRef contextRef = CGBitmapContextCreate(iplimage->imageData, iplimage->width, iplimage->height, 
                iplimage->depth, iplimage->widthStep, 
                colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault); 
    CGContextDrawImage(contextRef, CGRectMake(0, 0, image.size.width, image.size.height), imageRef); 
    CGContextRelease(contextRef); 
    CGColorSpaceRelease(colorSpace); 

    IplImage *ret = cvCreateImage(cvGetSize(iplimage), IPL_DEPTH_8U, 3); 
    cvCvtColor(iplimage, ret, CV_RGBA2RGB); 

    cvReleaseImage(&iplimage); 

    return ret; 
} 

這工作得很好,似乎不但是泄漏任何記憶,因爲我使用的OpenCV 2.2我想使用C++接口,所以我創建了下面的函數。

+ (Mat)MatFromUIImage:(UIImage *)image 
{ 
    IplImage *iplImage = [self IplImageFromUIImage:image]; 
    Mat result(iplImage, true); 
    cvReleaseImage(&iplImage); 
    return result; 
} 

一旦我開始使用這種方法,我的應用程序開始泄漏,從而被殺死。

關於我在做什麼的錯誤?

+0

因爲您正在使用'+',所以不應該是'[Classname IplImageFromUIImage:image]'而不是'self'? – slf 2011-05-14 04:41:38

+2

@slf:這個調用是在類方法中的,所以'self'指向類對象,而不是實例。 – 2011-05-14 05:28:48

回答

2

在這裏,你在呼喚

Mat::Mat(const IplImage* img, bool copyData=false) 

用了CopyData設置爲true,你可以肯定的是Mat::release()被稱爲?如果您的refcount永遠不會返回0,那麼您的析構函數絕不會觸發您在內存中留下大量圖像數據的副本。

+0

這當然是我的第一個想法。在閱讀Mat文檔後,它表明這只是處理所有事情。我只有堆棧裏有Mat對象,而不是堆,所以我會認爲當他們超出範圍時,refcount會變爲零。有關如何驗證正在發生的任何建議? – 2011-05-14 07:47:00

+0

在泄漏檢測儀上使用儀器,您可以看到什麼在泄漏,甚至可以捕獲運行中泄漏的RAM的內容。 – slf 2011-05-14 14:30:08

+0

我的程序中有其他錯誤導致了更高級別的內存問題。這就是說,我認爲這個答案是對我的問題的充分迴應。 – 2011-05-15 22:44:44

0

瞭解數據提供者和數據引用之間的區別是關鍵;銷燬引用或將引用重新分配給另一個對象不會影響存儲在提供程序中的數據,除非框架的開發人員如此(例如Apple)。 OpenCV不會將CGImageRef與任何存儲圖像數據的對象本身相關聯;因此,它需要您銷燬CGImageRef(即取消引用其圖像數據對象),然後釋放和取消分配存儲圖像數據(cv :: Mat)的OpenCV對象。

爲了確保您已經發布存儲的數據,比方說,CV ::墊,釋放和回收的對象後僅僅CV :: Mat.empty():

而...

if (mat.empty())... 

...返回FALSE,這...

mat.deallocate(); 
mat.release(); 

...會...

if (mat.empty())... 

...返回TRUE。