iOS ARKit教程:用裸露的手指在空中画画

最近,Apple公布了名为ARKit的新增强现实(AR)库。对于许多人来说,它看起来只是另一个优秀的AR库,而不是一个值得关注的技术破坏者。但是,如果你看一下过去几年的AR进展,就不应该太快得出这样的结论。

iOS ARKit教程:用裸露的手指在空中画画_第1张图片
ARKit教程插图:在iOS ARKit应用程序中与虚拟对象交互

在这篇文章中,我们将使用iOS ARKit创建一个有趣的ARKit示例项目。用户将手指放在桌子上,好像他们握笔,点击缩略图并开始绘图。完成后,用户将能够将其绘图转换为3D对象,如下面的动画所示。我们的iOS ARKit示例的完整源代码可以在GitHub上找到。

image

我们为什么要关注iOS ARKit?

每个有经验的开发人员都可能意识到AR是一个古老的概念。我们可以确定AR的第一次严重开发,以便开发人员可以从网络摄像头访问各个帧。当时的应用通常用于改变你的面貌。然而,人类并没有花很长时间才意识到将面孔变成兔子并不是他们最迫切的需求之一,很快就会褪色!

我相信AR一直缺少两个关键的技术飞跃,使它变得有用:可用性和沉浸感。如果您追踪其他AR炒作,您会注意到这一点。例如,当开发人员从移动摄像头访问各个帧时,AR炒作再次起飞。除了伟大的兔子变形金刚的强大回归,我们看到一波应用程序在打印的QR码上放下3D对象。但他们从未作为一个概念起飞。它们不是增强现实,而是增强QR码。

然后谷歌用一部科幻小说谷歌玻璃让我们感到惊讶。两年过去了,当这个神奇的产品有望复活时,它已经死了!许多评论家分析了谷歌眼镜失败的原因,将责任归咎于从社交方面到谷歌推出该产品的枯燥方法。但是,我们在这篇文章中关注的原因有一个 - 沉浸在环境中。虽然Google Glass解决了可用性问题,但它仍然只是在空中绘制的2D图像。

像微软,Facebook和苹果这样的科技巨头心中学到了这个苛刻的教训。2017年6月,Apple公布了其漂亮的iOS ARKit库,将沉浸感放在首位。拿着电话仍然是一个很大的用户体验拦截器,但Google Glass的教训告诉我们硬件不是问题。

我相信我们很快就会走向一个新的AR炒作高峰,通过这个新的重要支点,它最终可以找到它的本土市场,让增强现实应用程序开发成为主流。

但是有足够的历史,让我们用代码弄脏手,看看苹果增强现实!

ARKit浸入式功能

ARKit提供两个主要功能; 第一个是3D空间中的摄像机位置,第二个是水平面检测。为了实现前者,ARKit假设您的手机是在真实3D空间中移动的相机,因此在任何点丢弃一些3D虚拟对象将锚定到真实3D空间中的该点。对于后者,ARKit会检测水平平面,如表格,以便您可以在其上放置对象。

那么ARKit如何实现这一目标呢?这是通过一种名为Visual Inertial Odometry(VIO)的技术完成的。别担心,就像企业家在你弄清楚他们的创业公司名称背后的傻笑一样发现他们的笑声时,研究人员发现他们试图解读他们提出的任何术语的头部划痕的数量。命名他们的发明 - 让我们让他们享受他们的乐趣,继续前进。

VIO是一种技术,通过该技术,相机框架与运动传感器融合,以跟踪设备在3D空间中的位置。通过检测特征,或者换句话说,图像中具有高对比度的边缘点(例如蓝色花瓶和白色桌子之间的边缘)来跟踪来自相机帧的运动。通过检测这些点相对于彼此从一帧移动到另一帧的程度,可以估计设备在3D空间中的位置。这就是为什么ARKit在面向无特征的白色墙壁时放置时或者当设备移动得非常快而导致图像模糊时无法正常工作的原因。

iOS中的ARKit入门

截至撰写本文时,ARKit是iOS 11的一部分,它仍处于测试阶段。因此,要开始使用,您需要在iPhone 6s或更高版本以及新的Xcode Beta上下载iOS 11 Beta。我们可以从New> Project> Augmented Reality App开始一个新的ARKit项目。但是,我发现使用官方Apple ARKit示例启动此增强现实教程更方便,该示例提供了一些基本代码块,尤其有助于平面检测。那么,让我们从这个示例代码开始,先解释其中的要点,然后为我们的项目修改它。

