Face detection в iOS 5 SDK

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

Но все нашлась парочка вкусностей в новом SDK. Первым бросился в глаза метод для UIViewController viewWillUnload, который так был нужен несколько месяцев назад.
Весь перечень нововведений для iOS 5 смотреть здесь.
В списке добаленых фреймворков вызывает интерес CoreImage и в частности CIDetector.h.

Класс CIDetector создан в помощ поиска и определения лиц на изображении, что мы сейчас попробуем вкратце проделать.


Используем XCode 4.2 with iOS 5 SDK.

Создаем проект

Очень рекомендую отключать «Use Automatic Reference Counting».

Подключаем в проект framework CoreImage

image

Создаем UIViewController

#import <UIKit/UIKit.h>
 
@interface RootViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
    IBOutlet UIImageView *imageView;
    IBOutlet UILabel *label;
    CIDetector *detector;
}
 
@end


Загружаем картинку используя UIImagePickerController

- (IBAction)onImport:(id)sender
{
    UIImagePickerController *vc = [[UIImagePickerController alloc] init];
    vc.delegate = self;
    vc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    [self presentModalViewController:vc animated:YES];
    [vc release];
}


Свой девайс я не апгрейдил до iOS 5, потому все действия будут просходить на симуляторе с импортом из галереи, а не камеры.

Определяем лица на картинке

- (IBAction)onRecognize:(id)sender
{
    detector = [CIDetector detectorOfType:CIDetectorTypeFace context:nil options:[NSDictionary dictionaryWithObject:CIDetectorAccuracyHigh forKey:CIDetectorAccuracy]];
 
    NSDate *date = [NSDate date];
 
    NSArray *features = [detector featuresInImage:
                            [[[CIImage alloc] initWithCGImage:imageView.image.CGImage] autorelease]
                        ];
 
    NSTimeInterval ti = fabs([date timeIntervalSinceNow]);
 
    label.text = [NSString stringWithFormat:@"Time: %0.3f\nFaces: %i",ti,[features count]];
 
    UIGraphicsBeginImageContext(imageView.image.size);
 
    CGContextRef ctx = UIGraphicsGetCurrentContext();
 
    CGContextDrawImage(ctx, CGRectMake(00, imageView.image.size.width, imageView.image.size.height), imageView.image.CGImage);
 
 
    for (CIFeature *feature in features) 
    {
        CGRect r = feature.bounds;
 
        CGContextSetStrokeColor(ctx, CGColorGetComponents([UIColor yellowColor].CGColor));
        CGContextSetLineWidth(ctx, 1.0f);
 
        CGContextBeginPath(ctx);
        CGContextAddRect(ctx, r);
        CGContextClosePath(ctx)
        CGContextStrokePath(ctx);
 
    }
    imageView.image = [UIImage imageWithCGImage:UIGraphicsGetImageFromCurrentImageContext().CGImage scale:1.0f orientation:UIImageOrientationDownMirrored];
    UIGraphicsEndImageContext();
 
}
 


Результат

В документации экземпляр класса CIFeature дает информацию только о рамке лица и о своем типе, но можна надеяться, что когда в Apple полностью передерут OpenCV, то можно будет ждать обновлений класса (IMHO).





EDIT: Исправлен лик в методе onImport:

Комментарии 11

    +2
    Возвращает не только область лица, но и положения глаз и рта, смотрите CIFaceFeature. Интересная особенность, что у меня на втором айпаде ни разу не смогло распознать снимок сделанный его же камерой, а если подсунуть ему качественную фотку, где одно лицо клонированно несколько раз — находит лишь одно.
      +1
      Вроде как было известно еще летом, но за практический пример все равно спасибо :-) И еще, в порядке оффтопа, не подскажите, почему вы рекомендуете отключать ARC?
        +1
        Для примера:
        NSObject *obj = [[Nsobject alloc] init];
        [someOtherObject performSelector:@selector(someSelector:) withObject:obj afterDelay:2.0f];
        [obj release];

        По истечении 2 секунд екзмепляр obj уже будет мертв. Потому его надо освобождать вручную в методе someSelector: после использования или каким-то иным путем. А с autoReferenceCounting екземпляр может не дожить до того времени.
        ИМХО.
          +2
          Тут таки все будет работать, obj будет заритейнен.
            +3
            Следует сначала почитать поподроднее про ARC. ИМХО. Все будет работать с ARC!
            В функции onImport лик.
              0
              Исправил.
          +1
          Лучше бы сделали API для TTS на встроенном голосовом движке. Пригодилось бы нереально.
            0
            В следующе версии сделают :/
            SDK 5 доступен давно, а голосовой движок до последнего держался в тайне.
            0
            Пробовал использовать данную технологию в разрабатываемом приложении.
            Результаты, мягко говоря, отвратительные.
            Очень часто лицо определялось не верно. К примеру на одной фотографии рамку вывело в районе пересечения ног.
            Самое плохое в этом всем, что CIFeature возвращает только прямоугольную область.
            Было бы здорово, если бы вместе с этим rect'ом возвращалось и какое-то вероятностное значение (распознано с вероятностью 20%). Хотя я и не уверен, что такое технически возможно.
              +1
              Очень рекомендую отключать «Use Automatic Reference Counting».

              Что было хорошо для наших отцов — хорошо и для нас.

                0
                Приложите ваш исходник этого проекта в статье, все скажут спасибо!

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое