形态学操作
import cv2
import matplotlib
import matplotlib.pyplot as plt #取别名(用于绘图展示)
import numpy as np #取别名,下面是notepad专用,立即显示图像
%matplotlib inline
def cv_show(name, img): #定义函数用于显示图片,此处name为窗口名,img为cv2调用imread方法的返回值
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
def winds(images, scale):
shape = images[0].shape[1::-1]
for i in range(len(images)):
images[i] = cv2.resize(images[i], shape)
images[i] = cv2.resize(images[i], (0, 0), fx = scale, fy = scale)
images[i][ :,-2:,:] = 255
res = np.hstack(images)
cv_show('Compare', res)
一、腐蚀
-
处理办法:
以矩阵为操作单位,只要D8邻域存在黑点,即像素值为0,则就会将中心点置为0
-
注意:
腐蚀和膨胀都是不可逆操作,会直接在原图像 (空间域) 上面操作,导致图片丢失像素点信息
img = cv2.imread('Fur.png')
cv_show('Fur', img)
kernel = np.ones((3, 3), np.uint8) #腐蚀滤波器
erosion = cv2.erode(img, kernel, iterations = 1)
cv_show('Erosion', erosion)
- 效果对比:
winds([img, erosion],2)
round = cv2.imread('round.png')
cv_show("Round", round)
kernel = np.ones((5, 5), np.uint8) #腐蚀的范围
erosion_r = cv2.erode(round, kernel, iterations = 2) #
cv_show('Erosion-R', erosion_r)
res = np.hstack([round, erosion_r]) #只有自然数模块numpy才有此方法
cv_show('Test', res)
# *(腐蚀)迭代iterations次数
kernel = np.ones((30, 30), np.uint8) #腐蚀的范围,越大效果越明显
erosion_1 = cv2.erode(round, kernel, iterations = 1)
erosion_2 = cv2.erode(round, kernel, iterations = 2)
erosion_3 = cv2.erode(round, kernel, iterations = 3)
erosion_4 = cv2.erode(round, kernel, iterations = 4)
erosion = np.hstack([ round, erosion_1, erosion_2, erosion_3, erosion_4])
cv_show('Compare', erosion)
- 效果图:
二、膨胀
-
腐蚀的逆运算:
取方阵,若D8邻域内有白点255,则该中心值变为255
img = cv2.imread('Fur.png')
cv_show('Fur', img)
kernel = np.ones((3, 3), np.uint8) #腐蚀配置
e = cv2.erode(img, kernel, iterations = 1)
cv_show('Erosion', e)
kernel = np.ones((3, 3), np.uint8) #膨胀配置
dilate = cv2.dilate(e, kernel, iterations = 1) #把腐蚀变细的感兴趣的线条弥补回来
cv_show('Dilate', dilate)
round = cv2.imread('round.png')
kernel = np.ones((30, 30), np.uint8) #核矩阵越小,越接近圆
dilate_1 = cv2.dilate(round, kernel, iterations = 1)
dilate_2 = cv2.dilate(round, kernel, iterations = 2)
dilate_3 = cv2.dilate(round, kernel, iterations = 3)
res = np.hstack([dilate_1, dilate_2, dilate_3])
cv_show('Compare', res) #2333,也变方了,腐蚀会将圆侵蚀为菱形
效果对比:
四、开闭运算
-
开运算(morphologyEx,cv2.MORPH_OPEN):先腐蚀后膨胀,无迭代次数
-
闭运算(morphologyEx,cv2.MORPH_CLOSE): 先膨胀后腐蚀,不能淘汰细节
## 开:先腐蚀,再膨胀
img = cv2.imread('Fur.png')
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
res = np.hstack([img, opening])
cv_show('Test', res)
效果对比:
## 闭:先膨胀,再腐蚀
img = cv2.imread('Fur.png')
kernel = np.ones((3, 3), np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
res = np.hstack([img, closing])
cv_show('Test', res)
效果对比:
可以看出闭运算不能淘汰细节
四、梯度运算
- 梯度运算 = 膨胀 - 腐蚀
- 上述减法是图像减法,也就是阵列减法
## 梯度运算 = 膨胀 - 腐蚀
round = cv2.imread('round.png')
kernel = np.ones((10, 10), np.uint8)
dilate = cv2.dilate(round, kernel, iterations = 5)
erosion = cv2.erode(round, kernel, iterations = 5)
res = np.hstack([dilate, erosion])
cv_show('Test', res)
kernel = np.ones((10, 10), np.uint8)
gradient = cv2.morphologyEx(round, cv2.MORPH_GRADIENT, kernel)
cv_show('Gredient', gradient)
效果对比:
winds([round, dilate, erosion, gradient],0.9)
五、礼帽和黑帽
- 礼帽 = 原始输入 - 开(先腐蚀再膨胀)运算结果
- 黑帽 = 闭(先膨胀后腐蚀)运算结果 - 原始输入
# 礼帽
img = cv2.imread('Fur.png')
kernel = np.ones((5, 5) , np.uint8)
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv_show('TopHat', tophat)
# 黑帽
img = cv2.imread('Fur.png')
kernel = np.ones((5, 5), np.uint8)
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
cv_show('Black',blackhat)