OpenCV - day03 Morphology_Operation

148 阅读2分钟

形态学操作

 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)

腐蚀效果对比.PNG

 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)
  • 效果图: 圆腐蚀多次迭代.PNG

二、膨胀

  • 腐蚀的逆运算:

    取方阵,若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,也变方了,腐蚀会将圆侵蚀为菱形

效果对比:

圆膨胀多次迭代.PNG

四、开闭运算

  • 开运算(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)

效果对比: 开运算.PNG

## 闭:先膨胀,再腐蚀
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)

效果对比:

闭运算.PNG 可以看出闭运算不能淘汰细节

四、梯度运算

  • 梯度运算 = 膨胀 - 腐蚀
  • 上述减法是图像减法,也就是阵列减法
## 梯度运算 = 膨胀 - 腐蚀
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)

梯度运算.PNG

五、礼帽和黑帽

  • 礼帽 = 原始输入 - 开(先腐蚀再膨胀)运算结果
  • 黑帽 = 闭(先膨胀后腐蚀)运算结果 - 原始输入
 # 礼帽
 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)
 ​