本文做者 GeekPlux,首发于前端外刊评论-Web 前端中的加强现实(AR)开发技术,博客地址:geekplux.com/2018/01/18/…。注明做者和地址便可转载。html
加强现实(如下简称 AR)浪潮正滚滚而来,Web 浏览器做为人们最唾手可得的人机交互终端,正在大力发展 AR 技术。不少 Web 前端工程师也在寻求职业转型,因而我把我近半年的相关调研结果在此汇结成文。本文力求把目前前端方向的 AR 技术都罗列一遍,细节不赘述(保证文章篇幅不过长),只作归纳和科普(所以文章中的连接不少),零零散散写了一个多月(拖延症),欢迎已经在从事该领域或研究的道友前来纠正补充。前端
Web AR 初音将来git
AR 能够简单的理解为一种实时将虚拟图像叠加在现实场景中的技术,且能交互[1]。我我的以为 AR 比 VR 要有前景,主要由于:github
AR 的优点在于把目之所及的现实场景变成了背景,并将现实世界和数字世界无缝链接。web
固然这个“无缝”目前还谈不上,不过一直在进步。在谈 Web 前端如何作 AR 前,有必要先了解一下 AR 实现的 2 种主要方式和其关键技术:算法
AR 的主要实现方式有 2 种[2][3]:光学透视式 (Optical see-through) 和视频透视式 (Video see-through)。目前,市面上的头戴式设备一般采用 2 种方式中的 1 种或 2 种都采用,而手持设备(手机、平板等)一般采用视频透视式。光学透视式是将电脑生成的数字图像显示在眼前的一层半透明镜片上,这样就可使现实场景和虚拟信息同时出如今视网膜上。而视频透视式技术是将现实场景首先经过相机录入电脑,通过和虚拟对象整合、压缩,再统一呈如今用户眼前。二者各有优劣[4]:光学透视式中的现实场景由于没有通过电脑处理,所以显示得更天然、直接;虽然它实现简单,可是也存在定位精度不高、匹配不许确、显示有延迟等问题。而视频透视式由于通过整合,因此匹配准确,最终显示效果同步程度高,还能对生成的显示结果根据用户需求进行进一步处理;可是它实现难度较高,且丢失了一部分真实感。目前(2017 年末) Web 前端要想实现 AR,都是靠的视频透视式技术。后端
另外,计算机视觉技术在 AR 中起着相当重要的做用。由于实现 AR 最核心的是识别与追踪。首先,相机要先识别基准标志、关键点、光学图片等;而后再根据特征检测、边缘检测或其余图像处理方法来实时追踪;最后将虚拟图像叠加到真实场景中。根据 2008 年的统计结果显示,近十年著名的 AR 会议 ISMAR 中有关追踪技术的论文占到了 20%以上[3].api
根据上一节的阐述,咱们能够得出结论:要实现 AR 须要识别、追踪和渲染三步,在浏览器中也不外如是。另外,还能够结合传感器来提供更多的交互或让 AR 渲染得更准确、经过网络链接云端来加速计算或交换更多数据等。以下图所示,这是我本身整理出的一个 Web AR 流程图。Web AR 或者说移动 AR 在某些方面如便携性、传感器丰富、自带网络等仍是有很大优点的,在此我就很少说了。浏览器
Web AR 流程图性能优化
首先,Web AR 目前仍是一项前沿技术,没有标准也没有成熟的库供使用,不过已经有大公司和一部分开发者正在积极推动。2017 年 10 月 2 日 W3C 的 WebVR 组 发布了 WebVR 规范 1.1 版的初稿,2.0 版还在热火朝天地修订当中。
WebVR 是一个开放标准,使您能够在浏览器中体验 VR。咱们的目标是让每一个人均可以更轻松地体验 VR,不管您拥有什么设备。 - webvr.info
为何本文的题目是 Web AR,这里却提到 WebVR 呢?由于 WebVR 规范中的部分 API 对 Web AR 也一样适用。好比 VRDevicePose 能够获取摄像头位置。这是目前惟一接近 Web AR 的标准,有了标准咱们就能够只针对规范的接口作开发,从而适应绝大多数的设备。扩展阅读:WebVR 于加强现实, 针对智能手机 AR 的 WebVR API 扩展。
ARKit 和 ARCore 分别是苹果和谷歌两大巨头出品的移动 AR SDK,提供的功能也相似:运动追踪、环境感知和光线感应,我相信不少对 AR 感兴趣的开发者对这两个 SDK 都不陌生。但这两个都是移动 AR 的 SDK,因而谷歌的 AR 团队提供了 WebARonARKit 和 WebARonARCore 两个库,以便开发者能用 Web 技术来基于 ARKit 和 ARCore 开发,从而实现 WebAR。目前这两个库都还在试验阶段,想吃螃蟹的人赶忙去试试。其实现原理都是结合特定系统(iOS 和 Android)扩展了 WebVR API。Google AR 团队封装了一个 three.ar.js 的库,提供了一些实用的 AR API,包括 ARView, ARReticle, ARPerspectiveCamera, ARDebug 和 ARUtils 等。
2017 年 SIGGRAPH(图形学顶级会议)上 AR.js 可谓大放异彩,有人作了 Web AR 相关的 session 就是用了 AR.js 来说解。AR.js 是 Jerome Etienne 开发的一款 Web AR 库,能够用十行 HTML 就实现 AR,并有 60 FPS 的帧率。但其实 AR.js 作的事很简单,它主要封装了如下几个库:
由此观之,AR.js 像是一个把全部轮子都拼起来的瑞士军刀,简单易用。做者在 GitHub 和 Twitter 上都很活跃,有什么问题能够直接问他。
前三节咱们提到了一个正在成形的标准和两个框架,是目前 Web AR 的最新进展了。期望标准发布确定黄花菜都凉了,但咱们能够本身动手丰衣足食。
刚才咱们说到 AR 首先要识别,那就要用到 WebRTC 技术。WebRTC(Web 实时通讯,Web Real-Time Communication),顾名思义是一个支持网页浏览器进行实时语音对话或视频对话的技术。它其中有个很重要的 API:getUserMedia() 能够实时获取摄像头的视频流,这是视频透视式的 AR 实现的前提(目前 iOS 11 刚刚支持这个 API,Android 是很早就能用)。有了视频流咱们就能够分析其中的特征点,运用计算机视觉的算法识别和追踪视频流中的事物。这里有 2 个要点也要提一下:一是 getUserMedia 默认获取的是前置摄像头,若是想获取后置摄像头的视频流,须要用 navigator.mediaDevices.enumerateDevices() 将设备的音频、视频设备遍历获得,具体参照 demo;二是要用 https 打开网页才能访问摄像头。
获取到视频流以后的工做就是识别和追踪了。视频流你能够看做是一帧一帧的图像,因此处理视频流的过程能够理解为图像处理的过程。但这里其实还涉及到一个如何传输视频流的问题,通常有两种方式:
在前端直接进行图像处理,能够用 Tracking.js 和 JSFeat。这两个库相似,都是在前端作计算机视觉的,包括提取特征点、人脸识别等。把 WebRTC 拿到的视频流直接传给它们并调用 API 就能获得本身想要的效果。对于一些成熟的算法,如人脸识别,能够直接拿到识别结果,若是本身要识别的物体比较复杂你也能够本身进行特征点的计算,但这可能在前端会算力不足,关于性能的问题下文再论述。
提到计算机视觉,不得不提深度学习,毕竟如今不少图像处理算法被深度学习吊打。ConvNetJS,是斯坦福大学开源的一个前端深度学习框架,可让你在前端完成深度神经网络的训练。deeplearn.js 则是 Google Brain 团队搞的,功能和 ConvNetJS 相似。如今 ConvNetJS 好像不怎么维护了,deeplearn.js 还在频繁更新中,感兴趣的同窗能够试用一下。另一个紧锣密鼓开发的深度学习库 keras.js 则是让你能够在浏览器中运行已经训练好的 Keras 模型(Kears 是著名的深度学习开发框架),并支持 WebGL 2。
这些框架都在主页上提供了丰富的 Demo,很是有趣,把玩一下说不定激发你的灵感。
另外一种处理视频流的方法就是传到后端去处理,后端处理方式的选择就数不胜数了,如今实现 AR 大多数用的都是 SLAM 算法,后端处理完返回前端结果便可。那么如何传输成了咱们前端同窗的难题,通常有这两种方法:
除此以外应该还有其余方法,总之目标是将前端的图像信息传给后端,传输方式能够用 AJAX,也能够用 WebSocket,具体根据场景来定。
这一节主要讲了识别和追踪,其实除了单纯的对图像、视频流处理,咱们还能经过移动端设备的各类传感器数据获取到更多的距离、深度、光照等信息,从而使识别追踪更准确。
讲完识别和追踪,终于该聊聊渲染了。A-Frame 是 Mozilla 团队在 2015 年开源的一款作 WebVR 的框架,但日前 A-Frame 团队发布的 aframe-xr 其中包括了一些 Web AR 组件。一开始咱们也说过 VR 和 AR 中有部分实现是重合的,因此用 A-Frame 的各类组件可让你用不多的代码 构建出 AR 所须要的 3D 立体世界。提到 3D,不得不提 WebGL。WebGL 是 OpenGL ES 在浏览器端的实现,你能够理解其为 OpenGL 的子集。用 WebGL 你能够操做前端的每个像素点,懂一点图形学的同窗必定知道它的强大,并且它能调用 GPU,因此前端涉及到 GPU 的地方也缺不了它。WebGL 虽然强大,但写起来异常复杂,学习成本也很高,而前端最著名的 3D 库 Three.js 将繁琐的 WebGL API 进行了封装和优化,让你能够用可读性更好的代码在前端书写 WebGL。Pixi.js 和 Three.js 作了相似的事情,但它只支持 2D 渲染,不过它仍是很好用的,若是你只是想用 WebGL 来作复杂的渲染但没涉及到 3D 场景,不妨试试它。Babylon.js 就更牛了,它是一款游戏引擎,也是封装了 WebGL 在前端作高性能的渲染,但它和 Three.js 的关注点不同,若是你对渲染的精细程度很是有要求,好比光线、阴影等,那么你能够考虑下 babylon.js,毕竟这是款由微软前员工开发的游戏引擎啊……
这些基于 WebGL 的渲染方法,有一个共性的难题是如何交互,好比 hover, click 效果如何实现。其实在 Web AR 中交互很是局限:若是是桌面设备即电脑,和浏览网页的交互差很少,有 hover, click, drag 拖拽等;若是用的是移动设备,即手机、平板,则可能有 zoom 的交互(这里多嘴一句,其实移动 AR 中,应该尽可能避免手指去 zoom 的交互,而应该引导用户用移近或移远设备来进行放大缩小)。这些实现起来要依赖于 光线投射算法 Ray casting 方法。Three.js 直接提供了 Raycaster 类供实现 ray casting 算法。其实原理很简单,就是摄像头(这里的摄像头不是指手机的摄像头,而是你渲染时的 Camera,能够参考 Three.js 中的 Camera)视做视点,与你在屏幕上触碰的点坐标连城一条射线,看这条射线与你视图中哪些物体相交。
Ray casting 算法
这一节主要讲了渲染与交互,事实上在实现 AR 的时候,识别追踪和渲染交互是同时进行的,如何给用户更好、更流畅的体验是如今 Web AR 的又一大难题。
性能是不少人关心的问题。目前浏览器的算力确实还不足以与客户端去媲美,但较以前也有了巨大的提高。识别和追踪本质上是像素级的计算,对算力的要求都很高,所以 maker-based 的 AR 定位效率一般比 makerless 的要高不少。此外,计算机视觉算法的效率对性能影响也很大,好比人脸识别目前较其余识别要成熟不少,因此人脸识别的算法在 Web 前端运行还算流畅。
提高性能的方法有不少种,你们通常会先想到用 WebGL 调用 GPU 加速,其次会想到用 Web Worker,WebAssembly。前二者我都试过,把纯计算的代码移到 WebGL 的 shader 或 Web Worker 里,这二者虽然都是加速计算,但适用场景不一样。shader 能够用于加速只和渲染(重绘)有关的代码,无关渲染的代码放入 shader 中反而会形成重复计算。Web Worker 适用于事先计算或实时性要求不高的代码,如布局算法。WebAssembly 我还没在作 AR 的时候用过,还有一个库 gpu.js也没试过,但愿有大神试过以后告诉我有什么效果。
还有一种变相“提高”性能的方法是用滤波算法(好比卡尔曼滤波)将卡顿降到更小,让用户从视觉感觉上彷佛更流畅。
如今 Web AR 大潮刚刚开始,有不少高地须要人去攻克,好比光照估计、性能优化等,但愿有兴趣的同窗能够积极参与进来。并且 Web 前端不管是技术仍是人口都发展迅速,充满了无限可能,有限的只是你的想象力。我好久以前作了个人脸识别 + AR 的小 demo,在 GitHub 上 github.com/geekplux/AR…,你们能够玩玩,其实就几行代码。下一篇可能会写写 Web 前端作人脸识别相关的文章,感受又给本身挖了个大坑,但愿个人拖延症早日治好。
参考文献 [2] 中曾总结了当时全部的 AR 开发技术,以下表:
AR 开发技术
这张表将 AR 开发工具分红了四类,分别罗列出来。其实目前大多的 AR 开发都是用 Unity 去作的,不少第三方 SDK 也都是先集成到 Unity 上,再由 Unity 输出到对应设备所需的格式。表中的 Vuforia 据我观察是目前用的最多的第三方 SDK。ARToolKit 则在 Web 前端和移动端用的不少,它的开源版是基于标记的 (Marker-based),也提供机器学习的训练方法,让你能够将任意图片训练成 Marker。另外因为这张表是 2015 年的,当时苹果公司的 ARKit 和谷歌的 ARCore 这 2 个 SDK 尚未横空出世,能够将其归到表中的第三行。