博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS开发—AVFoundation实现动态人脸识别
阅读量:5734 次
发布时间:2019-06-18

本文共 4322 字,大约阅读时间需要 14 分钟。

###简介 AVFoundation 是一个可以用来使用和创建基于时间的视听媒体数据的框架。AVFoundation 的构建考虑到了目前的硬件环境和应用程序,其设计过程高度依赖多线程机制。充分利用了多核硬件的优势并大量使用block和GCD机制,将复杂的计算机进程放到了后台线程运行。会自动提供硬件加速操作,确保在大部分设备上应用程序能以最佳性能运行。

(技术交流群:923910776)

###介绍一些人脸识别的方式

  1. CoreImage静态人脸识别, 可识别照片, 图像等
  2. Face++是新一代云端视觉服务平台,提供一整套世界领先的人脸检测,人脸识别,面部分析的视觉技术服务
  3. OpenCV由一系列 C 函数和少量 C++ 类构成, 实现了图像处理和计算机视觉方面的很多通用算法
  4. Vision 是 Apple 在 WWDC 2017 伴随iOS 11推出的基于CoreML的图像识别框架
  5. AVFoundation可以用来使用和创建基于时间的视听媒体的框架,今天我们使用的人脸识别方式也是使用AVFoundation框架

###对关键类的简单介绍

  1. AVCaptureDevice 代表了输入设备,例如摄像头与麦克风。我们可以从这个类中获取手机硬件的照相机、声音传感器等。
  2. AVCaptureDeviceInput:设备输入数据管理对象,可以根据AVCaptureDevice创建对应的对象
  3. AVCaptureOutput代表输出数据,输出的可以是图片或者视频
  4. AVCaptureSession: 媒体(音、视频)捕捉会话
1 负责把捕捉的音频视频数据输出到输出设备中。2 一个AVCaptureSession可以有多个输入或输出。3是连接AVCaptureInput和AVCaptureOutput的桥梁,它协调input到output之间传输数据。4 它有startRunning和stopRunning两种方法来开启会话和结束会话。5 每个session称之为一个会话,也就是在应用运行过程中如果你需要改变会话的一些配置(例如:切换摄像头),此时需要先开启配置,配置完成之后再提交配置。复制代码
  1. AVCaptureVideoPreviewLayer: 图片预览层我们的照片以及视频是如何显示在手机上的呢?那就是通过把这个对象添加到UIView的layer上的

###添加扫描设备

  • 获取设备(摄像头)
  • 创建输入设备
  • 创建扫描输出
  • 创建捕捉回话

输出设备

  • 这里使用AVCaptureMetadataOutput, 可以扫描人脸, 二维码, 条形码等信息
  • 必须设置代理, 否则获取不到扫描结果
  • 需要设置要输出什么样的数据: face(人脸), qr(二维码)等等
//创建原数据的输出对象let metadataOutput = AVCaptureMetadataOutput()//设置代理监听输出对象输出的数据,在主线程中刷新metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)//告诉输出对象要输出什么样的数据,识别人脸, 最多可识别10张人脸metadataOutput.metadataObjectTypes = [.face]复制代码

切换摄像头

  • 获取当前摄像头方向
  • 创建新的输入input
  • 移除旧输入capture, 添加新的输入capture
  • 具体代码如下:
