实时跟踪用户的脸
Tracking the User’s Face in Real Time
Vision框架可以检测和跟踪一系列图像中的矩形、面孔和其他突出对象。
此示例演示如何创建跟踪人脸的请求并解释这些请求的结果。为了可视化观察到的面部特征的几何形状,代码围绕主要检测到的人脸及其最突出的特征绘制路径。
示例应用程序应用计算机视觉算法在提供的图像中找到一张人脸。一旦它找到一张脸,它就会尝试在视频的后续帧中跟踪该脸。最后,它在观察到的脸部周围画了一个绿色的盒子,以及概述面部特征的黄色路径,在核心动画层上。
要查看此示例应用程序的运行情况,请在iOS 11上构建并运行该项目。授予应用程序使用相机的权限。
配置摄像头来捕捉视频
本节演示如何使用代表为视觉准备图像设置相机捕捉会话。配置摄像头需要以下步骤。
- 首先,创建一个新的
AVCaptureSession来表示视频捕获。通过AVCaptureSession通道输出。 - 查询用户的输入设备,并通过指定其分辨率和相机将其配置为视频数据输出。
- 接下来,创建一个串行分派队列。该队列确保通过委托回调方法异步接收的视频帧按顺序传递。用
AVMediaType视频建立一个捕获会话,并设置其设备和分辨率。 - 最后,指定视频的预览层并将其添加到视图层次结构中,以便相机知道在捕获视频帧时在哪里显示它们。 此代码大多是样板设置,使您能够正确处理视频输入。只有当您选择不同的相机安排时,才会调整值。
解析人脸检测结果
您可以为Vision请求处理程序提供一个完成处理程序,以便在它完成时执行。完成处理程序指示请求成功还是导致错误。如果请求成功,其results属性包含特定于请求类型的数据,您可以使用这些数据来标识对象的位置和边界框。
对于人脸矩形请求,通过回调提供的VNFaceObservation为每个检测到的人脸包含一个边界框。样本使用这个边界框在预览图像上绘制每个检测到的人脸地标周围的路径。
let faceDetectionRequest = VNDetectFaceRectanglesRequest(completionHandler:
{ (request, error) in
if error != nil {
print("FaceDetection error: \(String(describing: error)).")
}
guard let faceDetectionRequest = request as? VNDetectFaceRectanglesRequest,
let results = faceDetectionRequest.results as? [VNFaceObservation] else {
return
}
DispatchQueue.main.async {
// Add the observations to the tracking list
for observation in results {
let faceTrackingRequest = VNTrackObjectRequest(detectedObjectObservation: observation)
requests.append(faceTrackingRequest)
}
self.trackingRequests = requests }})
除了在CALayer上绘制路径来可视化特征外,您还可以访问特定的面部特征数据,如面部观察的地标属性中的眼睛、瞳孔、鼻子和嘴唇分类。你的应用程序可以利用这些信息来跟踪用户的面部,并应用自定义效果。对于人脸地标请求,人脸矩形检测器也将隐式运行。
预处理图像
在委托方法fileOutput(_:didOutputSampleBuffer:from:)中执行任何图像预处理。在这个委托方法中,创建一个像素缓冲区来保存图像内容,确定设备的方向,并检查是否有一个面需要跟踪。
在Vision框架能够跟踪一个对象之前,它必须首先知道要跟踪哪个对象。通过创建VNImageRequestHandler并传递静态图像帧来确定要跟踪的面。在视频的例子中,当它们到达委托方法fileOutput(_:didOutputSampleBuffer:from:)时,提交单独的帧到请求处理程序。
let imageRequestHandler = VNImageRequestHandler(
cvPixelBuffer: pixelBuffer,orientation:
exifOrientation,options: requestHandlerOptions)
do {
guard let detectRequests = self.detectionRequests else {
return
}
try imageRequestHandler.perform(detectRequests)
} catch let error as NSError {
NSLog("Failed to perform FaceRectangleRequest: %@", error)
}
VNImageRequestHandler处理静态图像中的人脸和物体的检测,但它不携带从一帧到下一帧的信息。为了跟踪一个对象,创建一个VNSequenceRequestHandler,它可以处理VNTrackObjectRequest。
跟踪被检测的人脸
一旦您从图像请求处理程序的人脸检测中获得观察结果,将其输入序列请求处理程序。
try self.sequenceRequestHandler.perform(requests,on: pixelBuffer,orientation: exifOrientation)
如果检测器没有找到人脸,创建一个图像请求处理程序来检测人脸。一旦检测成功,您就有了一个面部观察,通过创建VNTrackObjectRequest来跟踪它。
// Setup the next round of tracking.
var newTrackingRequests = [VNTrackObjectRequest]()
for trackingRequest in requests {
guard let results = trackingRequest.results else {
return
}
guard let observation = results[0] as? VNDetectedObjectObservation else {
return
}
if !trackingRequest.isLastFrame {
if observation.confidence > 0.3 {
trackingRequest.inputObservation = observation
} else {
trackingRequest.isLastFrame = true
}
newTrackingRequests.append(trackingRequest)
}
}
然后调用序列处理程序的perform(_:)函数。这个方法是同步运行的,所以使用后台队列来避免主队列执行时阻塞,并且只有当你需要执行UI更新(如路径绘制)时才回调主队列。