【问题标题】:Transforming CGPoint results returned from CIFaceFeature转换从 CIFaceFeature 返回的 CGPoint 结果
【发布时间】:2013-01-17 02:24:45
【问题描述】:

我试图弄清楚如何转换从CIFaceFeature 返回的CGPoint 结果,以便在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,以便通过覆盖 UIImageView 的 CAShape 层来绘制它。

我正在做的(...或认为我在做...)是将左眼 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);

来自这篇文章:https://stackoverflow.com/a/14491293/840992,我需要根据 imageOrientation 进行旋转

方向

Apple/UIImage.imageOrientation Jpeg/文件 kCGImagePropertyOrientation

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

消息由 skinnyTOD 于 2013 年 2 月 1 日下午 4:09 编辑

【问题讨论】:

    标签: ios uiimage face-detection uiimageorientation cifacefeature


    【解决方案1】:

    我需要找出完全相同的问题。 Apple 示例“SquareCam”直接在视频输出上运行,但我需要仍然 UIImage 的结果。因此,我使用一些转换方法扩展了 CIFaceFeature 类,以获取关于 UIImage 及其 UIImageView(或 UIView 的 CALayer)的正确点位置和边界。完整的实现发布在这里: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;
    

    (需要注意的另一件事是在从 UIImage 方向提取面部特征时指定正确的 EXIF 方向。相当混乱......这是我所做的:

    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]}];
    

    )

    【讨论】:

      【解决方案2】:

      我认为您需要将找到的人脸坐标围绕图像的水平中心轴翻转

      你能试试这个转换吗:

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

      这种变换只有在我们在寻找人脸之前将 image.imageOrientation 设置为 0 时才有效。

      【讨论】:

      • 不,不起作用。坐标需要旋转(我相信)。我添加了一些图片来展示我认为的任务。
      • @skinnyTOD,对不起,我弄错了——这种变换只有在我们标准化(将方向设置为 imageOrientation 0)时才有效。我会尽快发布更新
      猜你喜欢
      • 2014-09-11
      • 2023-03-16
      • 2017-07-04
      • 2014-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多