首先,我们应该确定我们将使用哪种引擎。ARKit可以与Sprite SceneKit或Metal一起使用。在Apple ARKit示例中,我们使用的是Apple SceneKit,这是Apple提供的3D引擎。接下来,我们需要设置一个可以渲染3D对象的视图。这是通过添加类型视图来完成的ARSCNView

ARSCNView是一个名为SceneKit主视图的子类SCNView,但它使用一些有用的功能扩展了视图。它将来自设备相机的实时视频输入渲染为场景背景,同时它自动将SceneKit空间与现实世界相匹配,假设该设备是这个世界中移动的相机。

ARSCNView它本身不进行AR处理,但它需要一个AR会话对象来管理设备摄像头和运动处理。所以,首先,我们需要分配一个新的会话:

上面的最后一行添加了一个可视指示器,可以直观地帮助用户描述平面检测的状态。Focus Square由示例代码提供,而不是ARKit库,这是我们开始使用此示例代码的主要原因之一。您可以在示例代码中包含的自述文件中找到有关它的更多信息。下图显示了投影在桌子上的焦点方块:

iOS ARKit教程:用裸露的手指在空中画画_第2张图片
使用Apple ARKit将焦点正方形投影在桌子上

下一步是启动ARKit会话。每次出现视图时重新启动会话都是有意义的,因为如果我们不再跟踪用户,我们就可以不使用以前的会话信息。所以,我们将在viewDidAppear中启动会话:

在上面的代码中,我们首先设置ARKit会话配置来检测水平平面。在撰写本文时,Apple不提供除此之外的选项。但显然,它暗示将来会发现更复杂的物体。然后,我们开始运行会话并确保我们重置跟踪。

最后,每当摄像机位置(即实际设备方向或位置)发生变化时,我们都需要更新焦点广场。这可以在SCNView的渲染器委托功能中完成,每次要渲染3D引擎的新帧时都会调用它:

此时,如果您运行应用程序,您应该会在相机流上看到焦点方块搜索水平平面。在下一节中,我们将解释如何检测平面,以及如何相应地定位焦点平方。

在ARKit中检测平面

ARKit可以检测新平面,更新现有平面或删除它们。为了以方便的方式处理平面,我们将创建一个虚拟的SceneKit节点,该节点保存平面位置信息和对焦点方块的引用。平面在X和Z方向上定义,其中Y是表面的法线,即,如果我们想让它看起来好像在平面上打印,我们应该始终将我们的绘图节点位置保持在平面的相同Y值内。 。

平面检测通过ARKit提供的回调函数完成。例如,每当检测到新平面时,都会调用以下回调函数:

回调函数为我们提供了两个参数,anchornodenode是一个正常的SceneKit节点,放置在平面的确切位置和方向。它没有几何形状,因此它是不可见的。我们使用它来添加我们自己的平面节点,该节点也是不可见的,但保存有关平面方向和位置的信息anchor

那么如何保存位置和方向 ARPlaneAnchor?位置,方向和比例均以4x4矩阵编码。如果我有机会选择一个数学概念供你学习,那毫无疑问就是矩阵。无论如何,我们可以通过如下描述这个4x4矩阵来避免这种情况:一个包含4x4浮点数的明亮的二维数组。通过将这些数字以某种方式乘以3D顶点v1,在其局部空间中,它会生成一个新的3D顶点v2,它代表世界空间中的v1。因此,如果v1 =(1,0,0)在其局部空间中,并且我们希望将其置于世界空间中的x = 100,则v2将相对于世界空间等于(101,0,0)。当然,当我们添加关于轴的旋转时,这背后的数学变得更加复杂,但好消息是我们可以在不理解它的情况下做到(我强烈建议从中检查相关部分)这篇优秀文章深入解释了这个概念)。

checkIfObjectShouldMoveOntoPlane 检查我们是否已经绘制了对象并检查所有这些对象的y轴是否与新检测到的平面的y轴相匹配。

现在,回到上updateFocusSquare()一节中描述的。我们希望将焦点方块保持在屏幕的中心,但是投影在最近的检测平面上。下面的代码演示了这一点:

sceneView.hitTest通过将此2D点投影到最近的平面下方,搜索与屏幕视图中的2D点对应的真实平面。result.worldTransform是一个4x4矩阵,它保存检测到的平面的所有变换信息,同时result.worldTransform.translation是一个只返回位置的便捷函数。

现在,我们获得了在屏幕上给出2D点的情况下在检测到的曲面上放置3D对象所需的所有信息。那么,让我们开始画画。

画画

