一、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 團隊提供了 WebARonARKit 和 WebARonARCore 兩個庫,以便開發者能用 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 的幀率。它主要封裝了以下幾個庫:
- WebRTC。獲取視訊流。
- JSARToolKit。主要提供了識別和追蹤 marker 的功能
- Three.js, Babylon.js, A-Frame。這幾個都是基於 WebGL 的渲染庫,用於渲染要在 AR 環境中顯示的東西
由此觀之,AR.js 像是一個把所有輪子都拼起來的瑞士軍刀
-
React 360
-
EasyAR
技術背景
WebRTC 獲取視訊流
-
AR 首先要識別,那就要用到 WebRTC 技術。
WebRTC(Web 實時通訊,Web Real-Time Communication),顧名思義是一個支援網頁瀏覽器進行實時語音對話或視訊對話的技術。通過WebRTC,可以通過網頁呼起使用者的攝像頭,並且實時獲取使用者攝像頭的影象資料的。
它其中有個很重要的 API:getUserMedia() 可以實時獲取攝像頭的視訊流,這是視訊透視式的 AR 實現的前提(目前 iOS 11 剛剛支援這個 API,Android 是很早就能用)。
getUserMedia 預設獲取的是前置攝像頭,如果想獲取後置攝像頭的視訊流,需要用 navigator.mediaDevices.enumerateDevices() 將裝置的音訊、視訊裝置遍歷得到
要用 https 開啟網頁才能訪問攝像頭。
-
有了視訊流我們就可以分析其中的特徵點,運用計算機視覺的演算法識別和追蹤視訊流中的事物。
Tracking.js, JSFeat, ConvNetJS, deeplearn.js, keras.js 識別與追蹤
-
獲取到視訊流之後的工作就是識別和追蹤了。
視訊流你可以看作是一幀一幀的影象,所以處理視訊流的過程可以理解為影象處理的過程。但這裡其實還涉及到一個如何傳輸視訊流的問題,一般有兩種方式:
-
前端傳輸視訊流給後端,後端處理完畢返回結果到前端
-
在前端直接處理視訊流:
在前端直接進行影象處理,可以用 Tracking.js 和 JSFeat。這兩個庫類似,都是在前端做計算機視覺的,包括提取特徵點、人臉識別等。把 WebRTC 拿到的視訊流直接傳給它們並呼叫 API 就能得到自己想要的效果。對於一些成熟的演算法,如人臉識別,可以直接拿到識別結果,如果自己要識別的物體比較複雜你也可以自己進行特徵點的計算,但這可能在前端會算力不足。
提到計算機視覺,不得不提深度學習,畢竟現在很多影象處理演算法被深度學習吊打。ConvNetJS,是史丹佛大學開源的一個前端深度學習框架,可以讓你在前端完成深度神經網路的訓練。deeplearn.js 則是 Google Brain 團隊搞的,功能和 ConvNetJS 類似。現在 ConvNetJS 好像不怎麼維護了,deeplearn.js 還在頻繁更新中,感興趣的同學可以試用一下。另外一個緊鑼密鼓開發的深度學習庫 keras.js則是讓你可以在瀏覽器中執行已經訓練好的 Keras 模型(Kears 是著名的深度學習開發框架),並支援 WebGL 2。
-
-
除了單純的對影象、視訊流處理,我們還能通過移動端裝置的各種感測器資料獲取到更多的距離、深度、光照等資訊,從而使識別追蹤更準確。
A-Frame, Three.js, Babylon.js, Pixi.js, WebGL 渲染與互動
-
識別和追蹤之後,接下來是渲染。
- 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 的關注點不一樣,如果你對渲染的精細程度非常有要求,比如光線、陰影等,那麼你可以考慮下
-
渲染出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 然後對準 識別圖即可體驗,或本地執行專案來訪問。
-
下載專案
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem 複製程式碼
-
安裝http-server服務(需要nodejs)
npm install -g http-server 複製程式碼
-
使用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圖片
這裡開啟的是使用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效果
-
像往常一樣構建一個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> 複製程式碼
-
使用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-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