更新记录

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

使用方法

  1. 放置代码 下载ZIP压缩包,解压得到opencv文件夹,将整个文件夹放置在/static/js/目录下面

  2. 使用示例 前端代码

    <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;
    }
}

隐私、权限声明

1. 本插件需要申请的系统权限列表:

相机权限

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问