vieyahn2017 / pypy

python trial collections
1 stars 1 forks source link

图片修复js #12

Open vieyahn2017 opened 1 year ago

vieyahn2017 commented 1 year ago

inpaint.js, 在JS中,Telea修复算法 inpaint.js这主要是Telea修复算法的端口,来自 scikit图像 。 它利用快速行进法,根据周围区域来填充图像的特定区域。 具体细节在博客发布( 由最初实现这些修复程序的人)的博客发布中描述得非常好

vieyahn2017 commented 1 year ago

https://github.com/antimatter15/inpaint.js/blob/master/inpaint.js

vieyahn2017 commented 1 year ago

webassembly+opencv前端实现图片去水印 https://juejin.cn/post/6875964584436432909

webassembly环境搭建 下载emsdk项目,进行构建。

git clone https://github.com/juj/emsdk.git cd emsdk ./emsdk update ./emsdk install latest ./emsdk activate latest source ./emsdk_env.sh 复制代码 构建openCV的webassembly版本 下载 opencv 项目

git clone https://github.com/opencv/opencv.git 复制代码 构建 webassembly版本

python ./platforms/js/build_js.py build_wasm --build_wasm 复制代码 注意:构建这里有个坑,如果本地的webassembly环境名字不一定叫 EMSCRIPTEN ,这时就会提示该环境不存在;需要手动需要修改build_js.py文件 ,设置你本地emscripten环境地址,即令:

emscripten_dir='your emscripten path' 复制代码 构建文件为opencv/build_wasm/bin/opencv.js , wasm新型二进制代码已经被构建到了opencv.js 中,在HTML文件中直接引入。Opencv会暴露一个cv作为全局对象。我们通过cv来使用opencv的各种方法。

复制代码 图片去水印 主要使用了cv.inpaint方法给图片去水印,可以参考C++的使用方法。

void inpaint( InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags ); 复制代码 参数介绍:

src 输入1通道或3通道图像。 蒙版 1通道图像。非零像素表示需要修复的区域。大小跟原图像一致 dst 输出的经过修复的图像。 半径 该算法考虑的每个修补点的圆形邻域的半径。 标志 修复算法,有两种 INPAINT_NS或INPAINT_TELEA 复制代码 注意:在浏览器中使用cv.imread 方法读取图片,获取到的是四通道类型图像数据,而inpaint只支持处理一通道或三通道数据图像,所以我们还要进行下数据转换。

let dst = new cv.Mat(); let imgRGB = new cv.Mat(); let imgGrey = new cv.Mat(); let imageSource = cv.imread("img1", cv.CV_8UC3); //转成三通道图像 cv.cvtColor(imageSource, imgRGB, cv.COLOR_BGRA2BGR); //转成灰度图 cv.cvtColor(imageSource, imgGrey, cv.COLOR_RGBA2GRAY);

let imgMask = new cv.Mat(img1.height, img1.width, cv.CV_8UC1, new cv.Scalar(0, 0, 0, 0)); //通过阈值处理生成Mask cv.threshold(imgGrey, imgMask, 240, 255, cv.THRESH_BINARY); let kernel = cv.getStructuringElement(cv.MORPH_RECT, new cv.Size(3, 3));

//对Mask膨胀处理,增加Mask面积 cv.dilate(imgMask, imgMask, kernel);

cv.inpaint(imgRGB, imgMask, dst, 10, cv.INPAINT_TELEA); cv.imshow(outputCanvas, dst);

dst.delete(); imgRGB.delete(); imgGrey.delete(); imageSource.delete(); 复制代码 处理前

处理后

    处理时长为30ms,效果还是可以的。但是从蒙版图片可以看出,处理区域不仅是水印部分,还包括了原图其他部分,这并不是我们想要的结果;再进行下优化,只对水印区域进行处理。

    获取到水印区域坐标,对坐标内的图像阈值处理、生成Mask。

canvesBox.onmousedown = function (e) { x = e.offsetX; // 鼠标落下时的X y = e.offsetY; // 鼠标落下时的Y ctx.beginPath(); document.onmouseup = function (e) { console.log('onmouseup', e.offsetX, e.offsetY) rx = e.offsetX;//鼠标抬起时的X坐标 ry = e.offsetY;//鼠标抬起时的Y坐标 document.onmousemove = null; document.onmouseup = null;

    //获取选中区域的图像
    var dataImg = ctx.getImageData(x, y, rx - x, ry - y);
    objCanvas.width = canvesBox.width;
    objCanvas.height = canvesBox.height;
    objctx.putImageData(dataImg, x, y);
    url = canvesBox.toDataURL();
}

} 复制代码 结果

优化 按照官方的构建方式得到的opencv.js有9M多,这对于一个网站来说实在是太大了,需要优化一下;通过修改配置文件,把用到的方法都挑出来,可以有效降低opencv.js文件大小。

打开 Opencv/platforms/js/build_js.py 把除了js和photo外,把其他用不到的依赖项都设为OFF def get_cmake_cmd(self): -DBUILD_opencv_photo=ON, -DBUILD_opencv_js=ON, 复制代码

  1. 打开默认加载配置文件Opencv/platforms/js/build_js.config.py本次去水印功能,用到的函数并不多,这里把用到的函数挑出来,其他都删掉。

Classes and methods whitelist

imgproc = {'': ['cvtColor','threshold','getStructuringElement', 'dilate']} photo = {'': ['inpaint']} white_list = makeWhiteList([imgproc, photo]) 复制代码 再次构建,可以发现opencv文件缩小到了1.8M。1.8M对于一个js文件来说还是比较大的,但目前大小很难在往下缩减了,如果非要缩减,只能把opencv中inpaint函数独立出来,自己再封装成一个函数(封装方法可以参考我上一期的webassembly学习笔记)。这样实现的门槛比较高;比如,要对inpaint函数原理很了解,对C++很熟练,才有可能把它独立出来。

总结 Webassembly的性能还是很可观的 ,但是现阶段webassembly各项插件库并不多,资料少,应用场景少,门槛还高,不利于技术的发展。Opencv.js已经算是比较成熟的webassembly