CIDetector и UIImagePickerController

Я пытаюсь реализовать встроенный в iOS 5 API распознавания лиц. Я использую экземпляр UIImagePickerController чтобы позволить пользователю сделать фотографию, а затем я пытаюсь использовать CIDetector обнаружить черты лица. К несчастью, featuresInImage всегда возвращает массив размером 0.

Вот код:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage* picture = [info objectForKey:UIImagePickerControllerOriginalImage];

NSNumber *orientation = [NSNumber numberWithInt:
                         [picture imageOrientation]];
NSDictionary *imageOptions =
[NSDictionary dictionaryWithObject:orientation
                            forKey:CIDetectorImageOrientation];

CIImage *ciimage = [CIImage imageWithCGImage:[picture CGImage]
                                     options:imageOptions];


NSDictionary *detectorOptions =
[NSDictionary dictionaryWithObject:CIDetectorAccuracyLow
                            forKey:CIDetectorAccuracy];
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace
                                          context:nil
                                          options:detectorOptions];

NSArray *features = [detector featuresInImage:ciimage];
NSLog(@"Feature size: %d", features.count);
}

Это всегда возвращает 0 функций. Однако, если я использую UIImage из файла, встроенного в приложение, обнаружение лица работает отлично.

Я использую код из этой статьи Pragmatic Bookshelf.

Что бы это ни стоило, я думаю, что ошибка в том, что я конвертирую UIImage с камеры в CIImage, но это может быть что угодно.

4 ответа

Решение

@tonyc Ваше решение работает только для конкретного случая, который называется "UIImageOrientationRight". Проблема заключается в разнице между ориентацией в UIImage и CIDetectorImageOrientation. Из iOS документов:

CIDetectorImageOrientation

Клавиша, используемая для указания ориентации отображения изображения, функции которого вы хотите обнаружить. Этот ключ является объектом NSNumber с тем же значением, которое определено спецификациями TIFF и EXIF; значения могут находиться в диапазоне от 1 до 8. Значение указывает, где находится источник (0,0) изображения. Если нет, значение по умолчанию равно 1, что означает, что источник изображения вверху слева. Для получения дополнительной информации о происхождении изображения, заданном каждым значением, см. KCGImagePropertyOrientation.

Доступный в iOS 5.0 и позже.

Объявлено в CIDetector.h.

Итак, проблема сейчас заключается в преобразовании между этими двумя ориентациями, вот что я сделал в своем коде, я протестировал, и он работал для всех ориентаций:

int exifOrientation;
switch (self.image.imageOrientation) {
    case UIImageOrientationUp:
        exifOrientation = 1;
        break;
    case UIImageOrientationDown:
        exifOrientation = 3;
        break;
    case UIImageOrientationLeft:
        exifOrientation = 8;
        break;
    case UIImageOrientationRight:
        exifOrientation = 6;
        break;
    case UIImageOrientationUpMirrored:
        exifOrientation = 2;
        break;
    case UIImageOrientationDownMirrored:
        exifOrientation = 4;
        break;
    case UIImageOrientationLeftMirrored:
        exifOrientation = 5;
        break;
    case UIImageOrientationRightMirrored:
        exifOrientation = 7;
        break;
    default:
        break;
}

NSDictionary *detectorOptions = @{ CIDetectorAccuracy : CIDetectorAccuracyHigh }; // TODO: read doc for more tuneups
CIDetector *faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace context:nil options:detectorOptions];

NSArray *features = [faceDetector featuresInImage:[CIImage imageWithCGImage:self.image.CGImage]
                                          options:@{CIDetectorImageOrientation:[NSNumber numberWithInt:exifOrientation]}];

Конечно же, потратив день на изучение этого вопроса и будучи в тупике, я нашел решение через час после публикации этого сообщения.

В конце концов я заметил, что распознавание лиц работает в альбомной, а не в портретной ориентации.

Оказывается, мне были нужны эти опции:

NSDictionary *imageOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:6]
                                                         forKey:CIDetectorImageOrientation];
NSArray *features = [detector featuresInImage:ciimage options:imageOptions];

Версия Swift 3

var exifOrientation : Int
switch (inputImage.imageOrientation)
{
case UIImageOrientation.up:
    exifOrientation = 1;
case UIImageOrientation.down:
    exifOrientation = 3;
case UIImageOrientation.left:
    exifOrientation = 8;
case UIImageOrientation.right:
    exifOrientation = 6;
case UIImageOrientation.upMirrored:
    exifOrientation = 2;
case UIImageOrientation.downMirrored:
    exifOrientation = 4;
case UIImageOrientation.leftMirrored:
    exifOrientation = 5;
case UIImageOrientation.rightMirrored:
    exifOrientation = 7;
}

let ciImage = CIImage(cgImage: inputImage.cgImage!)
let options = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: options)!
let faces = faceDetector.features(in: ciImage, options:["CIDetectorImageOrientation":exifOrientation])

У меня была похожая проблема - детектор лица работал в ориентациях, которые не соответствовали свойству ориентации изображения. Ориентация детектора лица iOS и настройка ориентации CIImage

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

Я использовал этот код:

http://blog.logichigh.com/2008/06/05/uiimage-fix/

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

Другие вопросы по тегам