16

Apple 最近在CIDetector名为的类中添加了一个新常量,CIDetectorTracking它似乎能够在视频中的帧之间跟踪人脸。如果我能设法弄清楚它是如何工作的,这对我来说将是非常有益的..

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

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

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

指定了未知的 CIDetectorTracking。无视。

通常情况下,我不会猜到这一点,但是关于这个主题的资源几乎不存在。苹果的类参考状态:

用于启用或禁用检测器的面部跟踪的键。当您想要跨视频帧跟踪人脸时,请使用此选项。

除了可用性是 iOS 6+ 和 OS X 10.8+ 就是这样。

里面的评论CIDetector.h

/*选项字典中用于指定应使用特征跟踪的键。*/

如果这还不够糟糕,Google搜索会提供 7 个结果(当他们找到这篇文章时为 8 个),所有这些结果要么是 Apple 类引用、API 差异、一个询问如何在 iOS 5 中实现这一点的 SO 帖子,要么是第 3 方副本前者的。

话虽如此,任何正确使用的提示或技巧CIDetectorTracking将不胜感激!

4

1 回答 1

19

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

我尝试了不同的值,CIDetectorTracking唯一接受的值似乎是@(YES)and @(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];

有关详细信息,请查看WWDC 2012 中的示例代码

于 2012-11-24T21:41:20.597 回答