V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
darluc
V2EX  ›  Node.js

OpenCV 入门:用 Node.js 进行图片处理 (译文)

  •  2
     
  •   darluc · 2017-03-20 19:36:33 +08:00 · 11069 次点击
    这是一个创建于 2805 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在这篇 OpenCV 入门文章中,我将会向大家展示如何使用 Node.js 进行计算机视觉处理。并且结合实例讲解使用 OpenCV 这个开源库进行图像处理的基础方法。

    目前,我正在完成我的硕士论文,其中使用到了 React Native ,神经网络,和 OpenCV 计算机视觉库。请允许我向你们展示一些我在使用 OpenCV 过程中学习到的一些东西。

    计算机视觉是计算机科学中的一个领域,主要专注于使用不同的算法从图像和视频中获取数据。

    计算机视觉在许多领域得到了广泛地应用,例如安全摄像头的运动跟踪,控制车辆进行自动驾驶,从图片或视频中识别或搜索对象。

    要实现计算机视觉算法是一件非常繁复的工作,不过幸好有 OpenCV 这个非常好的开源库,此库起源于 1999 年,并一直发展到现在。

    OpenCV 官方支持 C , C ++, Python 和 Java 。幸运的是,由 Peter Braden 领导的一群 Javascript 程序员开发了一个 Javascript 的 OpenCV 接口库,名为 node-opencv

    利用该接口库,我们可以实现用于图像分析的 Node.js 应用。此库目前还没有实现所有的 OpenCV 特性 - 特别是 OpenCV 3 的一些特性 - 不过已经基本够用了。

    安装

    要在 Node.js 中使用 OpenCV 库,你得先进行全局安装。在 MacOS 上,你可以通过 Homebrew 来安装。在这篇文章中我安装并使用的是 OpenCV 的 2.4 版本。

    译者注:由于译者实际使用的是 OpenCV 3.2.0 版本,故在边缘侦测部分的代码相对于原文有所修改。

    brew tap homebrew/science
    brew install opencv
    

    如果你使用的是其它的操作系统,这里有 LinuxWindows 版本的教程。在成功安装之后,我们就可以在 Node.js 项目中安装 node-opencv 了。

    npm install --save opencv
    

    有时安装会失败(它是开源项目,还没有到达最终完成的阶段),不过你应该可以在该项目的 GitHub 页面上找到对应的解决办法。

    OpenCV 基础

    加载及保存图片 + 矩阵

    OpenCV 的最基本功能是加载和保存图像。你可以通过下面的方法调用这些功能:cv#readImage() 和 **Maritx#save()**;

    const cv = require('opencv');
    
    cv.readImage('./img/myImage.jpg', function(err, img) {
      if (err) {
        throw err;
      }
      
      const width = im.width();
      const height = im.height();
      
      if (width < 1 || height < 1) {
        throw new Error('Image has no size');
      }
      
      // do some cool stuff with img
      
      // save img
      img.save('./img/myNewImage.jpg');
    });
    

    承载加载图片数据的对象,是 OpenCV 使用的一个基本数据结构 - 矩阵。所有载入和生成的图像都是用矩阵来描述的,矩阵中的每一个元素都对应图像的一个像素。矩阵的大小由载入图像的大小决定。在 Node.js 中你可以使用特定参数调用 new Matrix() 构造方法来生成一个矩阵。

    new cv.Matrix(rows, cols);
    new cv.Matrix(rows, cols, type, fillValue);
    

    修改图像

    变换图像颜色是一个基础方法。例如,我们可以调用 Matrix#convertGrayscale() 得到一个灰度图片。

    img.convertGrayScale();
    img.save('./img/myGrayscaleImg.jpg');
    

    在进行边缘探测时经常会用到这个方法。

    我们可以使用 Matrix#convertHSVscale() 方法将图像转换为 HSV 圆柱坐标表示( HSV cylindrical-coordinate representation )。

    img.convertHSVscale();
    img.save('./img/myHSVscaleImg.jpg');
    

    我们可以使用 Matrix#crop(x, y, width, height) 方法来裁剪图片,并指定其中的参数。

    这个方法并不会改变当前的图像,而是返回一个全新的图像。

    let croppedImg = img.crop(1000, 1000, 1000, 1000);
    croppedImg.save('./img/croppedImg');
    

    如果我们想要将图像对象赋值给另一个变量,可以使用 Matrix#copy() 方法返回一个新的图片对象。

    let newImg = img.copy();
    

    这样,我们可以用一些基础的 Matrix 方法进行工作了。我们还能找到各种模糊和滤镜方法来进行图片编辑。你可以在 GitHub 项目里的 Matrix.cc 文件中找到 Matrix 对象实现的所有方法。

    腐蚀和膨胀

    腐蚀和膨胀是数学形态学( mathematical morphology )的基本方法。我将结合下面的图像修改操作来解释它们是如何工作的。(译者注:具体数学定义可参考此文

    二进制图像 A 通过结构元素 B 的膨胀定义如下

    OpenCV 有一个 Matrix#dilate(iterations, structEl) 方法,其中的 iterations 参数指定膨胀的量,structEl 参数是用于膨胀的结构元素(默认为 3X3 )。

    我们可以用此参数调用膨胀方法。

    img.dilate(3);
    

    OpenCV 调用膨胀方法时如下。

    cv::dilate(self->mat, self->mat, sturctEl, cv::Point(-1, -1), 3);
    

    调用过此方法后,我们可以得到如下修改过的图像。

    二进制图像 A 通过结构元素 B 的腐蚀定义如下

    在 OpenCV 中,我们可以调用 Martix#erode(iterations, structEl) 方法,和前面的膨胀方法相似。

    我们可以这样调用它:

    img.erode(3);
    

    同样我们可以得到一个腐蚀过的图像。

    边缘侦测

    关于边缘侦测,我们可以使用「坎尼边缘探测算法」。该算法起源于 1986 年,并且一个非常流行,被称作「最佳探测器」。算法规定了边缘侦测中三个重要的标准,列举如下:

    1. 边缘侦测要保证低错误率;
    2. 良好的边缘定位 - 探测到的边缘和实际边缘像素差必须最小;
    3. 图像的边缘只能被标记一次;

    在使用「坎尼边缘探测算法」前,我们可以先将图像转为灰度格式,通常这样做可以让我们获得更好的结果。接下来,我们可以通过高斯模糊滤镜消除图像上的噪点,它需要一个向量作为高斯核大小的参数( which receives a parameter as a field - Gaussian kernel size )。再调用这两个方法处理过后,我们可以在坎尼边缘侦测时获得更好更准确的结果。

    点击阅读全文

    翻译自:OpenCV tutorial: Computer vision with Node.js

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2732 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 07:04 · PVG 15:04 · LAX 23:04 · JFK 02:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.