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