Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 604
Tim Sullivan Avatar asked Feb 23 '12 19:02

Tim Sullivan


2 Answers

It's much easier and less messy to just use CIContext to crop your face from the image. Something like this:

CGImageRef cgImage = [_ciContext createCGImage:[CIImage imageWithCGImage:inputImage.CGImage] fromRect:faceFeature.bounds];
UIImage *croppedFace = [UIImage imageWithCGImage:cgImage];

Where inputImage is your UIImage object and faceFeature object is of type CIFaceFeature that you get from [CIDetector featuresInImage:] method.

like image 179
jlajlar Avatar answered Oct 17 '22 02:10

jlajlar


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.

like image 40
Tim Sullivan Avatar answered Oct 17 '22 02:10

Tim Sullivan