初识opencvjs

OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。该程序库也可以使用英特尔公司的IPP进行加速处理。
OpenCV.js------连接OpenCV与JS开发者
随着HTML5的兴起,在web端使用图像处理相关技术显得尤为重要,OpenCV.js为Javascript开发者与OpenCV之间搭建了桥梁。起初是由Intel公司发起的一项研究,后在2017年并入到OpenCV项目中。
Emscripten,一款LLVM-to-JavaScript的编译器,将C++的底层函数编译成可以直接在浏览器端运行的asm.js或者WebAssembly。而OpenCV.js是通过该Emscripten将OpenCV的函数编译进asm.js或WebAssembly中,并提供JS APIs给web应用使用。
OpenCV.js的目标:
1. 实现OpenCV在web端的开发与使用
2. 帮助网络社区,开发人员和计算机视觉研究人员交互访问各种基于Web的OpenCV示例,帮助他们理解特定的视觉算法。
基本概念与操作
矩阵
OpenCV.js 引入了新的变量类型 ------ Mat类型,即矩阵类型,使用 let mat = new cv.Mat(); 来创建新的矩阵类型,OpenCV.js 读取的图像均使用该类型存储。
图像的读取与写入
OpenCV.js 可以将 <img> 或者 <canvas> 的内容读取为矩阵类型用以变换,同时也可以将处理好的图像作为 <img> 或者 <canvas>的内容,具体方法如下:
csharp 复制代码
// 读取
let mat = cv.imread("inputCanvasId");
// 其中 inputCanvasId 为目标 DOM 元素的 id 属性

// 写入
cv.imshow(mat, "outputCanvasId");
// mat 为处理后图像矩阵变量
官方已经提供比较完整的说明文档,这里不详细介绍具体的 API 了,我们简单说一下用法。注意:所有的代码应该写在初始化函数onRuntimeInitialized中。cv 提供了imread(imageid | HTMLImageElement | HTMLCanvasElement) 的函数签名,这可以从指定的源读取图片内容,并返回一个cv.Mat类型的对象,这是一个基本的存储二维空间的数据结构------矩阵,这里用来存储图片的像素结构,后面很多操作都是基于Mat类型来操作的。输出图片也非常方便,直接调用cv.imshow(canvasid | HTMLCanvasElement, cv.Mat对象) 就可以把图像绘制在屏幕上。需要记住的是 WebAssembly 不会帮助你回收内存,所以记得 cv.Mat 对象用完后及时调用delete()方法释放内存。
图像数据类型
Mat 是 OpenCV 基础的图像数据结构,其数据类型对照表如下:

| Data Properties

| C++Type | JavaScript Typed Array | Mat Type | | --- | --- | --- | --- | | data | uchar | Uint8Array | CV_8U | | data8S | char | Int8Array | CV_8S | | data16U | ushort | Uint16Array | CV_16U | | data16S | short | Int16Array | CV_16S | | data32S | int | Int32Array | CV_32S | | data32F | float | Float32Array | CV_32F | | data64F | double | Float64Array | CV_64F |

灰度实现
xml 复制代码
<!DOCTYPE html>
<html>
    <head>
        <title>OpenCV.js</title>
        <style type="text/css">
            .wrap-image {
                display: flex;
                flex-direction: row;
                margin-top: 10px;
            }
            .wrap-image img,
            .wrap-image canvas {
                width: 300px;
                margin-right: 10px;
            }
        </style>
    </head>

    <body>
        <h3 id="status">Loading the Opencv ...</h3>
        <input type="file" id="fileInput-gray"/>
        <div class="wrap-image">
            <img id="imageUpload-gray" alt="No Image" />
            <canvas id="canvasOutput-gray"></canvas>
        </div>
        <script type="text/javascript">

            //图片灰度处理效果:
            let imgElement = document.getElementById('imageUpload-gray');
            let inputElement = document.getElementById('fileInput-gray');

            inputElement.onchange = function() {
              imgElement.src = URL.createObjectURL(event.target.files[0]);
            }

            imgElement.onload =function() {
                let src = cv.imread('imageUpload-gray');
                let dst = new cv.Mat();
                cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY, 0);
                cv.imshow('canvasOutput-gray', dst);
                src.delete(); dst.delete();
            };
            function onOpenCvReady() {
                document.getElementById('status').remove();
            }
        </script>
        <script async src="https://docs.opencv.org/4.5.3/opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
    </body>
</html>

image.png

图像阈值处理
ini 复制代码
//图片灰度处理效果:
let imgElement = document.getElementById('imageUpload');
let inputElement = document.getElementById('fileInput');

inputElement.onchange = function() {
  imgElement.src = URL.createObjectURL(event.target.files[0]);
}

