webAR 探究

3,638 阅读13分钟

一、AR是什么

AR 可以简单的理解为一种实时将虚拟图像叠加在现实场景中的技术,且能交互,优势在于把目之所及的现实场景变成了背景,并将现实世界和数字世界无缝连接。

AR 实现的方式和关键技术

AR 的主要实现方式有 2 种:光学透视式 (Optical see-through) 和视频透视式 (Video see-through)

  • 光学透视式是将电脑生成的数字图像显示在眼前的一层半透明镜片上,这样就可以使现实场景和虚拟信息同时出现在视网膜上。

  • 视频透视式技术是将现实场景首先通过相机录入电脑,经过和虚拟对象整合、压缩,再统一呈现在用户眼前。

目前(2018 年底) Web 前端要想实现 AR,都是靠的视频透视式技术。

计算机视觉技术在 AR 中起着至关重要的作用。因为实现 AR 最核心的是识别与追踪。首先,相机要先识别基准标志、关键点、光学图片等;然后再根据特征检测、边缘检测或其他图像处理方法来实时追踪;最后将虚拟图像叠加到真实场景中。

结合传感器来提供更多的交互或让 AR 渲染得更准确、通过网络连接云端来加速计算或交换更多数据等。

二、webAR

由上得出结论:要实现 AR 需要识别、追踪和渲染三步。

站在巨人的肩膀上

目前没有标准也没有成熟的库供使用,只有一些规范。

  • WebARonARKit, WebARonARCore ARKit 和 ARCore 分别是苹果和谷歌两大巨头出品的移动 AR SDK,提供的功能也类似:运动追踪、环境感知和光线感应但这两个都是移动 AR 的 SDK,于是谷歌的 AR 团队提供了 WebARonARKitWebARonARCore 两个库,以便开发者能用 Web 技术来基于 ARKit 和 ARCore 开发,从而实现 WebAR。目前这两个库都还在试验阶段,想吃螃蟹的人赶紧去试试。其实现原理都是结合特定系统(iOS 和 Android)扩展了 WebVR API。Google AR 团队封装了一个 three.ar.js 的库,提供了一些实用的 AR API,包括 ARView, ARReticle, ARPerspectiveCamera, ARDebug 和 ARUtils 等。

  • AR.js

    AR.js 是 Jerome Etienne 开发的一款 Web AR 库,可以用十行 HTML 就实现 AR,并有 60 FPS 的帧率。它主要封装了以下几个库:

    1. WebRTC。获取视频流。
    2. JSARToolKit。主要提供了识别和追踪 marker 的功能
    3. Three.js, Babylon.js, A-Frame。这几个都是基于 WebGL 的渲染库,用于渲染要在 AR 环境中显示的东西

    由此观之,AR.js 像是一个把所有轮子都拼起来的瑞士军刀

  • React 360

  • EasyAR

技术背景

WebRTC 获取视频流

  1. AR 首先要识别,那就要用到 WebRTC 技术。

    WebRTC(Web 实时通信,Web Real-Time Communication),顾名思义是一个支持网页浏览器进行实时语音对话或视频对话的技术。通过WebRTC,可以通过网页呼起用户的摄像头,并且实时获取用户摄像头的图像数据的。

    它其中有个很重要的 API:getUserMedia() 可以实时获取摄像头的视频流,这是视频透视式的 AR 实现的前提(目前 iOS 11 刚刚支持这个 API,Android 是很早就能用)。

    getUserMedia 默认获取的是前置摄像头,如果想获取后置摄像头的视频流,需要用 navigator.mediaDevices.enumerateDevices() 将设备的音频、视频设备遍历得到

    要用 https 打开网页才能访问摄像头。

  2. 有了视频流我们就可以分析其中的特征点,运用计算机视觉的算法识别和追踪视频流中的事物。

Tracking.js, JSFeat, ConvNetJS, deeplearn.js, keras.js 识别与追踪

  1. 获取到视频流之后的工作就是识别和追踪了。

    视频流你可以看作是一帧一帧的图像,所以处理视频流的过程可以理解为图像处理的过程。但这里其实还涉及到一个如何传输视频流的问题,一般有两种方式:

    • 前端传输视频流给后端,后端处理完毕返回结果到前端

    • 在前端直接处理视频流:

      在前端直接进行图像处理,可以用 Tracking.jsJSFeat。这两个库类似,都是在前端做计算机视觉的,包括提取特征点、人脸识别等。把 WebRTC 拿到的视频流直接传给它们并调用 API 就能得到自己想要的效果。对于一些成熟的算法,如人脸识别,可以直接拿到识别结果,如果自己要识别的物体比较复杂你也可以自己进行特征点的计算,但这可能在前端会算力不足。

      提到计算机视觉,不得不提深度学习,毕竟现在很多图像处理算法被深度学习吊打。ConvNetJS,是斯坦福大学开源的一个前端深度学习框架,可以让你在前端完成深度神经网络的训练。deeplearn.js 则是 Google Brain 团队搞的,功能和 ConvNetJS 类似。现在 ConvNetJS 好像不怎么维护了,deeplearn.js 还在频繁更新中,感兴趣的同学可以试用一下。另外一个紧锣密鼓开发的深度学习库 keras.js则是让你可以在浏览器中运行已经训练好的 Keras 模型(Kears 是著名的深度学习开发框架),并支持 WebGL 2。

  2. 除了单纯的对图像、视频流处理,我们还能通过移动端设备的各种传感器数据获取到更多的距离、深度、光照等信息,从而使识别追踪更准确。

