正确使用CIDetectorTracking

时间:2012-11-20 14:31:58

标签: objective-c ios face-detection

Apple最近在名为CIDetector的{​​{1}}类中添加了一个新常量,该类似乎能够跟踪视频中帧之间的面。如果我能弄清楚它是如何工作的话,这对我来说非常有益。

我尝试使用我能想到的远程相关的每个对象将此密钥添加到探测器选项字典中,包括我的AVCaptureStillImageOutput实例,我正在处理的UIImage,YES,1等。

CIDetectorTracking

但无论我尝试传递什么参数,它都会崩溃(显然我在这里猜它)或调试器输出:

  

指定了未知的CIDetectorTracking。忽略。

通常情况下,我不会猜到这一点,但这个主题的资源实际上是不存在的。 Apple's class reference州:

  

用于启用或禁用检测器的面部跟踪的键。使用   想要在视频中跨帧跟踪面部时使用此选项。

除了可用性,iOS 6+和OS X 10.8+就是它。

NSDictionary *detectorOptions = [[NSDictionary alloc] initWithObjectsAndKeys:CIDetectorAccuracyHigh, CIDetectorAccuracy,myAVCaptureStillImageOutput,CIDetectorTracking, nil]; 内的评论:

  

/ *选项字典中用于指定该功能的键   应该使用跟踪。 * /

如果这还不够糟糕,Google搜索会提供7个结果(当他们发现这篇帖子时有8个)所有这些都是Apple类引用,API差异,SO帖子询问如何实现这一点iOS 5,或前者的第三方副本。

所有这一切,我们将非常感谢任何正确使用CIDetector.h的提示或技巧!

1 个答案:

答案 0 :(得分:19)

你是对的,这个密钥没有很好的记录。除了API文档之外,它还在中解释:

我为CIDetectorTracking尝试了不同的值,唯一可接受的值似乎是@(YES)@(NO)。使用其他值,它会在控制台中打印此消息:

  

指定了未知的CIDetectorTracking。忽略。

当您将值设置为@(YES)时,您应该使用检测到的脸部特征来获取跟踪ID。


但是,当您想要检测从相机捕获的内容中的面部时,您应该更喜欢AVFoundation中的面部检测API。它具有内置的面部跟踪功能,并且在GPU的背景中进行人脸检测,并且比CoreImage人脸检测要快得多 它需要iOS 6,至少需要iPhone 4S或iPad 2。

将面部作为元数据对象(AVMetadataFaceObject)发送到AVCaptureMetadataOutputObjectsDelegate

您可以使用此代码(取自 StacheCam 2 和上述WWDC会话的幻灯片)来设置面部检测并获取面部元数据对象:

- (void) setupAVFoundationFaceDetection
{       
    self.metadataOutput = [AVCaptureMetadataOutput new];
    if ( ! [self.session canAddOutput:self.metadataOutput] ) {
        return;
    }

    // Metadata processing will be fast, and mostly updating UI which should be done on the main thread
    // So just use the main dispatch queue instead of creating a separate one
    // (compare this to the expensive CoreImage face detection, done on a separate queue)
    [self.metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    [self.session addOutput:self.metadataOutput];

    if ( ! [self.metadataOutput.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeFace] ) {
        // face detection isn't supported (via AV Foundation), fall back to CoreImage
        return;
    }

    // We only want faces, if we don't set this we would detect everything available
    // (some objects may be expensive to detect, so best form is to select only what you need)
    self.metadataOutput.metadataObjectTypes = @[ AVMetadataObjectTypeFace ];

}

// AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput
         didOutputMetadataObjects:(NSArray *)metadataObjects
         fromConnection:(AVCaptureConnection *)c
{
   for ( AVMetadataObject *object in metadataObjects ) {
     if ( [[object type] isEqual:AVMetadataObjectTypeFace] ) {
      AVMetadataFaceObject* face = (AVMetadataFaceObject*)object;
      CMTime timestamp = [face time];
      CGRect faceRectangle = [face bounds];
      NSInteger faceID = [face faceID];
      CGFloat rollAngle = [face rollAngle];
      CGFloat yawAngle = [face yawAngle];
      NSNumber* faceID = @(face.faceID); // use this id for tracking
      // Do interesting things with this face
     }
}

如果要在预览图层中显示面部框架,则需要获取转换后的面部对象:

AVMetadataFaceObject * adjusted = (AVMetadataFaceObject*)[self.previewLayer transformedMetadataObjectForMetadataObject:face];

有关详细信息,请查看sample code from WWDC 2012