Search code examples
iosxcodecore-graphicsface-detection

UIImage face detection


I am trying to write a routine that takes a UIImage and returns a new UIImage that contains just the face. This would seem to be very straightforward, but my brain is having problems getting around the CoreImage vs. UIImage spaces.

Here's the basics:

- (UIImage *)imageFromImage:(UIImage *)image inRect:(CGRect)rect {
    CGImageRef sourceImageRef = [image CGImage];
    CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    CGImageRelease(newImageRef);
    return newImage;
}


-(UIImage *)getFaceImage:(UIImage *)picture {
  CIDetector  *detector = [CIDetector detectorOfType:CIDetectorTypeFace 
                                             context:nil 
                                             options:[NSDictionary dictionaryWithObject: CIDetectorAccuracyHigh forKey: CIDetectorAccuracy]];

  CIImage *ciImage = [CIImage imageWithCGImage: [picture CGImage]];
  NSArray *features = [detector featuresInImage:ciImage];

  // For simplicity, I'm grabbing the first one in this code sample,
  // and we can all pretend that the photo has one face for sure. :-)
  CIFaceFeature *faceFeature = [features objectAtIndex:0];

  return imageFromImage:picture inRect:faceFeature.bounds;
}

The image that is returned is from the flipped image. I've tried adjusting faceFeature.bounds using something like this:

CGAffineTransform t = CGAffineTransformMakeScale(1.0f,-1.0f);
CGRect newRect = CGRectApplyAffineTransform(faceFeature.bounds,t);

... but that gives me results outside the image.

I'm sure there's something simple to fix this, but short of calculating the bottom-down and then creating a new rect using that as the X, is there a "proper" way to do this?

Thanks!


Solution

  • Since there doesn't seem to be a simple way to do this, I just wrote some code to do it:

    CGRect newBounds = CGRectMake(faceFeature.bounds.origin.x, 
                                  _picture.size.height - faceFeature.bounds.origin.y - largestFace.bounds.size.height, 
                                  faceFeature.bounds.size.width, 
                                  faceFeature.bounds.size.height);
    

    This worked a charm.