網易戲精 ARCore 短視訊新玩法實踐
《網易戲精》是網易人工智慧事業部旗下一款 AI 短視訊產品,使用者可以隨手拍出自己的特效視訊,其中包含數十個有趣的奇幻道具,其中放置類的道具只需要掃一下平面,即可擺放進現實世界中進行互動,既有充滿霓虹燈的旺角街頭、會隨音樂抖動的 DJ 打碟臺、迪廳球,也有煙霧繚繞的迷幻場景等等。
此類放置類道具在安卓端基於 Google 的 ARCore 技術實現。本文整理歸納專案研發中 ARCore 的使用及研發歷程,與大家一起分享在 AR 應用開發中遇到的問題及實踐。主要分為以下幾個方面,已有相關經驗的 ARCore 開發者可以選擇性跳過。
- ARCore 簡述
- ARCore 原理的進一步理解
- ARCore 和 ARKit 的功能性對比
- ARCore API 架構梳理
- ARCore 的相容性及解決方案
- 開發者可能會遇到的 Troubleshoot
ARCore 簡述
ARCore SDK 主要由三大模組構成: 運動跟蹤 、環境理解、光照估計。
- 運動跟蹤可以讓手機理解和跟蹤它相對於現實世界的位置。
- 環境理解 讓手機可以檢測各類表面(例如地面、咖啡桌或牆壁等水平、垂直表面)的大小和位置。
- 光估計讓手機可以估測環境當前的光照條件。
ARCore 原理的進一步理解
對 ARCore 底層原理的瞭解可以幫助我們瞭解計算的過程以及解決一些問題。
首先,ARCore 使用視覺慣性測距系統 (Visual Inertial Odometry,簡稱 VIO) 的演算法來實現運動跟蹤。VIO 將從裝置的攝像機中識別影象特徵與內部運動感測器結合起來,以獲得裝置的 6DOF(6 Degree Of Freedom,6 度自由度)資訊。我們常說的 6DOF 指的是三維的位置與三維的旋轉,而 3DOF 常指三維的旋轉(直接通過陀螺儀即可獲得,比起 6DOF 計算較為簡單)。
(上圖即是 6DoF 的圖示)
慣性測量單元 (Inertial measurement unit,簡稱 IMU) 的讀數大約為 1000 次每秒並且是基於加速度的(使用者的移動)。航跡推演算法(Dead Reckoning)用於測量 IMU 讀數之間的裝置移動,但這種方法推算是一種估算,就像如果我讓你向前走一步,然後猜測走了多遠一樣,此時會用航跡推演算法來估計距離。但慣導系統中的誤差會隨時間累積,所以 IMU 幀率越長,慣導系統從視覺系統中復位後的時間越長,追蹤位置距離真實位置偏差就越多。
視覺/光學測量使用的是攝像機來採集視覺資訊,裝置幀率通常為 30fps 並且依賴距離(不同的場景幀率也有所不同)。光學系統通常隨著距離的增大誤差也不斷的增大(時間也會有輕度影響),所以使用者運動得越遠,誤差就越大。
慣性導航系統與視覺測量系統各有各的優勢和不足。並且視覺和慣性跟蹤系統是基於完全不同的測量系統,他們之間並沒有相互依賴,所以他們整合在一起可以互相彌補缺陷。這意味著可以蓋住攝像機或者只看到一個具有很少光學特徵的場景(比如白牆),而慣性系統照樣可以正常工作,或者裝置在完全靜止的條件下,視覺系統可以呈現出一個比慣性系統更加穩定的姿態。在此之上這個演算法使用卡爾曼濾波器不斷地選擇最佳姿態,從而實現穩定跟蹤。
與 ARKit 的功能上的對比
為了儘可能保證 Android 使用者和 iOS 使用者的功能一致性,我們整理了 ARKit 和 ARCore 在各個版本上的功能。版本上需要注意的是,ARKit 的版本取決與手機的作業系統級別,ARCore 的執行版本取決於手機上安裝的 ARCore Runtime Apk,Runtime 對 SDK 採取向下相容機制,並且使用者如首次安裝 ARCore Runtime Apk 後,之後作為核心服務自動更新。
ARKit | ARCore | |
---|---|---|
6DOF 追蹤 | 支援(1.0)(iOS11) | 支援(1.0) |
相機解析度、自動對焦 | 支援(1.5)(iOS11.3) | 支援(1.4) |
圖片掃描 | 支援(1.5)(iOS11.3) | 支援(1.2) |
雲錨點 | 支援(2.0)(iOS12) | 支援(1.2) |
ARCore API 架構梳理
ARCore SDK 模組設計易於理解,開發者可以很簡單地找到相應的 API,簡單列了一張重要 / 常用 API 的對應概念:
Session: 負責整個 AR 演算法的生命週期和演算法配置檔案選項,主要有 Start\Pause\Resume\Stop,配置檔案可配置是否開啟位置追蹤、2D 圖片識別、環境光檢測等功能,多餘的配置涉及到可觀的效能開銷,並且在切換配置的過程中會涉及到相機畫面的重啟,建議產品根據各自情況進行選擇。
運動追蹤相關
Frame.CameraImage.Texture Frame.CameraImage.DisplayUvCoords | 相機紋理 ID,對應於 OpenGL 中一張 Texture 中的 Gluint,注意此 Texture 為一張旋轉的 External OES Texture,必須搭配 DisplayUvCoords 資訊才能正確渲染(OES Texture 與普通紋理有所區別,下文會舉例一個實戰 issue) |
---|---|
Frame.CameraBuffer.AcquireCameraImageBytes | 可獲得 Camera 的原始相機資料,格式為 YUV420_888,此格式為 Android Camera2 的預設格式(注意此格式將 YUV 分離為 3 個 Stride,與 Camera1 的 NV21 有所不同)。獲得原始資料一般用於進一步的影象處理或 CV 演算法 |
Frame.Pose.position Frame.Pose.rotation | 包含了運動追蹤的結構體,包括相機當前位置、旋轉等 |
環境理解相關
Session.GetTrackable | 可以獲得已經被 AR 演算法重建的平面 |
---|---|
Frame.Raycast | 從三維世界一個點沿一個方向發射出一條無限長的射線,在射線的方向上,一旦與現實世界的特徵點、平面產生碰撞,則返回碰撞物件包含的位置、方向及其他相關屬性 |
光估計相關
Frame.LightEstimate.pixelIntensity | 可以獲得當前估計的光照強度 |
---|
ARCore 相容性及解決方案
目前 ARCore 支援的機型主要為 17 年、18 年釋出的旗艦機,下圖列了支援的國內主流裝置列表,觀察到表中支援的裝置主要為高通晶片和 ARM 晶片,據官方所述後續還會支援聯發科晶片的機型。
OEM | Model |
---|---|
小米 | Mi Mix 2S, Mi Mix 3 Mi 8, Mi 8 SE |
華為 | Honor 10, Honor Magic 2, Maimang 7 Mate 20, Mate 20 Pro, Mate 20 X nova 3, nava 3i P20, P20 Pro Porsche Design Mate RS Porsche Design Mate 20 RS |
三星 | Galaxy Note9 Galaxy S9, Galaxy S9+ |
值得一提的是 Google 官方考慮到國內使用者無法在 Google Play 安裝 / 更新 ARCore Runtime,提供了小米、華為和三星應用商店作為國內安裝跳轉連結。
用於保證機型覆蓋率,我們選用了網易的 InsightSDK 作為 ARCore 的 fallback 的方案,開發的時候可以通過官網的 ARCore 裝置白名單或者 Session.CheckApkAvailability 的方式進行自動選擇 SDK。
開發者可能會遇到的問題
1. 運動中做運動跟蹤
例如,如果使用者是在火車上使用 ARCore,這時 IMU(Inertial Measurement Unit)獲取的資料不僅包括使用者的移動(實際是加速度),也包括火車的移動資料(實際是加速度),這樣將導致跟蹤失敗。
2. 跟蹤動態的環境
例如,如果使用者對著一面大白牆、波光粼粼的湖面,這時從攝像機獲取到的影象資訊是不穩定的,這將導致特徵點提取出錯進而導致跟蹤失敗。
3. 熱飄移
相機與 IMU 都是對溫度敏感的元器件,之前我們說過相機和 IMU 的 OEM 校準,但這個校準通常都會在某一個或者幾個特定溫度下進行,但在使用者裝置使用過程中,隨著時長的延長會導致裝置發熱,發熱就會影響到相機獲取的影象的顏色資訊和 IMU 測量的加速度資訊準確性,表現出來就是跟蹤的物體會飄移。
4. CPU 搶佔
從上面的 ARCore 演算法中發現 AR 演算法對 CPU 要求較高。如果你的 App 佔用了過多的 CPU,依然會導致 ARCore 的效果不穩。可以使用類似 SnapDragon Profiler 的工具進行一個性能排查。
5. 使用 Linear 渲染模式
為了追求正確的光照計算,我們使用了 Linear 渲染模式,但是 ARCore 並沒有提供 Linear 模式下相關的 shader。可以使用以下函式對顏色空間進行轉換:
pow(gl_FragColor.rgb,vec3(2.2));
6. External OES Texture 的特殊性
將 Camera Texture 渲染到螢幕的 shader 使用的是 External OES Texture,在實際的使用過程中發現單獨使用 External OES Texture 沒有問題,但是結合一張正常 Texture 會渲染成黑色,經過排查問題發現 External OES Texture 的底層實現是多個單通道 Texture 的打包,所以在 External OES Texture 之後 Bind 的正常 GLuint 可能會錯誤的繫結,這個時候可以將 External OES Texture 放在最後即可解決。
7. 結合計算機視覺
因為需要將 Camera 的相機資料做進一步數字影象處理或者 CV 檢測,除了直接獲得 TextureID,還需要獲得相機 Buffer,但是小米手機呼叫 Frame.acquireCameraImage() API 會丟擲 NotYetAvailableException,官方文件有在小米的手機上說明這個問題,所以使用這個 API 還不能做到完全統一相容。
總的來說,儘管 ARCore 推出的時間較 ARKit 遲,但功能上基本與 ARKit 持平。並且回顧 ARCore 近一年的發展上看,ARCore 也在率先提出一些行業標準,像 Cloud Anchor 這樣的新 feature 就是由 ARCore 率先提出,由此可見 Google 對 ARCore 的投入和在 AR 領域決心。同樣,社交化的應用方式也是 AR 技術落地的重要場景。預計未來幾年 AR 的開發生態會逐步完善並標準化,對開發者來說是十分值得期待的。
本文作者:鄧志鵬,網易人工智慧事業部資深技術美術專家,《Unity5.x 從入門到精通》作者之一,主要關注於將 AI、AR 等前沿技術用於圖形、互動領域。