【秣厉科技】LabVIEW工具包——OpenCV 教程(19):拾遗 - imgproc 基础操作(上)

文章目录

  • 前言
  • [imgproc 基础操作(上)](#imgproc 基础操作(上))
    • [1. 颜色空间](#1. 颜色空间)
    • [2. 直方图](#2. 直方图)
    • [3. 二值化](#3. 二值化)
    • [4. 腐蚀、膨胀、开闭运算](#4. 腐蚀、膨胀、开闭运算)
    • [5. 梯度与轮廓](#5. 梯度与轮廓)
    • [6. 简易绘图](#6. 简易绘图)
    • [7. 重映射](#7. 重映射)
  • 总结

前言

  1. 需要下载安装OpenCV工具包的朋友,请前往 此处
  2. 系统要求:Windows系统,LabVIEW>=2018,兼容32位和64位。

imgproc 基础操作(上)

本文对于之前教程中,未曾集中详细讲解的基础图像处理内容,进行必要的补充。

这些功能基本都来源于 imgproc 模块,大概可以分为以下几个方面。

1. 颜色空间

此内容之前已有教程,详见:【秣厉科技】LabVIEW工具包------OpenCV 教程(4):颜色空间


2. 直方图

直方图是一种统计表示方法,用于展示图像中不同像素强度出现的频率分布。

OpenCV中,用 calcHist 函数计算直方图,简单用法如下:

  • 例2-1:灰度图的直方图统计,区间数为5,均匀分割 8U 范围(0~255)

  • 作为常用的一维直方图,其输出结果 Hist 是个列向量,每一个数值代表相应灰度区间内的像素数。

  • calcHist 参数含义:

参数 含义
ImageArray Mat 数组,存储一张或多张输入图像,尺寸必须一致
Hist 一个 Mat 对象,直方图统计结果的输出容器,类型为 32F
channels int 数组,指定需要做直方图统计的通道序号。当 ImageArray 包含多张图片时,通道序号依次递增,比如第一张包含3个通道,序号为0、1、2;第二张也包含3个通道,序号为3、4、5,以此类推。 channels 只包含一个通道序号时,代表最常用的一维直方图;当包含多个通道序号时,则是多维直方图。
histSize int 数组,指定每个通道(维度)的直方图数量
ranges float 数组,指定每个通道中像素强度(灰度)值的统计范围。 当 uniform 为真,ranges 每通道只需两个数值,即(总下限,总上限),将自动平均分割成 histSize 指定的份数; 当 uniform 为假,ranges 每通道需手动分割,如(h0,h1,h2,h3)代表三个范围 h0-h1,h1-h2,h2-h3 ; 以上的每个范围都遵循 "包含左端,不包含右端" 的原则,即左闭右开。
uniform 布尔值,均一化标志,其功能如上面 ranges 所述。
accumulate 布尔值,累加标志。 当 accumulate 为假,函数左端传入的 Hist 将被清空后,再写入本次直方图统计结果; 当 accumulate 为真,函数左端传入的 Hist 不会被清空,而是直接累加上本次直方图统计结果。
Mask Mat 类型的掩码,可选参数,不连接代表全图参与统计。
  • 例2-2:灰度图的直方图统计,自定义非均匀分割区间
  • 例2-3:将两张彩色图片的 R通道 直方图累加在一起
  • 通道顺序是BGR,所以两张图片R通道的序号分别是2和5;
  • 第一次 calcHist 的 accumulate 参数是真、假都可以,因为传入的 Hist 初始为空矩阵;
  • 但第二次 calcHist 的 accumulate 参数必须为真,才能实现累加。
  • 例2-4:二维直方图范例
  • channels 同时给定2个通道序号,histSize 和 ranges 指定两组分割区间,将进行二维直方图统计;
  • 假如两组区间数分别为 M 和 N,那么输出的二维直方图尺寸就是 M x N;
  • 每个元素 Hist (i,j) 代表 同时满足 "第1个通道强度值落在第1组的第 i 区间,第2个通道强度值落在第2组的第 j 区间" 的像素数;
  • 不难看出,将二维直方图 "行向累加" 成一列,就是第1个通道的一维直方图;"列向累加" 成一行,就是第2个通道的一维直方图。

3. 二值化

二值化的任务,是将一张灰度图,按照设定的阈值,转化成仅有黑白两种颜色的单通道图像。

OpenCV中,用 threshold 函数实现灰度图的二值化,简单用法如下:

  • 例3-1:灰度图二值化,阈值127,最大值255,反向模式(大于阈值时置0,小于等于阈值时置最大值)
  • threshold 参数含义:
参数 含义
srcImage 源图像
dstImage 目标图像,即二值化的结果
thresh 阈值
maxval 最大值,即二值中的较大值(最小值固定为0)
type 转化类型,共 8 种,含义见下表
retValue(返回值) 当 type 设为 OTSU 或 TRIANGLE 时,返回自适应的阈值;否则原样返回 thresh 参数值。
-- --
type类型 含义
THRESH_BINARY 阈值二值化模式,大于阈值时置 maxval ,小于等于阈值时置 0
THRESH_BINARY_INV 反向阈值二值化模式,大于阈值时置 0 ,小于等于阈值时置 maxval
THRESH_TRUNC 截断模式,大于阈值时置 thresh ,小于等于阈值时维持原值
THRESH_TOZERO 取零模式,大于阈值时维持原值,小于等于阈值时置 0
THRESH_TOZERO_INV 反向取零模式,大于阈值时置 0 ,小于等于阈值时维持原值
THRESH_MASK 返回掩码(本类型已不支持,冗余残留)
THRESH_OTSU OTSU 自适应 阈值, 基于区分前景和背景。通常与其他模式叠加使用
THRESH_TRIANGLE TRIANGLE 自适应 阈值, 基于寻找直方图双峰之间的谷底。 通常与其他模式叠加使用
  • 例3-2:灰度图二值化,采用OTSU自动确定阈值,再按 THRESH_BINARY_INV 模式转化

4. 腐蚀、膨胀、开闭运算

腐蚀、膨胀、开闭运算都属于形态学操作,这些通常在二值化图像上进行。通过特殊的滤波规则,实现二值图中白色区域的收缩、扩张、去噪、联通、边缘润滑等效果。先腐蚀后膨胀,称为开运算;先膨胀后腐蚀,称为闭运算。

相关函数如下表:

函数 功能
erode 腐蚀,白色区域收缩,孤立的小型白色区域(噪声点)甚至完全消失
dilate 膨胀, 白色区域扩张,孤立的小型黑色区域(噪声点)甚至完全消失
morphology 可实现多种形态学运算,包括腐蚀、膨胀、开运算 和 闭运算(取决于 op 参数)
getStructuringElement 生成结构元素(一个小型二维Mat),作为上述运算的滤波 "核"
  • 例4-1:对同一个二值图,用 9x9 的矩形核,分别进行腐蚀、膨胀、开运算
  • 参考范例:examples/Molitec/OpenCV/imgproc/imgproc_3(binary).vi
  • 简单说明参数:
    anchor 是锚点,即 "核" 在图像上移动时的参考点,默认(-1,-1)代表中心点‌;
    iterations 是迭代次数;
    borderType 边界像素外推的方法,默认为 BORDER_CONSTANT ,即常量填充;
    borderValue 边界填充值,默认为 64F 的最大值 1.797693134862E+308 ;
    op 是 morphology 函数独有的参数,定义操作类型。开运算 MORPH_OPEN ,闭运算 MORPH_CLOSE;

5. 梯度与轮廓

图像梯度指的是像素强度(灰度)的变化率,可以用来确定图像的边缘轮廓。

OpenCV中,常用的边缘检测函数包括:Canny、Scharr、Sobel 和 Laplacian。

其中 Canny 是个多态VI,包含 image 输入 和 dxdy 输入 两种模式。

  • 例5-1:对同一个灰度图,分别用 Canny、Scharr、Sobel 和 Laplacian 进行梯度计算和边缘检测
  • 参考范例:examples/Molitec/OpenCV/imgproc/imgproc_4(gradient).vi


  • 各函数的 params 参数说明
Canny参数 含义
threshold1 低阈值,像素梯度低于这个阈值的,一定不是边缘。
threshold2 高阈值,像素梯度高于这个阈值的,一定是边缘,且为 "强边缘"。 如果介于两个阈值之间,只有与强边缘相邻时,才被视为边缘的一部分。
apertureSize Sobel 算子尺寸,必须取1、3、5 或 7。 默认为3,代表使用 3x3 的卷积核计算梯度。
L2gradient 布尔值,为真代表使用L2范数(欧几里得距离),为假代表使用L1范数(曼哈顿距离)
-- --
Scharr参数
ddepth 目标图像深度(数据类型,如 CV_8U 等),默认为-1,代表与源图像深度相同。
dx x方向的求导阶数。0表示不计算x方向导数。
dy y方向的求导阶数。0表示不计算y方向导数。
scale 计算导数时的缩放因子,默认为1。
delta 增量值,加到计算出的导数上,默认值为0。
borderType 边界类型,默认为 BORDER_DEFAULT,等同于 BORDER_REFLECT_101
-- --
Sobel参数
ddepth 同上
dx 同上
dy 同上
ksize Sobel 算子尺寸,必须取1、3、5 或 7。
scale 同上
delta 同上
borderType 同上
-- --
Laplacian参数
ddepth 同上
ksize Laplacian 算子尺寸,必须是奇数。
scale 同上
delta 同上
borderType 同上
  • 例5-2:采用 spatialGradient 分别计算dx、dy,再用 Canny 的dxdy模式进行边缘检测
  • 这相当于把 例5-1 的 Canny 计算过程一分为二。

在经过 Canny、Scharr、Sobel 和 Laplacian 计算之后,我们往往需要把其中的边缘轮廓提取出来,也就是把输出的二值图中 "连续的白色像素" 的坐标连接在一起,形成轮廓线条。

在OpenCV中,可以使用 findContours 提取梯度二值图中的轮廓线条。

  • 例5-3:使用 Canny + findContours 计算梯度并提取轮廓,最后用 drawContours 绘制轮廓
  • findContours 参数
  • mode 定义轮廓检索模式,默认 RETR_EXTERNAL 代表只检索最外层的轮廓;
  • method 定义轮廓近似方法,默认 CHAIN_APPROX_SIMPLE 代表简单近似法;
  • offset 是坐标偏移量,默认(0,0);
  • 输出 contours‌ 是轮廓结果,其中 pts 数组是全部点坐标序列,npts 代表每个轮廓包含的点数,ncontours 代表轮廓个数。这与之前教程(5)中 drawContours 的输入参数定义相同;
  • 输出 hierarchy 代表轮廓的层次结构,是1个(轮廓个数 x 4)的二维数组。每行4个整数,依次代表本行索引号轮廓的 "上一个、下一个、第一个、最后一个" 轮廓的索引号。-1 表示没有。

从上图 hierarchy 输出可以分析:

第0行(1,-1,-1,-1)代表0号轮廓的上一个是1号轮廓,下一个是 -1(没有);

第1行(2,0,-1,-1)代表1号轮廓的上一个是2号轮廓,下一个是0号轮廓;

第2行(3,1,-1,-1)代表2号轮廓的上一个是3号轮廓,下一个是1号轮廓;

...

最终得出,这6个轮廓的先后顺序为:5,4,3,2,1,0


6. 简易绘图

此内容之前已有教程,详见:【秣厉科技】LabVIEW工具包------OpenCV 教程(5):简易绘图


7. 重映射

图像重映射,指的是按照一定规则,重新排布源图像中的像素坐标位置,并渲染到目标图像中。

之前教程提到的 resize 就是一种重映射,用于实现图片的缩放。

  • 例7-1:使用 resize 将源图像尺寸缩小到原来的一半
  • resize 参数
  • dsize:目标图像尺寸。如果 dsize 不为0,输出图像尺寸以 dsize 为准;否则,将由下面的 fx、fy 计算决定;
  • fx:水平方向缩放因子;
  • fy:垂直方向缩放因子;
  • interpolation:插值方法,指的是当放大图像时,填补空缺的方法。默认 ‌INTER_LINEAR 双线性插值法。

下面,再介绍两种可以扭曲源图像形状的重映射:仿射变换(warpAffine)和 透视变换(warpPerspective)。

  • 例7-2:分别使用 warpAffine 和 warpPerspective,将图片中一块 "四边形" 区域重映射成 "矩形"
  • 参考范例:examples/Molitec/OpenCV/imgproc/imgproc_7(wrap).vi
  • 首先,锚定源图像四边形的4个顶点,再给定输出矩形的4个顶点,将这两组顶点分别输入到 getAffineTransform 和 getPerspectiveTransform 中,运行得到各自的变换矩阵 M;
  • 接着,使用 warpAffine 配合 getAffineTransform 输出的 M,完成仿射变换;
  • 使用 warpPerspective 配合 getPerspectiveTransform 输出的 M,完成透视变换;

如果你想完全自定义一种映射关系,即手动给定每一个像素在新图像中的坐标位置,那么可以使用 remap 函数。

  • 例7-3:使用 remap 实现图片的水平翻转
  • remap 函数 VI 的上方需要输入两个 Mat 参数,名称分别为 map1 和 map2,用于逐像素指定映射后的新坐标;
  • 上述 map1 和 map2 有两种组织方式:
    其一,map1 和 map2 都是单通道矩阵,那么 map1 指定所有像素映射之后的X坐标,map2 指定Y坐标;
    其二,map1 是双通道矩阵,那么由 map1 独自指定(X,Y)坐标,而 map2 为空矩阵 即可。
  • 参考范例:examples/Molitec/OpenCV/imgproc/imgproc_6(remap).vi

顺便一提,如果只是需要进行图片翻转、旋转这样常规的操作,那完全没必要用到 remap。使用 core 模块下的 flip 和 rotate 等函数,就完全可以做到,而且更为简洁。

core 模块下也有不少重映射的方法,感兴趣的读者可以试一试。


总结

  1. 本系列博文作为LabVIEW工具包---OpenCV的教程,将以专栏的形式陆续发布和更新。
  2. 对工具包感兴趣的朋友,欢迎下载试用:秣厉科技 - LabVIEW工具包 - OpenCV
  3. 各位看官有什么想法、建议、吐槽、批评,或新奇的需求,也欢迎留言讨论。
相关推荐
进来有惊喜23 分钟前
OpenCV 图像拼接
人工智能·opencv·计算机视觉
jndingxin10 小时前
OpenCV 图形API(31)图像滤波-----3x3 腐蚀操作函数erode3x3()
人工智能·opencv·计算机视觉
YOULANSHENGMENG10 小时前
使用opencv+python 实现图像的斜向矫正
opencv·计算机视觉
qp11 小时前
24.OpenCV中的霍夫直线检测
opencv·计算机视觉
新知图书11 小时前
OpenCV滑动条事件
人工智能·opencv·计算机视觉
zhongqu_3dnest13 小时前
VR 全景多维赋能,众趣科技助力零售业开启购物新时代
科技·vr
2201_7549184113 小时前
OpenCv--换脸
人工智能·opencv·计算机视觉
绝顶大聪明19 小时前
图像预处理(OpenCV)-part2
人工智能·opencv·计算机视觉
Despacito0o20 小时前
OpenCV图像增强实战教程:从理论到代码实现
人工智能·opencv·计算机视觉
编码小哥20 小时前
OpenCV直方图均衡化全面解析:从灰度到彩色图像的增强技术
人工智能·opencv·计算机视觉