【问题标题】:How to detect and show eyes and mouth in camera in iPhone?如何在 iPhone 的相机中检测和显示眼睛和嘴巴?
【发布时间】:2012-11-24 05:13:37
【问题描述】:

为了检测相机中的人脸,我参考 SquareCam(iOS 开发者库)。但我无法显示左眼、右眼和嘴的位置。我正在使用以下代码

NSArray *sublayers = [NSArray arrayWithArray:[previewLayer sublayers]];
NSInteger sublayersCount = [sublayers count], currentSublayer = 0;
NSInteger featuresCount = [features count], currentFeature = 0;

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

// hide all the face layers
for ( CALayer *layer in sublayers )
{
    if ( [[layer name] isEqualToString:@"FaceView"] )
        [layer setHidden:YES];
}

if ( featuresCount == 0 || !detectFaces ) {
    [CATransaction commit];
    return; // early bail.
}

CGSize parentFrameSize = [previewView frame].size;
NSString *gravity = [previewLayer videoGravity];
BOOL isMirrored = [previewLayer isMirrored];
CGRect previewBox = [SquareCamViewController videoPreviewBoxForGravity:gravity
                                                             frameSize:parentFrameSize
                                                          apertureSize:clap.size];

for ( CIFaceFeature *ff in features ) {


    // find the correct position for the square layer within the previewLayer
    // the feature box originates in the bottom left of the video frame.
    // (Bottom right if mirroring is turned on)
    CGRect faceRect = [ff bounds];

    CGRect leftEyeFrameRect;

    CGFloat temp             = faceRect.size.width;
    faceRect.size.width      = faceRect.size.height;
    faceRect.size.height     = temp;
    temp                     = faceRect.origin.x;
    faceRect.origin.x        = faceRect.origin.y;
    faceRect.origin.y        = temp;

    // scale coordinates so they fit in the preview box, which may be scaled
    CGFloat widthScaleBy     = previewBox.size.width / clap.size.height;
    CGFloat heightScaleBy    = previewBox.size.height / clap.size.width;
    faceRect.size.width     *= widthScaleBy;
    faceRect.size.height    *= heightScaleBy;
    faceRect.origin.x       *= widthScaleBy;
    faceRect.origin.y       *= heightScaleBy;


    if ( isMirrored )
    {

        faceRect = CGRectOffset(faceRect, previewBox.origin.x + previewBox.size.width - faceRect.size.width - (faceRect.origin.x * 2), previewBox.origin.y);


    }
    else
    {

        faceRect = CGRectOffset(faceRect, previewBox.origin.x, previewBox.origin.y);
          leftEyeFrameRect=CGRectOffset(faceRect,ff.leftEyePosition.x, ff.leftEyePosition.y);

    }

    CALayer *featureLayer   = nil;
    CALayer *eyeLayer       = nil;

    // re-use an existing layer if possible
    while ( !featureLayer && (currentSublayer < sublayersCount) )

    {
        CALayer *currentLayer = [sublayers objectAtIndex:currentSublayer++];
        if ( [[currentLayer name] isEqualToString:@"FaceLayer"] ) {
            featureLayer = currentLayer;

            [currentLayer setHidden:NO];
        }
    }



    // create a new one if necessary
    if ( !featureLayer ) {

        featureLayer = [CALayer new];
        [featureLayer   setContents:(id)[square CGImage]];
        [featureLayer   setName:@"FaceLayer"];
        [previewLayer addSublayer:featureLayer];
        [featureLayer   release];

    }
    [featureLayer setFrame:faceRect];


    if (faceView !=nil) {
        [faceView removeFromSuperview];
        [faceView release];
    }
    if (leftEyeView != nil) {
        [leftEyeView removeFromSuperview];
        [leftEyeView release];
    }

    faceView   = [[UIView alloc] initWithFrame:CGRectMake(faceRect.origin.x, faceRect.origin.y ,faceRect.size.width, faceRect.size.height)];

    faceView.layer.borderWidth   = 1;
    faceView.layer.borderColor   = [[UIColor redColor] CGColor];
    [self.view    addSubview:faceView];


    leftEyeView = [[UIView alloc] initWithFrame:CGRectMake(faceView.frame.origin.x+(faceView.frame.size.height/2), faceView.frame.origin.y+(faceView.frame.size.height*0.10) ,faceView.frame.size.width*0.40, faceView.frame.size.height*0.40)];

    UIImageView  *leftEyeImageView=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"eye.png"]];
    leftEyeImageView.frame = CGRectMake(0, 0, faceView.frame.size.width*0.40, faceView.frame.size.height*0.40);
    [leftEyeView addSubview:leftEyeImageView];
    [self.view    addSubview:leftEyeView];



    if (ff.hasLeftEyePosition) {
        CGPoint leftEyeCenter= ff.leftEyePosition;
        UIView *vv= [[UIView alloc] initWithFrame:CGRectMake(leftEyeCenter.x, leftEyeCenter.y, 50, 50)];
        vv.center = leftEyeCenter;
        vv.layer.borderWidth= 4.0;
        vv.layer.borderColor= [[UIColor blackColor]CGColor];
        [self.view addSubview:vv];  
    }

它正在检测眼睛但未显示在正确的位置。任何人都可以帮助解决这个问题。 提前致谢。

