0%

人脸检测

通过一个特定的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
}    

测试

编译运行程序,使用前置摄像头对准自己,或者后置摄像头对准他人或人像照片,观察人脸识别提示框.