当微信小程序遇到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;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四个分量的数值。