Opencv入门系列七
主要内容:形态学操作
通过形态学操作可以提取图形中描述形状的特征信息,在视觉检查,文字识别,医学图像处理等方面有重要作用。
- 腐蚀
- 膨胀
- 开运算
- 闭运算
- 形态学梯度
- 顶帽运算
- 黑帽运算
- 核函数
1.腐蚀
腐蚀:将图像边界点收缩,在小于一定范围会将像素点消除。可以用来除噪、元素分割等功能。如下图:
图中两个相交的圆,通过腐蚀操作成了两个小的圆形。
下面以一个例子,简单描述腐蚀的过程,如下图所描述:
从图中我们可以看到原图像与核函数。
① 找出核函数中心位置。
因为核函数比较简单,第二行的1就是核函数的中间位置。
② 遍历原图像,将核函数中心位填充于每个位置并将整个核函数填充于原函数中,像素匹配的中心位置为1,其余为0,如下图操作。
首先确定中心点,此图为原图像的第一个位置。
其次将核函数其余部分与原图像比较,看对应像素点是否匹配。
上图中,在将匹配像素点时,发现原图像边界像素不够,故和滤波操作中一样需要填充边界。我们简单默认边界填充都是1。那么可知原图像和填充图像不匹配(如下图),故腐蚀操作后第一个像素点位置为0。
③按照1,2 依次遍历整个原图像的像素点。我们发现仅有核函数中心点位于下图三个位置,才能保证匹配关系。
填充后,如下图
故腐蚀后图像为
在Opencv中提供了cv2.erode()函数实现腐蚀操作,其语法如下:
● dst:腐蚀后所输出目标图像。
● src:原图像,要求图像的深度必须是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F中的一种。
● kernel:腐蚀操作时所采用的结构类型。可以自定义生成,也可以通过函数cv2.getStructuringElement()生成。
● anchor:element结构中锚点的位置。该值默认为(-1,-1),在核的中心位置。
● iterations:腐蚀操作迭代的次数,该值默认为1,即只进行一次腐蚀操作。
● borderType:边界填充方式,一般采用其默认值BORDER_CONSTANT。
● borderValue:边界值,一般采用默认值。
borderType值可以为:
下面看一个简单的程序
import cv2
import numpy as np
lena = cv2.imread("Resources/lena.png",0)
kennel5 = np.ones((5,5),dtype=np.uint8)# 创建一个(5*5)的核
kennel9 = np.ones((9,9),dtype=np.uint8)# 创建一个(9*9)的核
lenaErodeTo5_i1 = cv2.erode(lena,kennel5)
lenaErodeTo9_i1 = cv2.erode(lena,kennel9)
lenaErodeTo5_i3 = cv2.erode(lena,kennel5,iterations=3)
cv2.imshow("lena",lena) #原图显示
cv2.imshow("lenaErodeTo5_i1",lenaErodeTo5_i1)#(5,5)核函数迭代一次
cv2.imshow("lenaErodeTo5_i3",lenaErodeTo5_i3)#(5,5)核函数迭代三次
cv2.imshow("lenaErodeTo9_i1",lenaErodeTo9_i1)#(9,9)核函数迭代三次
cv2.waitKey(0)
我们从运行结果可以看出,我们使用更大的核或者更多的迭代次数,可以提高腐蚀的效果有更好的滤波作用。
2.膨胀
膨胀:将图像边界点扩张。如下图
下面以一个例子,简单描述膨胀的过程,如下图所描述:
膨胀操作理解起来比腐蚀要简单,同样的我们取核函数中中心位置。然后依次在原图像中遍历,原图像像素点与核函数中心位置相等的点,就将核函数按结构覆盖到原图像中即可。
得到如下结果:
在Opencv中提供了cv2.dilate()函数实现腐蚀操作,其语法如下:
● dst:膨胀后的图像。
● src:原图像。要求图像的深度必须是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F中的一种。
● element:膨胀操作所采用的结构类型。可以自定义生成,也可以通过函数cv2.getStructuringElement()生成。
参数kernel、anchor、iterations、borderType、borderValue与函数cv2.erode()内相应参数的含义一致。
下面是一个简单的实验
import cv2
import numpy as np
img = cv2.imread("Resources/12.jpg",0)
kennel = np.ones((5,5),dtype=np.uint8)
dilateImg5_i1 = cv2.dilate(img,kennel,iterations=1)
dilateImg5_i5 = cv2.dilate(img,kennel,iterations=5)
cv2.imshow("img",img)
cv2.imshow("dilateImg5_i1",dilateImg5_i1)
cv2.imshow("dilateImg5_i5",dilateImg5_i5)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.cv2.morphologyEx()
在Opencv()中,cv2.morphologyEx()是一个形态学通用的函数,可以完成所有的形态学操作,其语法如下。
● dst:形态学处理后的图像。
● src:原图像。要求图像的深度必须是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F中的一种。
● op:操作类型。
● 参数kernel、anchor、iterations、borderType、borderValue与函数cv2.erode()内相应参数的含义一致。
op参数的操作类型可以是:
4.开运算
开运算:先腐蚀再膨胀。腐蚀可以消除小于某个临界值的边界,边界范围可以由核函数和迭代的次数决定。膨胀可以将剩下的图像的特征进行扩大。从此可以通过开运算提取理想的图像。
下图是一个开运算的例子:
左图经过腐蚀消除了毛刺,得到了中间所示的图像后再将所需的特征进行放大,即进行膨胀操作。
在Opencv中使用开运算语法如下:
5.闭运算
闭运算:先膨胀、后腐蚀的运算,它有助于关闭前景物体内部的小孔,或去除物体上的小黑点,还可以将不同的前景图像进行连接。
下图是一个闭运算的例子:
左图图像进行膨胀后内部的黑点被消除了。
在Opencv中使用闭运算语法如下:
6.形态学梯度运算
形态学梯度运算:膨胀的图像减去腐蚀的图像。用于获取图像的边缘。
下图是一个闭运算的例子:
在Opencv中使用形态学运算语法如下:
7.礼帽运算
礼帽运算:原始图像减去其开运算图像的操作。我们可以把开运算理解为滤波后的图像(即消除噪音的图像),有如下关系式:开运算后图像+噪音=原始图像。故礼帽运算能够获取图像的噪声信息,或者得到比原始图像的边缘更亮的边缘信息。
下面是一个礼帽运算的例子:
在Opencv中使用礼帽运算语法如下:
8.黑帽运算
黑帽运算:原始图像减去其闭运算图像的操作。我们可以把闭运算理解为滤波后的图像(即消除内部黑点,小孔),有如下关系式:闭运算后图像+黑点=原始图像。黑帽运算能够获取图像内部的小孔,或前景色中的小黑点,或者得到比原始图像的边缘更暗的边缘部分。
下面是一个黑帽运算的例子:
在Opencv中使用黑帽运算语法如下:
9.核函数
核函数:我们在前面的形态学操作时都有一个核(元结构),即函数中的参数kennel。在Opencv中有专门产生核的一个函数cv2.getStructuringElement(),是用于获取不同的核的函数。其语法如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RZRRIaeZ-1612338018443)(C:\Users\44338\AppData\Roaming\Typora\typora-user-images\image-20210203152516123.png)]
● shape:形状类型,其可能的取值如表8-3所示。
● ksize:结构元素的大小。
● anchor:结构元素中的锚点位置。默认的值是(-1,-1),是形状的中心。只有十字星型的形状与锚点位置紧密相关。在其他情况下,锚点位置仅用于形态学运算结果的调整。
shape参数可以是:
Rect:矩形
Cross:十字架
Ellipse:椭圆
Morph:
import cv2
import numpy as np
RectKennel = cv2.getStructuringElement(cv2.MORPH_RECT,(10,10))
CrossKennel = cv2.getStructuringElement(cv2.MORPH_CROSS,(10,10))
EllKennel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(10,10))
print(RectKennel)
print(CrossKennel)
print(EllKennel)