@IBAction func switchCameraAction(_ sender: Any) {    //执行转场动画    let anima = CATransition()    anima.type = "oglFlip"    anima.subtype = "fromLeft"    anima.duration = 0.5    view.layer.add(anima, forKey: nil)    //获取当前摄像头    guard let deviceIn = deviceInput else { return }    let position: AVCaptureDevice.Position = deviceIn.device.position == .back ? .front : .back    //创建新的input    let deviceSession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: position)    guard let newDevice = deviceSession.devices.filter({ $0.position == position }).first else { return }    guard let newVideoInput = try? AVCaptureDeviceInput(device: newDevice) else { return }    //移除旧输入,添加新输入    //设备加锁    session.beginConfiguration()    //移除旧设备    session.removeInput(deviceIn)    //添加新设备    session.addInput(newVideoInput)    //设备解锁    session.commitConfiguration()    //保存最新输入    deviceInput = newVideoInput复制代码

处理扫描结果

实现AVCaptureMetadataOutputObjectsDelegate该协议的协议方法(只有一个方法) AVMetadataFaceObject介绍

  1. faceID: 人脸的唯一标识
  • 扫描出来的每一个人, 有不同的faceID
  • 同一个人, 不同的状态下(摇头, 歪头, 抬头等), 都会有不同faceID
  1. hasRollAngle: 是否有倾斜角,侧倾角(左右歪头)(BOOL类型)
  2. rollAngle: 倾斜角,侧倾角的角度(CGFloat类型)
  3. hasYawAngle: 是否有偏转角(左右摇头)
  4. yawAngle: 偏转角角度

获取预览图层的人脸数组

  • 遍历扫描的人脸数组, 转换成在预览图层的人脸数组
  • 主要是人脸在图层的左边的转换
  • 返回转换后的新的数组
fileprivate func transformedFaces(faceObjs: [AVMetadataObject]) -> [AVMetadataObject] {    var faceArr = [AVMetadataObject]()    for face in faceObjs {        //将扫描的人脸对象转成在预览图层的人脸对象(主要是坐标的转换)        if let transFace = previewLayer.transformedMetadataObject(for: face){            faceArr.append(transFace)        }    }    return faceArr}复制代码

根据人脸位置添加红框

设置红框的frame

faceLayer?.frame = face.bounds复制代码

根据偏转角和倾斜角的角度获取CATransform3D

fileprivate func transformDegress(yawAngle: CGFloat) -> CATransform3D {        let yaw = degreesToRadians(degress: yawAngle)        //围绕Y轴旋转        let yawTran = CATransform3DMakeRotation(yaw, 0, -1, 0)        //红框旋转问题        return CATransform3DConcat(yawTran, CATransform3DIdentity)    }    //处理偏转角问题    fileprivate func transformDegress(rollAngle: CGFloat) -> CATransform3D {        let roll = degreesToRadians(degress: rollAngle)        //围绕Z轴旋转        return CATransform3DMakeRotation(roll, 0, 0, 1)    }    //角度转换    fileprivate func degreesToRadians(degress: CGFloat) -> CGFloat{        return degress * CGFloat(Double.pi) / 180    }复制代码

根据有无偏转角和倾斜角旋转红框

//设置偏转角(左右摇头)if face.hasYawAngle{    let tranform3D = transformDegress(yawAngle: face.yawAngle)    //矩阵处理    faceLayer?.transform = CATransform3DConcat(faceLayer!.transform, tranform3D)}//设置倾斜角,侧倾角(左右歪头)if face.hasRollAngle{    let tranform3D = transformDegress(rollAngle: face.rollAngle)    //矩阵处理    faceLayer?.transform = CATransform3DConcat(faceLayer!.transform, tranform3D)}复制代码

至此, 动态的人脸识别就完成了, 会在人脸位置增加红框显示, 并且红框会根据人脸的位置动态的, 实时的调整

下面就快拿起你的相机测试吧

转载于:https://juejin.im/post/5ce3d9976fb9a07eef69e1a2

你可能感兴趣的文章
ES6的一些文章
查看>>
LeetCode 198, 213 House Robber
查看>>
New Year Permutation(Floyd+并查集)
查看>>
Qt编写输入法V2018超级终结版
查看>>
<context:component-scan>详解
查看>>
DS博客作业07--查找
查看>>
[JOI2017] サッカー (Soccer)
查看>>
Git 方法
查看>>
[Python] numpy.nonzero
查看>>
2016-11-29
查看>>
C#反射的坑
查看>>
css3 box-shadow阴影(外阴影与外发光)讲解
查看>>
时间助理 时之助
查看>>
nginx快速安装
查看>>
自定义转场动画
查看>>
英国征召前黑客组建“网络兵团”
查看>>
Silverlight 2.5D RPG游戏“.NET技术”技巧与特效处理:(十二)魔法系统
查看>>
[NPM] Run npm scripts in series
查看>>
vs2013修改书签(vs书签文件位置)
查看>>
C语言学习笔记
查看>>