Правильное использование CIDetectorTracking

Недавно Apple добавила новую константу в класс CIDetector под названием CIDetectorTracking, который, как представляется, способен отслеживать лица между кадрами в видео. Это было бы очень полезно для меня, если бы мне удалось выяснить, как это работает.

Я попытался добавить этот ключ в словарь параметров детектора, используя каждый объект, который, как я могу думать, имеет отдаленное отношение, включая мой экземпляр AVCaptureStillImageOutput, UIImage, над которым я работаю, YES, 1 и т.д.

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

Но независимо от того, какой параметр я пытаюсь передать, он либо сбой (очевидно, я угадываю его здесь), либо выходы отладчика:

Указана неизвестная CIDetectorTracking. Не обращая внимания.

Обычно, я бы не догадывался об этом, но ресурсов по этой теме практически не существует. Ссылка на класс Apple:

Ключ, используемый для включения или отключения отслеживания лица для детектора. использование эта опция, когда вы хотите отслеживать лица по кадрам в видео.

Помимо доступности - iOS 6+ и OS X 10.8+, это.

Комментарии внутри CIDetector.h:

/* Ключ в словаре опций, используемый для указания этой функции следует использовать отслеживание. */

Если это не так плохо, поиск Google содержит 7 результатов (8, когда они находят это сообщение), все из которых являются ссылками класса Apple, API diffs, сообщение SO, спрашивающее, как это сделать в iOS 5, или сторонние копии первого.

Все, что сказано, любые советы или подсказки для правильного использования CIDetectorTracking были бы с благодарностью!

Ответы

Ответ 1

Вы правы, этот ключ не очень хорошо документирован. Помимо документов API, это также не объясняется в:

  • заголовочный файл CIDetector.h
  • Руководство по программированию основных изображений
  • сессия WWDC 2012 520 - что нового в захвате камеры
  • пример кода для этого сеанса (StacheCam 2)

Я пробовал разные значения для CIDetectorTracking, и единственными признанными значениями были @(YES) и @(NO). С другими значениями оно печатает это сообщение в консоли:

Указана неизвестная CIDetectorTracking. Не обращая внимания.

Когда вы устанавливаете значение @(YES), вы должны получить идентификатор отслеживания с обнаруженными функциями лица.


Однако, когда вы хотите обнаружить лица в контенте, снятом с камеры, вам следует предпочесть API обнаружения лиц в AVFoundation. У него встроено слежение за лицом и обнаружение лица происходит в фоновом режиме на графическом процессоре и будет намного быстрее, чем обнаружение лица 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.