前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用CoreML和ARKit进行人脸检测和识别

使用CoreML和ARKit进行人脸检测和识别

作者头像
代码医生工作室
发布2019-08-05 11:47:12
2.3K0
发布2019-08-05 11:47:12
举报
文章被收录于专栏:相约机器人相约机器人

作者 | Omar M'Haimdat

来源 | Medium

编辑 | 代码医生团队

创建单视图应用程序

首先,需要使用单个视图应用创建一个iOS项目:

创建一个视图应用程序

现在已经拥有了自己的项目,并且因为不喜欢使用故事板,所以应用程序以编程方式完成,这意味着没有按钮或开关切换,只需要纯粹的代码。

必须删除main.storyboard并设置您的AppDelegate.swift文件,如下所示:

代码语言:javascript
复制
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.makeKeyAndVisible()
        let controller = ViewController()
        window?.rootViewController = controller
        
        return true
    }

确保从部署信息中删除故事板“Main”。

创建场景并将其添加到子视图

只有一个ViewController,它将是应用程序的主要入口点。

在这个阶段,需要导入ARKit并实例化一个ARSCNView自动渲染来自设备相机的实时视频作为场景背景。它还会自动移动其SceneKit摄像头以匹配设备的真实世界移动,这意味着不需要锚点来跟踪我们添加到场景中的对象的位置。

需要给它屏幕边界,以便摄像机会话占据整个屏幕:

代码语言:javascript
复制
let sceneView = ARSCNView(frame: UIScreen.main.bounds)

在该ViewDidLoad方法中,将设置一些内容,例如委托,还需要查看帧统计信息以监视帧丢弃:

代码语言:javascript
复制
self.view.addSubview(sceneView) // add the scene to the subview
sceneView.delegate = self // Setting the delegate for our view controller
sceneView.showsStatistics = true // Show statistics

开始一个ARFaceTrackingConfiguration会话

现在需要开始一个会话ARFaceTrackingConfiguration,这个配置让可以访问仅适用于iPhone X,Xs和Xr的前置TrueDepth摄像头。以下是Apple文档中的更详细说明:

面部跟踪配置会根据设备的前置摄像头检测用户的脸部。运行此配置时,AR会话将检测用户的面部(如果在前置摄像头图像中可见),并在其锚点列表中添加表示面部的ARFaceAnchor对象。每个面部锚点提供有关面部位置和方向,其拓扑以及描述面部表情的特征的信息。

ViewDidLoad方法应如下所示:

代码语言:javascript
复制
override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(sceneView)
        sceneView.delegate = self
        sceneView.showsStatistics = true
        guard ARFaceTrackingConfiguration.isSupported else { return }
        let configuration = ARFaceTrackingConfiguration()
        configuration.isLightEstimationEnabled = true
        sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
    }

训练人脸识别模型

有多种方法可以创建与CoreML兼容的.mlmodel文件,这些是常见的:

  1. Turicreate:它是python库,简化了自定义机器学习模型的开发,更重要的是,可以将模型导出到可由Xcode解析的.mlmodel文件中。
  2. MLImageClassifierBuilder():它是一个内置的解决方案,提供Xcode开箱即用,可以访问几乎一个拖放界面来训练一个相对简单的模型。

https://pypi.org/project/turicreate/?source=post_page---------------------------

MLImageClassifierBuilder

已经创建了多个模型来测试这两个解决方案,因为没有大数据集,决定使用MLImageClassifierBuilder()和一组67个图像,这些图像是'Omar MHAIMDAT '和一组261 在unsplash上找到的'未知'的面孔。

https://unsplash.com/

打开游乐场并编写此代码:

代码语言:javascript
复制
import CreateMLUI
 
let builder = MLImageClassifierBuilder()
builder.showInLiveView()

建议将最大迭代次数设置为20并添加裁剪增强,这将为每个图像添加4个裁剪图像实例。

捕获相机帧并将其注入模型

