我们在图像的形态学操作(一)中介绍了形态学的基本操作膨胀和腐蚀,我们将在这一篇将利用膨胀和腐蚀操作实现对图像更高级的形态学操作,而这些都是建立在膨胀和腐蚀操作基础之上。
图像的形态学由J. Serra 于1964年提出,其基础是利用数学中的集合论的知识,是利用一种特殊的结构元来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别,形态学操作在图像处理中的主要应用有:
(1). 利用形态学的基本运算对图像进行观察和处理,从而达到改善图像质量的目的。
(2). 描述和定义图像的各种几何参数和特征如面积、周长、连通、颗粒度、骨架和方向性。
我们通过腐蚀和膨胀两种基本的形态学操作实现开运算、闭运算、形态梯度、顶帽、黑帽五种形态学操作。
1. 开运算与闭运算
1.1 开运算
开运算是通过先对图像腐蚀再膨胀实现,其原理表达式如下:
imgdst = cv2.morphologyEx(imgsrc, cv2.MORPH_OPEN, kernel)
通过开运算可以将特定图像中的噪声点和毛刺消除,我们还是用上节课中的图像,注意腐蚀是黑色侵蚀白色,所以开运算对于黑色背景的图像能实现上述效果。
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\liuge2.jpg')
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel2 = np.ones((8, 8), np.uint8)
imgOpen = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel2)
cv2.imshow('imgOpen', imgOpen)
cv2.waitKey(0)
cv2.destroyAllWindows()
原图像为:
进行开运算后的图像为:
通过开运算有效祛除了图像中的噪点和毛刺。
1.2 闭运算
闭运算是通过先对图像膨胀再腐蚀实现,其原理表达式如下:
imgdst = cv2.morphologyEx(imgsrc, cv2.MORPH_CLOSE, kernel)
通过闭运算可以将特定图像中的噪声点和毛刺消除,我们还是用上节课中的图像,注意腐蚀是黑色侵蚀白色,所以闭运算对于白色背景的图像能实现上述效果。
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\liuge.jpg')
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#闭运算
kernel = np.ones((5, 5), np.uint8)
imgClose = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.imshow('imgClose', imgClose)
cv2.waitKey(0)
cv2.destroyAllWindows()
原图像为:
闭运算后的图像为:
2. 梯度运算
梯度运算相当于膨胀减去腐蚀,即梯度 = 膨胀 -腐蚀。
imgdst = cv2.morphologyEx(imgsrc, cv2.MORPH_GRADIENT, kernel)
对图像进行梯度运算的结果为:
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\2.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((5, 5), np.uint8)
imgGradient = cv2.morphologyEx(gray, cv2.MORPH_GRADIENT, kernel)
cv2.imshow('imgGradient', imgGradient)
cv2.waitKey(0)
cv2.destroyAllWindows()
原图像为:
梯度预算后图像为:
下面我们对比下OpenCV中直接提供的梯度操作和先进行膨胀在进行腐蚀的结果是否相同。
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\lena.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((5, 5), np.uint8)
imgGradient = cv2.morphologyEx(gray, cv2.MORPH_GRADIENT, kernel)
dilate = cv2.dilate(gray, kernel, iterations=1)
erosion = cv2.erode(gray, kernel, iterations=1)
imgGradient2 = dilate - erosion
diff = imgGradient-imgGradient2
res = np.hstack((imgGradient, imgGradient2,diff))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果为:
二种操作方法的差图像基本为0,可见对图像进行梯度梯相当于膨胀减去腐蚀。
3. 顶帽与黑帽操作
3.1 顶帽运算
顶帽运算 = 原始输入 -开运算结果,开运算为先腐蚀在膨胀,消除了原图像的高频细节部分,顶帽操作则是提出去这些被消除的细节。顶帽运算的作用是:把值高于邻近点的孤立点或斑块分离出来。把较小的连通域分离出来。
把较窄的狭颈和两个物体的纤细连接处分离出来。我们也对比下OpenCV中提供的顶帽操作的结果与原始输入 -开运算结果。
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\2.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((5, 5), np.uint8)
imgTophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, kernel)
imgOpen = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)
# imgTophat= cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, kernel)
imgTophat2 = gray - imgOpen
res = np.hstack((gray, imgTophat, imgTophat2))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出结果为:
3.2 黑帽运算
黑帽运算 = 闭运算结果 - 原始输入 ,黑帽操作是闭运算结果与原图像之间的差值,它把闭运算“增加”的细节显现出来。黑帽操作的作用是
把值低于邻近点的孤立点或斑块分离出来。把较窄的间断和细长的沟壑显现出来;把连通域内的小型空洞显现出来;我们也对比下OpenCV中提供的顶帽操作的结果与原始输入 -开运算结果。
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\2.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((5, 5), np.uint8)
imgBLACKHAT = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, kernel)
imgClose = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel)
# imgTophat= cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, kernel)
imgBLACKHAT2 = imgClose - gray
res = np.hstack((gray, imgBLACKHAT, imgBLACKHAT2))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出结果为:
这里图片的选取不是特别具有代表意义,可以根据自身的需要去实验看下效果。