imgElement.onload =function() {
    let src = cv.imread('imageUpload');
    let dst = new cv.Mat();
    // cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY, 0);
    cv.threshold(src, dst, 177, 200, cv.THRESH_BINARY);
    cv.imshow('canvasOutput', dst);
    src.delete(); dst.delete();
};
function onOpenCvReady() {
    document.getElementById('status').remove();
}

image.png

自适应阈值
ini 复制代码
let imgElement = document.getElementById('imageUpload');
let inputElement = document.getElementById('fileInput');

inputElement.onchange = function() {
  imgElement.src = URL.createObjectURL(event.target.files[0]);
}

imgElement.onload =function() {
    let src = cv.imread('imageUpload');
    let dst = new cv.Mat();
    cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
    // You can try more different parameters
    cv.adaptiveThreshold(src, dst, 200, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 3, 2);

    cv.imshow('canvasOutput', dst);
    src.delete(); dst.delete();
};
function onOpenCvReady() {
    document.getElementById('status').remove();
}

image.png

滤镜处理
ini 复制代码
let imgElement = document.getElementById('imageUpload');
let inputElement = document.getElementById('fileInput');

inputElement.onchange = function() {
  imgElement.src = URL.createObjectURL(event.target.files[0]);
}

imgElement.onload =function() {
  let src = cv.imread('imageUpload');
  let dst = new cv.Mat();
  let M = cv.Mat.eye(3, 3, cv.CV_32FC1);
  let anchor = new cv.Point(-1, -1);
  // You can try more different parameters
  cv.filter2D(src, dst, cv.CV_8U, M, anchor, 0, cv.BORDER_DEFAULT);

  cv.imshow('canvasOutput', dst);
  src.delete(); dst.delete();
};
function onOpenCvReady() {
  document.getElementById('status').remove();
}

image.png

图像模糊
ini 复制代码
let imgElement = document.getElementById('imageUpload');
let inputElement = document.getElementById('fileInput');

inputElement.onchange = function() {
  imgElement.src = URL.createObjectURL(event.target.files[0]);
}

imgElement.onload =function() {
    let src = cv.imread('imageUpload');
    let dst = new cv.Mat();
    let ksize = new cv.Size(3, 3);
// You can try more different parameters
cv.GaussianBlur(src, dst, ksize, 0, 0, cv.BORDER_DEFAULT);
    cv.imshow('canvasOutput', dst);
    src.delete(); dst.delete();
};
function onOpenCvReady() {
    document.getElementById('status').remove();
}

image.png

图像直方图
ini 复制代码
let imgElement = document.getElementById('imageUpload');
let inputElement = document.getElementById('fileInput');

inputElement.onchange = function() {
  imgElement.src = URL.createObjectURL(event.target.files[0]);
}

imgElement.onload =function() {
    let src = cv.imread('imageUpload');
        // let dst = new cv.Mat();
        // let src = cv.imread('canvasInput');
    cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
    let srcVec = new cv.MatVector();
    srcVec.push_back(src);
    let accumulate = false;
    let channels = [0];
    let histSize = [256];
    let ranges = [0, 255];
    let hist = new cv.Mat();
    let mask = new cv.Mat();
    let color = new cv.Scalar(255, 255, 255);
    let scale = 2;
    // You can try more different parameters
    cv.calcHist(srcVec, channels, mask, hist, histSize, ranges, accumulate);
    let result = cv.minMaxLoc(hist, mask);
    let max = result.maxVal;
    let dst = new cv.Mat.zeros(src.rows, histSize[0] * scale,
                            cv.CV_8UC3);
    // draw histogram
    for (let i = 0; i < histSize[0]; i++) {
        let binVal = hist.data32F[i] * src.rows / max;
        let point1 = new cv.Point(i * scale, src.rows - 1);
        let point2 = new cv.Point((i + 1) * scale - 1, src.rows - binVal);
        cv.rectangle(dst, point1, point2, color, cv.FILLED);
    }
    cv.imshow('canvasOutput', dst);
    src.delete(); dst.delete(); srcVec.delete(); mask.delete(); hist.delete();
}
function onOpenCvReady() {
    document.getElementById('status').remove();
}

image.png

参考文献

相关推荐
GIS程序媛—椰子13 分钟前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_00119 分钟前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端22 分钟前
Content Security Policy (CSP)
前端·javascript·面试
木舟100926 分钟前
ffmpeg重复回听音频流,时长叠加问题
前端
王大锤439137 分钟前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
我血条子呢1 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
黎金安1 小时前
前端第二次作业
前端·css·css3
啦啦右一1 小时前
前端 | MYTED单篇TED词汇学习功能优化
前端·学习
半开半落1 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt