Преобразование результатов CGPoint, возвращаемых из CIFaceFeature

Я пытаюсь выяснить, как преобразовать CGPoint результаты возвращены из CIFaceFeature чтобы нарисовать с ними в CALayer, Ранее я нормализовал свое изображение, чтобы оно имело угол поворота 0, чтобы упростить задачу, но это вызывает проблемы с изображениями, снятыми устройством, работающим в альбомном режиме.

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

исходное изображение с камеры

Согласно документации для CIDetectorfeaturesInImage:options: метод

A dictionary that specifies the orientation of the image. The detection is 
adjusted to account for the image orientation but the coordinates in the 
returned feature objects are based on those of the image.

изображение, как показано в UIImageView

В приведенном ниже коде я пытаюсь повернуть CGPoint, чтобы нарисовать его через слой CAShape, который перекрывает UIImageView.

То, что я делаю (... или думаю, что я делаю...), переводит CGPoint для левого глаза в центр обзора, поворачивая его на 90 градусов, а затем переводя точку назад туда, где она была. Это не правильно, но я не знаю, где я иду не так. Это мой подход не так или как я его реализую?

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)

- leftEyePosition - это CGPoint

CGAffineTransform  transRot = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(90));

float x = self.center.x;
float y = self.center.y;
CGAffineTransform tCenter = CGAffineTransformMakeTranslation(-x, -y);
CGAffineTransform tOffset = CGAffineTransformMakeTranslation(x, y);

leftEyePosition = CGPointApplyAffineTransform(leftEyePosition, tCenter);
leftEyePosition = CGPointApplyAffineTransform(leftEyePosition, transRot);
leftEyePosition = CGPointApplyAffineTransform(leftEyePosition, tOffset);

Из этого поста: /questions/41336834/zastavte-uiimagepickercontroller-sfotografirovat-v-portretnoj-orientatsii-razmerah-ios/41336836#41336836, мне нужно сделать повороты на основе imageOrientation

ориентация

Apple/UIImage.imageOrientation Jpeg/File kCGImagePropertyOrientation

UIImageOrientationUp    = 0  =  Landscape left  = 1
UIImageOrientationDown  = 1  =  Landscape right = 3
UIImageOrientationLeft  = 2  =  Portrait  down  = 8
UIImageOrientationRight = 3  =  Portrait  up    = 6

Сообщение отредактировал skinnyTOD - 1.02.13 в 16:09

2 ответа

Мне нужно выяснить точно такую ​​же проблему. Образец Apple "SquareCam" работает напрямую с видеовыходом, но мне нужны результаты еще от UIImage. Поэтому я расширил класс CIFaceFeature некоторыми методами преобразования, чтобы получить правильные местоположения и границы точек относительно UIImage и его UIImageView (или CALayer UIView). Полная реализация размещена здесь: https://gist.github.com/laoyang/5747004. Вы можете использовать напрямую.

Вот самое основное преобразование для точки из CIFaceFeature, возвращенный CGPoint конвертируется на основе ориентации изображения:

- (CGPoint) pointForImage:(UIImage*) image fromPoint:(CGPoint) originalPoint {

    CGFloat imageWidth = image.size.width;
    CGFloat imageHeight = image.size.height;

    CGPoint convertedPoint;

    switch (image.imageOrientation) {
        case UIImageOrientationUp:
            convertedPoint.x = originalPoint.x;
            convertedPoint.y = imageHeight - originalPoint.y;
            break;
        case UIImageOrientationDown:
            convertedPoint.x = imageWidth - originalPoint.x;
            convertedPoint.y = originalPoint.y;
            break;
        case UIImageOrientationLeft:
            convertedPoint.x = imageWidth - originalPoint.y;
            convertedPoint.y = imageHeight - originalPoint.x;
            break;
        case UIImageOrientationRight:
            convertedPoint.x = originalPoint.y;
            convertedPoint.y = originalPoint.x;
            break;
        case UIImageOrientationUpMirrored:
            convertedPoint.x = imageWidth - originalPoint.x;
            convertedPoint.y = imageHeight - originalPoint.y;
            break;
        case UIImageOrientationDownMirrored:
            convertedPoint.x = originalPoint.x;
            convertedPoint.y = originalPoint.y;
            break;
        case UIImageOrientationLeftMirrored:
            convertedPoint.x = imageWidth - originalPoint.y;
            convertedPoint.y = originalPoint.x;
            break;
        case UIImageOrientationRightMirrored:
            convertedPoint.x = originalPoint.y;
            convertedPoint.y = imageHeight - originalPoint.x;
            break;
        default:
            break;
    }
    return convertedPoint;
}

И вот методы категории, основанные на вышеупомянутом преобразовании:

// Get converted features with respect to the imageOrientation property
- (CGPoint) leftEyePositionForImage:(UIImage *)image;
- (CGPoint) rightEyePositionForImage:(UIImage *)image;
- (CGPoint) mouthPositionForImage:(UIImage *)image;
- (CGRect) boundsForImage:(UIImage *)image;

// Get normalized features (0-1) with respect to the imageOrientation property
- (CGPoint) normalizedLeftEyePositionForImage:(UIImage *)image;
- (CGPoint) normalizedRightEyePositionForImage:(UIImage *)image;
- (CGPoint) normalizedMouthPositionForImage:(UIImage *)image;
- (CGRect) normalizedBoundsForImage:(UIImage *)image;

// Get feature location inside of a given UIView size with respect to the imageOrientation property
- (CGPoint) leftEyePositionForImage:(UIImage *)image inView:(CGSize)viewSize;
- (CGPoint) rightEyePositionForImage:(UIImage *)image inView:(CGSize)viewSize;
- (CGPoint) mouthPositionForImage:(UIImage *)image inView:(CGSize)viewSize;
- (CGRect) boundsForImage:(UIImage *)image inView:(CGSize)viewSize;

(Еще одна вещь, на которую следует обратить внимание, это указание правильной ориентации EXIF ​​при извлечении элементов лица из ориентации UIImage. Довольно запутанно... вот что я сделал:

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 };
CIDetector *faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace context:nil options:detectorOptions];

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

)

Я думаю, что вам нужно, чтобы перевернуть найденные лица координаты вокруг горизонтальной центральной оси изображения

Можете ли вы попробовать с этим преобразованием:

CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, 0.0f, image.size.height);
transform = CGAffineTransformScale(transform, 1.0f, -1.0f);
[path applyTransform:transform];

Это преобразование работает только в том случае, если мы установили для image.imageOrientation значение 0 до нахождения лиц.

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