iOS开发iOS技能程序员

AVFoundation-06人脸检测

2017-07-26  本文已影响807人  秦明Qinmin

概述

AVFoundation 是一个可以用来使用和创建基于时间的视听媒体数据的框架。AVFoundation 的构建考虑到了目前的硬件环境和应用程序,其设计过程高度依赖多线程机制。充分利用了多核硬件的优势并大量使用block和GCD机制,将复杂的计算机进程放到了后台线程运行。会自动提供硬件加速操作,确保在大部分设备上应用程序能以最佳性能运行。该框架就是针对64位处理器设计的,可以发挥64位处理器的所有优势。

iOS 媒体环境.png

实现效果

人脸识别.jpeg

捕捉会话

AV Foundation 捕捉栈的核心类是AVCaptureSession。一个捕捉会话相当于一个虚拟的插线板,用于连接输入和输出的资源。捕捉会话管理从物理设备得到的数据流。

self.captureSession = [[AVCaptureSession alloc] init];
[self.captureSession setSessionPreset:AVCaptureSessionPreset640x480];
[self.previewView setSession:self.captureSession];

AVCaptureMetadataOutput

在使用捕捉设备进行处理前,首先要添加输入、输出。输出的类型是 AVCaptureOutput,它是一个抽象基类,用于将捕捉到的数据输出。AV Foundation 框架定义了AVCaptureOutput 的一些扩展,但是在人脸动态识别的时候我们用到是它的子类 AVCaptureMetadataOutput。AVCaptureMetadataOutput 用于输出元数据,如二维码、条形码、以及人脸等。我们在使用的时候需要指定 Metadata 的相关类型,我们可以通过 AVCaptureMetadataOutput 的 ```@property(nonatomic, readonly) NSArray<AVMetadataObjectType> *availableMetadataObjectTypes;


// Output
self.metaDataOutput = [[AVCaptureMetadataOutput alloc] init];
[self.metaDataOutput setMetadataObjectsDelegate:self queue:dispatch_get_global_queue(0, 0)];

if ([self.captureSession canAddOutput:self.metaDataOutput]) {
[self.captureSession addOutput:self.metaDataOutput];
}
for (NSString *metaType in self.metaDataOutput.availableMetadataObjectTypes) {
NSLog(@"%@", metaType);
}
self.metaDataOutput.metadataObjectTypes = @[AVMetadataObjectTypeFace];


####AVMetadataFaceObject
当检测到人脸的时候AVCaptureMetadataOutput 会输出子类型为 AVMetadataFaceObject 的数组。AVMetadataFaceObject 定义了多个描述检测到人脸的属性。其中最重要的是人脸的边界(bounds),它是CGRect类型的变量。它的坐标系是基于设备标量坐标系,它的范围是摄像头原始朝向左上角(0,0)到右下角(1,1)。除了边界,AVMetadataFaceObject还提供了检测到人脸的斜倾角和偏转角。斜倾角(rollAngle)表示人的头部向肩的方向侧倾角度, 偏转角(yawAngle)表示人沿Y轴旋转的角度。AVMetadataFaceObject 定义如下:

@interface AVMetadataFaceObject : AVMetadataObject <NSCopying>
{
@private
AVMetadataFaceObjectInternal *_internal;
}
@property(readonly) NSInteger faceID;
// 斜倾角
@property(readonly) BOOL hasRollAngle;
@property(readonly) CGFloat rollAngle;
// 偏转角
@property(readonly) BOOL hasYawAngle;
@property(readonly) CGFloat yawAngle;
@end


###捕捉预览
AVCaptureVideoPreviewLayer是CALayer的子类,可以对捕捉视频进行实时预览。它有个AVLayerVideoGravity属性可以控制画面的缩放和拉升效果。

AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
previewLayer.frame = [UIScreen mainScreen].bounds;
[self.view.layer addSublayer:previewLayer];

####坐标变换
由于 AVMetadataFaceObject 中的人脸的边界(bounds)的坐标系是基于设备标量坐标系,它的范围是摄像头原始朝向左上角(0,0)到右下角(1,1),因此需要将它转换到我们的视图坐标系中。在转换的时候系统会考虑orientation, mirroring, videoGravity 等许多因素。在转换的时候我们只需要使用捕捉预览 AVCaptureVideoPreviewLayer 提供的 ```- (nullable AVMetadataObject *)transformedMetadataObjectForMetadataObject:(AVMetadataObject *)metadataObject;``` 方法。


####实现动态人脸检测
+ 创建捕捉会话,并设置输入、输出以及预览图层。将 AVCaptureMetadataOutput 的metadataObjectTypes 设为捕获人脸 AVMetadataObjectTypeFace。


+ 创建预览视图 QMPreviewView,将预览视图的 layerClass 设置为 AVCaptureVideoPreviewLayer,并初始化相关视图。由于我们用到了偏转角(yawAngle)在旋转的时候我们需要用到透视投影,这样在绕Y轴旋转的时候才更加逼真。

// 透视投影
static CATransform3D PerspectiveTransformMake(CGFloat eyePosition)
{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1.0 / eyePosition;
return transform;
}


+ 初始化QMPreviewView,初始化后需要为它设置 AVCaptureSession 才能进行捕捉的实时预览。

+ 处理AVCaptureMetadataOutputObjectsDelegate回调方法解析并绘制人脸矩形。每个人脸 AVFoundation 都会给出唯一的faceID,当人脸离开屏幕时候,对应的人脸也会在回调中消失。我们根据人脸ID保存着绘制的矩形,当人脸消失的时候,我们需要将绘制的矩形去除。

pragma mark - Public



####参考
[AVFoundation开发秘籍:实践掌握iOS & OSX应用的视听处理技术](https://book.douban.com/subject/26577333/)

源码地址:[AVFoundation开发 https://github.com/QinminiOS/AVFoundation](https://github.com/QinminiOS/AVFoundation)
上一篇 下一篇

猜你喜欢

热点阅读