iOS – 人脸识别

我正在参加「掘金·启航计划」

前言

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

话不多说,直接开整…

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

效果

RPReplay_Final1688031757.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)")
        }
    }

结尾

识别单个人脸的时候没有太大问题,但是多个人脸位置不是很准确,有知道原因的小伙伴告知一下

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYT42XJg' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片