當微信小程序遇到AR,會擦出怎么樣的火花?期待與激動......
通過該教程,可以從基礎開始打造一個微信小程序的AR框架,所有代碼開源,提供大家學習。
本課程需要一定的基礎:微信開發者工具,JavaScript,Html,Css
第二章:基石-攝像頭數據獲取
【前情提要】
上一章,我們了解了微信小程序與AR相遇一些前因后果,同時也,羅列出來是要實現這樣的功能,我們要做的事情:
1. 實現在微信小程序中訪問攝像頭,並且可以實時的拿到每一幀畫面的數據。 |
2. 實現在微信小程序中訪問WebGL接口,實現繪制三維物體。該教程采用Three.js引擎 |
3. 實現在背景為攝像頭實時畫面的背景上顯示WebGL的3D物體。 |
4. 整體框架搭建 |
5. 圖像算法接入 |
【目的】
微信小程序獲取攝像頭數據,可以實時獲得每一幀的每一個像素數據。
【准備】
下面需要搭建環境,做一些准備工作。
首先,需要注冊微信小程序開發者。注冊地址=>
注冊成功之后,需要下載微信小程序開發工具。下載地址=>
目前筆者的開發環境是:Windows 10
下載的微信小程序版本為:RC v1.0.2.1909111
【創建工程】
打開,微信開發者工具之后,會看到如下的頁面。
用注冊好的微信掃描二維碼之后,就可以登陸開發工具。下面可以選擇”小程序項目“下的”小程序“選項,創建一個系的呢小程序。
其中有幾個項目可以按照下面的說明填寫:
項目名稱:為該小程序的項目名稱,目前我們用CameraTest
目錄:項目文件保存的本地文件目錄,可以點擊右側的小箭頭,選擇本地的一個空目錄
AppID:這個微信小程序綁定的ID,每個需要上線的小程序都要有自己的ID。我們做測試的時候,可以用測試號來創建。當然這樣創建的小程序只能用來測試,不可以發布。點擊“AppID”下面的“測試號”幾個字,即可以自動使用測試號。
開發模式:我們選擇“小程序”模式
后端服務:這是微信小程序新推出的功能,可以使用微信自己的雲平台開發數據庫,我們目前不需要,所以選擇不適用雲服務器。(選擇測試賬號之后,就不會顯示后端服務選項,測試賬號不支持后端服務)
語言:選擇“JavaScript”
配置還之后可以參考下圖:
配置完成后,選擇“新建”按鈕,創建一個新的小程序項目。
關於小程序開發工具的使用,不是本教程的重點,所以這里不會做過多的闡述。感興趣的同學,可以自行學習=>
這時候可以看到,工具已經為我們創建好了一個新的預定義的工程,工程文件目錄,可以在編輯器中查看到,如下圖:
當然,目前創建的工程中有很多不需要的內容,我們把不需要的文件刪掉,做一個最簡單的工程。刪減之后的文件目錄如下:
剩下,需要刪除一些不需要的代碼。
首先“app.js”文件,將不需要的代碼刪除,最后保留如下的代碼:
//app.js App({ onLaunch: function () { }, })
同時,我們需要將“app.wxss”中的內容全部刪除。
然后,我們需要刪除“app.json”中不需要的內容,最后保留如下內容:
{
"pages": [
"pages/index/index"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
},
"sitemapLocation": "sitemap.json"
}
接着刪除“index.js”文件中不需要的代碼:
//index.js //獲取應用實例 const app = getApp() Page({ data: { }, onLoad: function () { }, })
最后,刪除“index.wxml”中不需要的部分:
<view> </view>
另外,我們需要用到小程序最新的SDK,這樣才可以用到獲取攝像頭數據的功能。該功能是從2.7.0版本之后支持的。
打開開發工具,的“詳情”按鈕,然后選擇“本地設置”,在調用基礎庫中選擇大於2.7.0的版本,如下圖:
這樣我們就建立了一個簡單的基本工程(后面的章節中如需創建基本工程,也是按照相同的步驟)。
小知識:
微信小程序的架構類似於網頁程序
wxml文件類似於Html文件,用於頁面的布局
wxss文件類似於css文件,用於定義頁面的樣式
js文件都是用於實現業務邏輯
json文件是微信小程序特有的,用於定義該頁面的權限等相關參數
【開發】
下面我們就來實現一下,微信小程序獲取攝像頭每一幀數據的功能。
首先,在index.wxml文件中,添加攝像頭Camera標簽,如下:
<view class="container"> <camera mode="normal" device-position="back" flash="auto" frame-size="medium" style="position:fixed;width:100%;height:100%"> </camera> </view>
在camera的標簽中,我們添加了幾個屬性
mode:代表攝像頭開啟的模式,是拍照或者攝像模式
device-position:代表我們開啟的是前置的還是后置的攝像頭
flash:標記攝像頭閃光燈的模式
frame-size:就是我們在每一幀畫面中獲得的數據內容的大小
style:指示頁面的上camera區域的大小位置
小知識:
有關camera標簽的更多設置,可以參考微信公眾號的文檔=>
設置完wxml文件之后,就已經可以在模擬器中看到攝像頭的畫面了。其次,我們需要在代碼中,獲取到每一幀畫面的數據。
微信基礎庫2.7.0版本之后提供了camera的幀回調函數,可以通過回調函數拿到每一幀的畫面數據。在“index.js”的文件中,添加代碼,如下:
//index.js //獲取應用實例 const app = getApp() Page({ data: { }, onLoad: function () { //獲取視頻context var cameraContext = wx.createCameraContext(); //注冊幀回調函數 var listener = cameraContext.onCameraFrame((frame)=>{ //打印返回數據是否是一個ArrayBuffer,並且返回每一幀的大小 console.log(frame.data instanceof ArrayBuffer, frame.width, frame.height); }); //啟動監聽 listener.start(); }, })
代碼首先通過createCameraContext()函數,獲得當前頁面上的攝像頭內容,其次通過onCameraFrame函數注冊一個事件監聽函數,最后啟動監聽。
在回調函數中,會返回一個frame的對象,該對象有三個屬性:width,height和data,width與height保存了每一幀畫面的寬度和高度,data屬性保存了每一幀畫面的像素列表。
如果一切正常,保存代碼后在輸出面板,我們可以看到回調函數里的輸出:
true 480 640
這代表每一幀得到的data是一個ArryBuffer數組,並且每一幀的畫面寬度是480個像素,高度是640個像素。
其次的我們想更進一步了解data中的數據,每一個像素到底用了多少空間,包含了哪些顏色的值。
為此,我們可以加一些代碼:
//index.js //獲取應用實例 const app = getApp() Page({ data: { }, onLoad: function () { //獲取視頻context var cameraContext = wx.createCameraContext(); //注冊幀回調函數 var listener = cameraContext.onCameraFrame((frame)=>{ //獲取每一幀data的長度 var data = new Uint8Array(frame.data); console.log(data.length); }); //啟動監聽 listener.start(); }, })
用一個Uint8Array對象來保存frame中的data數據,然后我們輸出data.length得到數組的長度。在筆者的環境中,獲得到的輸出如下:
1228800
這樣我們可以計算一下,每個像素占用了幾個Uint8的空間。現在已知每幀畫面的長寬為640*480,所以每一幀畫面有
640*480=307200 個像素
每個像素占用的Uint8空間的個數為:
1228800/307200=4 個
由此可知,每個像素占用了4個Uint8的空間。也就是說,一個像素存儲的形式是"[0-255],[0-255],[0,255],[0,255]" 4個0-255的數值。可以很容易的聯想到,每個像素應該是按照RGBA的格式,即紅色分量,綠色分量,藍色分量以及透明度這四個值存儲的。(事實也是如此)
有興趣的同學,也可以試驗一下在攝像頭前面放不同顏色的紙驗證一下這個猜測。
至此,我們就可以獲得每一幀的數據,以及每一幀每個像素RGBA四個分量的值。這些值將有助於后面圖像相關的各種算法,了解這些值在frame.data中的組成結構也可以幫助我們今后更好的實現我們的AR功能。
【總結】
為了給后面的框架結構打好基礎,這一章我們主要學習了,如何在微信公眾號環境下打開攝像頭並實時的獲取到每一幀的數據。
實現的方法主要是通過,createCameraContext接口獲取攝像頭的內容,再通過onCameraFrame注冊幀回調函數從而在回調函數傳回的數據中得到每一幀具體的像素內容。
通過這樣的方法,我們可以得到每一幀的大小,以及每一幀每個像素RGBA四個分量的數值。