2012-02-23 10 views
8

Estoy tratando de escribir una rutina que toma un UIImage y devuelve un nuevo UIImage que contiene solo la cara. Esto parece ser muy sencillo, pero mi cerebro está teniendo problemas para desplazarse por los espacios de CoreImage y UIImage.UIImage detección de rostros

Aquí es lo básico:

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

La imagen que se devuelve es de la imagen volteada. He intentado ajustar faceFeature.bounds usar algo como esto:

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

... pero eso me da resultados fuera de la imagen.

Estoy seguro de que hay algo sencillo para solucionar esto, pero si no se calcula el bottom-down y luego se crea un nuevo rect usando eso como X, ¿hay una forma "adecuada" de hacerlo?

Gracias!

Respuesta

3

Dado que no parece ser una forma sencilla de hacer esto, que acabo de escribir algo de código para hacerlo:

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); 

Esto trabajó un encanto.

+5

Estoy investigando lo mismo, ¿podría explicar el cálculo que realizó para el eje y, por favor? ¿Y qué es la "cara más grande"? –

0

No hay una manera simple de lograr esto, el problema es que las imágenes de la cámara del iPhone siempre están en modo vertical, y la configuración de metadatos se usa para que se visualicen correctamente. También obtendrá una mayor precisión en su llamada de detección de rostros si le indica la rotación de la imagen de antemano. Para complicar las cosas, debes pasarle la orientación de la imagen en formato EXIF.

Afortunadamente no es un proyecto de ejemplo de manzana que cubre todo esto llama Squarecam, le sugiero que comprobar que los detalles

+0

Sí, ya estoy acomodando para la rotación de la imagen. Mi problema está relacionado con el origen diferente de UIImage y las rutinas CG. –

5

Es mucho más fácil y menos complicado usar CIContext para recortar su cara de la imagen. Algo como esto:

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

Dónde inputImage es su objeto UIImage y faceFeature es objeto de CIFaceFeature tipo que se obtiene de [CIDetector featuresInImage:] método.

Cuestiones relacionadas