ARKit系列文章目录git
The Parallax View是个国外开发者开发的好玩的软件,它利用iPhoneX实现了裸眼3D的效果. github
经过使用ARKit和iPhone X进行3D头部追踪来得到深度幻象。swift
为得到最佳效果,应该只打开一只眼睛(该应用容许选择要追踪的眼睛,或者能够尝试自动选择眼睛)session
经过跟踪用户头部方向和位置,能够找到3D中的眼睛位置。app
应用能够在该显示器上呈现从该位置看到的正确视图。框架
为了呈现该视图,使用离轴投影(非对称相机平截头体)。编辑器
这给人一种错觉,即物体出如今屏幕的前面和后面。post
受此启发,我尝试在非iPhoneX设备上用人脸识别框架来实现低精度的裸眼3D效果. 原理是:测试
本来打算,用识别出人脸的大小,作为依据来判断摄像机在z轴上的位置,但测试中发现,人脸识别出的大小变化很大,无规律可转换.ui
原来觉得苹果的新框架Vision会更好,结果在个人iPhone SE上很是卡,并且Vision框架在识别人脸时对方向有要求,须要指定方向.全部最后仍是使用了AVFoundation中的metadataObjectTypes来识别.
if session.canAddOutput(metaDataOutput) {
session.addOutput(metaDataOutput)
}
//7.AVFoundation框架识别类型
metaDataOutput.metadataObjectTypes = [.face]
复制代码
在代理方法中处理识别到的人脸:
//AV框架人脸识别
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
for obj in metadataObjects {
if obj.type == .face {
print("face---\(obj.bounds)")
// 坐标转换
let oldRect = obj.bounds;
let w = oldRect.size.height * self.previewView.bounds.size.width;
let h = oldRect.size.width * self.previewView.bounds.size.height;
let x = oldRect.origin.y * self.previewView.bounds.size.width;
let y = oldRect.origin.x * self.previewView.bounds.size.height;
// 添加矩形
rectLayer.frame = CGRect(x: x, y: y, width: w, height: h)
rectLayer.isHidden = false
//凑出合理的数据
let cameraX = (oldRect.origin.y - 0.3) * 2
let cameraY = (0.4 - oldRect.origin.x) * 2
// 移动摄像机
self.cameraNode.position = SCNVector3(cameraX, cameraY, 20)
}else {
rectLayer.isHidden = true
}
}
}
复制代码
效果初步有了:
可是咱们还应该看到,咱们的3D效果是经过直接移动摄像机的位置来实现,摄像机的视野范围并无改变,因此看上去像是透过窗户看后面的景物,而不是像The Parallax View那样,3D物体像是与手机屏幕绑在一块儿.
最主要缘由是:The Parallax View使用了离轴投影(非对称相机平截头体)处理摄像机看到的物体范围,以下图,不论如何移动,FOV(Field Of View)都始终对齐了底座的四个角:
在SceneKit中,是能够给camera设置自定义的投影变换矩阵的 self.cameraNode.camera?.projectionTransform
苹果也给出了说明,一旦设置该项,则对摄像机设置的 zFar
,zNear
, 和fieldOfView
都会失效,缘由是这些值没法从矩阵中获得(数学上不可逆). 另外须要注意的是:ARKit中的ARSCNView类会重写这个投影变换,因此不要在AR应用中修改.
若是有深厚的3D数学功底,只要重写这个投影变换矩阵,就能够获得离轴投影效果,惋惜我如今不会,相关配置还须要研究,之后更新.
代码地址NakedEye3D