使用opencv.js实现图片指定区域高斯模糊(多边形)

468 阅读2分钟

需求描述

人脸识别训练后的数据在前端页面展示,并在前端使用Opencv.js进行人脸打码。

实现

虽然识别框是矩形,但是支持旋转,因此没办法直接使用Opencv对矩形区域的操作来实现。一番折腾下,使用与、或操作实现。代码如下:

getGaussian(){  
    const img = new Image();  
    img.onload = (e)=>{  
        let image = cv.imread(e.target);  
        // 备份一份图片
        const gaussianImage = new cv.Mat()  
        image.copyTo(gaussianImage)  
        // 并将图片整个高斯模糊  
        const kSize = new cv.Size(11,11);  
        cv.GaussianBlur(gaussianImage,gaussianImage,kSize,10,10,cv.BORDER_DEFAULT) 
        // 多边形区域(多个,根据业务需要循环)
        const pointArray1 = [[100,100],[100,300],[200,200],[200,100]];  
        const pointArray2 = [[200,400],[200,300],[400,400],[400,600]];  
        // 创建掩膜图像(为后面进行与、或运算准备)
        // 创建一个与图像大小相同的全黑(0,0,0,0)掩膜
        const mask = new cv.Mat.zeros(image.rows,image.cols,cv.CV_8UC1)  
        const poly = new cv.MatVector();  
        const ployData1 = cv.matFromArray(pointArray1.length,1,cv.CV_32SC2,pointArray1.flat())  
        const ployData2 = cv.matFromArray(pointArray2.length,1,cv.CV_32SC2,pointArray2.flat())  
        poly.push_back(ployData1)  
        poly.push_back(ployData2)
        // 将mask的多边形区域填充为白色(255,255,255,255)
        cv.fillPoly(mask,poly,new cv.Scalar(255,255,255,255),cv.LINE_8);  
        const polygonRegion = new cv.Mat()  
        // 进行与运算,在高斯模糊后的图片中获取指定区域  
        cv.bitwise_and(gaussianImage,gaussianImage,polygonRegion,mask);  
        // 将原图指定多边形区域填充黑色  
        cv.fillPoly(image,poly,new cv.Scalar(0,0,0,0),cv.LINE_8)  
        // 进行或运算,合并得到高斯模糊指定区域的图像  
        cv.bitwise_or(image,polygonRegion,image)  

        // Save the result  
        let raw_data = {  
        data: image.data,  
        width: image.size().width,  
        height: image.size().height  
        };  
        const data = new Uint8ClampedArray(raw_data.data);  
        const imageData = new ImageData(data,raw_data.width,raw_data.height);  
        const canvas = document.createElement("canvas");  
        canvas.width = raw_data.width;  
        canvas.height = raw_data.height;  
        const ctx = canvas.getContext('2d');  
        ctx.putImageData(imageData,0,0);  
        canvas.toBlob((blob)=>{  
        const newUrl = URL.createObjectURL(blob)  
        console.log(newUrl)  
        this.imageData.url = newUrl;  
        this.switchImageData(0);  
        },'image/png')  

        // 释放内存  
        image.delete();  
        gaussianImage.delete()  
        mask.delete()  
        polygonRegion.delete()  
    }  
    img.src = this.imageData.url;  
},

效果

  • 原图 image.png
  • 添加马赛克后

image.png

说明

使用的是@techstark/opencv-js这个库。也试过自己编译opencv.js文件,但是总是不好用,直到发现了这个库。要是哪个大佬知道编译后的opencv.js文件怎么使用请教教小弟,不胜感激!毕竟编译那玩意儿挺不容易的。