注册
iOS

iOS - 人脸识别

前言


最近公司提出了一个有趣的新需求,需要开发一个功能来自动识别用户前置摄像头中的人脸,并且能够对其进行截图。


话不多说,直接开整...

  • 技术点:
  • AVCaptureSession:访问和控制设备的摄像头,并捕获实时的视频流。
  • Vision:提供了强大的人脸识别和分析功能,能够快速准确地检测和识别人脸。

效果


31d57bd763c5a684eabbcc1f177eadc6.gif


开始


首先,工程中引入两个框架

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
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册