目录
背景说明
形态学操作是图像处理中常用的一种操作,主要用于对图像进行形状和结构的改变。形态学操作常用于图像的降噪、边缘检测、图像分割等方面。在OpenCV中,形态学操作可以通过cv2模块中的函数来实现。
目标
- 学习不同的形态学操作,例如膨胀、腐蚀、开运算、闭运算等
- 我们学习的函数有cv2.erode()、cv2.dilate()、cv2.morphologyEx() 等
形态学操作原理
形态学操作是根据图像形状的简单操作。一般情况下对二值化图像的操作。需要输入两个参数,一个是原始图像,第二个称为结构化元素或核,它是用来决定操作的性的。两个基本的形态学操作是腐蚀和膨胀。他们的变体构成了开运算,闭运算、梯度等。我们会以下图为例来介绍它们。(白色是前景色,黑色是背景色)
腐蚀
原理
卷积核沿着图像滑动如果与卷积核对应的原图像的所有像素值是 1,那么中心元素就保持原来的像素值,否则就变为0。
效果
就像土壤腐蚀一样,该操作会把前景物体的边界腐蚀掉(但是前景色仍然是白色),边界会变得更加清晰。
影响
根据卷积核的大小,靠近前景色的所有像素都会腐掉变为0,所以前景物体会变小,整幅图像的白色区域会减少。对于去白噪声很有用,也可以用来断开两个连在一块的物体等。
示例
我们下面这个例子使用一个 5x5 的卷积核,其中所有的值是默认。 我们看看他是如何工作的。所用函数为:cv2.erode(),该函数接受两个参数:输入图像和腐蚀的核大小。
import cv2
import numpy as np
img = cv2.imread('j.png',0)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
结果:
膨胀
原理
与腐蚀相反,与卷积核对应的原图像的像素值中只要有一个是 1,中心元素的像素值就是 1。
效果
该操作会增加图像中的白色区域前景,使边界变得模糊。
作用
实际图像处理中先用腐蚀再用膨胀可以去除噪声。因为腐蚀在去掉白噪声的同时也会使前景相对变小,所以我们再对它膨胀,此时噪声已经去除了,不会再回来了,但是前景还在并会增加。膨胀也可以用来连接两个分开的物体。所用函数为:cv2.dilate(),该函数接受两个参数:输入图像和膨胀的核大小。
dilation = cv2.dilate(img,kernel,iterations = 1)
结果:
开运算
先进行腐蚀再膨胀就叫做开算。就像我们上介绍的样它用来去噪声。我们用到的函数是 cv2.morphologyEx(),该函数接受三个参数:输入图像、操作类型(cv2.MORPH_OPEN)和运算核大小。
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
结果:
闭运算
先膨胀再腐蚀。它经常用来填充前景物体中的小洞或者前景物体上的小点。该函数接受三个参数:输入图像、操作类型(cv2.MORPH_CLOSE)和运算核大小。
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
形态学梯度
图像形态学梯度是一种形态学操作,它可以用来检测图像中的边缘或轮廓。形态学梯度可以通过膨胀和腐蚀操作之间的差异来计算,(其实就是一幅图像膨胀与腐的差别) 结果看上去就像前景物体的轮廓。
形态学梯度的作用包括:
1.边缘检测:形态学梯度可以用来检测图像中的边缘或轮廓。由于形态学梯度突出了图像中的边界区域,因此在图像分割、目标检测等领域有广泛应用。
2.物体测量:形态学梯度可以用来测量物体的大小、形状和结构。通过计算形态学梯度,可以获取物体的边界信息,并进一步进行物体测量和分析。
3.形态学重建:形态学梯度可以用来进行形态学重建操作。形态学重建是一种基于形态学操作的图像处理技术,用于从图像中提取感兴趣的对象或区域。
4.形态学滤波:形态学梯度可以用来进行图像的滤波操作。通过选择合适的结构元素,可以实现对图像中的噪声或干扰的去除。
5.图像增强:形态学梯度可以用来增强图像的边缘或轮廓,从而使图像更加清晰和鲜明。
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
礼帽
原始图像与开运算之后得到的图像的差。主要实际应用场景如下:
- 检测亮区域:礼帽运算可以用来检测图像中的亮区域或亮斑。亮区域可能是图像中的目标物体、光源或者其他特定区域。
- 表面缺陷检测:礼帽运算可以用来检测表面缺陷,如划痕、凹陷等。通过与原始图像进行比较,可以突出表面缺陷的区域。
- 细胞核分析:在细胞核分析中,礼帽运算可以用来检测细胞核的亮区域,并进一步进行细胞核的分割和分析。
下的例子是用一个 9x9 的 核礼帽操作的结果。
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
黑帽
进行闭运算之后得到的图像与原始图像的差。主要用途如下:
- 检测暗区域:黑帽运算可以用来检测图像中的暗区域或暗斑。暗区域可能是图像中的阴影、污渍或者其他特定区域。
- 文字图像分割:在文字图像分割中,黑帽运算可以用来检测文字的阴影或背景干扰。通过与原始图像进行比较,可以突出文字区域。
- 血管分割:在医学图像处理中,黑帽运算可以用来分割血管。血管通常呈现为暗区域,通过黑帽运算可以突出血管的形状和位置
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
形态学操作之间的关系
结构化元素
在前的例子中我们使用 Numpy 构建的结构化元素它是正方形的。 有时我们需要构建一个椭圆形/圆形的核。为了实现这种需求。OpenCV 提供了函数 cv2.getStructuringElement()。你只告他你的核的形状和大小就可以。
# Rectangular Kernel
>>> cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
array([[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]], dtype=uint8)
# Elliptical Kernel
>>> cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
array([[0, 0, 1, 0, 0],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 0]], dtype=uint8)
# Cross-shaped Kernel
>>> cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
array([[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0]], dtype=uint8)
更多参考
详细学习地点可以参考:https://homepages.inf.ed.ac.uk/rbf/HIPR2/morops.htm
下面是一个使用形态学操作的综合示例代码:
import cv2
import numpy as np
# 读取图像
image = cv2.imread("image.jpg", 0)
# 创建一个 5x5 的腐蚀核
kernel = np.ones((5, 5), np.uint8)
# 腐蚀操作
erosion = cv2.erode(image, kernel, iterations=1)
# 膨胀操作
dilation = cv2.dilate(image, kernel, iterations=1)
# 开运算操作
opening = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
# 闭运算操作
closing = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
# 显示结果
cv2.imshow("Erosion", erosion)
cv2.imshow("Dilation", dilation)
cv2.imshow("Opening", opening)
cv2.imshow("Closing", closing)
cv2.waitKey(0)
cv2.destroyAllWindows()
在上述代码中,首先使用cv2.imread函数读取一张灰度图像,然后创建一个 5x5 的腐蚀核,接着分别使用cv2.erode、cv2.dilate、cv2.morphologyEx函数实现腐蚀、膨胀、开运算、闭运算操作。最后,使用cv2.imshow函数显示结果,并使用cv2.waitKey和cv2.destroyAllWindows函数来保持图像窗口的显示。