iOS + OpenCV - утечка памяти на мат - PullRequest
0 голосов
/ 14 мая 2011

Я использую OpenCV 2.2, скомпилированный и собранный из исходного кода для iOS. Я использовал это сообщение в блоге в качестве руководства.

Я поиграл с тем, чтобы заставить работать некоторые вещи, такие как создание изображений в градациях серого, размывание их и даже запуск 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 ]

2 голосов
/ 14 мая 2011

Здесь вы звоните

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

Если для copyData установлено значение true, можете ли вы быть уверены, что вызывается Mat::release()?Если ваш refcount никогда не возвращается к 0, ваш деструктор никогда не срабатывает, оставляя вас с большим количеством копий данных изображения в оперативной памяти.

0 голосов
/ 10 мая 2017

Знание разницы между поставщиком данных и ссылкой на данные является ключевым; Уничтожение ссылки или переназначение ссылки на другой объект не влияет на данные, хранящиеся в поставщике, за исключением случаев, когда разработчик платформы делает это (например, Apple). OpenCV не связывает CGImageRef ни с одним из его объектов, которые хранят данные изображения, как таковые; поэтому требуется уничтожить CGImageRef (то есть разыменовать его объект данных изображения), а затем освободить и освободить объект OpenCV, в котором хранятся данные изображения (cv :: Mat).

Чтобы убедиться, что вы освободили данные, хранящиеся, скажем, в cv :: Mat, просто cv :: Mat.empty () после освобождения и освобождения объекта:

Принимая во внимание ...

if (mat.empty())...

... возвращает FALSE, это ...

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

... будет ...

if (mat.empty())...

... вернуть TRUE.

...