【问题讨论】:

  • 也许这会对你有所帮助.. maniacdev.com/2011/11/…
  • “没有显示在正确的位置” - 请更具体一点,到底是什么问题?
  • 眼睛位置未根据眼睛在脸部的位置显示。
  • 感谢您的回复,但我需要在实时摄像头中检测眼睛位置,而不是在图像中。

标签: iphone camera face-detection


【解决方案1】:

这可能是由于您的输入、检测器和输出之间的方向不正确造成的。如果检测到人脸,则可能只需要将输出坐标从横向转换为纵向,反之亦然。否则,看看here

【讨论】:

    【解决方案2】:

    您可以在 Haar 级联训练文件和 OPENGL 中进行调查,但这是完全不同的方法。它确实支持低于 6.0 的 iOS 版本,这是一个专业版。但它比 Apple 的 Squarecam 样本更难(con)。

    此 OpenGL 能够检测耳朵、眼睛等。网络上可能已经有一些训练文件。

    【讨论】:

    • 另一种方法是在脸上做一些数学运算(如果你取'facerect'的高度和宽度,眼睛的位置(或多或少)是可预定义的)
    【解决方案3】:

    在使用前置摄像头时,我在预览中遇到了与您相同的问题,因为预览是镜像的,我找不到任何可以缩放的好信息。

    以下代码是我得到的最接近的代码。请注意,我将图像定义为名为@9​​87654321@ 的属性,并且我假设您使用的是名为 SquareCam 的 Apple 示例。

    - (void)drawFaceBoxesForFeatures:(NSArray *)features forVideoBox:(CGRect)clap orientation:(UIDeviceOrientation)orientation方法中

            if(ff.hasLeftEyePosition)
        {
            //swap coordinates
            CGFloat leftEyeRectOriginX = ff.leftEyePosition.y ; 
            CGFloat leftEyeRectOriginY = ff.leftEyePosition.x ;
            CGFloat leftEyeRectWidth = faceRect.size.width*0.3;
            CGFloat leftEyeRectHeight = faceRect.size.width*0.3;
    
            //adjust scale
            leftEyeRectOriginX *= widthScaleBy;
            leftEyeRectOriginY *= heightScaleBy;
    
            NSLog(@"LeftEyePosition: %@", NSStringFromCGPoint(ff.leftEyePosition));
            CGRect r = CGRectMake(leftEyeRectOriginX -  (leftEyeRectWidth/2) , leftEyeRectOriginY - (leftEyeRectHeight/2), leftEyeRectWidth, leftEyeRectHeight);
    
            if ( isMirrored ){
                r = CGRectOffset(r, previewBox.origin.x + previewBox.size.width - (rightEyeRectOriginX*2) - rightEyeRectWidth+ faceRect.origin.x, previewBox.origin.y);
                NSLog(@"LeftEyeRect mirrored: %@", NSStringFromCGRect(r));
            }
            else{
                r = CGRectOffset(r, previewBox.origin.x, previewBox.origin.y);
            }
    
    
            while ( !leftEyeEyeLayer && (currentSublayer < sublayersCount) ) {
                CALayer *currentLayer = [sublayers objectAtIndex:currentSublayer++];
                if ( [[currentLayer name] isEqualToString:@"LeftEyeLayer"] ) {
                    leftEyeEyeLayer = currentLayer;
                    [currentLayer setHidden:NO];
                }
            }
    
            // create a new one if necessary
            if ( !leftEyeEyeLayer ) {
                leftEyeEyeLayer = [CALayer new];
                [leftEyeEyeLayer setContents:(id)[heartImage CGImage]];
                [leftEyeEyeLayer setName:@"LeftEyeLayer"];
                [previewLayer addSublayer:leftEyeEyeLayer];
                [leftEyeEyeLayer release];
            }
            [leftEyeEyeLayer setFrame:r];
    
        }
    

    这同样适用于右眼,除了我在它被镜像的情况下使用它:r = CGRectOffset(r, previewBox.origin.x + previewBox.size.width - (rightEyeRectOriginX*2) - rightEyeRectWidth+ faceRect.origin.x, previewBox.origin.y); 。 与示例代码的唯一区别是您首先要删除所有功能层,因此我的代码上方的某些行如下所示:

        // hide all the face layers
    for ( CALayer *layer in sublayers ) {
        if ( [[layer name] isEqualToString:@"FaceLayer"] || [[layer name] isEqualToString:@"LeftEyeLayer"] || [[layer name] isEqualToString:@"RightEyeLayer"] )
            [layer setHidden:YES];
    }   
    

    确切地说,我只在实时相机预览中遇到问题。当使用将图片保存在库中的方法(- (CGImageRef)newSquareOverlayedImageForFeatures:(NSArray *)features inCGImage:(CGImageRef)backgroundImage withOrientation:(UIDeviceOrientation)orientation frontFacing:(BOOL)isFrontFacing )时,使用以下方法可以正常工作:

            if(ff.hasLeftEyePosition)
        {
            CGRect r = CGRectMake(ff.leftEyePosition.x-faceWidth*0.15, ff.leftEyePosition.y-faceWidth*0.15, faceWidth*0.3, faceWidth*0.3);
            CGContextDrawImage(bitmapContext, r, [rotatedHeartImage CGImage]);
    
        }
    

    请告诉我是否应该以及如何改进我的答案。

    【讨论】:

      猜你喜欢
      • 2013-07-14
      • 2013-10-21
      • 1970-01-01
      • 2013-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 2012-10-19
      相关资源
      最近更新 更多