16

Appleは最近、ビデオのフレーム間の顔を追跡できるように見えるというCIDetectorクラスに新しい定数を追加しました。CIDetectorTrackingそれがどのように機能するかを理解できれば、これは私にとって非常に有益です。

AVCaptureStillImageOutputインスタンス、作業中のUIImage、YES、1など、リモートで関連すると考えられるすべてのオブジェクトを使用して、このキーを検出器オプションディクショナリに追加しようとしました。

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

しかし、どのパラメーターを渡そうとしても、クラッシュするか(明らかにここで推測しています)、デバッガーは次のように出力します。

不明なCIDetectorTrackingが指定されました。無視します。

通常、私はこれを推測しませんが、このトピックに関するリソースは事実上存在しません。Appleのクラスリファレンスは次のように述べています。

検出器の顔追跡を有効または無効にするために使用されるキー。ビデオのフレーム全体で顔を追跡する場合は、このオプションを使用します。

iOS6以降とOSX10.8以降が利用可能であることを除けば、それだけです。

内部のコメントCIDetector.h

/*機能追跡を使用するように指定するために使用されるオプションディクショナリのキー。* /

それが十分に悪くなかった場合、Google検索は7つの結果(この投稿を見つけたときに8つ)を提供します。これらはすべて、Appleクラス参照、API差分、iOS 5でこれを達成する方法を尋ねるSO投稿、またはサードパーティのコピーのいずれかです。前者の。

そうは言っても、適切に使用するためのヒントやヒントをCIDetectorTrackingいただければ幸いです。

4

1 に答える 1

19

そうです、このキーはあまり文書化されていません。APIドキュメントのほかに、次の場所でも説明されていません。

に対して異なる値を試しましたが、CIDetectorTracking受け入れられる値はとのみのようです。他の値を使用すると、コンソールに次のメッセージが出力されます。@(YES)@(NO)

不明なCIDetectorTrackingが指定されました。無視します。

値をに設定する@(YES)と、検出された顔の特徴を含む追跡IDを取得する必要があります。


ただし、カメラからキャプチャされたコンテンツで顔を検出する場合は、AVFoundationの顔検出APIを使用する必要があります。顔追跡機能が組み込まれており、顔検出はGPUのバックグラウンドで行われ、CoreImageの顔検出よりもはるかに高速になります。iOS6と少なくともiPhone4SまたはiPad2が必要です。

顔はメタデータオブジェクト(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];

詳細については、WWDC2012のサンプルコードを確認してください。

于 2012-11-24T21:41:20.597 に答える