OpenCV数字图像处理基于C++之图像形态学处理详解

目录
  • 1、图像腐蚀
    • 1.1 CV腐蚀函数
    • 1.2 自定义腐蚀函数
    • 1.3 对比
  • 2、图像膨胀
    • 2.1 CV膨胀函数
    • 2.2 自定义膨胀函数
    • 2.3 对比
  • 3、开运算
    • 3.1 方法一
    • 3.2 方法二
  • 4、闭运算
    • 4.1 方法一
    • 4.2 方法二
    • 4.3 morphologyEx函数介绍
  • 5、顶帽运算
    • 5.1 方法一
    • 5.2 方法二
  • 6、黑帽运算
    • 6.1 方法一
    • 6.2 方法二
  • 7、形态学梯度
    • 7.1 方法一
    • 7.2 方法二
  • 总结

1、图像腐蚀

原理:腐蚀用来收缩或细化二值图像中的前景,借此实现去噪声、元素分割等功能。和所有形态学滤波器一样,腐蚀和膨胀这两个滤波器的作用范围是由结构元素定义的像素集。在某个像素上应用结构元素时,结构元素的锚点与该像素对齐,所有与结构元素相交的像素就包含在当前集合中。腐蚀就是把当前像素替换成所定义像素集合中的最小像素值膨胀是腐蚀的反运算,它把当前像素替换成所定义像素集合中的最大像素值。由于输入的二值图像只包含黑色(值为0)和白色(值为255)像素,因此每个像素都会被替换成白色或黑色像素。

​ 要形象地理解这两种运算的作用,可考虑背景(黑色)和前景(白色)的物体。腐蚀时,如果结构元素放到某个像素位置时碰到了背景(即交集中有一个像素是黑色的),那么这个像素就变为背景;膨胀时,如果结构元素放到某个背景像素位置时碰到了前景物体,那么这个像素就被标为白色。正因如此,图像腐蚀后物体尺寸会缩小(形状被腐蚀),而图像膨胀后物体会扩大。在腐蚀图像中,有些面积较小的物体(可看作背景中的“噪声”像素)会彻底消失。与之类似,膨胀后的物体会变大.而物体中一些“空隙”会被填满。OpenCV默认使用3×3正方形结构元素。在调用函数时,就能得到默认的结构元素。你也可以通过提供一个矩阵来指定结构元素的大小(以及形状),矩阵中的非零元素将构成结构元素。

作用去除图像中的某些部分以及会缩小细化目标

1.1 CV腐蚀函数

CV_EXPORTS_W void erode(
    InputArray src,
    OutputArray dst,
    InputArray kernel,
    Point anchor = Point(-1,-1),
    int iterations = 1,
    int borderType = BORDER_CONSTANT,
    const Scalar& borderValue = morphologyDefaultBorderValue()
);

src 输入图像;通道的数量可以是任意的,但是深度值应该是以下之一:
CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
dst 和源图像同样大小和类型的输出图像。
kernel 用于腐蚀的结构元素;如果element=Mat(),是一个3 x 3的矩形结构元素. Kernel 可以通过使用getStructuringElement来创建。
anchor 素中的锚点的位置,默认是值(-1,-1),也就是说锚点在元素的中心位置。
iterations 腐蚀的迭代次数。
borderType像素外推方法。参见#BorderTypes, BORDER_WRAP不支持。
borderValue 固定边缘的情况下的边缘值。
参考 dilate,morphologyEx,getStructuringElement
Mat cv::getStructuringElement(
int  shape,
Size  ksize,
Point  anchor = Point(-1,-1)
 )
参数1:结构元的形状(0:矩形结构元;1:十字架结构元;2:椭圆结构元);
参数2:结构元大小(size(m, n));
参数3:结构元中心点所在位置(point(x, y))默认为中心点
Mat element = getStructuringElement(0, Size(3, 3)); //构造矩形结构元素
	Mat image_erosion;
	erode(image_bw, image_erosion, element, Point(-1, -1), 3); //执行腐蚀操作
	imshow("image_erosion", image_erosion);

原图

二值图

CV腐蚀

1.2 自定义腐蚀函数

void erode_my(Mat &src,Mat &dst,int size) {
	for (int i = 0; i < src.rows; ++i)
	{
		for (int j = 0; j < src.cols; ++j)
		{
			uchar minV = 255;
			//uchar maxV = 0;

			//遍历周围最小像素值
			for (int yi = i - size / 2; yi <= i + size / 2; yi++)
			{
				for (int xi = j - size / 2; xi <= j + size / 2; xi++)
				{
					if (xi < 0 || xi >= src.cols || yi < 0 || yi >= src.rows)
					{
						continue;
					}
					minV = (std::min<uchar>)(minV, src.at<uchar>(yi, xi));
					//maxV = (std::max<uchar>)(maxV, src.at<uchar>(yi, xi));
				}
			}
			dst.at<uchar>(i, j) = minV;
		}
	}
}

自定义腐蚀

1.3 对比

erode_my(image_bw, image_erosion_my,9);
当腐蚀结构扩大到9×9时效果基本与cv自带函数一致。

2、图像膨胀

原理:腐蚀用来收缩或细化二值图像中的前景,借此实现去噪声、元素分割等功能。腐蚀过程:用结构元来逐个像素扫描被腐蚀图像,并根据结构元和被腐蚀图像的关系确定腐蚀结果。

注意,腐蚀操作等形态学操作,是逐个像素地来确定值的,每次判定的点都与结构元中心点所对应,如果结构元完全处于前景图像中,就将结构元中心点所对应的腐蚀结果图像中的像素点处理为前景色(如1)。如果结构元不完全处于前景图像中,就将结构元中心点所对应的腐蚀结果图像中的像素点处理为背景色(如0)。(结构元也被称为核

作用增大图像中的目标,或者填充、连接某些目标

2.1 CV膨胀函数

CV_EXPORTS_W void dilate(
    InputArray src,
    OutputArray dst,
    InputArray kernel,
    Point anchor = Point(-1,-1),
    int iterations = 1,
    int borderType = BORDER_CONSTANT,
    const Scalar& borderValue = morphologyDefaultBorderValue()
);

src 输入图像;通道的数量可以是任意的,但是深度值应该是以下之一:CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
dst 和源图像同样大小和类型的输出图像。
kernel 膨胀核元素,如果elemenat=Mat(), 是一个3 x 3的矩形核元素,核可以使用getStructuringElement来创建。
anchor 元素中的锚点的位置,默认是值(-1,-1),也就是说锚点在元素的中心位置。
iterations 膨胀的迭代次数。
borderType 像素外推方法。参见#BorderTypes, BORDER_WRAP不支持。
borderValue 固定边缘的情况下的边缘值。
参考:erode,morphologyEx,getStructuringElement
//膨胀
Mat element = getStructuringElement(0, Size(3, 3)); //构造矩形结构元素
Mat image_dilate;
dilate(image_bw, image_dilate, element, Point(-1, -1), 9); //执行膨胀操作
imshow("image_dilate", image_dilate);

二值图

CV膨胀

2.2 自定义膨胀函数

void dilate_my(Mat& src, Mat& dst, int size) {
	for (int i = 0; i < src.rows; ++i)
	{
		for (int j = 0; j < src.cols; ++j)
		{
			//uchar minV = 255;
			uchar maxV = 0;

			//遍历周围最大像素值
			for (int yi = i - size / 2; yi <= i + size / 2; yi++)
			{
				for (int xi = j - size / 2; xi <= j + size / 2; xi++)
				{
					if (xi < 0 || xi >= src.cols || yi < 0 || yi >= src.rows)
					{
						continue;
					}
					//minV = (std::min<uchar>)(minV, src.at<uchar>(yi, xi));
					maxV = (std::max<uchar>)(maxV, src.at<uchar>(yi, xi));
				}
			}
			dst.at<uchar>(i, j) = maxV;
		}
	}

}

自定义膨胀

2.3 对比

dilate_my(image_bw, image_dilate_my, 9);
当膨胀结构扩大到9×9时效果基本与cv自带函数一致。

腐蚀图像相当于对其反色图像膨胀后再取反色;
膨胀图像相当于对其反色图像腐蚀后再取反色。

3、开运算

原理先腐蚀,再膨胀

作用平滑物体轮廓、断开狭窄的狭颈、消除细长的突出和物体。可以去掉图像上一些小的对象。(假设图像前景色是白色,背景色是黑色)

原图

3.1 方法一

//先腐蚀后膨胀
Mat open_image;
Mat element = getStructuringElement(0, Size(3, 3)); //构造矩形结构元素
erode(image_bw, image_erosion, element, Point(-1, -1), 3); //执行腐蚀操作
dilate(image_erosion, open_image, element, Point(-1, -1), 3); //执行膨胀操作
imshow("open", open_image);

3.2 方法二

morphologyEx(image_bw, open_image, MORPH_OPEN, element);
	imshow("open2", open_image);

4、闭运算

原理先膨胀,再腐蚀

作用闭运算可以填充小洞,填充小的噪点

4.1 方法一

Mat close_image;
Mat element = getStructuringElement(0, Size(3, 3)); //构造矩形结构元素
dilate(image_bw, image_dilate, element, Point(-1, -1), 3); //执行膨胀操作
erode(image_dilate, close_image, element, Point(-1, -1), 3); //执行腐蚀操作
imshow("close", close_image);

4.2 方法二

morphologyEx(image_bw, close_image, MORPH_CLOSE, element);
imshow("close2", close_image);

4.3 morphologyEx函数介绍

void morphologyEx(
InputArray src,
OutputArray dst,
int op,
InputArray kernel,
Point anchor = Point(-1,-1),
int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue()
);
(1)参数1:InputArray src
输入图像,图像数据类型必须为CV_8U, CV_16U, CV_16S, CV_32F or CV_64F中的一种。
(2)参数2:OutputArray dst
输出图像,数据类型与大小和输入图像一样。
(3)参数3:int op 形态学处理的类型:
MORPH_ERODE = 0:腐蚀处理
MORPH_DILATE = 1:膨胀处理
MORPH_OPEN = 2:开运算处理
MORPH_CLOSE = 3:闭运算处理
MORPH_GRADIENT = 4:形态学梯度
MORPH_TOPHAT = 5:顶帽变换
MORPH_BLACKHAT = 6:黑帽变换
MORPH_HITMISS = 7 :击中-击不中变换
(4)参数4:InputArray kernel结构元矩阵
(5)参数5:Point anchor = Point(-1,-1)
结构元中心点, 默认值Point(-1,-1), 表示正中心
(6)参数6:int iterations = 1
腐蚀膨胀处理的次数,默认值为1;
如果是开运算闭运算,次数表示先腐蚀或者膨胀几次,再膨胀腐蚀几次,而不是开运算闭运算几次:
如开运算且次数为2:erode -> erode -> dilate -> dilate
(7)参数7:int borderType = BORDER_CONSTANT
图像边框插值类型,默认类型为固定值填充
BORDER_CONSTANT = 0:固定值 i 填充:iiiiii | abcdefgh | iiiiiii
BORDER_REPLICATE = 1:两端复制:aaaaaa | abcdefgh | hhhhhhh
BORDER_REFLECT = 2:镜像复制:fedcba | abcdefgh | hgfedcb
BORDER_WRAP = 3:去除一端的值然后复制: cdefgh | abcdefgh | abcdefg
BORDER_REFLECT_101 = 4:去除一端的值然后镜像复制: gfedcb|abcdefgh|gfedcba
BORDER_TRANSPARENT = 5:推导赋值 uvwxyz | abcdefgh | ijklmno
BORDER_REFLECT101 = BORDER_REFLECT_101: same as BORDER_REFLECT_101
BORDER_DEFAULT = BORDER_REFLECT_101: same as BORDER_REFLECT_101
BORDER_ISOLATED = 16:< do not look outside of ROI
(8)参数8:const Scalar& borderValue = morphologyDefaultBorderValue()
文档中说明:param borderValue Border value in case of a constant border. The default value has a special meaning.

5、顶帽运算

原理顶帽(或礼帽)运算是原始图像减去图像开运算的结果。

顶帽运算:原始图像 — 图像开运算

作用:得到图像的噪声。如下图所示:

5.1 方法一

//构造结构元
Mat kernel = getStructuringElement(0, Size(5, 5));
Mat image_lm;
//顶帽变换(礼帽变换)
morphologyEx(image_bw, image_lm, 5, kernel);
cv::imshow("image_lm", image_lm);

5.2 方法二

Mat image_lm2;	//**顶帽运算:原始图像 — 图像开运算**
//dst=img1-img2;//这两个减法效果相同    若dst<0,则dst=0
subtract(image_bw,open_image2, image_lm2);//注意:要求被处理图片尺寸一致
cv::imshow("image_lm2",image_lm2);

Mat image_lm2;
absdiff(image_bw, open_image2, image_lm2);//若dst<0,则dst=|dst|>=0    用于检测两幅相似图像的不同点,效果比上面的两种减法好
cv::imshow("image_lm2", image_lm2);

6、黑帽运算

原理黑帽运算是图像闭运算操作减去原始图像的结果。

黑帽运算:闭运算 — 原始图像

作用:得到图像内部的小孔,或者前景色中的小黑点。如下图所示:

6.1 方法一

//构造结构元
Mat kernel = getStructuringElement(0, Size(5, 5));
//底帽变换(黑帽变换)
Mat image_hm;
morphologyEx(image_bw, image_hm, 6, kernel);
cv::imshow("image_hm", image_hm);

6.2 方法二

Mat image_hm2;
	subtract(image_bw, close_image2, image_hm2);//注意:要求被处理图片尺寸一致
	cv::imshow("image_hm2", image_hm2);

Mat image_hm2;
absdiff(image_bw, close_image2, image_hm2);//若dst<0,则dst=|dst|>=0    用于检测两幅相似图像的不同点,效果比上面的两种减法好
cv::imshow("image_hm2", image_hm2);

7、形态学梯度

原理膨胀图与腐蚀图之差;

作用对二值图进行这一操作可以得到图像中白色区域的边界,因此可以用形态学梯度来保留物体的边界轮廓

7.1 方法一

//构造结构元
Mat kernel = getStructuringElement(0, Size(5, 5));
Mat image_lm;

//形态学梯度
morphologyEx(image_bw, image_td, 4, kernel);
cv::imshow("image_td", image_td);

7.2 方法二

Mat image_tw2;
subtract(image_dilate, image_erosion, image_tw2);//注意:要求被处理图片尺寸一致
cv::imshow("image_tw2", image_tw2);

Mat image_tw2;
absdiff(image_dilate, image_erosion, image_tw2);//若dst<0,则dst=|dst|>=0    用于检测两幅相似图像的不同点,效果比上面的两种减法好
cv::imshow("image_tw2", image_tw2);

部分参考来自:数字图像处理(c++ opencv)–持续更新 - 知乎 (zhihu.com)

总结

到此这篇关于OpenCV数字图像处理基于C++之图像形态学处理的文章就介绍到这了,更多相关OpenCV数字图像处理基于C++内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python+OpenCV数字图像处理之ROI区域的提取

    目录 1.实现原理 2.使用的函数简述 3.代码实现过程 (1)读入原始图像 (2)获取mask (3)获取人物mask (4)获取人物 (5)新建一张与原始图一样大小的蓝色的背景图 (6)得到蓝色背景的mask 4.整体代码  利用mask(掩模)技术提取纯色背景图像ROI区域中的人和物,并将提取出来的人或物添加在其他图像上. 1.实现原理 先通过cv.cvtColor()函数,将原RGB彩色图像转换为hsv色彩空间的图像,然后通过cv.inRange()函数获得ROI区域的Mask,最后利用

  • OpenCV数字图像处理基于C++之图像形态学处理详解

    目录 1.图像腐蚀 1.1 CV腐蚀函数 1.2 自定义腐蚀函数 1.3 对比 2.图像膨胀 2.1 CV膨胀函数 2.2 自定义膨胀函数 2.3 对比 3.开运算 3.1 方法一 3.2 方法二 4.闭运算 4.1 方法一 4.2 方法二 4.3 morphologyEx函数介绍 5.顶帽运算 5.1 方法一 5.2 方法二 6.黑帽运算 6.1 方法一 6.2 方法二 7.形态学梯度 7.1 方法一 7.2 方法二 总结 1.图像腐蚀 ​ 原理:腐蚀用来收缩或细化二值图像中的前景,借此实现去

  • OpenCV学习之图像形态学处理详解

    目录 1.腐蚀操作 2.膨胀操作 3.开闭运算 4.梯度运算 5.Top Hat Black Hat运算 本文是OpenCV图像视觉入门之路的第11篇文章,本文详细的在图像形态学进行了图像处理,例如:腐蚀操作.膨胀操作.开闭运算.梯度运算.Top Hat Black Hat运算等操作. 1.腐蚀操作 从下面代码中可以看到有三幅腐蚀程度不同的图,腐蚀越严重像素就越模糊 import cv2 import numpy as np from numpy import unicode if __name

  • Python数字图像处理之霍夫线变换实现详解

    在图片处理中,霍夫变换主要是用来检测图片中的几何形状,包括直线.圆.椭圆等. 在skimage中,霍夫变换是放在tranform模块内,本篇主要讲解霍夫线变换. 对于平面中的一条直线,在笛卡尔坐标系中,可用y=mx+b来表示,其中m为斜率,b为截距.但是如果直线是一条垂直线,则m为无穷大,所有通常我们在另一坐标系中表示直线,即极坐标系下的r=xcos(theta)+ysin(theta).即可用(r,theta)来表示一条直线.其中r为该直线到原点的距离,theta为该直线的垂线与x轴的夹角.如

  • OpenCV图像分割之分水岭算法与图像金字塔算法详解

    目录 前言 一.使用分水岭算法分割图像 1.cv2.distanceTransform()函数 2.cv2.connectedComponents()函数 3.cv2.watershed()函数 二.图像金字塔 1.高斯金字塔向下采样 2.高斯金字塔向上采样 3.拉普拉斯金字塔 4.应用图像金字塔实现图像的分割和融合 前言 主要介绍OpenCV中的分水岭算法.图像金字塔对图像进行分割的方法. 一.使用分水岭算法分割图像 分水岭算法的基本原理为:将任意的灰度图像视为地形图表面,其中灰度值高的部分表

  • Python常用图像形态学操作详解

    目录 腐蚀 膨胀 开运算与闭运算 开运算 闭运算 梯度运算 礼帽与黑帽 礼帽 黑帽 腐蚀 在一些图像中,会有一些异常的部分,比如这样的毛刺: 对于这样的情况,我们就可以应用复式操作了.需要注意的是,腐蚀操作只能处理二值图像,即像素矩阵的值只有0(黑色)和255(白色).我们先看看代码和效果: import cv2 import numpy as np img = cv2.imread('dagongren.png') # 腐蚀的代码 kernel = np.ones((3,3),np.uint8

  • Python OpenCV图像处理之图像滤波特效详解

    目录 1分类 2邻域滤波 2.1线性滤波 2.2非线性滤波 3频域滤波 3.1低通滤波 3.2高通滤波 1 分类 图像滤波按图像域可分为两种类型: 邻域滤波(Spatial Domain Filter),其本质是数字窗口上的数学运算.一般用于图像平滑.图像锐化.特征提取(如纹理测量.边缘检测)等,邻域滤波使用邻域算子——利用给定像素周围像素值以决定此像素最终输出的一种算子 频域滤波(Frequency Domain Filter),其本质是对像素频率的修改.一般用于降噪.重采样.图像压缩等. 按

  • python数字图像处理图像的绘制详解

    目录 正文 一.用figure函数和subplot函数分别创建主窗口与子图 二.用subplots来创建显示窗口与划分子图 三.其它方法绘图并显示 正文 实际上前面我们就已经用到了图像的绘制,如: io.imshow(img) 这一行代码的实质是利用matplotlib包对图片进行绘制,绘制成功后,返回一个matplotlib类型的数据.因此,我们也可以这样写: import matplotlib.pyplot as plt plt.imshow(img) imshow()函数格式为: matp

  • C++ OpenCV实现图像双三次插值算法详解

    目录 前言 一.图像双三次插值算法原理 二.C++ OpenCV代码 1.计算权重矩阵 2.遍历插值 3. 测试及结果 前言 近期在学习一些传统的图像处理算法,比如传统的图像插值算法等.传统的图像插值算法包括邻近插值法.双线性插值法和双三次插值法,其中邻近插值法和双线性插值法在网上都有很详细的介绍以及用c++编写的代码.但是,网上关于双三次插值法的原理介绍虽然很多,也有对应的代码,但是大多都不是很详细.因此基于自己对原理的理解,自己编写了图像双三次插值算法的c++ opencv代码,在这里记录一

  • Python图像处理之图像量化处理详解

    目录 一.图像量化处理原理 二.图像量化实现 三.图像量化等级对比 四.K-Means聚类实现量化处理 五.总结 一.图像量化处理原理 量化(Quantization)旨在将图像像素点对应亮度的连续变化区间转换为单个特定值的过程,即将原始灰度图像的空间坐标幅度值离散化.量化等级越多,图像层次越丰富,灰度分辨率越高,图像的质量也越好:量化等级越少,图像层次欠丰富,灰度分辨率越低,会出现图像轮廓分层的现象,降低了图像的质量.图8-1是将图像的连续灰度值转换为0至255的灰度级的过程[1-3]. 如果

随机推荐