需要使用场景委托来扩展ViewController ARSCNViewDelegate。需要两个委托方法,一个用于设置面部检测,另一个用于在检测到面部时更新场景:

人脸检测:

代码语言:javascript
复制
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        
        guard let device = sceneView.device else {
            return nil
        }
        
        let faceGeometry = ARSCNFaceGeometry(device: device)
        
        let node = SCNNode(geometry: faceGeometry)
        
        node.geometry?.firstMaterial?.fillMode = .lines
        
        return node
    }

不幸的是,当睁开眼睛或嘴巴时,场景不会更新。在这种情况下,需要相应地更新场景。

更新场景:

代码语言:javascript
复制
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
        
        guard let faceAnchor = anchor as? ARFaceAnchor,
            let faceGeometry = node.geometry as? ARSCNFaceGeometry else {
                return
        }
        
        faceGeometry.update(from: faceAnchor.geometry)
}

采用整个面几何和映射,并更新节点。

获取相机框架:

这很有趣,因为ARSCNView继承自AVCaptureSession,意味着可以得到一个cvPixelFuffer可以提供模型。

这是从sceneView属性中获取它的简单方法:

代码语言:javascript
复制
guard let pixelBuffer = self.sceneView.session.currentFrame?.capturedImage else { return }

将相机框架注入模型:

现在可以检测到面部并拥有每个相机框架,已准备好为模型提供一些内容:

代码语言:javascript
复制
guard let model = try? VNCoreMLModel(for: FaceRecognition3().model) else {
            fatalError("Unable to load model")
        }
        
        let coreMlRequest = VNCoreMLRequest(model: model) {[weak self] request, error in
            guard let results = request.results as? [VNClassificationObservation],
                let topResult = results.first
                else {
                    fatalError("Unexpected results")
            }
 
            DispatchQueue.main.async {[weak self] in
                print(topResult.identifier)
            }
        }
        
        guard let pixelBuffer = self.sceneView.session.currentFrame?.capturedImage else { return }
        
        
        let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])
        DispatchQueue.global().async {
            do {
                try handler.perform([coreMlRequest])
            } catch {
                print(error)
            }
        }

在识别的脸部上方显示名称

最后也可能是最令人沮丧的部分是在识别出的脸部上方投射3D文本。如果考虑一下,配置就不如ARWorldTrackingConfiguration能够访问众多方法和类的功能那样强大。使用的是前置摄像头,可以实现的功能很少。

尽管如此,仍然可以在屏幕上投影3D文本,但它不会跟踪面部运动并相应地进行更改。

代码语言:javascript
复制
let text = SCNText(string: "", extrusionDepth: 2)
let font = UIFont(name: "Avenir-Heavy", size: 18)
text.font = font
let material = SCNMaterial()
material.diffuse.contents = UIColor.black
text.materials = [material]
text.firstMaterial?.isDoubleSided = true
        
let textNode = SCNNode(geometry: faceGeometry)
textNode.position = SCNVector3(-0.1, -0.01, -0.5)
textNode.scale = SCNVector3(0.002, 0.002, 0.002)
textNode.geometry = text

现在有了SCNText对象,需要使用相应的face更新它并将其添加到rootNode:

代码语言:javascript
复制
      let coreMlRequest = VNCoreMLRequest(model: model) {[weak self] request, error in
            guard let results = request.results as? [VNClassificationObservation],
                let topResult = results.first
                else {
                    fatalError("Unexpected results")
            }
 
            DispatchQueue.main.async {[weak self] in
                print(topResult.identifier)
                if topResult.identifier != "Unknown" {
                    text.string = topResult.identifier
                    self!.sceneView.scene.rootNode.addChildNode(textNode)
                    self!.sceneView.autoenablesDefaultLighting = true
                }
            }
        }

最后结果:

这是面部检测和识别的最终结果。

该项目可从Github帐户下载

https://github.com/omarmhaimdat/WhoAreYou

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 相约机器人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档