目录
(6)形态学梯度(Morphological Gradient)
(7)顶帽(Top-hat)和黑帽(Black-hat)转换
一、基本概念:
图像形态学是图像处理中的一种数学方法,它基于图像的形状和结构特征进行分析和处理。图像形态学的基本操作包括膨胀、腐蚀、开运算和闭运算等,这些操作通常使用结构元素来实现。
(1)结构元素(Structuring Element):
结构元素是一个小的矩阵,用于定义形态学操作的尺寸和形状。它在图像上滑动(或叫扫描),与图像的局部区域进行比较和计算。结构元素的形状可以是矩形、圆形、十字形等,大小和形状影响着形态学操作的结果。
(2)膨胀(Dilation):
膨胀操作是图像形态学中的一种基本操作,它通过将图像中的每个像素替换为其邻域(包括自身)中的最大值来实现。膨胀操作可以使图像中的物体边界向外扩展,连接邻近的物体。
(3)腐蚀(Erosion):
腐蚀操作是图像形态学中的另一种基本操作,它通过将图像中的每个像素替换为其邻域(包括自身)中的最小值来实现。腐蚀操作可以使图像中的物体边界向内收缩,分离接触的物体。
(4)开运算(Opening)
开运算是先进行腐蚀操作,再进行膨胀操作的过程。这种组合操作可以去除小的物体或细节,平滑较大物体的边界,同时不明显改变其面积。
(5)闭运算(Closing)
闭运算是先进行膨胀操作,再进行腐蚀操作的过程。这种组合操作可以填充小的孔洞或裂缝,连接邻近物体的边界。
(6)形态学梯度(Morphological Gradient)
形态学梯度是膨胀图像和腐蚀图像之差,用于突出显示物体的边界。
(7)顶帽(Top-hat)和黑帽(Black-hat)转换
顶帽转换是原始图像与开运算结果之差,用于提取小物体或细节。黑帽转换是闭运算结果与原始图像之差,用于提取大物体的暗区域。
(8)应用领域
- 图像预处理:去噪声、平滑边界。
- 图像分割:分离和识别图像中的不同对象。
- 图像增强:增强图像的特定特征。
- 特征提取:提取图像的形状和纹理信息。
二、膨胀:
图像膨胀(Dilation)是图像形态学中的一种基本操作,它用于图像处理和计算机视觉中的图像增强、图像分割、特征提取等任务。膨胀操作的目的是增加图像中特定对象的大小,特别是对于那些较小的、分散的对象,或者用于连接邻近的对象。
(1)基本概念:
膨胀操作通过使用一个称为结构元素(structuring element)或卷积核的小矩阵来与图像进行卷积,从而实现对图像的膨胀。结构元素定义了膨胀操作的范围和形状。
(2)原理:
在膨胀过程中,结构元素会在整个图像上滑动,对于图像中的每一个像素点,如果结构元素覆盖的图像区域中至少有一个像素值满足特定条件(通常是非零或特定值),则将该像素点的值设置为最大值(在二值图像中通常是255,表示白色)。
(3)方法:
-
标准膨胀:
- 对于每个像素,将结构元素与其对齐,检查结构元素覆盖的图像区域。
- 如果结构元素下的任何像素值大于零,则将中心像素的值设置为最大值。
-
迭代膨胀:
- 迭代地应用膨胀操作,直到达到所需的对象大小或满足特定条件。
(4)OpenCV中的膨胀函数:
在OpenCV中,可以使用cv2.dilate
函数来实现图像膨胀:
dst = cv2.dilate(src, kernel, iterations=1)
src
:输入图像。kernel
:结构元素,定义了膨胀的形状和大小。iterations
:膨胀操作的迭代次数。
(5)代码示例:
import cv2
import numpy as np
# 读取图像
image = cv2.imread("C:\\Users\\86173\\Desktop\\TI\\Coin0.jpg", cv2.IMREAD_GRAYSCALE)
# 定义结构元素
kernel = np.ones((5, 5), np.uint8)
# 应用Otsu阈值法进行二值化
retval, binary_image = cv2.threshold(image, 0, 255,cv2.THRESH_OTSU)
dst = cv2.dilate(binary_image, kernel, iterations=2)
# 显示结果
cv2.imshow('Binary Image', binary_image)
cv2.imshow('swell', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
(6)应用领域:
- 图像增强:增强图像中的特定特征,如边缘。
- 图像分割:在图像分割过程中扩大前景区域。
- 图像预处理:在进一步的图像分析之前改善图像质量。
(7)注意事项:
- 结构元素的选择对膨胀效果有重要影响,应根据具体应用选择合适的结构元素大小和形状。
- 过度膨胀可能导致对象之间的边界模糊,因此需要仔细调整膨胀的迭代次数。
三、腐蚀:
图像腐蚀(Erosion)是图像形态学中的另一种基本操作,与膨胀操作相反,它用于减小图像中对象的尺寸或消除对象的细小部分。腐蚀操作在图像处理和计算机视觉中用于多种应用,如去噪、细化图像中的对象、分离接触的对象等。
(1)基本概念:
腐蚀操作通过使用一个称为结构元素(structuring element)或卷积核的小矩阵来与图像进行卷积,从而实现对图像的腐蚀。结构元素定义了腐蚀操作的范围和形状。
(2)原理:
在腐蚀过程中,结构元素会在整个图像上滑动,对于图像中的每一个像素点,只有当结构元素覆盖的图像区域完全满足特定条件(通常是所有像素值都为非零或特定值)时,才将该像素点的值设置为最大值(在二值图像中通常是255,表示白色)。如果结构元素下的任何像素值不满足条件,则中心像素的值设置为最小值(在二值图像中通常是0,表示黑色)。
(3)方法:
-
标准腐蚀:
- 对于每个像素,将结构元素与其对齐,检查结构元素覆盖的图像区域。
- 如果结构元素下的所有像素值都大于零,则将中心像素的值设置为最大值。
-
迭代腐蚀:
- 迭代地应用腐蚀操作,直到对象达到所需的大小或满足特定条件。
(4)OpenCV中的腐蚀函数:
在OpenCV中,可以使用cv2.erode
函数来实现图像腐蚀:
dst = cv2.erode(src, kernel, iterations=1)
src
:输入图像。kernel
:结构元素,定义了腐蚀的形状和大小。iterations
:腐蚀操作的迭代次数。
(5)示例代码:
import cv2
import numpy as np
# 读取图像
image = cv2.imread("C:\\Users\\86173\\Desktop\\TI\\Coin0.jpg", cv2.IMREAD_GRAYSCALE)
# 定义结构元素
kernel = np.ones((5, 5), np.uint8)
# 应用Otsu阈值法进行二值化
retval, binary_image = cv2.threshold(image, 0, 255,cv2.THRESH_OTSU)
dst = cv2.dilate(binary_image, kernel, iterations=2)
dst1 = cv2.erode(binary_image, kernel, iterations=1)
# 显示结果
cv2.imshow('Binary Image', binary_image)
cv2.imshow('swell', dst)
cv2.imshow('corrosion', dst1)
cv2.waitKey(0)
cv2.destroyAllWindows()
(6)应用领域:
- 去噪:去除图像中的小噪声点。
- 细化:减小图像中对象的尺寸,用于对象的细化。
- 分离对象:分离接触的对象,特别是在二值图像中。
(7)注意事项:
- 结构元素的选择对腐蚀效果有重要影响,应根据具体应用选择合适的结构元素大小和形状。
- 过度腐蚀可能导致对象的过度细化或丢失重要信息,因此需要仔细调整腐蚀的迭代次数。
四、开运算:
开运算(Opening Operation)是图像形态学中的一个基本操作,它结合了腐蚀和膨胀两个步骤。开运算的目的是去除图像中的小物体、平滑较大物体的边界,同时保持其面积基本不变。开运算通常用于去除小的噪声点、断开狭窄的连接,以及平滑较大物体的边界。
(1)开运算的数学定义:
开运算可以定义为先对图像进行腐蚀,然后对腐蚀结果进行膨胀。数学上,开运算可以用以下公式表示:
其中,A 是输入图像,B 是结构元素。
(2)开运算的原理:
- 腐蚀:腐蚀操作会缩小图像中的物体,移除小的突出部分和细小的物体。
- 膨胀:随后的膨胀操作会尝试恢复物体的大小,但由于腐蚀已经移除了小物体和细节,这些部分不会在膨胀过程中恢复。
(3)开运算的应用:
开运算在图像处理中有多种应用,包括但不限于:
- 去噪:去除图像中的小噪声点。
- 平滑边界:平滑较大物体的边界,同时保持物体的基本形状。
- 分离物体:分离接触或接近的物体。
(4)cv2.morphologyEx
函数:
cv2.morphologyEx
函数是 OpenCV 库中用于执行高级形态学操作的函数。这个函数可以执行腐蚀、膨胀、开运算、闭运算、梯度、顶帽和黑帽等操作。它是一个非常灵活的工具,可以用来处理各种图像处理任务,如去噪、特征提取、图像分割等。
函数原型:
dst = cv2.morphologyEx(src, op, kernel, anchor=None,
iterations=None, borderType=cv2.BORDER_CONSTANT)
参数:
src
:输入图像,可以是灰度图像或彩色图像。op
:指定要执行的形态学操作类型,如cv2.MORPH_ERODE
、cv2.MORPH_DILATE
、cv2.MORPH_OPEN
等。kernel
:结构元素,用于定义形态学操作的形状和大小。可以是cv2.getStructuringElement
函数生成的矩阵。anchor
:定义结构元素的锚点位置,默认为(-1, -1)
,表示结构元素的中心。iterations
:操作的迭代次数。对于腐蚀和膨胀操作,可以指定执行多次迭代。borderType
:边界像素的填充类型,如cv2.BORDER_CONSTANT
、cv2.BORDER_REPLICATE
等。
常用的形态学操作:
cv2.MORPH_ERODE
:腐蚀操作。cv2.MORPH_DILATE
:膨胀操作。cv2.MORPH_OPEN
:开运算(先腐蚀后膨胀)。cv2.MORPH_CLOSE
:闭运算(先膨胀后腐蚀)。cv2.MORPH_GRADIENT
:形态学梯度(膨胀图像减去腐蚀图像)。cv2.MORPH_TOPHAT
:顶帽变换(原始图像减去开运算结果)。cv2.MORPH_BLACKHAT
:黑帽变换(闭运算结果减去原始图像)。
(4)代码示例:
在OpenCV中,开运算可以通过cv2.morphologyEx
函数实现。
import cv2
import numpy as np
# 读取图像
image = cv2.imread("C:\\Users\\86173\\Desktop\\TI\\Coin0.jpg", cv2.IMREAD_GRAYSCALE)
# 定义结构元素
kernel = np.ones((3, 3), np.uint8)
# 应用Otsu阈值法进行二值化
retval, binary_image = cv2.threshold(image, 0, 255,cv2.THRESH_OTSU)
# 应用开运算
opened_image = cv2.morphologyEx(binary_image, cv2.MORPH_OPEN, kernel)
# 显示结果
cv2.imshow('Binary Image', binary_image)
cv2.imshow('opened_image', opened_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
首先定义了一个3x3的结构元素,然后使用cv2.morphologyEx
函数对图像进行开运算。这将去除图像中的小噪声点,并平滑物体的边界。
(5)注意事项:
- 结构元素的选择对开运算的结果有重要影响。较大的结构元素可以去除更大的噪声,但可能会导致图像中较大物体的边界变得模糊。
- 开运算不会改变图像中物体的总面积,但会改变物体的形状。
五、闭运算:
闭运算(Closing Operation)是图像形态学中的一个基本操作,它是先膨胀后腐蚀的过程。闭运算的目的在于填充前景物体内部的小孔洞、连接临近的物体以及平滑物体的边界,同时尽量保持物体的原始面积和形状。
(1)基本原理:
闭运算可以定义为对图像先进行膨胀操作,然后进行腐蚀操作。数学上,闭运算可以用以下公式表示:
其中,A 是输入图像,B 是结构元素,⊕ 表示闭运算,⊖ 表示腐蚀操作,⊙ 表示膨胀操作。
(2)应用场景:
闭运算在图像处理中的应用包括但不限于:
- 填充孔洞:在图像中填充小的孔洞或裂缝。
- 连接物体:连接接近的物体,使它们成为一个整体。
- 平滑边界:平滑物体的边界,减少边界的不规则性。
- 去除小物体:去除小的噪声点或细小的物体。
(3)OpenCV中的闭运算:
在OpenCV中,可以使用 cv2.morphologyEx
函数来执行闭运算。
import cv2
import numpy as np
# 读取图像
image = cv2.imread("C:\\Users\\86173\\Desktop\\TI\\Coin0.jpg", cv2.IMREAD_GRAYSCALE)
# 定义结构元素
kernel = np.ones((3, 3), np.uint8)
# 应用Otsu阈值法进行二值化
retval, binary_image = cv2.threshold(image, 0, 255,cv2.THRESH_OTSU)
# 应用闭运算
closed_image = cv2.morphologyEx(binary_image, cv2.MORPH_CLOSE, kernel)
# 显示结果
cv2.imshow('Binary Image', binary_image)
cv2.imshow('opened_image', closed_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
首先读取一幅图像,并定义了一个3x3的结构元素。然后,我们使用 cv2.morphologyEx
函数对图像进行闭运算,这有助于填充图像中的小孔洞,并平滑物体的边界。最后,显示处理后的图像。
(4)注意事项:
- 结构元素的选择对闭运算的效果有重要影响。较大的结构元素可以填充更大的孔洞,但可能会导致图像中较大物体的边界变得模糊。
- 闭运算不会改变图像中物体的总面积,但会改变物体的形状。
六、 顶帽和黑帽:
在图像处理中,顶帽(Top Hat)和黑帽(Black Hat)变换是两种高级形态学操作,它们用于增强图像中的特定特征。
(1)顶帽变换:
顶帽变换是原图像与开运算结果之差。它用于突出比其周围亮的物体,即提取比结构元素小的亮区域。顶帽变换可以用于增强小的亮物体,例如在暗背景下的小亮点。数学上,顶帽变换定义为:
其中,src
是输入图像,open(src)
是对 src
应用开运算的结果。
(2)黑帽变换:
黑帽变换是闭运算结果与原图像之差。它用于突出比其周围暗的物体,即提取比结构元素小的暗区域。黑帽变换可以用于增强小的暗物体,例如在亮背景下的小暗点。数学上,黑帽变换定义为:
其中,close(src)
是对 src
应用闭运算的结果。
(3)OpenCV中的实现:
在OpenCV中,可以使用 cv2.morphologyEx
函数来实现顶帽和黑帽变换。
import cv2
import numpy as np
# 读取图像
image = cv2.imread("C:\\Users\\86173\\Desktop\\TI\\Coin0.jpg", cv2.IMREAD_GRAYSCALE)
# 定义结构元素
kernel = np.ones((3, 3), np.uint8)
# 应用Otsu阈值法进行二值化
retval, binary_image = cv2.threshold(image, 0, 255,cv2.THRESH_OTSU)
# 应用顶帽变换
tophat = cv2.morphologyEx(binary_image, cv2.MORPH_TOPHAT, kernel)
# 应用黑帽变换
blackhat = cv2.morphologyEx(binary_image, cv2.MORPH_BLACKHAT, kernel)
# 显示结果
cv2.imshow('Binary Image', binary_image)
cv2.imshow('tophat', tophat)
cv2.imshow('blackhat', blackhat)
cv2.waitKey(0)
cv2.destroyAllWindows()
(4)应用场景:
- 顶帽变换:用于增强图像中的小亮物体,如星星、文字等。
- 黑帽变换:用于增强图像中的小暗物体,如孔洞、裂缝等。
(5)注意事项:
- 结构元素的选择对变换结果有重要影响。较大的结构元素可以提取更大的特征,但可能会导致图像中的细节丢失。
- 顶帽和黑帽变换对噪声敏感,可能需要先进行噪声抑制处理。
七、膨胀-腐蚀实现形态学边缘检测:
在图像形态学中,膨胀-腐蚀操作可以用来实现边缘检测。这种组合操作通常被称为形态学梯度,它可以用来突出图像中的边缘和细节。以下是如何使用膨胀和腐蚀来实现形态学边缘检测的详细说明:
(1)基本原理:
形态学梯度是通过计算图像的膨胀和腐蚀之间的差异来实现的。膨胀操作会使图像中的亮区域变大,而腐蚀操作则会使亮区域变小。将膨胀后的图像减去腐蚀后的图像,可以得到图像的边缘。
(2)数学表达:
形态学梯度 G可以表示为: G=D−E
其中,D 是膨胀操作,E 是腐蚀操作。
(3)OpenCV中的实现:
在OpenCV中,可以使用 cv2.dilate
和 cv2.erode
函数来实现膨胀和腐蚀操作,然后计算它们的差值来得到形态学梯度。
import cv2
import numpy as np
# 读取图像
image = cv2.imread("C:\\Users\\86173\\Desktop\\TI\\canny.jpg", cv2.IMREAD_GRAYSCALE)
# 定义结构元素
kernel = np.ones((3, 3), np.uint8)
# 应用膨胀操作
dilated_image = cv2.dilate(image, kernel, iterations=1)
# 应用腐蚀操作
eroded_image = cv2.erode(image, kernel, iterations=1)
# 计算形态学梯度
morph_gradient = cv2.subtract(dilated_image, eroded_image)
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Dilated Image', dilated_image)
cv2.imshow('Eroded Image', eroded_image)
cv2.imshow('Morphological Gradient', morph_gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()
(4)应用场景:
- 边缘检测:形态学梯度可以用来检测图像中的边缘,尤其是在图像中存在噪声时。
- 细节增强:形态学梯度也可以用来增强图像的细节,如纹理和轮廓。
(5)注意事项:
- 结构元素的选择对边缘检测的结果有重要影响。较大的结构元素可以检测更宽的边缘,但可能会丢失细节。
- 迭代次数也会影响结果,更多的迭代次数会增加膨胀和腐蚀的效果。
八、击中与不击中:
击中与不击中变换(Hit-or-Miss Transform)是图像形态学中的一种操作,它用于在二值图像中检测特定形状或模式。这种变换特别适用于检测图像中的特定结构,如线条的端点、交叉点、角点等。
(1)基本原理:
击中与不击中变换使用两个结构元素:一个用于“击中”(hit)感兴趣的目标形状,另一个用于“不击中”(miss)不希望的形状或背景。这种变换通过两次腐蚀操作来实现:
- 击中腐蚀:使用一个结构元素对图像进行腐蚀,以识别与结构元素匹配的前景区域。
- 不击中腐蚀:使用另一个结构元素对图像的补集进行腐蚀,以识别与结构元素不匹配的背景区域。
- 逻辑与操作:将两次腐蚀的结果进行逻辑与操作,得到最终的击中与不击中变换结果。
(2)数学表达:
击中与不击中变换可以表示为: 其中,f(x,y) 是输入图像,B 是由两个结构元素 B1 和 B2 组成的复合结构元素,fc(x,y) 是 f(x,y) 的补集。
(3)OpenCV中的实现:
在OpenCV中,可以使用 cv2.morphologyEx
函数来实现击中与不击中变换。以下是一个Python代码示例:
import cv2
import numpy as np
# 读取图像并转换为二值图像
image = cv2.imread('path_to_your_image.jpg', cv2.IMREAD_GRAYSCALE)
_, binary_image = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)
# 定义击中和不击中结构元素
kernel_hit = np.array([
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]
], dtype=np.uint8)
kernel_miss = np.array([
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
], dtype=np.uint8)
# 应用击中与不击中变换
hit_miss_image = cv2.morphologyEx(binary_image, cv2.MORPH_HITMISS, kernel_hit)
# 显示结果
cv2.imshow('Hit-Miss Transform', hit_miss_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
首先将图像转换为二值图像,然后定义了击中和不击中结构元素。cv2.morphologyEx
函数用于执行击中与不击中变换。结果图像中,满足击中结构元素的形状将被突出显示。
(4)应用场景:
击中与不击中变换在图像处理中的应用包括:
- 特定形状检测:如检测图像中的特定形状或模式。
- 图像预处理:在进一步的图像分析之前,用于去除或突出特定结构。
- 特征提取:在图像识别和分析中提取有用的特征。
(5)注意事项:
- 结构元素的设计对于击中与不击中变换的效果至关重要。需要根据目标形状的大小和形状来设计合适的结构元素。
- 击中与不击中变换通常用于二值图像,因此可能需要先对图像进行二值化处理。
九、利用形态学运算提取水平线和垂直线:
利用形态学运算提取图像中的线条是一种常见的图像处理技术。在OpenCV中,可以通过自定义结构元素(structuring element)来实现膨胀和腐蚀操作,从而提取水平线和垂直线。
(1)提取水平线和垂直线的原理:
- 膨胀:在图像中添加像素,使得线条变粗。
- 腐蚀:在图像中移除像素,使得线条变细。
- 开运算:先腐蚀后膨胀,用于移除小对象并平滑较大对象的边界。
(2)实现步骤:
- 读取图像:加载需要处理的图像。
- 灰度转换:将图像转换为灰度图像,以便进行二值化处理。
- 二值化:将灰度图像转换为二值图像,以便进行形态学操作。
- 定义结构元素:创建水平和垂直的结构元素,用于提取相应的线条。
- 开运算:对二值图像进行开运算,提取水平或垂直线。
(3)示例代码:
import cv2
import numpy as np
# 读取图像
image = cv2.imread("C:\\Users\\86173\\Desktop\\TI\\Coin0.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 二值化
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
# 定义水平和垂直结构元素
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 1))
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 30))
# 提取水平线
horizontal_lines = cv2.morphologyEx(binary, cv2.MORPH_OPEN, horizontal_kernel)
# 提取垂直线
vertical_lines = cv2.morphologyEx(binary, cv2.MORPH_OPEN, vertical_kernel)
# 显示结果
cv2.imshow('Horizontal Lines', horizontal_lines)
cv2.imshow('Vertical Lines', vertical_lines)
cv2.waitKey(0)
cv2.destroyAllWindows()
首先将图像转换为灰度图像,然后进行二值化处理。接着,定义水平和垂直的结构元素,并使用开运算提取了水平线和垂直线。最后,显示提取线条的结果。
(4)注意事项:
- 结构元素的大小和形状对提取线条的效果有重要影响。较大的结构元素可以提取更粗的线条,但可能会包含非目标线条。
- 二值化阈值的选择也会影响提取线条的效果。适当的阈值可以帮助更好地区分线条和背景。