Отслеживание глаз с помощью Vision Framework
Как вы можете использовать новую платформу Vision в iOS 11, чтобы отслеживать глаза в видео, когда голова или камера движутся? (используя фронтальную камеру).
я обнаружил VNDetectFaceLandmarksRequest
чтобы быть очень медленным на моем iPad - запросы ориентиров выполняются примерно раз в 1-2 секунды. Я чувствую, что делаю что-то не так, но на сайте Apple не так много документации.
Я уже смотрел видео WWDC 2017 на Vision:
https://developer.apple.com/videos/play/wwdc2017/506/
а также прочитайте это руководство:
https://github.com/jeffreybergier/Blog-Getting-Started-with-Vision
Мой код выглядит примерно так прямо сейчас (извините, это Objective-C):
// Capture session setup
- (BOOL)setUpCaptureSession {
AVCaptureDevice *captureDevice = [AVCaptureDevice
defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera
mediaType:AVMediaTypeVideo
position:AVCaptureDevicePositionFront];
NSError *error;
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if (error != nil) {
NSLog(@"Failed to initialize video input: %@", error);
return NO;
}
self.captureOutputQueue = dispatch_queue_create("CaptureOutputQueue",
DISPATCH_QUEUE_SERIAL);
AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];
captureOutput.alwaysDiscardsLateVideoFrames = YES;
[captureOutput setSampleBufferDelegate:self queue:self.captureOutputQueue];
self.captureSession = [[AVCaptureSession alloc] init];
self.captureSession.sessionPreset = AVCaptureSessionPreset1280x720;
[self.captureSession addInput:captureInput];
[self.captureSession addOutput:captureOutput];
return YES;
}
// Capture output delegate:
- (void)captureOutput:(AVCaptureOutput *)output
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection {
if (!self.detectionStarted) {
return;
}
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
if (pixelBuffer == nil) {
return;
}
NSMutableDictionary<VNImageOption, id> *requestOptions = [NSMutableDictionary dictionary];
CFTypeRef cameraIntrinsicData = CMGetAttachment(sampleBuffer,
kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix,
nil);
requestOptions[VNImageOptionCameraIntrinsics] = (__bridge id)(cameraIntrinsicData);
// TODO: Detect device orientation
static const CGImagePropertyOrientation orientation = kCGImagePropertyOrientationRight;
VNDetectFaceLandmarksRequest *landmarksRequest =
[[VNDetectFaceLandmarksRequest alloc] initWithCompletionHandler:^(VNRequest *request, NSError *error) {
if (error != nil) {
NSLog(@"Error while detecting face landmarks: %@", error);
} else {
dispatch_async(dispatch_get_main_queue(), ^{
// Draw eyes in two corresponding CAShapeLayers
});
}
}];
VNImageRequestHandler *requestHandler = [[VNImageRequestHandler alloc] initWithCVPixelBuffer:pixelBuffer
orientation:orientation
options:requestOptions];
NSError *error;
if (![requestHandler performRequests:@[landmarksRequest] error:&error]) {
NSLog(@"Error performing landmarks request: %@", error);
return;
}
}
Это правильно называть -performRequests:..
в той же очереди, что и видеовыход? Судя по моим экспериментам, этот метод, похоже, вызывает синхронный обработчик завершения запроса. Разве я не должен вызывать этот метод на каждом кадре?
Для ускорения вещей я также пытался использовать VNTrackObjectRequest
отслеживать каждый глаз отдельно после того, как в видео были обнаружены ориентиры (путем создания ограничивающего прямоугольника из точек региона ориентиров), но это не сработало очень хорошо (все еще пытаясь выяснить это).
Какова лучшая стратегия для слежения за видео? Должен ли я отслеживать прямоугольник лица, а затем выполнить запрос наземных ориентиров внутри его области (будет ли он быстрее)?