更新记录
V1.0.1(2022-04-13) 下载此版本
基于https:/github.com/sanyuered/WeChat-MiniProgram-AR-WASM修改而来
平台兼容性
Vue2 | Vue3 |
---|---|
√ | √ |
App | 快应用 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节小程序 | QQ小程序 |
---|---|---|---|---|---|---|
app-vue | × | √ | × | × | × | × |
钉钉小程序 | 快手小程序 | 飞书小程序 | 京东小程序 |
---|---|---|---|
× | × | × | × |
H5-Safari | Android Browser | 微信浏览器(Android) | QQ浏览器(Android) | Chrome | IE | Edge | Firefox | PC-Safari |
---|---|---|---|---|---|---|---|---|
× | × | × | × | × | × | × | × | × |
RboyUploadSfz 身份证正反面上传
组件名:opencv-uni 代码块:
opencv-exec
使用方法
-
放置代码 下载ZIP压缩包,解压得到opencv文件夹,将整个文件夹放置在/static/js/目录下面
-
使用示例 前端代码
<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(); }, } }
css代码
.title{
width: 750rpx;
height: 60rpx;
background-color: #00aa00;
font-size: 30rpx;
text-align:center;
margin-top: 20rpx;
// margin-bottom: 20rpx;
color: #ffffff;
}
.visibleCanvas{
margin-top: 25rpx;
}
.button-box{
width: 750rpx;
height: 80rpx;
padding-top: 10rpx;
button{
width: 600rpx;
height: 70rpx;
font-size: 24rpx;
background-color: #4CD964;
color: #ffffff;
// line-height: 50rpx;
border-radius: 50rpx;
margin-top: 20rpx;
}
}