2012-02-23 2 views
8

Я пытаюсь написать процедуру, которая берет UIImage и возвращает новый UIImage, который содержит только лицо. Это казалось бы очень простым, но у моего мозга возникают проблемы, связанные с пространствами CoreImage и UIImage.Обнаружение лица UIImage

Вот основы:

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

Изображение, которое возвращается от перевернутого изображения. Я попытался корректировки faceFeature.bounds используя что-то вроде этого:

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

... но это дает мне результаты за пределы изображения.

Я уверен, что есть что-то простое, чтобы исправить это, но не удалось вычислить нижний нижний и затем создать новый прямоугольник, используя это как X, есть ли «правильный» способ сделать это?

Спасибо!

ответ

3

Так, кажется, не быть простым способом сделать это, я просто написал код для этого:

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

Это сработало очарование.

+5

Я изучаю то же самое, не могли бы вы объяснить расчет, который вы выполнили для оси y, пожалуйста ?. А что такое «большая поверхность»? –

0

Нет простого способа добиться этого, проблема заключается в том, что изображения с камеры iPhone всегда находятся в портретном режиме, а настройки метаданных используются для правильного отображения их. Вы также получите лучшую точность при вызове обнаружения лица, если вы сообщите об этом вращению изображения заранее. Чтобы усложнить ситуацию, вы должны передать ей ориентацию изображения в формате EXIF.

К счастью, есть образец яблока проект, который охватывает все это называется Squarecam, я предлагаю вам проверить это для деталей

+0

Да, я уже размещаю для вращения изображения. Моя проблема связана с разным происхождением для UIImage и подпрограмм CG. –

5

Это намного проще и менее беспорядочно использовать CIContext, чтобы обрезать лицо с изображения. Что-то вроде этого:

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

Где inputImage Ваш объект UIImage и faceFeature объект типа CIFaceFeature, что вы получаете от [CIDetector featuresInImage:] метод.