开发者

iOS + OpenCV - Mat memory leak

开发者 https://www.devze.com 2023-03-06 07:55 出处:网络
I am using OpenCV 2.2 compiled and built from source for iOS. I used this blog post as a guide. I have played around with getting some stuff to work like making images grayscale, blurring them and ev

I am using OpenCV 2.2 compiled and built from source for iOS. I used this blog post as a guide.

I have played around with getting some stuff to work like making images grayscale, blurring them and even running FAST. My problem however is that my code is leaking memory and this very quickly causes the app to be killed when run on a device.

From the blog post above I use the code below to turn a UIImage into an 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;
}

This works fine and does not seem to leak any memory however since I am using OpenCV 2.2 I am trying to use the C++ interface so I created the function below.

+ (Mat)MatFromUIImage:(UIImage *)image
{
    IplImage *iplImage = [self IplImageFromUIImage:image];
    Mat result(iplImage, true);
    cvReleaseImage(&iplImage);
    return resul开发者_JAVA技巧t;
}

Once I start using this method my app starts leaking and consequently gets killed.

Any ideas on what I am doing wrong?


Here you are calling

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

With copyData set to true, can you be sure that Mat::release() is being called? If your refcount never returns to 0, your destructor never fires leaving you with lots of copies of the image data in ram.


Knowing the difference between a data provider and a data reference is key; destroying a reference or reassigning the reference to another object does not affect the data stored in the provider, except where the developer of the framework makes it so (such as Apple). OpenCV does not associate a CGImageRef with any of its objects that store image data, per se; therefore, it requires you to destroy the CGImageRef (i.e., dereference its image data object) and then release and deallocate the OpenCV object that stores the image data (cv::Mat).

To ensure you've released the data stored in, say, cv::Mat, just cv::Mat.empty() after releasing and deallocating the object:

Whereas...

if (mat.empty())...

...returns FALSE, this...

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

...will...

if (mat.empty())...

...return TRUE.

0

精彩评论

暂无评论...
验证码 换一张
取 消