2

我一直在努力将 CIDetector(面部检测)结果转换为相对于显示图像的 UIImageView 的坐标,以便我可以使用 CGPaths 绘制坐标。

我已经查看了这里的所有问题以及我能找到的所有教程,其中大多数使用在 UIImageView 中显示时未缩放的小图像(示例)。我遇到的问题是使用aspectFit在 UIImageView 中显示时使用缩放的大图像并确定正确的比例 + 平移值。

在使用不同尺寸/纵横比的图像进行测试时,我得到的结果不一致,所以我认为我的例程存在缺陷。我已经为此苦苦挣扎了一段时间,所以如果有人有一些提示或可以对我做错的地方进行 X 光检查,那将是一个很大的帮助。

我在做什么:

  • 获取人脸坐标
  • 使用frameForImage下面的例程(在 SO 上找到)来获取 UIImageView 图像的比例和边界
  • 为缩放 + 平移创建变换
  • 对 CIDetector 结果应用变换

// 我确定变换值的例程

NSDictionary* data = [self frameForImage:self.imageView.image inImageViewAspectFit:self.imageView];

CGRect scaledImageBounds = CGRectFromString([data objectForKey:@"bounds"]);
float scale = [[data objectForKey:@"scale"] floatValue];

CGAffineTransform transform = CGAffineTransformMakeScale(scale, -scale);

transform = CGAffineTransformTranslate(transform, 
          scaledImageBounds.origin.x / scale, 
          -(scaledImageBounds.origin.y / scale + scaledImageBounds.size.height / scale));

CIDetector 结果转换使用:

     mouthPosition = CGPointApplyAffineTransform(mouthPosition, transform);

// 错误结果示例:比例似乎不正确

在此处输入图像描述

// 下面的例程在 SO 上找到,用于确定使用“aspectFit”在 UIImageView 中缩放的图像的界限

-(NSDictionary*)frameForImage:(UIImage*)image inImageViewAspectFit:(UIImageView*)myImageView
{
    float imageRatio = image.size.width / image.size.height;
    float viewRatio = myImageView.frame.size.width / myImageView.frame.size.height;

    float scale;
    CGRect boundingRect;
    if(imageRatio < viewRatio)
    {
        scale = myImageView.frame.size.height / image.size.height;
        float width = scale * image.size.width;
        float topLeftX = (myImageView.frame.size.width - width) * 0.5;
        boundingRect = CGRectMake(topLeftX, 0, width, myImageView.frame.size.height);
    }
    else
    {
        scale = myImageView.frame.size.width / image.size.width;
        float height = scale * image.size.height;
        float topLeftY = (myImageView.frame.size.height - height) * 0.5;
        boundingRect = CGRectMake(0, topLeftY, myImageView.frame.size.width, height);
    }

    NSDictionary * data = [NSDictionary dictionaryWithObjectsAndKeys:
                           [NSNumber numberWithFloat:scale], @"scale",
                           NSStringFromCGRect(boundingRect), @"bounds",
                           nil];

    return data;
}
4

2 回答 2

4

我完全理解你想要做什么,但让我为你提供一种不同的方式来实现你想要的。

  • 你有一个过大的图像
  • 你知道imageView的大小
  • 向图像询问其 CGImage
  • 确定“比例”因子,即 imageView 宽度除以图像宽度
  • 将此值和您的图像高度相乘,然后从 imageViewHeight 中减去结果,以获得 imageView 中的“空”高度,让我们称之为“fillHeight”
  • 将“fillHeight”除以 2 并四舍五入得到下面使用的“偏移”值
  • 使用 UIGraphicsBeginImageContextWithOptions(imageView.size, NO, 0) 提供的上下文,绘制你想要的任何颜色的背景,然后绘制你的 CGImage

    CGContextDrawImage (context, CGRectMake(0, offset, imageView.size.width, rintf(image.size.height*scale)), [image CGImage]);

  • 使用以下方法获取此新图像:

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); 返回图像;

  • 设置图像:imageView.image = image;

现在您可以准确地映射回您的图像,因为您知道确切的缩放比例和偏移量。

于 2012-08-30T17:47:55.447 回答
0

这可能是您正在寻找的简单答案。如果你的 x 和 y 坐标是倒置的,你可以自己镜像它们。在下面的片段中,我循环遍历我返回的功能并需要反转 y 坐标,如果它是前置摄像头,则需要反转 x 坐标:

    for (CIFaceFeature *f in features) {
        float newy = -f.bounds.origin.y + self.frame.size.height - f.bounds.size.height;

        float newx = f.bounds.origin.x;
        if( isMirrored ) {
            newx = -f.bounds.origin.x + self.frame.size.width - f.bounds.size.width;
        }
        [[soups objectAtIndex:rnd] drawInRect:CGRectMake(newx, newy, f.bounds.size.width, f.bounds.size.height)];
    }
于 2016-12-15T23:17:02.500 回答