通过一个特定的AVCaptureOutput类型的AVCaptureMetadataOutput可以实现人脸检测功能.支持硬件加速以及同时对10个人脸进行实时检测.
当使用人脸检测时,会输出一个具体的子类类型AVMetadataFaceObject,该类型定义了多个用于描述被检测到的人脸的属性,包括人脸的边界(设备坐标系),以及斜倾角(roll angle,表示人头部向肩膀方向的侧倾角度)和偏转角(yaw angle,表示人脸绕Y轴旋转的角度).
本文的代码将在Kcamera中添加人脸识别功能.
代码清单
添加FaceDetectionDelegate
新建一个FaceDetectionDelegate.swift文件,用来传递检测结果,文件内容如下:
protocol FaceDetectionDelegate {
//检测到的人脸数组
func didDetectFaces(faces:[AnyObject]) -> Void
}
设置FaceDetectionDelegate
在CaptureModel中新增一个属性:
var faceDelegate:FaceDetectionDelegate?
打开ViewController.swift,在初始化捕捉会话成功后添加如下代码:
self.captureModel.faceDelegate = self.preView
设置AVCaptureMetadataOutput
在CaptureModel中新增一个属性:
//元数据输出,用于人脸检测
var metadataOutput:AVCaptureMetadataOutput!
并在setupSession()方法中进行初始化:
//9. 创建用于人脸检测的元数据输出
self.metadataOutput = AVCaptureMetadataOutput()
if self.captureSession.canAddOutput(self.metadataOutput) {
self.captureSession.addOutput(self.metadataOutput)
self.metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeFace]
self.metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
}
实现AVCaptureMetadataOutputObjectsDelegate
在按上文设置AVCaptureMetadataOutput之后,Xcode会提示还没有实现具体的代码方法,因此需要在CaptureModel中实现下面的代码方法:
//MARK: - AVCaptureMetadataOutputObjectsDelegate
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
self.faceDelegate?.didDetectFaces(metadataObjects)
}
实现FaceDetectionDelegate
首先需要在PreView类中增加一个属性latestFaces,用途是避免在UI上重复展示同一张人脸信息:
//存储最新的人脸检测faceID
var latestFaces = Set<Int>()
FaceDetectionDelegate声明的didDetectFaces()方法实现如下:
//MARK: - FaceDetectionDelegate
func didDetectFaces(faces: [AnyObject]) {
//1. 创建一个数组用于保存转换后的人脸数据
var transformedFaces = [AVMetadataObject]()
//2. 遍历传入的人脸数据进行转换
for face in faces {
//3. 元数据对象就会被转化成图层的坐标
let transformedFace = (self.layer as! AVCaptureVideoPreviewLayer).transformedMetadataObjectForMetadataObject(face as! AVMetadataObject)
transformedFaces.append(transformedFace)
}
//4.遍历新检测到的人脸信息
var faces = Set<Int>()
for face in transformedFaces {
let faceID = (face as! AVMetadataFaceObject).faceID
faces.insert(faceID)
//5. 如果为新检测出的人脸信息
if !self.latestFaces.contains(faceID) {
//6. 可视化检测结果
let view = UIView(frame: face.bounds)
view.layer.borderColor = UIColor(colorLiteralRed: 1.000, green: 0.421, blue: 0.054, alpha: 1.000).CGColor
view.layer.borderWidth = 2
self.addSubview(view)
UIView.animateWithDuration(1, animations: {
view.alpha = 0
}, completion: { (_) in
view.removeFromSuperview()
})
}
}
//7. 更新保存最新的人脸信息
self.latestFaces = faces
}
测试
编译运行程序,使用前置摄像头对准自己,或者后置摄像头对准他人或人像照片,观察人脸识别提示框.