iOS + OpenCV - Mat内存泄漏

时间:2011-05-14 04:31:11

标签: iphone objective-c memory-leaks opencv objective-c++

我正在使用从iOS源代码编译和构建的OpenCV 2.2。我以blog post为指导。

我已经开始使用一些东西来制作图像灰度,模糊它们甚至运行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;
}

一旦我开始使用这种方法,我的应用程序就会开始泄漏并因此被杀死。

关于我做错的任何想法?

2 个答案:

答案 0 :(得分:2)

你在这里打电话

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

将copyData设置为true,您能确定正在调用Mat::release()吗?如果您的引用计数永远不会返回0,那么您的析构函数永远不会触发,从而在ram中留下大量的图像数据副本。

答案 1 :(得分:0)

了解数据提供者和数据引用之间的区别是关键;销毁引用或将引用重新分配给另一个对象不会影响存储在提供程序中的数据,除非框架的开发人员这样做(例如Apple)。 OpenCV本身并不将CGImageRef与其存储图像数据的任何对象相关联;因此,它要求您销毁CGImageRef(即取消引用其图像数据对象),然后释放并释放存储图像数据的OpenCV对象(cv :: Mat)。

为确保您在释放和解除分配对象后释放存储在cv :: Mat中的数据,只需cv :: Mat.empty():

...而

if (mat.empty())...

...返回FALSE,这......

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

...会...

if (mat.empty())...

...返回TRUE。