基于CoreML和ARKit,建立人脸检

全文共字,预计学习时长10分钟

本文将详细介绍一个人脸检测与识别系统的创建过程。

创建单视图应用程序

首先,需要用单视图应用程序创建iOS的项目:

创建单视图应用程序

创建一个新的项目之后,我们计划用纯代码的应用程序来实现,不需要来回切换的按键或开关。

首先要删除main.storyboard,并按如下所示设置AppDelegate.swift文件:

funcapplication(_application:UIApplication,didFinishLaunchingWithOptionslaunchOptions:[UIApplication.LaunchOptionsKey:Any]?)-Bool{

//在应用程序启动后覆盖自定义点。

window=UIWindow(frame:UIScreen.main.bounds)

窗口?.makeKeyAndVisible()

让controller=ViewController()

window?.rootViewController=controller

返回true

}

AppDelegate.swift

确保从部署信息中删除主函数故事板。

创建镜头并添加到子视图中

视图控制器只有一个,这是应用程序的主要切入点。

在此阶段,需要引入ARKit并把ARSCNView实例化,自动将摄像机设备的实时视频源变成镜头背景。此外,还能让SceneKit摄像机自动与设备的现实动作相匹配,这意味着不再需要用锚来追踪添加到镜头的物体位置。

提供屏幕边界使摄像机会话占据整个屏幕:

让sceneView=ARSCNView(frame:UIScreen.main.bounds)

ARSCNView实例化

在ViewDidLoad函数中,要建立诸如委托函数之类的东西,还需要观察帧统计信息从而监控是否有丢罗的情况:

self.view.addSubview(sceneView)//将场景添加到子视图中

sceneView.delegate=self//为视图控制器设置委托

sceneView.showsStatistics=true//显示统计信息

在ViewDidLoad函数中设置镜头

开启AR人脸跟踪配置会话

现在需要以AR人脸跟踪配置开启会话,该配置可以让我们使用iPhoneX,Xs,和Xr专用的前置TrueDepth相机。以下是来自苹果公司的详细解释:

人脸跟踪配置通过设备的前置摄像头检测用户面部。运行该配置时,AR会话检测用户面部(如果在前置摄像头画面可见),将代表人脸的AR面锚添加到锚定列表。面锚会提供关于人脸的位置与方向,其拓扑结构以及描述面部表情特征的信息。

ViewDidLoad函数示例:

overridefuncviewDidLoad(){

super.viewDidLoad()

self.view.addSubview(sceneView)

sceneView.delegate=self

sceneView.showsStatistics=true

警卫ARFaceTrackingConfiguration.isSupportedelse{return}

letconfiguration=ARFaceTrackingConfiguration()

configuration.isLightEstimationEnabled=true

sceneView.session.run(配置,选项:[。resetTracking,.removeExistingAnchors])

}

viewDidLoad中()函数

训练人脸识别模型

创建CoreML兼容的.mlmodel文件函数很多,在此介绍使用较为普遍的:

1.Turicreate:简化了自定义机器学习模型研发的python库,更重要的是可以将模型输出到.mlmodel文件,用Xcode进行语法分析。

2.MLImageClassifierBuilder():这是一个内置的可以随时使用的解决方法,通过Xcode连接到大量拖放界面,对相简单的模型进行训练。

MLImageClassifierBuilder

因为没有大型数据库,所以我们创建了大量模型测试这两种解决方法,最后决定使用MLImageClassifierBuilder(),设有67张“OmarMHAIMDAT”的照片(也就是我),还有在unsplash上找到的张陌生面孔。

打开操场上输入以下代码:

导入CreateMLUI

让builder=MLImageClassifierBuilder()

builder.showInLiveView()

MLImageClassifierBuilder

建议最高迭代次数设为20,再进行剪裁增强,每张图像会添加4个剪裁图像实例。

捕获帧并添加到模型中

需要用镜头委托ARSCNViewDelegate来扩展的ViewController,这得用到两种委托函数,一个用于人脸检测设置,另一个在检测到人脸时更新镜头:

人脸检测:

func渲染器(_渲染器:SCNSceneRenderer,nodeForanchor:ARAnchor)-SCNNode?{

guardletdevice=sceneView.deviceelse{

返回零

}

让faceGeometry=ARSCNFaceGeometry(设备:设备)

letnode=SCNNode(geometry:faceGeometry)

node.geometry?.firstMaterial?.fillMode=.lines

返回节点

}

人脸检测

很遗憾,镜头并没有在我们睁眼或者张嘴时更新。这种情况下,就得相应地更新镜头。

更新镜头:

funcrenderer(_renderer:SCNSceneRenderer,didUpdatenode:SCNNode,foranchor:ARAnchor){

警卫让faceAnchor=锚定为?ARFaceAnchor,

让faceGeometry=node.geometry为?ARSCNFaceGeometryelse{

返回

}

faceGeometry.update(来自:faceAnchor.geometry)

提取整个面部的几何结构信息,更新节点。

获取相机的帧:

既然ARSCNView承自AVCaptureSession,那就可以获得cvPixelFuffer填充入模型。

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

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

将相机的帧添加到模型:

到这一步,可以检测到人脸了,相机的帧也已完备,接下来就能为模型填充内容了:

警卫让模特=试试?VNCoreMLModel(for:FaceRecognition3()。model)else{

fatalError(“无法加载模型”)

}

让coreMlRequest=VNCoreMLRequest(model:model){[weakself]request,errorin

警卫让结果=request.results为?[VNClassificationObservation]

让topResult=results.first

其他{

fatalError(“意外结果”)

}

DispatchQueue.main.async{[弱自我]in

打印(topResult.identifier)

}

}

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

lethandler=VNImageRequestHandler(cvPixelBuffer:pixelBuffer,options:[:])

DispatchQueue.global()。async{

做{

尝试handler.perform([coreMlRequest])

}catch{

打印(错误)

}

}

didUpdate渲染器

显示被识别者的姓名

最后一个恼人的部分就是把3D文本投射到识别的人脸上。我们稍加思考就会想到,配置不如ARWorldTrackingConfiguration功能那么强,提供的函数和类并不多。用前置摄像头代替,能实现的功能有限。

尽管不能跟踪面部动作并进行相应的改变,但我们仍能将3D文本投射到屏幕上。

lettext=SCNText(string:“”,extrusionDepth:2)

letfont=UIFont(名称:“Avenir-Heavy”,大小:18)

text.font=font

letmaterial=SCNMaterial()

material.diffuse.contents=UIColor.black

text.materials=[material]

text.firstMaterial?.isDoubleSided=true

lettextNode=SCNNode(geometry:faceGeometry)

textNode.position=SCNVector3(-0.1,-0.01,-0.5)

textNode.scale=SCNVector3(0.,0.,0.)

textNode.geometry=tex

SCNText示例

有了SCNText对象后,需要随着相应的人脸进行更新,然后添加到根节点:

让coreMlRequest=VNCoreMLRequest(model:model){[weakself]request,errorin

警卫让结果=request.results为?[VNClassificationObservation]

让topResult=results.first

其他{

fatalError(“意外结果”)

}

DispatchQueue.main.async{[弱自我]in

打印(topResult.identifier)

iftopResult.identifier!=“Unknown”{

text.string=topResult.identifier

自我!.sceneView.scene.rootNode.addChildNode(textNode)

self!.sceneView.autoenablesDefaultLighting=true

}

}

}

最终结果

人脸检测与识别系统成果展示。

项目


转载请注明:http://www.aierlanlan.com/tzrz/1599.html

  • 上一篇文章:
  •   
  • 下一篇文章: