youcans 的图像处理学习课11. 形态学图像处理(上)
Posted YouCans
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了youcans 的图像处理学习课11. 形态学图像处理(上)相关的知识,希望对你有一定的参考价值。
专栏地址:『youcans 的图像处理学习课』
文章目录:『youcans 的图像处理学习课 - 总目录』
【youcans 的 OpenCV 学习课】11. 形态学图像处理(上)
文章目录
1. 形态学图像处理简介
形态学是生物学的概念,主要研究动植物的形态和结构。数学形态学(Mathematical morphology)是建立在集合论和拓扑学基础之上的图像分析学科。
图像处理中的形态学是指基于形状的图像处理操作,以数学形态学为工具从图像中提取表达和描绘区域形状的图像结构信息,如边界、骨架、凸壳等,还包括用于预处理或后处理的形态学过滤、细化和修剪等。形态学图像处理最初用于处理二值图,进而推广到灰度级图像处理,其运算简单、效果良好。
形态学图像处理的运算是用集合定义的,基本运算包括:二值腐蚀和膨胀,二值开闭运算,骨架抽取,极限腐蚀,击中击不中变换,形态学梯度,顶帽变换,颗粒分析,流域变换,灰值腐蚀和膨胀,灰值开闭运算,灰值形态学梯度等。
形态学的基本思想是利用结构元素测量或提取输入图像中的形状或特征,以便进行图像分析和目标识别。结构元的功能是检查给定图像中的特定结构特征。形态学操作都是基于各种形状的结构元,结构元对输入图像进行操作得到输出图像。
在二值图像中,所有黑色像素的集合是图像完整的形态学描述。假定二值图像 A 和形态学处理的结构元素 B 是定义在笛卡儿网格上的集合,结构元素(Structuring Elements,SE)可以是任意形状,如矩形、十字形。结构元有一个锚点 O,定义为结构元的中心。
2. 形态学基本操作
2.1 腐蚀
腐蚀和膨胀是图像处理中最基本的形态学操作,是很多高级处理方法的基础。
腐蚀和膨胀是对白色部分(高亮部分)而言的,膨胀就是图像中的高亮部分进行膨胀,腐蚀就是原图中的高亮部分被腐蚀。
腐蚀使图像中白色高亮部分被腐蚀,“邻域被蚕食”,腐蚀的效果拥有比原图更小的高亮区域,可以去掉毛刺,去掉孤立的像素,提取骨干信息。
腐蚀的原理是求局部最小值的操作,将 0 值扩充到邻近像素,从而扩大黑色值范围、压缩白色值范围。
结构元 B 对集合 A 的腐蚀定义为:
A
⊖
B
=
z
∣
(
B
)
z
⊆
A
A \\ominus B = \\ z | (B)_z \\subseteq A\\
A⊖B=z∣(B)z⊆A
用卷积来描述腐蚀操作,结构元素 B 是中心为 1、其它为 0 的卷积模板(核):
(1)卷积核 B 沿着图像滑动,扫描图像 A 的每一个像素;
(2)用结构元素与其覆盖的二值图像进行 “或操作”;
(3)如果图像与卷积核对应区域的所有像素值都是 1,则图像的该像素值仍为 1;否则为 0。
OpenCV 提供了函数 cv.erode 可以实现图像的腐蚀。
函数说明:
cv.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) → dst
函数 cv.erode 使用指定的结构元(卷积核)侵蚀源图像,结构元确定像素邻域的形状,在该邻域上取最小值:
d
s
t
(
x
,
y
)
=
min
(
x
′
,
y
′
)
:
e
l
e
m
e
n
t
(
x
′
,
y
′
≠
0
)
s
r
c
(
x
+
x
′
,
y
+
y
′
)
dst(x,y)= \\min_\\enspace (x',y'):element(x',y' \\neq 0) \\enspace src(x+x',y+y')
dst(x,y)=(x′,y′):element(x′,y′=0)minsrc(x+x′,y+y′)
参数说明:
- src:输入图像,可以为单通道或多通道,图像深度必须为 CV_8U, CV_16U, CV_16S, CV_32F 或 CV_64F
- dst:输出图像,大小和类型与 src 相同
- kernel:结构元(卷积核),null 时使用 3*3 矩形结构元素
- anchor:卷积核的锚点位置,默认值 (-1, -1) 表示以卷积核的中心为锚点
- iterations:应用腐蚀操作的次数,可选项,默认值为 1
- borderType:边界扩充的类型
- borderValue:当 borderType=BORDER_CONSTANT 时以常量 value 填充扩充边界,默认值为 (0,0,0)
注意事项:
- 函数支持就地模式,腐蚀操作可以迭加使用多次。
- 在多通道图像的情况下,每个通道独立处理 。
例程 10.1:图像的腐蚀 (cv.erode)
# 10.1 图像的腐蚀 (cv.erode)
# 读取原始图像
imgGray = cv2.imread("../images/Fig0905a.tif", flags=0) # flags=0 读取为灰度图像
ret, imgBin = cv2.threshold(imgGray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) # 二值化处理
# 图像腐蚀
kSize = (3, 3) # 卷积核的尺寸
kernel = np.ones(kSize, dtype=np.uint8) # 生成盒式卷积核
imgErode1 = cv2.erode(imgBin, kernel=kernel) # 图像腐蚀
kSize = (9, 9)
kernel = np.ones(kSize, dtype=np.uint8)
imgErode2 = cv2.erode(imgBin, kernel=kernel)
kSize = (25, 25)
kernel = np.ones(kSize, dtype=np.uint8)
imgErode3 = cv2.erode(imgBin, kernel=kernel)
plt.figure(figsize=(10, 5))
plt.subplot(141), plt.axis('off'), plt.title("Origin")
plt.imshow(imgBin, cmap='gray', vmin=0, vmax=255)
plt.subplot(142), plt.title("eroded kSize=(3,3)"), plt.axis('off')
plt.imshow(imgErode1, cmap='gray', vmin=0, vmax=255)
plt.subplot(143), plt.title("eroded kSize=(9,9)"), plt.axis('off')
plt.imshow(imgErode2, cmap='gray', vmin=0, vmax=255)
plt.subplot(144), plt.title("eroded kSize=(25,25)"), plt.axis('off')
plt.imshow(imgErode3, cmap='gray', vmin=0, vmax=255)
plt.tight_layout()
plt.show()
2.2 膨胀
膨胀使图像中的白色高亮部分进行膨胀,“邻域扩张”,膨胀效果拥有比原图更大的高亮区域,可以填补图像缺陷,用来扩充边缘或填充小的孔洞,也可以用来连接两个分开的物体。
膨胀的原理是求局部最大值的操作,将 1 值扩充到邻近像素,从而扩大白色值范围、压缩黑色值范围。
结构元 B 对集合 A 的膨胀定义为:
A
⊕
B
=
z
∣
(
B
^
)
z
∩
A
≠
∅
A \\oplus B = \\ z | (\\hat B)_z \\cap A \\neq \\varnothing \\
A⊕B=z∣(B^)z∩A=∅
用卷积来描述膨胀操作,中心为 1、其它为 0 的卷积核沿着图像滑动卷积,与卷积核对应的原图像的像素值中只要有一个为 1, 则图像的中心元素的像素值为 1,否则(全 0)为 0。
用卷积来描述膨胀操作,结构元素 B 是中心为 1、其它为 0 的卷积模板(核):
(1)卷积核 B 沿着图像滑动,扫描图像 A 的每一个像素;
(2)用结构元素与其覆盖的二值图像进行 “与操作”;
(3)如果图像与卷积核对应区域的所有像素值都是 0,则图像的该像素值仍为 0;否则为 1。
在去噪声时通常先进行腐蚀,在去掉白噪声的同时,使前景对象变小;然后再对进行膨胀,此时噪声已经被去除,可以增加前景。
OpenCV 提供了函数 cv.dilate 可以实现图像的膨胀。
函数说明:
cv.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) → dst
函数 cv.dilate 使用指定的结构元(卷积核)膨胀源图像,结构元确定像素邻域的形状,在该邻域上取最大值:
d s t ( x , y ) = max ( x ′ , y ′ ) : e l e m e n t ( x ′ , y ′ ≠ 0 ) s r c ( x + x ′ , y + y ′ ) dst(x,y)= \\max_\\enspace (x',y'):element(x',y' \\neq 0) \\enspace src(x+x',y+y') dst(x,y)=(x′,y′):element(x′,y′=0)maxsrc(x+x′,y+y′)
参数说明:
- src:输入图像,可以为单通道或多通道,图像深度必须为 CV_8U, CV_16U, CV_16S, CV_32F 或 CV_64F
- dst:输出图像,大小和类型与 src 相同
- kernel:结构元(卷积核),null 时使用 3*3 矩形卷积核
- anchor:卷积核的锚点位置,默认值 (-1, -1) 表示以卷积核的中心为锚点
- iterations:应用膨胀的次数,可选项,默认值为 1
- borderType:边界扩充的类型
- borderValue:当 borderType=BORDER_CONSTANT 时以常量 value 填充扩充边界,默认值为 (0,0,0)
注意事项:
-
函数支持就地模式,腐蚀操作可以迭加使用多次。
-
在多通道图像的情况下,每个通道独立处理 。
例程 10.2:图像的膨胀 (cv.dilate)
# 10.2 图像的膨胀 (cv.dilate)
# cv.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) → dst
# 读取原始图像
imgGray = cv2.imread("../images/handwriting01.png", flags=0) # flags=0 读取为灰度图像
ret, imgBin = cv2.threshold(imgGray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) # 二值化处理
# 图像膨胀
kSize = (3, 3) # 卷积核的尺寸
kernel = np.ones(kSize, dtype=np.uint8) # 生成盒式卷积核
imgDilate1 = cv2.dilate(imgBin, kernel=kernel) # 图像膨胀
kSize = (5, 5)
kernel = np.ones(kSize, dtype=np.uint8)
imgDilate2 = cv2.dilate(imgBin, kernel=kernel) # 图像膨胀
kSize = (7, 7)
kernel = np.ones(kSize, dtype=np.uint8)
imgDilate3 = cv2.dilate(imgBin, kernel=kernel) # 图像膨胀
plt.figure(figsize=(10, 5))
plt.subplot(141), plt.axis('off'), plt.title("Origin")
plt.imshow(imgBin, cmap='gray', vmin=0, vmax=255)
plt.subplot(142), plt.title("dilate kSize=(3,3)"), plt.axis('off')
plt.imshow(imgDilate1, cmap='gray', vmin=0, vmax=255)
plt.subplot(143), plt.title("dilate kSize=(5,5)"), plt.axis('off')
plt.imshow(imgDilate2, cmap='gray', vmin=0, vmax=255)
plt.subplot(144), plt.title("dilate kSize=(7,7)"), plt.axis('off')
plt.imshow(imgDilate3, cmap='gray', vmin=0, vmax=255)
plt.tight_layout()
plt.show()
2.3 开运算
膨胀扩展集合的组成部分,而腐蚀缩小集合的组成部分。开运算就是先腐蚀后膨胀的过程,通常用于去除噪点、断开狭窄的狭颈、消除细长的突出、平滑物体边界但不改变面积。
结构元 B 对集合 A 的开运算定义为:
A ∘ B = ( A ⊖ B ) ⊕ B A \\circ B = (A \\ominus B) \\oplus B A∘B=(A⊖B)⊕B
首先 B 对 A 腐蚀,然后 B 对腐蚀结果膨胀。
开运算是一个基于几何运算的滤波器,结构元大小的不同将导致不同的滤波效果,提取出不同的特征 。
OpenCV 提供了函数 cv.morphologyEx 可以实现图像的开运算。
函数说明:
cv.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]] )→ dst
函数 cv.morphologyEx 使用侵蚀(erosion)和膨胀(dilation)作为基本操作来执行高级形态转换。
参数说明:
- src:输入图像,可以为单通道或多通道,图像深度必须为 CV_8U, CV_16U, CV_16S, CV_32F 或 CV_64F
- dst:输出图像,大小和类型与 src 相同
- op:形态学运算类型
- cv.MORPH_ERODE:腐蚀
- cv.MORPH_DILATE:膨胀
- cv.MORPH_OPEN:开运算, 先腐蚀再膨胀
- cv.MORPH_CLOSE:闭运算, 先膨胀再腐蚀
- cv.MORPH_GRADIENT:形态学梯度, 膨胀图与腐蚀图之差
- cv.MORPH_TOPHAT:顶帽变换, 原图像与开运算之差
- cv.MORPH_BLACKHAT:黑帽变换, 闭运算图与原图像之差
- cv.MORPH_HITMISS: 击中击不中运算
- kernel:结构元(卷积核),null 时使用 3*3 矩形卷积核
- anchor:卷积核的锚点位置,负值表示以卷积核的中心为锚点
- iterations:应用腐蚀和膨胀的次数,可选项,默认值为 1
- borderType:边界扩充的类型
- borderValue:当 borderType=BORDER_CONSTANT 时以常量 value 填充扩充边界,默认值为 (0,0,0)
注意事项:
- 函数支持就地模式,开运算操作可以迭加使用多次。
- 迭代次数是应用腐蚀和膨胀操作的次数,注意两次迭代的开操作相当于应用“腐蚀→腐蚀→膨胀→膨胀”,而不是“腐蚀→膨胀→腐蚀→膨胀”。
例程 10.3:图像的开运算 (morphologyEx)
# 10.3 图像的开运算 (cv.morphologyEx)
# 读取原始图像
imgGray = cv2.imread("../images/Fig0905a.tif", flags=0) # flags=0 读取为灰度图像
ret, imgBin = cv2.threshold(imgGray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) # 二值化处理
# 图像腐蚀
kSize = (3, 3) # 卷积核的尺寸
kernel = np.ones(kSize, dtype=np.uint8) # 生成盒式卷积核
imgErode = cv2.erode(imgBin, kernel=kernel) # 图像腐蚀
# 图像的开运算
kSize = (3, 3) # 卷积核的尺寸
kernel = np.ones(kSize, dtype=np.uint8) # 生成盒式卷积核
imgOpen = cv2.morphologyEx(imgGray, cv2.MORPH_OPEN, kernel)
plt.figure(figsize=(9, 5))
plt.subplot(131), plt.axis('off'), plt.title("Origin")
plt.imshow(imgGray, cmap='gray', vmin=0, vmax=255)
plt.subplot(132), plt.title("Eroded kSize=(3,3)"), plt.axis('off')
plt.imshow(imgErode, cmap='gray', vmin=0, vmax=255)
plt.subplot(133), plt.title("Opening kSize=(3,3)"), plt.axis('off')
plt.imshow(imgOpen, cmap='gray', vmin=0, vmax=255)
plt.tight_layout()
plt.show()
2.4 闭运算
闭运算就是先膨胀后腐蚀的过程,通常用于弥合狭窄的断裂和细长的沟壑,消除小孔,填补轮廓中的缝隙,消除噪点,连接相邻的部分。
结构元 B 对集合 A 的闭运算定义为:
A ∙ B = ( A ⊕ B ) ⊖ B A \\bullet B = (A \\oplus B) \\ominus B A∙B=以上是关于youcans 的图像处理学习课11. 形态学图像处理(上)的主要内容,如果未能解决你的问题,请参考以下文章
youcans 的图像处理学习课11. 形态学图像处理(中)
youcans 的图像处理学习课11. 形态学图像处理(上)
youcans 的图像处理学习课11. 形态学图像处理(下)
youcans 的图像处理学习课11. 形态学图像处理(下)