将iOS CIDetector(面部检测)坐标从aspectRatioThumbnail缩放到fullScreenImage

时间:2013-01-18 18:12:32

标签: ios core-image

(忽略下面的大量代码。只是在那里供参考/资源以防其他人想要一起玩)

CoreImage中的面部检测程序自然在较小的图像上工作得更快,所以我一直在调查使用aspectRatioThumbnail生成面部数据,并计划将其放大以绘制fullScreenImage表示。我这样做的原因是我可能有20到30张图像要处理,所以我想减少任务时间。

这可能是一个简单的数学问题,但我在尝试将一个图像中的一个点映射到另一个图像时得到的结果不准确。

90 x 120图像 - CGPoint(64,50)rightEyePosition

480 x 640 image - CGPoint(331,303)rightEyePosition

(480/90)* 64 = 341.333 - 但它应该是331,是吗?我做错了吗?

更新 - 稍后再进行一些测试。因此,由于图像分辨率不同,面部数据结果可能会略有不同?这是有道理的:数据结果之间没有可扩展的关系。我仍然想知道:上面我的缩放数学错误了吗?


Using CIDetectorAccuracyHigh     
useImageOptions:     0
------------ aspectRatioThumbnail   90.000000  120.000000 orientation: 0
2013-01-18 12:33:30.378 SeqMeTestBed[9705:907] aspectRatioThumbnail: features {
    bounds = "{{23, 16}, {56, 56}}";
    hasLeftEyePosition = 1;
    hasMouthPosition = 1;
    hasRightEyePosition = 1;
    leftEyePosition = "{43, 59}";
    mouthPosition = "{51, 31}";
    rightEyePosition = "{64, 50}";
}
------------ fullScreenImage   480.000000  640.000000 orientation: 0
2013-01-18 12:33:33.029 SeqMeTestBed[9705:907] fullScreenImage: features {
    bounds = "{{135, 81}, {298, 298}}";
    hasLeftEyePosition = 1;
    hasMouthPosition = 1;
    hasRightEyePosition = 1;
    leftEyePosition = "{228, 321}";
    mouthPosition = "{290, 156}";
    rightEyePosition = "{331, 303}";
}
------------ fullResolutionImage   640.000000  480.000000 orientation: 0
2013-01-18 12:33:35.745 SeqMeTestBed[9705:907] fullResolutionImage: features {
    bounds = "{{195, 105}, {366, 366}}";
    hasLeftEyePosition = 1;
    hasMouthPosition = 1;
    hasRightEyePosition = 1;
    leftEyePosition = "{356, 411}";
    mouthPosition = "{350, 201}";
    rightEyePosition = "{455, 400}";

//使用的代码 //

- (void)detectFacialFeatures
{

    NSDictionary *detectorOptions = [[NSDictionary alloc] initWithObjectsAndKeys:CIDetectorAccuracyHigh, CIDetectorAccuracy, nil];
    CIDetector* faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace context:nil options:detectorOptions];


    NSDictionary *imageOptions = nil;

    UIImage *tmpImage;
    NSNumber* orientation; 
    CIImage *ciImage;
    NSArray *array;
    NSMutableDictionary* featuresDictionary;

    Boolean useImageOptions = NO;

    printf("Using CIDetectorAccuracyHigh     \n");
    printf("useImageOptions:     %d\n", useImageOptions);

    //-----------------aspectRatioThumbnail
    tmpImage = [[UIImage alloc] initWithCGImage:self.asset.aspectRatioThumbnail];
    orientation = [NSNumber numberWithInt:tmpImage.imageOrientation];

    printf("------------ aspectRatioThumbnail   %f  %f orientation: %d\n", tmpImage.size.width, tmpImage.size.height, [orientation integerValue]);
    ciImage = [CIImage imageWithCGImage:tmpImage.CGImage];
    if (ciImage == nil) printf("----------!!!aspectRatioThumbnail: ciImage is nil    \n");

    imageOptions = [NSDictionary dictionaryWithObjectsAndKeys:orientation, CIDetectorImageOrientation,
                    CIDetectorAccuracyHigh, CIDetectorAccuracy, nil];

    if (useImageOptions) {
        array = [faceDetector featuresInImage:ciImage];
    } else {
        array = [faceDetector featuresInImage:ciImage options:imageOptions];
    }

    featuresDictionary = [self convertFeaturesToDictionary:array];
    NSLog(@"aspectRatioThumbnail: features %@", featuresDictionary);

   //-----------------fullScreenImage
    tmpImage = [[UIImage alloc] initWithCGImage:self.asset.defaultRepresentation.fullScreenImage];
    orientation = [NSNumber numberWithInt:tmpImage.imageOrientation];
    printf("------------ fullScreenImage   %f  %f orientation: %d\n", tmpImage.size.width, tmpImage.size.height, [orientation integerValue]);

    ciImage = [CIImage imageWithCGImage:tmpImage.CGImage];
    if (ciImage == nil) printf("----------!!!fullScreenImage: ciImage is nil    \n");

    imageOptions = [NSDictionary dictionaryWithObjectsAndKeys:orientation, CIDetectorImageOrientation,
                    CIDetectorAccuracyHigh, CIDetectorAccuracy, nil];

    if (useImageOptions) {
        array = [faceDetector featuresInImage:ciImage];
    } else {
        array = [faceDetector featuresInImage:ciImage options:imageOptions];
    }

    featuresDictionary = [self convertFeaturesToDictionary:array];
    NSLog(@"fullScreenImage: features %@", featuresDictionary);

    //-----------------fullResolutionImage
    tmpImage = [[UIImage alloc] initWithCGImage:self.asset.defaultRepresentation.fullResolutionImage];
    orientation = [NSNumber numberWithInt:tmpImage.imageOrientation];

    printf("------------ fullResolutionImage   %f  %f orientation: %d\n", tmpImage.size.width, tmpImage.size.height, [orientation integerValue]);

    ciImage = [CIImage imageWithCGImage:tmpImage.CGImage];
    if (ciImage == nil) printf("----------!!!fullResolutionImage: ciImage is nil    \n");

    imageOptions = [NSDictionary dictionaryWithObjectsAndKeys:orientation, CIDetectorImageOrientation,
                    CIDetectorAccuracyHigh, CIDetectorAccuracy, nil];

    if (useImageOptions) {
        array = [faceDetector featuresInImage:ciImage];
    } else {
        array = [faceDetector featuresInImage:ciImage options:imageOptions];
    }

    featuresDictionary = [self convertFeaturesToDictionary:array];
    NSLog(@"fullResolutionImage: features %@", featuresDictionary);

}







