本文做者 GeekPlux,博客地址: http://geekplux.com/2018/01/18/augmented-reality-development-tech-in-web-frontend.html。註明做者和地址便可轉載。
加強現實(如下簡稱 AR)浪潮正滾滾而來,Web 瀏覽器做爲人們最唾手可得的人機交互終端,正在大力發展 AR 技術。不少 Web 前端工程師也在尋求職業轉型,因而我把我近半年的相關調研結果在此匯結成文。本文力求把目前前端方向的 AR 技術都羅列一遍,細節不贅述(保證文章篇幅不過長),只作歸納和科普(所以文章中的連接不少),零零散散寫了一個多月(拖延症),歡迎已經在從事該領域或研究的道友前來糾正補充。html
AR 能夠簡單的理解爲一種實時將虛擬圖像疊加在現實場景中的技術,且能交互[1]。我我的以爲 AR 比 VR 要有前景,主要由於:前端
AR 的優點在於把目之所及的現實場景變成了背景,並將現實世界和數字世界無縫鏈接。
固然這個「無縫」目前還談不上,不過一直在進步。在談 Web 前端如何作 AR 前,有必要先了解一下 AR 實現的 2 種主要方式和其關鍵技術:git
AR 的主要實現方式有 2 種[2][3]:光學透視式 (Optical see-through) 和視頻透視式 (Video see-through)。目前,市面上的頭戴式設備一般採用 2 種方式中的 1 種或 2 種都採用,而手持設備(手機、平板等)一般採用視頻透視式。光學透視式是將電腦生成的數字圖像顯示在眼前的一層半透明鏡片上,這樣就可使現實場景和虛擬信息同時出如今視網膜上。而視頻透視式技術是將現實場景首先經過相機錄入電腦,通過和虛擬對象整合、壓縮,再統一呈如今用戶眼前。二者各有優劣[4]:光學透視式中的現實場景由於沒有通過電腦處理,所以顯示得更天然、直接;雖然它實現簡單,可是也存在定位精度不高、匹配不許確、顯示有延遲等問題。而視頻透視式由於通過整合,因此匹配準確,最終顯示效果同步程度高,還能對生成的顯示結果根據用戶需求進行進一步處理;可是它實現難度較高,且丟失了一部分真實感。目前(2017 年末) Web 前端要想實現 AR,都是靠的視頻透視式技術。github
另外,計算機視覺技術在 AR 中起着相當重要的做用。由於實現 AR 最核心的是識別與追蹤。首先,相機要先識別基準標誌、關鍵點、光學圖片等;而後再根據特徵檢測、邊緣檢測或其餘圖像處理方法來實時追蹤;最後將虛擬圖像疊加到真實場景中。根據 2008 年的統計結果顯示,近十年著名的 AR 會議 ISMAR 中有關追蹤技術的論文佔到了 20%以上[3].web
根據上一節的闡述,咱們能夠得出結論:要實現 AR 須要識別、追蹤和渲染三步,在瀏覽器中也不外如是。另外,還能夠結合傳感器來提供更多的交互或讓 AR 渲染得更準確、經過網絡鏈接雲端來加速計算或交換更多數據等。以下圖所示,這是我本身整理出的一個 Web AR 流程圖。Web AR 或者說移動 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 擴展。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)視做視點,與你在屏幕上觸碰的點座標連城一條射線,看這條射線與你視圖中哪些物體相交。
這一節主要講了渲染與交互,事實上在實現 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 上 https://github.com/geekplux/AR-AI-VIS-demo,你們能夠玩玩,其實就幾行代碼。下一篇可能會寫寫 Web 前端作人臉識別相關的文章,感受又給本身挖了個大坑,但願個人拖延症早日治好。
參考文獻 [2] 中曾總結了當時全部的 AR 開發技術,以下表:
這張表將 AR 開發工具分紅了四類,分別羅列出來。其實目前大多的 AR 開發都是用 Unity 去作的,不少第三方 SDK 也都是先集成到 Unity 上,再由 Unity 輸出到對應設備所需的格式。表中的 Vuforia 據我觀察是目前用的最多的第三方 SDK。ARToolKit 則在 Web 前端和移動端用的不少,它的開源版是基於標記的 (Marker-based),也提供機器學習的訓練方法,讓你能夠將任意圖片訓練成 Marker。另外因爲這張表是 2015 年的,當時蘋果公司的 ARKit 和谷歌的 ARCore 這 2 個 SDK 尚未橫空出世,能夠將其歸到表中的第三行。