
作者|方曦(千之)
出品|阿裡巴巴新零售淘系技術部
一句話概括全文:
現在,商家應用支援 AR 效果了!
AR 是什麼?是一種現實增強技術(Augmented Reality),可以将虛拟效果應用到真實世界。AR 技能加身後,商家應用可以幫你給你的真實世界加點料。
今年雙十一前夕,商家應用團隊和歐萊雅集團深度合作,雙方團隊基于阿裡統一小程式容器把 Modiface 試妝引擎在手淘上成功落地。目前已經支援了 YSL 和 Armani 兩個頂級品牌的 AR 試妝應用在對應的官方旗艦店裡上線。體驗方式可以見文末。
Modiface 是歐萊雅集團旗下的美妝科技公司,Modiface 本次推出的 AR 試妝應用,專為手淘環境量身定制,利用小程式容器提供的基礎設施能力,把自己的 AR 美妝引擎 “搬到“ 手淘上了。
那麼,商家應用 + AR 是如何支撐 Modiface 試妝引擎落地的?下文将給大家分享我們雙方在技術合作過程中一些心得。
鍊路概覽
整體玩法鍊路是這樣的,品牌方提供整體應用的設計和互動玩法,Modiface 試妝引擎基于商家應用提供的基礎能力上實作自己的試妝引擎,然後統一輸出給商家應用服務商,再裝修到對應的品牌店鋪上。
可以注意到,這個項目中涉及到多方協作,小程式容器提供的是非常基礎的能力,AR 引擎負責的是能力的上層組合和自身算法能力的內建,商家應用服務商負責承接品牌的業務訴求并制作商家應用,再由品牌商的店鋪裝修同學把商家應用裝修到對應的店鋪上。
品牌方本身可以和 AR 引擎合作來定制自身的個性化需求,再把這種個性化的體驗帶給自家店鋪的使用者。
技術架構
為了支撐商家應用 AR 業務,我們在架構設計上以 API 群組件方式提供了非常多的标準原子化能力。
通過能力的組裝和調用,AR 引擎可以快速驗證自身的算法&渲染能力,我們支援以 MNN 方式或者 TensorFlow.js 的方式來運作推理 AR 引擎的算法,我們支援标準的 WebGL 接口和 Canvas2D API 以供業務繪制。我們也支援攝像頭資料的采集和相機幀的透出。除此之外,我們還提供了非常多的底層能力來供上層引擎調用。
基于這些小程式容器提供的基礎能力,上層 AR 引擎服務商可以建構出豐富的應用場景,包括但不限于虛拟試妝,虛拟穿戴,虛拟家居等等。
那麼,Modiface 試妝引擎究竟是如何在小程式容器裡運作的,我們來一起看一下整個鍊路。
- 品牌試妝應用加載 Modiface 試妝插件,插件會調用小程式容器的 Camera 元件來打開相機并監聽來自 Native的相機幀資料,插件也會初始化一個 WebGL Canvas 元件來執行 TensorFlow.js。
- Modiface 試妝引擎擁有兩個人臉模型,分别是輪廓檢測模型和 Landmark 檢測模型,前者運作在 TensorFlow.js 環境中,後者使用 MNN 插件來運作推理。(後續将全部遷移至 MNN 實作)
- 輪廓模型檢測到目前相機幀中存在人臉後,會切換至 Landmark 檢測,此時會進行人臉精确點的采集推理。
- 同步會采集相機幀中的環境光線的強度以調整美顔算法。
- 提取要繪制的區域位置點陣,譬如人臉嘴唇位置,在 WebGL 的 shader 裡開始渲染上妝,并把所有像素繪制 在 WebGL Canvas 元件上。
- 如目前檢測不到人臉,則不執行渲染上妝邏輯。
整個試妝流程鍊路絕大部分運作在小程式容器的 JavaScript 環境裡,并通過 JS binding 的方式和 Native 容器進行互動。
商家應用 + AR 的前提是 AR 引擎動态化,相對以往手淘 AR Case 最大的變化是:
- 整個 AR 引擎全部運作在小程式容器的 JavaScript 環境裡,在不依賴手淘發版的情況下可以大量快速複制給不同的品牌,并且支援動态定制效果。
- 商家應用 + AR 支援各種不同的行業引擎接入,AR 引擎層和業務層是分離的,通過架構的解耦來支撐各種行業場景。容器底層專注于垂直能力的建設,上層業務快速疊代發展。
核心能力
我們基于 JavaScript 引擎提供了三種核心能力,分别是實時相機幀能力、深度學習推理加速能力、渲染能力。下面将分别介紹三種核心能力的技術細節。
▐ 實時相機幀能力
實時相機幀的輸出是一切 AR 效果的開始,小程式目前已經支援實時相機幀的輸出,在開發者接口層是 ArrayBuffer 類型的二進制資料。
- 實時相機幀能力在小程式裡以标準原生 Camera 元件作為載體,在小程式裡使用了同層渲染的方式嵌入在 WebView 中,可以實作原生元件和 WebView 元件混合使用的效果。
- 鑒于 iOS / Android 系統原生并沒有提供相機幀的提取接口,加上 WebRTC 的标準在小程式體系裡不适用,我們目前的做法是将從系統相機回調中把幀取出來,利用 OpenGL 的接口繪制在一塊離屏的 FBO 上 ,這是一塊自定義的幀緩沖區,我們可以利用這塊幀緩沖區來實作包括 YUV 和 RGB 顔色空間的轉換加速,再從這塊 FBO 中讀取像素點擷取位圖資料。
- JavaScript 語言會以數組的文法處理二進制資料,我們一般會使用 ArrayBuffer 對象,我們需要實作原生 ByteData -> ArrayBuffer 的鍊路,這裡有很大一部分工作是由 JavaScript 虛拟機( JSC / V8 )承擔的,但是在部分 JavaScript 虛拟機不支援特性的 OS 版本下,譬如iOS9,我們使用了社群的開源方案 expo 來完成了 TypedArray 的建構。
- 目前的相機元件使用方式是使用了一個 1px*1px 大小的元素作為占位,使用者不可見該元件,後續我們會支援離屏相機元件的建立。
- 目前在低端機上,小程式的實時幀率輸出能達到 30 FPS,能滿足絕大部分場景需要。
▐ 深度學習推理加速能力
利用小程式的深度學習推理加速能力,非常多的算法能力能夠被內建到手淘裡來。目前我們支援兩種推理引擎 MNN 和 TensorFlow.js,在手淘環境上我們建議使用 MNN 來作為推理引擎加速,在 Modiface 場景下實測能比 TensorFlow.js 快1倍以上。
MNN:
- MNN 是一個阿裡開源的輕量級的深度學習端側推理引擎,核心解決深度神經網絡模型在端側推理運作問題,涵蓋深度神經網絡模型的優化、轉換和推理,其前身為 AliNN,更多詳細内容,可以點選: 《阿裡開源!輕量級深度學習端側推理引擎 MNN》 。MNN 更注重在推理時的加速和優化,解決在模型部署的階段的效率問題,進而在移動端更高效地實作模型背後的業務。
- MNN 小程式插件在 JavaScript 環境中動态完成了模型結構的搭建,MNN 本身使用 flatbuffer 作為模型描述工具,而 flatbuffer 支援 JavaScript 後端,可以利用 flatc 從描述檔案生成 JavaScript 的模型加載代碼,使用這部分代碼就可以從引擎傳入的 ByteArray 解析出模型資料了;在MNN的小程式插件中,使用 MNN 提供的表達式語句,根據模型資料動态建構出完整的模型圖,在這之後的推理,也可以直接調用表達式來完成。
- 在小程式裡,MNN 目前支援了常用的 20+ 種 op ,可以覆寫絕大部分推理場景。在 JS binding 的能力之上,MNN 可以調用手淘裡的 Native MNN SDK 來加速推理,MNN 相比 TensorFlow.js 占用記憶體會低非常多,此外推理速度也通常是 TensorFlow.js 的數倍。
TensorFlow.js:
- TensorFlow.js 是一個 Google 開源的基于硬體加速的 JavaScript 庫,用于在浏覽器和 Node.js 環境訓練和部署機器學習模型。現在,TensorFlow.js 也能支援在購物小程式裡來推理模型了。Web 開發者也可以在小程式環境裡使用熟悉的 JavaScript 來進行機器學習。
- 在小程式裡,TensorFlow.js 的 backend 是我們的 WebGL Canvas元件,在小程式裡利用 WebGL 的能力,TensorFlow.js 可以使用 GPU 來加速機器學習的運作。
▐ 渲染能力
- 承載小程式渲染能力的 Canvas 元件是一個原生元件,同樣是利用同層渲染方式實作的。Canvas 元件的後端渲染 backend 是 GCanvas。GCanvas 的更多詳細内容,可以移步: 《5分鐘帶你看懂GCanvas引擎的演進》
- Canvas 元件既可以作為畫布來繪制像素,也可以作為推理加速的 backend 來做計算。在小程式裡我們實作了 WebGL 1.0 接口和 Canvas2D 的标準API,以降低開發者的使用成本。
- 為什麼不用 WebView 的 Canvas?
在小程式架構下,Worker 和 Render 是分離的,也就是說 運作 JavaScript 的虛拟機和負責渲染的虛拟機對象不是同一個,目前兩者間通信是通過 Native 容器作為 bridge。如果有高頻且資料量巨大的 WebGL 調用,需要每次涉及 Render 和 Worker 之間的互動,這個通信成本非常高。 我們的解決方案是在Native 實作了符合 W3C 标準的 WebGL 标準和 Canvas2D 的接口,無縫支援各種渲染架構對接。
能力演進
在旗艦店2.0之中,商家應用實作了店鋪開放的可能性,AR 更是給商家應用帶來了新的技術營銷的方式。商家應用 + AR 會繼續演進并支撐更多能力,我們也非常歡迎各類 AR 算法引擎和品牌方找我們合作提供好的創意和想法。
我們後續會繼續在目前的基礎能力上做更多的優化工作,主要分為幾方面:
引擎 WebAssembly 化:目前的 AR 引擎是使用 JavaScript 語言建構的,使用 WebAssembly 技術我們可以補充 JavaScript 本身性能不夠理想帶來的影響,并友善開發者移植已經成熟的 C++/C 工程到 Web 。在包括很多對密集運算要求很高的場景下,譬如遊戲引擎,實體引擎,音視訊處理,加密算法等,我們使用 WebAssembly 可以直接把 JavaScript 運算帶來的性能開銷降低。此外,在小程式場景下,WebAssembly 可以大大降低小程式包的體積大小,降低使用者加載時長。WebAssembly 在代碼安全性上相較 JavaScript 也具備一定優勢。問題現在在于 JavaScript 和 WebAssembly 之間函數調用是非常慢的,針對這個場景我們參考了業界的
一些實作,以特定類型的通信接口來維護 WebAssembly 和 JavaScript 之間的互動。
圖形性能優化:我們計劃在目前使用 WebGL1.0 的場景下,繼續增加 WebGL2.0 的标準接口,并計劃切換至 Metal / Vulkan 的底層圖形能力,以幫助開發者享受到最新的 OpenGL ES 3.0 的特性,包括延遲渲染、色調映射、GPU 粒子效果等等。
通信優化:目前 Camera 元件的幀資料是每一幀都從 Native 發送至 JavaScript 裡的,巨量且頻繁的通信對于性能的消耗是非常巨大的,消費幀資料的對象一般都是 Canvas 元件和 MNN 插件,這裡面是存在很大的優化空間的。針對這個場景我們重新設計了一個方案,我們利用紋理共享的機制,将相機采集到的所有圖像資訊寫入一塊共享的紋理中,這塊共享紋理的textureid 可以在 JavaScript 側被擷取到使用,開發者在無需感覺具體圖像内容的情況下調用 Canvas 元件的 textureid 接口可以直接取出共享紋理的資料并繪制在畫布上。此外在避免了 JavaScript 的通信成本之後,我們還可以繼續優化 GPU -> CPU -> GPU這個鍊路的性能,熟悉圖形學的同學都知道,CPU 和GPU 之間的資源交換是非常耗時的,通常從CPU拷貝/讀取資料到GPU的操作很昂貴,耗時一般是幾十到數百毫秒級的,我們可以利用 sharegroup 的特性在 Camera 元件和 Canvas 元件之間共享 OpenGL 上下文環境,最大限度減低 CPU 和 GPU 之間的通信成本。
能力提供:我們後續會計劃提供更多的基礎能力,包括但不限于如下:
- 目标跟蹤:虛拟内容固定在圖檔上或者定位在空間中,實作目标跟蹤能力;
- 圖檔識别:識别平面圖檔渲染内容;可以基于此識别商标、産品包裝圖案、活動海報、宣傳冊等平面物料,進行品牌數字化内容展示和互動;
- 手勢識别:識别手勢渲染内容;定制手勢,與使用者互動,更好的将品牌與消費者連接配接;
- 姿勢檢測:檢測出人體姿勢;可以基于此實作很多強肢體的互動能力,适合線下互動;
- 空間識别:識别真實實體空間;可基于此能力實作 AR 紅包等更具沉浸式的 AR 互動體驗;
- 人臉檢測:檢測出人臉;可以基于此實作虛拟試妝,虛拟試戴等體驗;
- ...
總而言之,商家應用向全行業全品牌開放的 AR 能力還有多種可能性。
體驗
真人教學彩蛋時間,感謝 Rena 小姐姐的出鏡。
現在可以通過通路 YSL 旗艦店首頁或者 Armani 旗艦店首頁來體驗兩個試妝應用,或者通過淘密碼 Or 二維碼通路:
【阿瑪尼試妝小程式】
https://m.tb.cn/h.eulervi?sm=a85a01¥siZiYwbC9Sd¥
【YSL試妝小程式】
https://m.tb.cn/h.eul5nNq?sm=27f9ea¥25W2YwbC97e¥
One More Thing
Hey,我們現在也在招人。業界領先的淘寶小程式團隊現在緻力于推進小程式底層能力建設和創意互動項目,我們非常歡迎具備 iOS / Android / C++ / Flutter / 渲染引擎 / JS引擎等技術棧的同學加入我們。
歡迎履歷投遞 Email:[email protected]
更多技術幹貨,關注「淘系技術」微信公衆号~