需求描述:将摄像头预览的数据实时捕获,每一视频帧+时间戳信息+当前摄像机定位信息,传递到服务端。ARKit为我们提供了极为丰富的封装类,极大的便捷了开发。
什么是增强现实?
概览:对于所有的 AR 场景而言,最基本要求是:创建并追踪现实空间和虚拟空间之间的关系,其中,现实空间是用户所处的世界,虚拟空间是可对可视化内容进行建模的世界,这同时也是 ARKit 的基本特征。当您的应用将这些虚拟内容与实时视频结合,并一起显示的时候,用户就可以体验到所谓的「增强现实」:您的虚拟内容成为了真实世界的一部分,尽管这只是「错觉」而已。
全局追踪(World Tracking)
全局追踪对应的其实就是Google Tango 的三大核心功能之一的运动追踪,其目的是一致的,但实现方式略有不同。
为了在现实世界和虚拟世界之间建立对应关系,ARKit 使用了一种被称为视觉惯性里程计的技术。这项技术会将 iOS 设备的动作感测硬件信息,加上对可见场景的计算机视觉分析功能,然后与设备的摄像头相结合。ARKit 将会去识别场景图像当中的显著特征,然后在视频帧中追踪这些特征位置的距离,然后再将这些信息与动作感测数据进行比较。从而生成具备设备位置和动作特征的高精度模型。
全局追踪 (World Tracking) 同样也可以分析和识别场景当中的内容。通过使用点击测试 (hit-testing) 方法(参见ARHitTestResult类),从而找到与相机图像中的某个点所对应的真实世界面。如果您在 Session (会话) 配置当中启用了planeDetection配置的话,那么 ARKit 就会去检测相机图像当中的水平面,并报告其位置和大小。您可以使用点击测试所生成的结果,或者使用所检测到的水平面,从而就可以在场景当中放置虚拟内容,或者与之进行交互。
全局追踪是一项不精确的科学 (inexact science)。尽管在这个过程当中,经常会产生可观的准确度,从而让 AR 的体验更加真实。然而,它严重依赖于设备物理环境的相关细节,而这些细节并不总是一致,有些时候也难以实时测量,这也就导致这些物理细节往往都会存在某种程度的错误。要建立高品质的 AR 体验,那么请注意下述这些注意事项和提示:
基于可见的照明条件来设计 AR 场景。全局追踪涉及到了图像分析的相关内容,因此就需要我们提供清晰的图像。如果摄像头没有办法看到相关的物理细节,比如说摄像头拍到的是一面空空如也的墙壁,或者场景的光线实在太暗的话,那么全局追踪的质量就会大大降低。
根据追踪质量的相关信息来给用户进行反馈提示。全局追踪会将图像分析与设备的动作模式关联起来。如果设备正在移动的话,那么 ARKit 就可以更好地对场景进行建模,这样即便设备只是略微晃动,也不 会影响追踪质量。但是一旦用户的动作过多、过快或者晃动过于激烈,就会导致图像变得模糊,或者导致视频帧中要追踪的特征之间的距离过大,从而致使追踪质量的降低。ARCamera类能够提供追踪状态,此外还能提供导致该状态出现的相关原因,您可以在 UI 上展示这些信息,告诉用户如何解决追踪质量低这个问题。
给水平面检测预留点时间来生成清晰的结果,一旦您获得所需的结果后,就禁用水平面检测。一开始对水平面进行检测的时候,所检测到的水平面位置和范围很可能不准确。不过随着时间的推移,只要水平面仍然保持在场景当中,那么 ARKit 就能够较为精确地估计水平面的位置和范围。当场景中有一个比较大的平坦表面的话,就算您已经使用过这个水平面来放置内容,那么ARKit 可能还会继续对水平面的锚点位置、范围和变换点进行修正 。
言归正传,我们的需求主要是利用全局追踪技术,获取摄像头实时预览视频帧数据+时间戳+定位信息。如果是安卓开发,我的思路是摄像头实时获取视频帧预览数据并将每一个视频帧利用Android原生压缩或者第三库LibJpeg/LibJpegTurbo压缩成JPEG,或者通过Android MediaCodec进行H264硬编码,或者通过FFMPEG软编码同时利用Tango运动追踪定位技术获取当前视频帧的定位信息并通过传输协议发送到Server端。Apple是一个伟大的公司,推出的ARKit完全满足了我们的需求,基于ARKit全局定位的开发框架极大的便捷了我们的开发。
使用Metal来展示AR场景
何为Metal?
2014苹果开发者大会上,Apple专为游戏开发者推出了一款名为Metal的新型平台技术,并声称其能够为3D图像提高10倍的渲染性能。除此之外,该技术还摆脱了一些硬件与游戏软件之间的中间件。使开发者在编写游戏项目时可以直接使用Metal,也就是说,它让开发人员编写软件更容易,并能够在iOS设备上直接访问3D图像软件。
MetalKit 是Apple为开发者提供的基于Metal的开发框架。
用例概述
该用例通过渲染相机图像,以及使用位置追踪信息来展示覆盖物,从而来构建自定义的 AR 视图场景。从该用例中我们可以了解到全局追踪技术+Metal渲染视图。
ARKit 中内置了一些视图类,从而能够轻松地用 SceneKit 或者 SpriteKit 来展示 AR 场景。然而,如果您使用的是自己的渲染引擎(或者集成了第三方引擎),那么 ARKit 还提供了自定义视图以及其他的支持环境,来展示 AR 场景。
在所有的 AR 场景中,首先就是要配置一个ARSession对象,用来管理摄像头拍摄和对设备动作进行处理。Session 定义并维护现实空间和虚拟空间之间的关联关系,其中,现实空间是用户所处的世界,虚拟空间是可对可视化内容进行建模的世界。如果要在自定义视图当中展示您的 AR 场景的话,那么您需要:
从 Session 中检索视频帧和追踪信息;
将这些帧图像作为背景,渲染到自定义视图当中;
使用追踪信息,从而在相机图像上方定位并绘制 AR 内容。
从 Session 中获取视频帧和追踪数据
您所选择的配置对象的类型,决定了您所创建的 AR 场景的风格和质量:
在具备 A9 或者更高版本处理器的 iOS 设备当中,ARWorldTrackingSessionConfiguration子类提供了高精度的设备动作追踪功能,可以帮助您将虚拟内容「放置」在现实世界中的某个表面上。
在 ARKit 所支持的其他设备当中,ARSessionConfiguration这个基础类则提供了基本的动作追踪功能,可以提供略弱的沉浸式 AR 体验。
几个非常重用的类
ARSession:ARSession对象会协调增强现实过程中的大部分处理,这些处理包括:从设备的动作感应硬件读取数据、控制设备内置摄像头和对捕捉到的摄像图像进行分析。
运行一个session需要一个session configuration
ARWorldTrackingSessionConfiguration:一个用于追踪设备方向和位置,并且监测现实世界平面的设置。
相比于ARSessionConfiguration,它可以从六自由度来追踪设备的运动,除了上述三自由度,还包括三个平移坐标(表示在x、y、z轴上的移动)。
ARFrame:AR session的一部分,被捕获的视频图像和位置追踪信息。
一个运行的AR session会不断的通过设备相机捕捉视频帧。对于每一个frame,ARKit会结合图像和从设备运动感应硬件获得的数据来分析设备的真实位置。这些追踪信息和视图参数就是以ARFrame对象来保存和传递的。
ARCamera:表示AR session中一个被捕获的视图帧相关的相机位置和视图特征的信息。
ARWorldTrackingSessionConfiguration与ARFrame
(1).ARWorldTrackingSessionConfiguration与ARFrame。要启动 AR Session,那么首先要使用您所需要的配置(ARSessionConfiguration),来创建 Session 配置对象,并通过调用run方法运行
ARSession搭建沟通桥梁的参与者主要有两个ARWorldTrackingSessionConfiguration与ARFrame
(2) .ARWorldTrackingSessionConfiguration(会话追踪配置)的作用是跟踪设备的方向和位置,以及检测设备摄像头看到的现实世界的表面。它的内部实现了一系列非常庞大的算法计算以及调用了你的iPhone必要的传感器来检测手机的移动及旋转甚至是翻滚
无需关心内部实现,ARKit框架帮助我们封装的非常完美,只需调用一两个 属性即可
(3).当ARWorldTrackingSessionConfiguration计算出相机在3D世界中的位置时,它本身并不持有这个位置数据,而是将其计算出的位置数据交给ARSession去管理(与前面说的session管理内存相呼应),而相机的位置数据对应的类就是ARFrame
ARSession类一个属性叫做currentFrame,维护的就是ARFrame这个对象
(4).ARCamera只负责捕捉图像,不参与数据的处理。它属于3D场景中的一个环节,每一个3D Scene都会有一个Camera,它决定了我们看物体的视野
它们三者之间的关系看起来如下图:
ARCamera在3D世界的位置看起来是这样的
该用例代码实现代码如下:
(1).定义变量session
(2).在viewDidLoad()方法中,初始化session并为其设置代理
(3)设置帧率(设置采样帧率)
(4).在viewWillAppear()方法中创建Session配置对象并运行,当离开此界面时,在viewWillDisappear()方法中中止session
2、Session从摄像机当中捕获视频,然后在建模的3D空间中追踪设备的位置和方向,并提供ARFrame对象,每个ARFrame对象都包含有单独的视频帧(frame)图像和被捕获时的设备追踪信息
访问AR Session中生产的ARFrame对象,有主动拉取(pull)和被动推送(push)两种方式。
主动拉取设计模式
主动拉取,即定时获取视频帧,利用Sesson的currentFrame属性,这样就可以每次重绘内容时,获取当前的帧图像和追踪信息。通过session.currentFrame(ARFrame)可以获取很多信息。
通过session.currentFrame可以获取到许多有用的信息
当前视频帧时间戳、当前摄像头分辨率大小、当前视频帧YUV数据、当前相机位置(4*4矩阵)、当前相机方向(旋转)的矢量欧拉角等。
被动推送设计模式
被动推送设计模式需要实现session(_:didUpdate) 代理方法,当每个视频帧被捕获后,Session就会调用这个代理方法(默认每秒捕获60帧。)
至此,关于需求部分已经基本满足。不再赘述。
更新界面:
视频帧时间戳会实时显示到界面当中!
触摸屏幕生成2D图像悬浮在3D空间当中
补充部分:
通常情况下,当我们拿到当前视频帧数据后,是需要对视频帧进行处理,并渲染到视图中,因为我们的需求,拿到视频帧之后,进行压缩处理后,发送到Server端后,由后端进行视频合成处理。在这里只涉及部分获得视频帧数据后的处理。
每个ARFrame对象的capturedImage属性都包含了从设备相机中捕获的像素缓冲区(pixel buffer)。本例是将YUV格式转化成了RGB格式。