使用iPhoneX True-Depth相机可以获取任何物体的3D坐标,并使用该信息来定位和缩放物体,但是对于较旧的iPhone,我们无法使用正面相机上的AR,到目前为止,要做的就是使用Apple Vison框架检测面部,并在面部或地标周围绘制一些2D路径。 我制作了一个 SceneView 并将其应用为背景清晰的我的视图的顶层,在它的下方是 AVCaptureVideoPreviewLayer ,在检测到人脸后,我的3D对象出现在屏幕上但是根据面部boundingBox正确定位和缩放它需要未投影的东西和其他卡在其中的东西,我也尝试使用 CATransform3D 将2D BoundingBox转换为3D,但是我失败了!我想知道我是否想要实现?我记得如果我没记错的话,SnapChat就是在ARKit在iPhone上可用之前就已经这样做了!
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.sceneView)
self.sceneView.frame = self.view.bounds
self.sceneView.backgroundColor = .clear
self.node = self.scene.rootNode.childNode(withName: "face",
recursively: true)!
}
fileprivate func updateFaceView(for result:
VNFaceObservation, twoDFace: Face2D) {
let box = convert(rect: result.boundingBox)
defer {
DispatchQueue.main.async {
self.faceView.setNeedsDisplay()
}
}
faceView.boundingBox = box
self.sceneView.scene?.rootNode.addChildNode(self.node)
let unprojectedBox = SCNVector3(box.origin.x, box.origin.y,
0.8)
let worldPoint = sceneView.unprojectPoint(unprojectedBox)
self.node.position = worldPoint
/* Here i have to to unprojecting
to convert the value from a 2D point to 3D point also
issue here. */
}
答案 0 :(得分:0)
我建议您看一下使用后置或前置摄像头支持Apple AR场景的Google AR Core产品...但是,对于非面部深度摄像头设备,它会增加Apple之外的一些其他功能。
Apple的Core Vision与Google的Core Vision框架几乎相同,该框架返回代表眼睛/嘴巴/鼻子等的2D点以及面部倾斜组件。
但是,如果您想要一种简单的方法将2D纹理应用于响应式3D脸部,或者将3D模型附加到脸部上的点,请查看Google的Core Augmented Faces框架。它在iOS和Android上具有出色的示例代码。
答案 1 :(得分:0)
实现此目的的唯一方法是使用带有地形相机的SceneKit,并使用SCNGeometrySource
将Vision的界标与网格的顶点相匹配。
首先,您需要网格具有相同数量的Vision顶点(66-77,具体取决于您所在的Vision Revision)。您可以使用Blender之类的工具来创建一个。
然后,在代码上,每次处理地标时,请执行以下步骤: 1-获取网格顶点:
func getVertices() -> [SCNVector3]{
var result = [SCNVector3]()
let planeSources = shape!.geometry?.sources(for: SCNGeometrySource.Semantic.vertex)
if let planeSource = planeSources?.first {
let stride = planeSource.dataStride
let offset = planeSource.dataOffset
let componentsPerVector = planeSource.componentsPerVector
let bytesPerVector = componentsPerVector * planeSource.bytesPerComponent
let vectors = [SCNVector3](repeating: SCNVector3Zero, count: planeSource.vectorCount)
// [SCNVector3](count: planeSource.vectorCount, repeatedValue: SCNVector3Zero)
let vertices = vectors.enumerated().map({
(index: Int, element: SCNVector3) -> SCNVector3 in
var vectorData = [Float](repeating: 0, count: componentsPerVector)
let byteRange = NSMakeRange(index * stride + offset, bytesPerVector)
let data = planeSource.data
(data as NSData).getBytes(&vectorData, range: byteRange)
return SCNVector3( x: vectorData[0], y: vectorData[1], z: vectorData[2])
})
result = vertices
}
return result
}
2-取消投影Vision捕获的每个地标,并将它们保存在SCNVector3
数组中:
let unprojectedLandmark = sceneView.unprojectPoint( SCNVector3(landmarks[i].x + (landmarks[i].x,landmarks[i].y,0))
3-使用新的顶点修改几何:
func reshapeGeometry(_顶点:[SCNVector3]){
let source = SCNGeometrySource(vertices: vertices)
var newSources = [SCNGeometrySource]()
newSources.append(source)
for source in shape!.geometry!.sources {
if (source.semantic != SCNGeometrySource.Semantic.vertex) {
newSources.append(source)
}
}
let geometry = SCNGeometry(sources: newSources, elements: shape!.geometry?.elements)
let material = shape!.geometry?.firstMaterial
shape!.geometry = geometry
shape!.geometry?.firstMaterial = material
}
我能够做到这一点,这就是我的方法。 希望这会有所帮助!