介绍
相比使用JavaScript版本的OpenCV,微信小程序使用WebAssembly版本的OpenCV,体积较小,运行速度较快。
网页版
在线预览,和小程序版使用的是相同的wasm文件。
https://sanyuered.github.io/WeChat-MiniProgram-AR-WASM/opencv_dev/lesson2.html
小程序版
https://github.com/sanyuered/WeChat-MiniProgram-AR-WASM
首页

灰度化
imgProcess1(imageData, canvasDom) {
// 读取图像
let src = cv.imread(imageData);
let dst = new cv.Mat();
// 灰度化
cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY, 0);
// 显示图像
cv.imshow(canvasDom, dst);
// 回收对象
src.delete();
dst.delete()
}

边缘检测
imgProcess2(imageData, canvasDom) {
let src = cv.imread(imageData);
let dst = new cv.Mat();
// 灰度化
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
// 边缘检测
cv.Canny(src, dst, 50, 100, 3, false);
cv.imshow(canvasDom, dst);
src.delete();
dst.delete()
}

特征点检测
imgProcess3(imageData, canvasDom) {
let src = cv.imread(imageData);
let dst = new cv.Mat();
// 灰度化
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
var orb = new cv.ORB();
var keypoints = new cv.KeyPointVector();
var descriptors = new cv.Mat();
// 特征点
orb.detect(src, keypoints)
// 特征点的描述因子
orb.compute(src, keypoints, descriptors)
// 绘制特征点
cv.drawKeypoints(src, keypoints, dst)
cv.imshow(canvasDom, dst);
src.delete();
dst.delete()
}

技术难点
1、如何获取OpenCV的wasm文件?
从OpenCV官方网站下载opencv.js,该js中包含了Base64编码的wasm文件。从opencv.js文件中的变量wasmBinaryFile提取Base64编码,将Base64编码转换为二进制文件。下方地址中的3.4.16表示OpenCV版本号,可以更改为其它版本号。
下载地址:https://docs.opencv.org/3.4.16/opencv.js
2、OpenCV 3的wasm文件有5MB大小,怎样部署到小程序2MB的分包里?
将.wasm压缩为.wasm.br,文件大小变为1.14MB。符合了小程序的分包大小限制。
3、小程序如何运行OpenCV的wasm?
错误示例:
WXWebAssembly.instantiate(wasmBinaryFile, {})
正确示例:
WXWebAssembly.instantiate(wasmBinaryFile, info)
对象info来自opencv.js文件。
4、小程序不支持new Function()和Function.Apply(),无法编译和运行opencv.js。
将opencv.js的new Function()和Function.Apply()的代码改写。
文件修改的位置使用了IsWechat变量标识。具体修改请见源代码。
const IsWechat = true;
5、opencv.js有3个地方使用了new Function(),2个修改简单,1个修改复杂。
修改前:
return new Function("body", "return function " + name + "() {\n" +
'' "use strict";'' +
" return body.apply(this, arguments);\n" + "};\n")(body)
修改后:
var f1 = function (body) {
return function () {
"use strict";
return body.apply(this, arguments);
}
}
return f1(body)
6、opencv如何在小程序里读取和显示图像?
使用ImageData读取图像,使用Canvas显示图像。
常见问题
1、调用了其它OpenCV函数,发生错误?
js调用OpenCV函数的变量数量、变量类型、变量位置等要和调用OpenCV的C++写法一样。不能和Python写法一样。
2、这个支持OpenCV的全部API吗?
支持OpenCV 3.4.16版本(目前OpenCV 3的最新版本)的API。因为OpenCV 4体积比OpenCV 3大,所以没有考虑把OpenCV 4放进小程序。项目包含的opencv3.4.16.wasm文件是OpenCV官方编译的。
3、这个需要的小程序基础库的最低版本是多少?
WXWebAssembly依赖的基础库
全局访问 :基础库 v2.13.0
允许传入brotli压缩的.wasm文件:基础库 v2.14.0
在 Worker 内使用 :基础库 v2.15.0
在小程序插件使用 :基础库 v2.18.1
wx.createOffscreenCanvas()依赖的基础库
全局访问和小程序插件:基础库2.16.1
4、使用方法cv.imread(图片,0)将彩色图片转换为灰色图片,不起作用。
WebAssembly版本的OpenCV和C++版本的OpenCV有些差异,方法cv.imread()只接受一个输入参数。
使用cv.cvtColor(图片)方法代替cv.imread(图片,0)。
let src = cv.imread(imageData);
let dst = new cv.Mat();
// 灰度化
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);5、小程序使用OpenCV能做什么?
图像处理、运动估计、人脸识别、目标识别、图像分割、运动跟踪、增强现实等。