2011-05-14 101 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。