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

使用CoreML和ARKit进行人脸检测和识别_第1张图片

作者 | Omar M'Haimdat

来源 | Medium

编辑 | 代码医生团队

创建单视图应用程序

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


使用CoreML和ARKit进行人脸检测和识别_第2张图片

创建一个视图应用程序

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

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

funcapplication(_application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey:Any]?)->Bool{// Override point for customization after application launch.window =UIWindow(frame:UIScreen.main.bounds)        window?.makeKeyAndVisible()letcontroller =ViewController()        window?.rootViewController = controller        returntrue    }

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


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

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

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

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

letsceneView = ARSCNView(frame: UIScreen.main.bounds)

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

self.view.addSubview(sceneView)// add the scene to the subviewsceneView.delegate =self// Setting the delegate for our view controllersceneView.showsStatistics =true// Show statistics

开始一个ARFaceTrackingConfiguration会话

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

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


ViewDidLoad方法应如下所示:

overridefuncviewDidLoad(){super.viewDidLoad()self.view.addSubview(sceneView)sceneView.delegate =selfsceneView.showsStatistics =trueguardARFaceTrackingConfiguration.isSupportedelse{return}letconfiguration =ARFaceTrackingConfiguration()configuration.isLightEstimationEnabled =true        sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])    }

训练人脸识别模型

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

Turicreate:它是python库,简化了自定义机器学习模型的开发,更重要的是,可以将模型导出到可由Xcode解析的.mlmodel文件中。

MLImageClassifierBuilder():它是一个内置的解决方案,提供Xcode开箱即用,可以访问几乎一个拖放界面来训练一个相对简单的模型。

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


使用CoreML和ARKit进行人脸检测和识别_第3张图片

MLImageClassifierBuilder

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

https://unsplash.com/


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

importCreateMLUI letbuilder =MLImageClassifierBuilder()builder.showInLiveView()

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

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

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

人脸检测:

funcrenderer(_renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor)->SCNNode? {        guardletdevice = sceneView.deviceelse{returnnil        }        letfaceGeometry =ARSCNFaceGeometry(device: device)        letnode =SCNNode(geometry: faceGeometry)                node.geometry?.firstMaterial?.fillMode = .lines        returnnode    }

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


更新场景:

funcrenderer(_renderer: SCNSceneRenderer, didUpdate node: SCNNode,foranchor: ARAnchor){        guardletfaceAnchor = anchoras?ARFaceAnchor,letfaceGeometry = node.geometryas?ARSCNFaceGeometryelse{return        }                faceGeometry.update(from: faceAnchor.geometry)}

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

获取相机框架:

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

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

guardletpixelBuffer =self.sceneView.session.currentFrame?.capturedImageelse{return}

将相机框架注入模型:

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

guardletmodel =try?VNCoreMLModel(for:FaceRecognition3().model)else{fatalError("Unable to load model")        }        letcoreMlRequest =VNCoreMLRequest(model: model) {[weakself] request, erroringuardletresults = request.resultsas? [VNClassificationObservation],lettopResult = results.firstelse{fatalError("Unexpected results")            } DispatchQueue.main.async {[weakself]inprint(topResult.identifier)            }        }        guardletpixelBuffer =self.sceneView.session.currentFrame?.capturedImageelse{return}                lethandler =VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])DispatchQueue.global().async {do{tryhandler.perform([coreMlRequest])}catch{print(error)            }        }

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

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

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

let text =SCNText(string:"", extrusionDepth:2)let font =UIFont(name:"Avenir-Heavy", size:18)text.font = fontlet material =SCNMaterial()material.diffuse.contents =UIColor.blacktext.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:

letcoreMlRequest =VNCoreMLRequest(model: model) {[weakself] request, erroringuardletresults = request.resultsas? [VNClassificationObservation],lettopResult = results.firstelse{fatalError("Unexpected results")            } DispatchQueue.main.async {[weakself]inprint(topResult.identifier)iftopResult.identifier !="Unknown"{                    text.string = topResult.identifierself!.sceneView.scene.rootNode.addChildNode(textNode)self!.sceneView.autoenablesDefaultLighting =true                }            }        }

最后结果:

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

视频

该项目可从Github帐户下载

https://github.com/omarmhaimdat/WhoAreYou

你可能感兴趣的:(使用CoreML和ARKit进行人脸检测和识别)