Преобразование результатов CGPoint, возвращаемых из CIFaceFeature
Я пытаюсь выяснить, как преобразовать CGPoint
результаты возвращены из CIFaceFeature
чтобы нарисовать с ними в CALayer
, Ранее я нормализовал свое изображение, чтобы оно имело угол поворота 0, чтобы упростить задачу, но это вызывает проблемы с изображениями, снятыми устройством, работающим в альбомном режиме.
Я работал над этим какое-то время безуспешно, и я не уверен, что мое понимание задачи неверно, или мой подход неверен, или и то, и другое. Вот что я считаю правильным:
Согласно документации для CIDetector
featuresInImage: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.
В приведенном ниже коде я пытаюсь повернуть 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 до нахождения лиц.