形态学变换
- 1. 核
- 2.腐蚀(cv2.erode)
- 3. 膨胀(cv2.dilate)
- 4. 开运算(cv.MORPH_OPEN)
- 5. 闭运算(cv2.MORPH_CLOSE)
- 6. 礼帽运算(找出增多的白色区域)
- 7. 黑帽运算
- 8. 形态学梯度
形态学变换(Morphological Transformations)是一种 基于形状的简单变换,它的处理对象通常是二值化图像。形态学变换有两个输入,一个输出:输入为 原图像、核(结构化元素),输出为形态学**变换后的图像。**其基本操作有腐蚀和膨胀,这两种操作是相反的,即较亮的像素会被腐蚀和膨胀。下面我们来说一下核、腐蚀与膨胀的概念。
1. 核
其实在上一章节自适应二值化中,我们已经接触过核了,还记得吗?就是那个在原图中不断滑动计算的3*3的小区域,那其实就是一个3*3的核。
核(kernel)其实就是一个小区域,通常为3*3、5*5、7*7大小,有着其自己的结构,比如矩形结构、椭圆结构、十字形结构,如下图所示。通过不同的结构可以对不同特征的图像进行形态学操作的处理。
2.腐蚀(cv2.erode)
腐蚀操作就是使用核在原图(二值化图)上进行从左到右、从上到下的滑动(也就是从图像的左上角开始,滑动到图像的右下角)。在滑动过程中,令核值为1的区域与被核覆盖的对应区域进行相乘,得到其最小值,该最小值就是卷积核覆盖区域的中心像素点的新像素值,接着继续滑动。由于操作图像为二值图,所以不是黑就是白,这就意味着,在被核值为1覆盖的区域内,只要有黑色(像素值为0),那么该区域的中心像素点必定为黑色(0)。这样做的结果就是会将二值化图像中的白色部分尽可能的压缩,如下图所示,该图经过腐蚀之后,“变瘦”了。
腐蚀操作的详细流程
腐蚀原理的代码:
'''腐蚀操作——原理'''img=np.zeros((10,10),dtype=np.uint8)img[3:7,3:7]=255img[2,2]=10print(img)print("="*20)kernel=np.ones((3,3),dtype=np.uint8)#填充了一个全1的核img2=cv2.erode(img,kernel=kernel)#第一个填入一个二值图,print(img2)'''[ 0 0 10 0 0 0 0 0 0 0][ 0 0 0 255 255 255 255 0 0 0][ 0 0 0 255 255 255 255 0 0 0][ 0 0 0 255 255 255 255 0 0 0][ 0 0 0 255 255 255 255 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0]]
====================
[[ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 255 255 0 0 0 0][ 0 0 0 0 255 255 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0]]'''
由上面代码可以知道腐蚀是以每个元素为中心做一个3*3的全1的核找到最小值填充到核的中心
腐蚀操作代码部分:
'''腐蚀操作'''img=cv2.imread(r'../15day4.10\src\long.png',cv2.IMREAD_GRAYSCALE)kernel=np.ones((3,3),dtype=np.uint8)#填充了一个全1的核img_erode=cv2.erode(img,kernel=kernel,iterations=2)#表示进行腐蚀两次cv2.imshow('img',img)cv2.imshow("img_erode",img_erode)cv2.waitKey(0)
注意:
- 腐蚀的本质是输出将一个以一个像素点为中心的核的最小值,若是上图则是白色被腐蚀了(白色变少了)
- 腐蚀可以去除图像中的白色噪点
3. 膨胀(cv2.dilate)
膨胀与腐蚀刚好相反,膨胀操作就是使用核在原图(二值化图)上进行从左到右、从上到下的滑动(也就是从图像的左上角开始,滑动到图像的右下角),在滑动过程中,令核值为1的区域与被核覆盖的对应区域进行相乘,得到其最大值,该最大值就是核覆盖区域的中心像素点的新像素值,接着继续滑动。由于操作图像为二值图,所以不是黑就是白,这就意味着,在卷积核覆盖的区域内,只要有白色(像素值为255),那么该区域的中心像素点必定为白色(255)。这样做的结果就是会将二值化图像中的白色部分尽可能的扩张,如下图所示,该图经过膨胀之后,“变胖”了。
膨胀的详细操作
膨胀原理代码:
'''膨胀操作——原理'''img=np.zeros((10,10),dtype=np.uint8)img[3:7,3:7]=255img[2,2]=10img[2,4]=100print(img)print("="*20)kernel=np.ones((3,3),dtype=np.uint8)#填充了一个全1的核img2=cv2.dilate(img,kernel=kernel)#第一个填入一个二值图,print(img2)'''[[ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 10 0 100 0 0 0 0 0][ 0 0 0 255 255 255 255 0 0 0][ 0 0 0 255 255 255 255 0 0 0][ 0 0 0 255 255 255 255 0 0 0][ 0 0 0 255 255 255 255 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0]]
====================
[[ 0 0 0 0 0 0 0 0 0 0][ 0 10 10 100 100 100 0 0 0 0][ 0 10 255 255 255 255 255 255 0 0][ 0 10 255 255 255 255 255 255 0 0][ 0 0 255 255 255 255 255 255 0 0][ 0 0 255 255 255 255 255 255 0 0][ 0 0 255 255 255 255 255 255 0 0][ 0 0 255 255 255 255 255 255 0 0][ 0 0 0 0 0 0 0 0 0 0][ 0 0 0 0 0 0 0 0 0 0]]'''
由上面代码可以知道腐蚀是以每个元素为中心做一个3*3的全1的核找到最大值填充到核的中心
膨胀的操作的代码:
'''膨胀操作'''img=cv2.imread(r'../15day4.10\src\long.png',cv2.IMREAD_GRAYSCALE)kernel=np.ones((3,3),dtype=np.uint8)img_dilate=cv2.dilate(img,kernel=kernel,iterations=3)cv2.imshow('img',img)cv2.imshow("img_dilate",img_dilate)cv2.waitKey(0)
注意:
- 膨胀的本质是输出将一个以一个像素点为中心的核的最大值,若是上图则是白色扩大了
- 膨胀可以去除图像中的黑色噪点
4. 开运算(cv.MORPH_OPEN)
开运算是先腐蚀后膨胀,其作用是:分离物体,消除小区域。特点:消除噪点,去除小的干扰块,而不影响原来的图像
代码如下:
'''开运算:先腐蚀后膨胀'''img=cv2.imread(r'../15day4.10\src\open.png',cv2.IMREAD_GRAYSCALE)kernel=np.ones((3,3),dtype=np.uint8)img_open=cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel=kernel)cv2.imshow('img',img)cv2.imshow("img_open",img_open)cv2.waitKey(0)
5. 闭运算(cv2.MORPH_CLOSE)
闭运算与开运算相反,是先膨胀后腐蚀,作用是消除/“闭合”物体里面的孔洞,特点:可以填充闭合区域
代码如下:
'''闭运算:先膨胀后腐蚀'''img=cv2.imread(r'../15day4.10\src\car.png',cv2.IMREAD_GRAYSCALE)kernel=np.ones((3,3),dtype=np.uint8)img_close=cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel=kernel)cv2.imshow('img',img)cv2.imshow("img_close",img_close)cv2.waitKey(0)
6. 礼帽运算(找出增多的白色区域)
cv2.MORPH_TOPHAT
原图像与“开运算“的结果图之差,因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作和选择的核的大小相关。
礼帽运算用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用礼帽运算进行背景提取(找到原图中的白色噪点)
代码如下:
'''礼帽运算''' img=cv2.imread(r'../15day4.10\src\open.png',cv2.IMREAD_GRAYSCALE)kernel=np.ones((5,5),np.uint8)img2=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel=kernel)cv2.imshow('img',img)cv2.imshow('img2',img2)cv2.waitKey(0)
7. 黑帽运算
cv2.MORPH_BLACKHAT
黑帽运算为”闭运算“的结果图与原图像之差,
黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。
黑帽运算用来分离比邻近点暗一些的斑块
代码如下:
'''黑帽运算'''img=cv2.imread(r'../15day4.10\src\car.png',cv2.IMREAD_GRAYSCALE)kernel=np.ones((3,3),np.uint8)img2=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel=kernel)cv2.imshow('img',img)cv2.imshow('img2',img2)cv2.waitKey(0)
8. 形态学梯度
cv2.MORPH_GRADIENT
形态学梯度是一个基于结构元素的图像处理方法,它通过比较原图像与膨胀图和腐蚀图之间的差异来突出图像边缘特征。具体来说,对于图像中的每个像素点,其形态学梯度值是该像素点在膨胀后的图像值与其在腐蚀后的图像值之差。这样得到的结果通常能够强化图像的边缘信息,并且对噪声有一定的抑制作用
代码如下:
'''形态学梯度''' img=cv2.imread(r'../15day4.10\src\car.png',cv2.IMREAD_GRAYSCALE)kernel=np.ones((3,3),np.uint8)img2=cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel=kernel) #gradientcv2.imshow('img',img)cv2.imshow('img2',img2)cv2.waitKey(0)
形态学梯度是图像膨胀后与腐蚀后的差值,这样可以得到原图像的轮廓