A-Frame, Three.js, Babylon.js, Pixi.js, WebGL 渲染与交互

  1. 识别和追踪之后,接下来是渲染。

    • A-Frame Mozilla 团队在 2015 年开源的一款做 WebVR 的框架
    • aframe-xr A-Frame 团队发布的 其中包括了一些 Web AR 组件,用 A-Frame 的各种组件可以让你用很少的代码构建出 AR 所需要的 3D 立体世界
    • WebGL OpenGL ES 在浏览器端的实现,用 WebGL 你可以操作前端的每一个像素点,能调用 GPU,虽然强大,但写起来异常复杂,学习成本也很高
    • Three.js 将繁琐的 WebGL API 进行了封装和优化,让你可以用可读性更好的代码在前端书写 WebGL
    • Babylon.js 和 Three.js 的关注点不一样,如果你对渲染的精细程度非常有要求,比如光线、阴影等,那么你可以考虑下
  2. 渲染出3D场景后,如何交互?

    这些基于 WebGL 的渲染方法,有一个共性的难题是如何交互,比如 hover, click 效果如何实现。这些实现起来要依赖于 光线投射算法 Ray casting 方法。Three.js 直接提供了 Raycaster 类供实现 ray casting 算法。摄像头(这里的摄像头不是指手机的摄像头,而是你渲染时的 Camera,可以参考 Three.js 中的 Camera)视作视点,与你在屏幕上触碰的点坐标连城一条射线,看这条射线与你视图中哪些物体相交。

事实上在实现 AR 的时候,识别追踪和渲染交互是同时进行的,如何给用户更好、更流畅的体验是现在 Web AR 的又一大难题。

性能

目前浏览器的算力确实还不足以与客户端去媲美,识别和追踪本质上是像素级的计算,对算力的要求都很高,因此 maker-based 的 AR 定位效率通常比 makerless 的要高很多。此外,计算机视觉算法的效率对性能影响也很大。

三、 demo实现

1.终端适配性参考

目前,在web端,无论采用哪种实现手段,最主要是运行环境对webRTC、webGL 两个特性的支持程度。

测试发现IOS 12以下不支持、IOS版微信QQ不支持、Safari支持;安卓支持良好。

2.技术方案

采用: AR.js Efficient Augmented Reality for the Web

AFrame.js A web framework for building virtual reality experiences

AFrame-ar.js Augmented reality for a-frame.

AFrame-extras.min.js Add-ons and helpers for A-Frame VR.

注意:这种技术方案的特性是基于标记图Maker,也就是说需要一张特定的训练出的标记图才能渲染出AR效果,

由于识别图需要训练,且有特定要求,所以识别图的外观和识别率有关系,识别率低则会导致模型抖动剧烈。

demo1:运行AR.js官网例子

可以使用设备打开 官网demo 然后对准 识别图即可体验,或本地运行项目来访问。

  1. 下载项目

    openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
    
  2. 安装http-server服务(需要nodejs)

    npm install -g http-server
    
  3. 使用git bash 工具或其他(除Windows CMD)进入到需要预览的页面,生成SSL证书并通过HTTPS访问

    首先进入项目

    cd AR.js
    

    生成SSL证书

    openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
    

    启动HTTPS服务,通过127.0.0.1 或IP访问

    http-server -S -C cert.pem -o
    

    例如 https://192.168.3.52:8080/three.js/examples/dev.html 可以看到这里打开了一个dev页面,PC端缺失摄像头而报错。如果你是微信打开,则报错webRTC不支持,可用Safari访问。

    使用你的手机打开该页面,扫描特定的识别图,即可感受webAR的强大。这里也体现了该框架的特性:基于maker图片

    img

  这里打开的是使用three.js写法的demo,渲染出了一个立方体并带有动效。



  **而在AR.js中分为两种写法:使用three.js结合一堆js库来实现、使用AFrame.js**

  在该项目中的example对比发现,使用 three.js 来构建3D场景后,还需要结合 artoolkit.js、threex.js等,<u>学习成本非常高。</u>

  使用 AFrame.js 写法时,代码量减少很多,但也需要了解 AFrame.js 、AFrame-ar.js 、AFrame-extras.min.js

demo2:使用AFrame.js、AFrame-ar.js 、AFrame-extras.min.js

AFrame.js是火狐的项目,它包含了three.js

AFrame-ar.js可以在web页面上渲染3d

在参考AR.js官网给出的“10行代码实现AR效果”的例子时发现,该demo引用的aframe的版本较旧,而引用官网最新的版本时,所呈现的demo效果会有所不同。具体原因未知。

