iOS - 人脸识别
前言
最近公司提出了一个有趣的新需求,需要开发一个功能来自动识别用户前置摄像头中的人脸,并且能够对其进行截图。
话不多说,直接开整...
- 技术点:
- AVCaptureSession:访问和控制设备的摄像头,并捕获实时的视频流。
- Vision:提供了强大的人脸识别和分析功能,能够快速准确地检测和识别人脸。
效果
开始
首先,工程中引入两个框架
import Vision
import AVFoundation
接下来,我们需要确保应用程序具有访问设备摄像头的权限。先判断是否拥有权限,如果没有权限我们通知用户去获取
let videoStatus = AVCaptureDevice.authorizationStatus(for: .video)
switch videoStatus {
case .authorized, .notDetermined:
print("有权限、开始我们的业务")
case .denied, .restricted:
print("没有权限、提醒用户去开启权限")
default:
break
}
然后,我们需要对摄像头进行配置,包括确认前后置摄像头、处理视频分辨率、设置视频稳定模式、输出图像方向以及设置视频数据输出
配置
确认前后置摄像头:
使用AVCaptureDevice类可以获取设备上的所有摄像头,并判断它们是前置摄像头还是后置摄像头
// 获取所有视频设备
let videoDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .unspecified).devices
// 筛选前置摄像头和后置摄像头
var frontCamera: AVCaptureDevice?
var backCamera: AVCaptureDevice?
for device in videoDevices {
if device.position == .front {
frontCamera = device
} else if device.position == .back {
backCamera = device
}
}
// 根据需要选择前置或后置摄像头
let cameraDevice = frontCamera ?? backCamera
处理视频分辨率:
可以通过设置AVCaptureSession的sessionPreset属性来选择适合的视频分辨率。常见的分辨率选项包括.high、.medium、.low等。
let captureSession = AVCaptureSession()
captureSession.sessionPreset = .high
输出图像方向:
可以通过设置AVCaptureVideoOrientation来指定输出图像的方向。通常,我们需要根据设备方向和界面方向进行调整。
if let videoConnection = videoOutput.connection(with: .video) {
if videoConnection.isVideoOrientationSupported {
let currentDeviceOrientation = UIDevice.current.orientation
var videoOrientation: AVCaptureVideoOrientation
switch currentDeviceOrientation {
case .portrait:
videoOrientation = .portrait
case .landscapeRight:
videoOrientation = .landscapeLeft
case .landscapeLeft:
videoOrientation = .landscapeRight
case .portraitUpsideDown:
videoOrientation = .portraitUpsideDown
default:
videoOrientation = .portrait
}
videoConnection.videoOrientation = videoOrientation
}
}
视频数据输出:
可以使用AVCaptureVideoDataOutput来获取摄像头捕捉到的实时视频数据。首先,创建一个AVCaptureVideoDataOutput对象,并将其添加到AVCaptureSession中。然后,设置代理对象来接收视频数据回调。
let videoOutput = AVCaptureVideoDataOutput()
captureSession.addOutput(videoOutput)
let videoOutputQueue = DispatchQueue(label: "VideoOutputQueue")
videoOutput.setSampleBufferDelegate(self, queue: videoOutputQueue)
视频处理、人脸验证
接下来,我们将对视频进行处理,包括人脸验证和圈出人脸区域。我们将在AVCaptureVideoDataOutputSampleBufferDelegate 的代理方法中来实现这些功能
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard let bufferRef = CMSampleBufferGetImageBuffer(sampleBuffer) else {
return
}
let detectFaceRequest = VNDetectFaceRectanglesRequest()
let detectFaceRequestHandler = VNImageRequestHandler(cvPixelBuffer: bufferRef, options: [:])
do {
try detectFaceRequestHandler.perform([detectFaceRequest])
guard let results = detectFaceRequest.results else {
return
}
DispatchQueue.main.async { [weak self] in
guard let self = self else {
return
}
// 移除先前的人脸矩形
for layer in self.layers {
layer.removeFromSuperlayer()
}
self.layers.removeAll()
for observation in results {
let oldRect = observation.boundingBox
let w = oldRect.size.width * self.view.frame.size.width
let h = oldRect.size.height * self.view.frame.size.height
let x = oldRect.origin.x * self.view.bounds.size.width
let y = self.view.frame.size.height - (oldRect.origin.y * self.view.frame.size.height) - h
// 添加矩形图层
let layer = CALayer()
layer.borderWidth = 2
layer.cornerRadius = 3
layer.borderColor = UIColor.orange.cgColor
layer.frame = CGRect(x: x, y: y, width: w, height: h)
self.layers.append(layer)
}
// 将矩形图层添加到视图的图层上
for layer in self.layers {
self.view.layer.addSublayer(layer)
}
}
} catch {
print("错误: \(error)")
}
}
结尾
识别单个人脸的时候没有太大问题,但是多个人脸位置不是很准确,有知道原因的小伙伴告知一下
作者:土豆崽xxx
链接:https://juejin.cn/post/7250008208159997989
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
链接:https://juejin.cn/post/7250008208159997989
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。