CIDetector не освобождает память

Я использую CIDetector несколько раз следующим образом:

    -(NSArray *)detect:(UIImage *)inimage
    {
        UIImage *inputimage = inimage;
        UIImageOrientation exifOrientation = inimage.imageOrientation;
        NSNumber *orientation = [NSNumber numberWithInt:exifOrientation];

        NSDictionary *imageOptions = [NSDictionary dictionaryWithObject:orientation forKey:CIDetectorImageOrientation];
        CIImage* ciimage = [CIImage imageWithCGImage:inputimage.CGImage options:imageOptions];


        NSDictionary *detectorOptions = [NSDictionary dictionaryWithObject:orientation forKey:CIDetectorImageOrientation];

        NSArray* features = [self.detector featuresInImage:ciimage options:detectorOptions];

        if (features.count == 0)
        {
            PXLog(@"no face found");
        }

        ciimage = nil;
        NSMutableArray *returnArray = [NSMutableArray new];


        for(CIFaceFeature *feature in features)
        {
            CGRect rect = feature.bounds;
            CGRect r = CGRectMake(rect.origin.x,inputimage.size.height - rect.origin.y - rect.size.height,rect.size.width,rect.size.height);

            FaceFeatures * ff = [[FaceFeatures new] initWithLeftEye:CGPointMake(feature.leftEyePosition.x, inputimage.size.height - feature.leftEyePosition.y )
                                                           rightEye:CGPointMake(feature.rightEyePosition.x, inputimage.size.height - feature.rightEyePosition.y )
                                                              mouth:CGPointMake(feature.mouthPosition.x, inputimage.size.height - feature.mouthPosition.y )];

            Face *ob = [[Face new] initFaceInRect:r withFaceFeatures:ff] ;


            [returnArray addObject:ob];
        }

        features = nil;
        return returnArray;
    }

-(CIContext*) context{
    if(!_context){
        _context = [CIContext contextWithOptions:nil];
    }
    return _context;
}
-(CIDetector *)detector
{
    if (!_detector)
    {
        // 1 for high 0 for low
#warning not checking for fast/slow detection operation
        NSString *str = @"fast";//[SettingsFunctions retrieveFromUserDefaults:@"face_detection_accuracy"];


        if ([str isEqualToString:@"slow"])
        {
            //DDLogInfo(@"faceDetection: -I- Setting accuracy to high");
            _detector = [CIDetector detectorOfType:CIDetectorTypeFace context:nil
                                           options:[NSDictionary dictionaryWithObject:CIDetectorAccuracyHigh forKey:CIDetectorAccuracy]];
        } else {
            //DDLogInfo(@"faceDetection: -I- Setting accuracy to low");
            _detector = [CIDetector detectorOfType:CIDetectorTypeFace context:nil
                                           options:[NSDictionary dictionaryWithObject:CIDetectorAccuracyLow forKey:CIDetectorAccuracy]];
        }

    }
    return _detector;
}

но после различных проблем с памятью и, согласно Instruments, похоже, что NSArray* features = [self.detector featuresInImage:ciimage options:detectorOptions]; не выпускается

Есть ли утечка памяти в моем коде?

введите здесь описание изображения

введите здесь описание изображения


person Avner Barr    schedule 03.10.2013    source источник
comment
Вы вызываете функцию detect() из фонового потока, например, из функции captureOutput() или чего-то подобного?   -  person FractalDoctor    schedule 07.10.2013
comment
Попробуйте окружить детектор блоком @autorelease. У нас были проблемы с тем, что память не освобождалась автоматически в потоках, отличных от пользовательского интерфейса, и это решило многие из них для нас.   -  person FractalDoctor    schedule 08.10.2013
comment
это работает и для ARC?   -  person Avner Barr    schedule 09.10.2013
comment
какую часть вы также обернули блоком @autorelease?   -  person Avner Barr    schedule 09.10.2013


Ответы (2)


Я столкнулся с той же проблемой, и это похоже на ошибку (или, может быть, на дизайн, для целей кэширования) с повторным использованием CIDetector.

Я смог обойти это, не используя повторно CIDetector, вместо этого создавая экземпляр по мере необходимости, а затем выпуская его (или, в терминах ARC, просто не сохраняя ссылку), когда обнаружение завершено. Это требует определенных затрат, но если вы выполняете обнаружение в фоновом потоке, как вы сказали, эти затраты, вероятно, того стоят по сравнению с неограниченным ростом памяти.

Возможно, лучшим решением было бы, если вы обнаруживаете несколько изображений подряд, создать один детектор, использовать его для всех (или, может быть, если рост слишком велик, выпускать и создавать новый каждые N изображений. Вы будете нужно поэкспериментировать, чтобы увидеть, каким должно быть N).

Я отправил сообщение об ошибке Radar в Apple: http://openradar.appspot.com/radar?id=6645353252126720

person Kevin    schedule 13.02.2014

Я исправил эту проблему, вы должны использовать @autorelease, где вы используете метод обнаружения, например, в swift

            autoreleasepool(invoking: { 
                let result = self.detect(image: image)
                // do other things
            })
person cleexiang    schedule 29.11.2016
comment
после игры с ним в течение нескольких дней (‹angryface›) это, вероятно, лучший и единственный вариант, пока Apple не исправит это (smh), но я хотел бы указать кое-что: cidetector должен быть внутри функции обнаружения - Apple говорит что лучше всего создать один экземпляр и использовать его повторно — быки *** и асинхронные вызовы также работают. В моем случае память без autoreleasepool уходит от 50 до мин. 140мб так и остается, с авторелизпулом от 50 до 75-79мб сколько бы ни было фото - person Kam Wo; 27.04.2017