以下demo与该例子所用的标签有些许不同,但也能实现demo,具体原由及细节需要研究 AFrame.js 。

大致思路是:

  • 引用框架

  • 在代码中使用框架的语法构建:

  • 使用maker generator 训练出一个特定的maker,下载并在代码中指定该maker文件,maker文件与识别图相关联。

  • 运行demo,使用设备的摄像头对准maker关联的图像,即可看到AR效果

  1. 像往常一样构建一个web页面,引入所需要的框架。

    <!-- include A-Frame obviously -->
    <script src="/aframe.min.js"></script>
    <!-- include ar.js for A-Frame -->
    <script src="/aframe-ar.js"></script>
    <!-- include A-Frame-Extras -->
    <script src="/static/js/aframe-extras.min.js"></script>
    
  2. 使用AFrame的标签,类似HTML的写法来实现AR效果

    <body style='margin : 0px; overflow: hidden;'>
        <!-- 构建一个3d场景 -->
        <a-scene embedded arjs>
            
        <!-- 设置一个识别图,这个很重要,AR效果能不能显示出来全凭这张识别图是否被识别  -->
        <a-marker preset='custom' type='pattern' url='/static/marker/test/20/pattern-marker(2).patt'>
            
            <!-- load gltf model 加载一个GLTF格式的模型,该模型就是我们想渲染到屏幕上的效果-->
            <a-entity gltf-model="/static/gltf/CNtower.glb"  scale='0.01 0.01 0.01' rotation="-90 0 0"></a-entity>    
    
            <!-- a-entity标签也能渲染一个模型,animation-mixer属性还可也添加动效,理解具体细节需要参考AFrame.js文档 -->    
            <!-- <a-entity gltf-model="/static/gltf/scene.gltf" animation-mixer scale="1 1 1" rotation="-120 0 0" position="0 0.5 0"></a-entity> -->    
    
            <!-- 或者像这样 渲染一个立方体 -->    
            <!-- <a-box position='0 0.5 0' material='color: black;'></a-box> -->
           
        </a-marker>
    
        <!-- add camera 添加一个摄像机,写法也不同,具体需要看文档-->
        <!-- <a-entity camera id="my"></a-entity> -->
        <a-camera ar-raycaster raycaster cursor="fuse:false"></a-camera>
        </a-scene>
    </body>
    

四:总结

1、由于项目运行在web中,因此web环境的兼容性很大程度取决于用户运行环境的浏览器内核。目前webAR所依赖的技术始终逃不了 webRTC 、webGL 、如果运行环境(浏览器)连这两个人特性都无法支持,则无法进行下一步。

经测试IOS版本微信和QQ内置的浏览器均无法支持这两个特性,折中的办法是提示用户使用Safari进行体验。安卓端尚可。

2、AR最核心的是识别与追踪,web领域的js版artoolkit不像Apple的ARCore 和Google的ARKit那样强大,而且业界还没形成一个成熟的解决方案,只有一些规范,草案等。

基于maker识别图来进行识别和追踪是一个比较高效的做法,受限于识别算法和摄像机追踪的能力有限,所以上述demo对识别图有着非常高的要求,经过测试28张识别图,如果不按规则来设定识别图则会导致识别失败。设备摄像头需要离识别图非常近否则模型抖动会非常明显,严重影响体验。

如果抛开依赖识别图这种方法,目前还没有解决方案。

所以从体验上看,目前最大的问题是识别图的识别率低且有特定要求,模型抖动剧烈影响体验,与模型交互困难。页面一直处于视频流状态会导致设备发热,耗电量大幅上升。

3、在3D场景渲染,模型渲染这一层面,首先需要对底层的webGL有一定熟悉程度,最重要的是three.js这个框架,或是经过封装的AFrame,它们用来构建3d场景和3d模型需要对这个框架有很深入的了解,如何与模型进行交互等等,这些将导致一些学习成本。

经过测试,超过1MB的GITF2.0模型 使用AFrame加载不出,具体原因还需要进一步分析,

4、国内外对webAR 的讨论和demo 案例目前都比较少,能够搜到的资料几乎都是英文版。成熟的产品更少,阴阳师的AR抽取SSR卡牌的也是基于maker图来实现,且抖动明显,追踪能力也比较差。王者荣耀刚刚更新在英雄界面能够显示AR效果目前也只在特定的OPPO联合开发机型中实现,况且这两款产品是更强大的APP端。

本文部分内容节选自以下参考文章

参考: Web 前端中的增强现实(AR)开发技术

webAR涉及的技术

JSARToolKit

Web-Powered Augmented Reality: a Hands-On Tutorial

Augmented Reality in 10 Lines of HTML - AR.js with a-frame magic

Developing Augmented Reality For The Web Using AR.Js

Build and access your first AR webapp in less than 10mn using ARjs

Using 3D models with AR.js and A-Frame

web AR探索和总结

Web 3D哪家强?

Web前端也能做的AR互动

实现一个简单但有趣的AR效果(Web)

前端WebAR实现简单版pokemon Go

黑暗大法师demo