使用示例
前端代码
<view class="panel__bd">
<image class="inputImage" :src="imageUrl" mode="" style="width:750rpx;height:425rpx;"></image>
<canvas id="canvas" type="2d" class="visibleCanvas" style="width:750rpx;height:425rpx;"></canvas>
<view class="button-box">
<button @click="button1" class="marginTop10" >灰度化</button>
<button @click="button2" class="marginTop10" >边缘检测</button>
<button @click="button3" class="marginTop10">特征点检测</button>
<button @click="button4" class="marginTop10">轮廓提取</button>
</view>
</view>
js代码
// 画布
const canvas = 'canvas'
// 示例图片
const imageUrl="http://news.youth.cn/sh/201605/W020160510004428589095.jpg"
// wasm路径
global.wasm_url = '/static/js/opencv/opencv3.4.16.wasm.br'
// opencv_exec.js会从global.wasm_url获取wasm路径
let cv = require('../../static/js/opencv/opencv_exec.js');
export default {
data() {
return {
canvasWidth: 375,
canvasHeight: 236,
// 示例图片
imageUrl: imageUrl,
canDom:"",
}
},
onReady: function (e) {
this.init(canvas)
},
methods: {// 获取画布
init(canvasId) {
let _that = this;
uni.createSelectorQuery()
.select('#' + canvasId)
.fields({ node: true, size: true })
.exec((res) => {
const canvas2d = res[0].node;
// 设置画布的宽度和高度
canvas2d.width = res[0].width;
canvas2d.height = res[0].height;
_that.canDom = canvas2d
});
},
// 创建图像对象
async createImageElement() {
let _that = this;
// 创建2d类型的离屏画布(需要微信基础库2.16.1以上)
let offscreenCanvas = uni.createOffscreenCanvas({type: '2d', width: this.canvasWidth, height: this.canvasHeight});
const image = offscreenCanvas.createImage();
await new Promise(function (resolve, reject) {
image.onload = resolve;
image.onerror = reject;
image.src = _that.imageUrl
})
// 离屏画布的宽度和高度不能小于图像的
offscreenCanvas.width = this.canvasWidth;
offscreenCanvas.height = this.canvasHeight;
// draw image on canvas
let ctx = offscreenCanvas.getContext('2d')
ctx.drawImage(image, 0, 0, this.canvasWidth, this.canvasHeight);
// get image data from canvas
let imgData = ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
return imgData;
},
async button1() {
let _that = this;
// 将图像转换为ImageData
let imageData = await _that.createImageElement()
// _that.imgProcess1(image1Data, _that.canDom)
// 读取图像
let src = cv.imread(imageData);
let dst = new cv.Mat();
// 灰度化
cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY, 0);
// 显示图像
cv.imshow(_that.canDom, dst);
// 回收对象
src.delete();
dst.delete()
},
async button2() {
// 同上
let _that = this;
const imageData = await _that.createImageElement()
let src = cv.imread(imageData);
let dst = new cv.Mat();
// 灰度化
cv.cvtColor(src, src, cv.COLOR_BGR2GRAY, 0);
let ksize = new cv.Size(5, 5)
cv.GaussianBlur(src, src, ksize, 0, 0)//高斯模糊
let esize = new cv.Size(3, 3)
let element = cv.getStructuringElement(cv.MORPH_RECT, esize)
cv.dilate(src, src, element) //实现过程中发现,适当的膨胀很重要
let low = Math.ceil(src.cols / 30)
cv.Canny(src, dst, 30, 100, 3) //边缘提取
cv.imshow(_that.canDom, dst);
src.delete();
dst.delete()
},
async button3() {
// 同上
let _that = this;
const imageData =await _that.createImageElement()
// _that.imgProcess3(imageData, _that.canDom)
let src = cv.imread(imageData);
let dst = new cv.Mat();
// 灰度化
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
let orb = new cv.ORB();
let keypoints = new cv.KeyPointVector();
let descriptors = new cv.Mat();
// 特征点
orb.detect(src, keypoints)
// 特征点的描述因子
orb.compute(src, keypoints, descriptors)
// 绘制特征点
cv.drawKeypoints(src, keypoints, dst)
cv.imshow(_that.canDom, dst);
src.delete();
dst.delete()
},
async button4() {
let ratio = 1
// 同上
let _that = this;
const imageData = await _that.createImageElement()
let src = cv.imread(imageData);
let mat = src.clone()
// 灰度化
cv.cvtColor(src, src, cv.COLOR_BGR2GRAY, 0);
let ksize = new cv.Size(5, 5)
cv.GaussianBlur(src, src, ksize, 0, 0)//高斯模糊
let esize = new cv.Size(3, 3)
let element = cv.getStructuringElement(cv.MORPH_RECT, esize)
cv.dilate(src, src, element) //实现过程中发现,适当的膨胀很重要
let low = Math.ceil(src.cols / 30)
cv.Canny(src, src, 30, 100, 3) //边缘提取
let contours = new cv.MatVector()
let contours2 = new cv.MatVector()
let hierarchy = new cv.Mat()
cv.findContours(src, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
//轮廓筛选
let parentIdx = -1
let max_aera = 0
let contours3 = new cv.MatVector()
for (let i = 0; i < contours.size(); i++) {
let cnt = contours.get(i)
let area = Math.abs(cv.contourArea(cnt))
if (max_aera < area) {
max_aera = area
parentIdx = i
}
}
if (parentIdx != -1) {
let color = new cv.Scalar(0, 255, 0, 255)
let mat3 = cv.Mat.zeros(src.rows / ratio, src.cols / ratio, cv.CV_8UC3)
//找到定位点信息
contours2.push_back(contours.get(parentIdx))
let points = []
let points2 = []
let cnt = contours2.get(0)
let tmp = new cv.Mat()
let cnt_len = cv.arcLength(cnt, true) //计算轮廓周长
cv.approxPolyDP(cnt, tmp, 0.02 * cnt_len, true) //多边形逼近
for (let i = 0; i < tmp.total(); i++) {
points[i] = { x: points2[i * 2], y: points2[i * 2 + 1] }
// cv.circle(mat3, points[i], 3, color, 1) //画顶点
}
// 绘制轮廓
// cv.drawContours(mat3, contours2, 0, color, cv.FILLED)
cv.drawContours(mat3, contours2, 0, color, 2)
cv.imshow(_that.canDom, mat3)
mat3.delete()
} else {
console.log('识别失败')
}
src.delete();
},
}
}