- (NSMutableDictionary*)convertFeaturesToDictionary:(NSArray*)foundFaces
{
    NSMutableDictionary * faceFeatures = [[NSMutableDictionary alloc] init];

    if (foundFaces.count) {

        CIFaceFeature *face = [foundFaces objectAtIndex:0];
        NSNumber* hasMouthPosition = [NSNumber numberWithBool:face.hasMouthPosition];
        NSNumber* hasLeftEyePosition = [NSNumber numberWithBool:face.hasLeftEyePosition];
        NSNumber* hasRightEyePosition = [NSNumber numberWithBool:face.hasRightEyePosition];

        [faceFeatures setValue:hasMouthPosition forKey:@"hasMouthPosition"];
        [faceFeatures setValue:hasLeftEyePosition forKey:@"hasLeftEyePosition"];
        [faceFeatures setValue:hasRightEyePosition forKey:@"hasRightEyePosition"];

        NSString * boundRect = NSStringFromCGRect(face.bounds);
       // NSLog(@"------------boundRect %@", boundRect);
        [faceFeatures setValue:boundRect forKey:@"bounds"];

        if (hasMouthPosition){
            NSString * mouthPosition = NSStringFromCGPoint(face.mouthPosition);
            [faceFeatures setValue:mouthPosition forKey:@"mouthPosition"];
        }

        if (hasLeftEyePosition){
            NSString * leftEyePosition = NSStringFromCGPoint(face.leftEyePosition);
            [faceFeatures setValue:leftEyePosition forKey:@"leftEyePosition"];
        }

        if (hasRightEyePosition){
            NSString * rightEyePosition = NSStringFromCGPoint(face.rightEyePosition);
            [faceFeatures setValue:rightEyePosition forKey:@"rightEyePosition"];
        }

    }
    return faceFeatures;
}

1 个答案:

答案 0 :(得分:0)

基于缩略图保留检测所需的所有面部数据的假设,您的数学是正确的。

这个假设并不成立,因为在缩略图中,即使对于人来说,识别面部也是比较困难的。

因此,对于分辨率更高的图像,引擎应该返回更准确的面部位置,该面部位置应该更紧密地绑定到实际面部。通过简单地缩放缩略图图像中的值,它通常仍应与检测到的面部匹配,但您肯定会期望精度较低。