让我们首先解释在计算机视觉中绘制跟随人类手指的形状的方法。绘制形状是通过检测移动手指的每个新位置,在该位置放下顶点,以及将每个顶点与前一个顶点连接来完成的。如果我们需要平滑输出,顶点可以通过简单的线连接,或通过贝塞尔曲线连接。

为简单起见,我们将采用一些天真的绘图方法。对于手指的每个新位置,我们将在检测到的计划上放下一个圆角非常小的盒子,高度几乎为零。它看起来好像是一个点。一旦用户完成绘制并选择3D按钮,我们将根据用户手指的移动更改所有掉落对象的高度。

以下代码显示了PointNode表示点的类:

您将在上面的代码中注意到我们将几何体沿y轴平移了一半的高度。这样做的原因是为了确保对象的底部始终位于y = 0,以便它出现在平面上方。

接下来,在SceneKit的渲染器回调函数中,我们将使用相同的PointNode类绘制一些像笔尖点一样的指示器。如果启用了绘图,我们将在该位置放置一个点,或者如果启用了3D模式,则将绘图提升为3D结构:

virtualObjectManager是一个管理绘制点的类。在3D模式中,我们估计与最后位置的差异,并使用该值增加/减少所有点的高度。

到目前为止,我们正在绘制检测到的表面,假设虚拟笔位于屏幕的中心。现在为了有趣的部分 - 检测用户的手指并使用它而不是屏幕中心。

检测用户的指尖

Apple在iOS 11中引入的一个很酷的库是Vision Framework。它以非常方便和有效的方式提供了一些计算机视觉技术。特别是,我们将使用对象跟踪技术来实现增强现实教程。对象跟踪的工作原理如下:首先,我们为它们提供一个图像和一个正方形的坐标,用于我们想要跟踪的对象的图像边界。之后我们调用一些函数来初始化跟踪。最后,我们输入一个新图像,其中该对象的位置发生变化,并且前一个操作的分析结果也是如此。鉴于此,它将返回对象的新位置。

我们将使用一个小技巧。我们将要求用户将他们的手放在桌子上,就像他们握笔一样,并确保他们的缩略图面向相机,之后他们应该点击屏幕上的缩略图。这里有两点需要详述。首先,缩略图应具有足够的独特功能,可通过白色缩略图,皮肤和表格之间的对比来追踪。这意味着较深的皮肤色素将导致更可靠的跟踪。其次,由于用户将他们的手放在桌子上,并且由于我们已经将桌子检测为平面,因此将缩略图的位置从2D视图投影到3D环境将导致手指的几乎准确位置。表。

下图显示了Vision库可以检测到的功能点:

iOS ARKit教程:用裸露的手指在空中画画_第3张图片
iOS ARKit Vision库检测到的要素点

我们将按照以下步骤初始化缩略图跟踪:

上面最棘手的部分是如何将点击位置从UIView坐标空间转换为图像坐标空间。ARKit为我们提供了displayTransform从图像坐标空间转换到视口坐标空间的矩阵,但不是相反。那么我们怎么做反过来呢?通过使用矩阵的逆。我真的试图在这篇文章中尽量减少对数学的使用,但在3D世界中它有时是不可避免的。

接下来,在渲染器中,我们将以新图像的形式输入以跟踪手指的新位置:

一旦对象跟踪完成,它将调用回调函数,我们将在其中更新缩略图位置。它通常是在点击识别器中编写的代码的反转:

最后,我们将self.lastFingerWorldPos在绘图时使用而不是屏幕中心,我们就完成了。

ARKit和未来

在这篇文章中,我们已经演示了AR如何通过与用户手指和现实生活表的交互来沉浸其中。随着计算机视觉的进步,以及为小工具(如深度相机)添加更多AR友好的硬件,我们可以访问我们周围越来越多的物体的3D结构。

虽然尚未向大众发布,但值得一提的是微软如何通过其Hololens设备赢得AR竞赛非常认真,该设备将AR定制的硬件与先进的3D环境识别技术相结合。你可以等着看谁将赢得这场比赛,或者你可以通过开发真正的沉浸式增强现实应用程序来参与其中!但请,请人类帮忙,不要将活物变成兔子。

原文:https://www.toptal.com/swift/ios-arkit-tutorial-drawing-in-air-with-fingers
作者:

iOS ARKit教程:用裸露的手指在空中画画_第4张图片
Osama AbdelKarim AboulHassan

Osama AbdelKarim AboulHassan,埃及

你可能感兴趣的:(iOS ARKit教程:用裸露的手指在空中画画)