Я изменяю приложение для определения лица Apple SquareCam, чтобы оно обрезало лицо перед записью в рулон камеры, вместо того, чтобы рисовать красный квадрат вокруг лица. Я использую тот же CGRect, чтобы сделать обрезку, как было использовано для рисования красного квадрата. Однако поведение отличается. В портретном режиме, если лицо находится в горизонтальном центре экрана, оно обрывает лицо, как ожидалось (то же самое место было бы красным квадратом). Если лицо выключено влево или вправо, урожай всегда берется из середины экрана, а не там, где был бы красный квадрат.Обрезать лицо с распознаванием лица
Вот яблоки исходный код:
- (CGImageRef)newSquareOverlayedImageForFeatures:(NSArray *)features
inCGImage:(CGImageRef)backgroundImage
withOrientation:(UIDeviceOrientation)orientation
frontFacing:(BOOL)isFrontFacing
{
CGImageRef returnImage = NULL;
CGRect backgroundImageRect = CGRectMake(0., 0., CGImageGetWidth(backgroundImage), CGImageGetHeight(backgroundImage));
CGContextRef bitmapContext = CreateCGBitmapContextForSize(backgroundImageRect.size);
CGContextClearRect(bitmapContext, backgroundImageRect);
CGContextDrawImage(bitmapContext, backgroundImageRect, backgroundImage);
CGFloat rotationDegrees = 0.;
switch (orientation) {
case UIDeviceOrientationPortrait:
rotationDegrees = -90.;
break;
case UIDeviceOrientationPortraitUpsideDown:
rotationDegrees = 90.;
break;
case UIDeviceOrientationLandscapeLeft:
if (isFrontFacing) rotationDegrees = 180.;
else rotationDegrees = 0.;
break;
case UIDeviceOrientationLandscapeRight:
if (isFrontFacing) rotationDegrees = 0.;
else rotationDegrees = 180.;
break;
case UIDeviceOrientationFaceUp:
case UIDeviceOrientationFaceDown:
default:
break; // leave the layer in its last known orientation
}
UIImage *rotatedSquareImage = [square imageRotatedByDegrees:rotationDegrees];
// features found by the face detector
for (CIFaceFeature *ff in features) {
CGRect faceRect = [ff bounds];
NSLog(@"faceRect=%@", NSStringFromCGRect(faceRect));
CGContextDrawImage(bitmapContext, faceRect, [rotatedSquareImage CGImage]);
}
returnImage = CGBitmapContextCreateImage(bitmapContext);
CGContextRelease (bitmapContext);
return returnImage;
}
и моя замена:
- (CGImageRef)newSquareOverlayedImageForFeatures:(NSArray *)features
inCGImage:(CGImageRef)backgroundImage
withOrientation:(UIDeviceOrientation)orientation
frontFacing:(BOOL)isFrontFacing
{
CGImageRef returnImage = NULL;
//I'm only taking pics with one face. This is just for testing
for (CIFaceFeature *ff in features) {
CGRect faceRect = [ff bounds];
returnImage = CGImageCreateWithImageInRect(backgroundImage, faceRect);
}
return returnImage;
}
Update *
на основе ввода Wains, я пытался сделать мой код больше похож на оригинал, но результатом был то же самое:
- (NSArray*)extractFaceImages:(NSArray *)features
fromCGImage:(CGImageRef)sourceImage
withOrientation:(UIDeviceOrientation)orientation
frontFacing:(BOOL)isFrontFacing
{
NSMutableArray *faceImages = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
CGImageRef returnImage = NULL;
CGRect backgroundImageRect = CGRectMake(0., 0., CGImageGetWidth(sourceImage), CGImageGetHeight(sourceImage));
CGContextRef bitmapContext = CreateCGBitmapContextForSize(backgroundImageRect.size);
CGContextClearRect(bitmapContext, backgroundImageRect);
CGContextDrawImage(bitmapContext, backgroundImageRect, sourceImage);
CGFloat rotationDegrees = 0.;
switch (orientation) {
case UIDeviceOrientationPortrait:
rotationDegrees = -90.;
break;
case UIDeviceOrientationPortraitUpsideDown:
rotationDegrees = 90.;
break;
case UIDeviceOrientationLandscapeLeft:
if (isFrontFacing) rotationDegrees = 180.;
else rotationDegrees = 0.;
break;
case UIDeviceOrientationLandscapeRight:
if (isFrontFacing) rotationDegrees = 0.;
else rotationDegrees = 180.;
break;
case UIDeviceOrientationFaceUp:
case UIDeviceOrientationFaceDown:
default:
break; // leave the layer in its last known orientation
}
// features found by the face detector
for (CIFaceFeature *ff in features) {
CGRect faceRect = [ff bounds];
NSLog(@"faceRect=%@", NSStringFromCGRect(faceRect));
returnImage = CGBitmapContextCreateImage(bitmapContext);
returnImage = CGImageCreateWithImageInRect(returnImage, faceRect);
UIImage *clippedFace = [UIImage imageWithCGImage:returnImage];
[faceImages addObject:clippedFace];
}
CGContextRelease (bitmapContext);
return faceImages;
}
Я взял три фотографии и вошли faceRect с этими результатами;
Снимок сделан с лицом, расположенным рядом с левым краем устройства. Захват изображения полностью пропускает лицо вправо: faceRect = {{972, 43.0312}, {673.312, 673.312}}
Снимок сделан с лицом, расположенным в середине устройства. Захват изображения хорош: faceRect = {{1060.59, 536.625}, {668.25, 668.25}}
Снимок сделан с лицом, расположенным вблизи правого края устройства. Захват изображения полностью пропускает лицо влево: faceRect = {{982.125, 999.844}, {804.938, 804.938}}
Таким образом, оказывается, что «x» и «y» меняются на противоположные. Я держу устройство на портрете, но faceRect похоже на ландшафт. Тем не менее, я не могу понять, какая часть исходного кода Яблоков учитывает это. Код ориентации в этом методе, по-видимому, влияет только на изображение с красным квадратом.
ли вы попробовать мой ответ, но все еще видите проблемы? – Wain