v2-7d25463449a61f22c123054b4e3192a4_720w.jpg
Def.[开运算(opening)] 开运算(opening)是指先腐蚀再膨胀的过程。开运算是结构元素B在集合A内完全匹配的并集,完全删除了不能包含结构元素的对象区域。开运算使图像的轮廓变得光滑,断开狭窄的间断,去掉细小的突出物。
Def.[闭运算(closing)] 闭运算(closing)是先膨胀再腐蚀的过程。结构元素B在集合A外侧平移,这些平移的并集就是闭运算的结果。闭运算使图像的轮廓变得光滑,但与开运算不同的是,它会将狭窄的缺口连接形成细长的弯口,并填充比结构元素小的洞。
Def.[形态学梯度运算] 求取膨胀与腐蚀结果间的差分,其效果是突出边缘轮廓。
Def.[顶帽(top hat)变换] 求取输入图像与其开运算间的差分。
Def.[黑帽(black hat)变换] 求取输入图像闭运算与其本身间的差分。
https://zhuanlan.zhihu.com/p/36652585

一. 图像形态学简介:

图像处理之形态学 - 图2


经验之谈:形态学操作一般作用于二值图像,来连接相邻的元素(膨胀)或分离成独立的元素(侵蚀)。腐蚀和膨胀是针对图片中的白色(即前景)部分!


二. 图像形态学操作 膨胀和腐蚀的算法:

膨胀算法:
对于待操作的像素 f(x,y),不论 f(x,y-1) 、f(x,y+1) 、f(x-1,y) 、f(x+1,y) 哪一个为255,则 f(x,y)=255。

图像处理之形态学 - 图3

膨胀操作 ↑


换句话说:将待操作的图像像素与以下 4-近邻矩阵 相乘,结果大于255的话,将中心像素设为255。

图像处理之形态学 - 图4

膨胀:待操作像素 上面矩阵 > =255,f(x,y) = 255。 ↑

腐蚀算法:
对于待操作的像素 f(x,y),只有 f(x,y-1) 、f(x,y+1) 、f(x-1,y) 、f(x+1,y) 都为255,则 f(x,y)=255。
换句话说:将待操作的图像像素与以下 4-近邻矩阵 相乘,结果小于255
4的话,将中心像素设为0。

图像处理之形态学 - 图5

腐蚀:待操作像素 上面矩阵 < 2554,f(x,y) = 0 。↑


python实现图像膨胀和腐蚀

  1. # Writer : wojianxinygcl@163.com
  2. # Date : 2020.3.21
  3. import cv2
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. # Gray scale
  7. def BGR2GRAY(img):
  8. b = img[:, :, 0].copy()
  9. g = img[:, :, 1].copy()
  10. r = img[:, :, 2].copy()
  11. # Gray scale
  12. out = 0.2126 * r + 0.7152 * g + 0.0722 * b
  13. out = out.astype(np.uint8)
  14. return out
  15. # Otsu Binalization
  16. def otsu_binarization(img, th=128):
  17. H, W = img.shape
  18. out = img.copy()
  19. max_sigma = 0
  20. max_t = 0
  21. # determine threshold
  22. for _t in range(1, 255):
  23. v0 = out[np.where(out < _t)]
  24. m0 = np.mean(v0) if len(v0) > 0 else 0.
  25. w0 = len(v0) / (H * W)
  26. v1 = out[np.where(out >= _t)]
  27. m1 = np.mean(v1) if len(v1) > 0 else 0.
  28. w1 = len(v1) / (H * W)
  29. sigma = w0 * w1 * ((m0 - m1) ** 2)
  30. if sigma > max_sigma:
  31. max_sigma = sigma
  32. max_t = _t
  33. # Binarization
  34. print("threshold >>", max_t)
  35. th = max_t
  36. out[out < th] = 0
  37. out[out >= th] = 255
  38. return out
  39. # Morphology Dilate
  40. def Morphology_Dilate(img, Dil_time=1):
  41. H, W = img.shape
  42. # kernel
  43. MF = np.array(((0, 1, 0),
  44. (1, 0, 1),
  45. (0, 1, 0)), dtype=np.int)
  46. # each dilate time
  47. out = img.copy()
  48. for i in range(Dil_time):
  49. tmp = np.pad(out, (1, 1), 'edge')
  50. for y in range(1, H):
  51. for x in range(1, W):
  52. if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) >= 255:
  53. out[y, x] = 255
  54. return out
  55. # Morphology Erode
  56. def Morphology_Erode(img, Erode_time=1):
  57. H, W = img.shape
  58. out = img.copy()
  59. # kernel
  60. MF = np.array(((0, 1, 0),
  61. (1, 0, 1),
  62. (0, 1, 0)), dtype=np.int)
  63. # each erode
  64. for i in range(Erode_time):
  65. tmp = np.pad(out, (1, 1), 'edge')
  66. # erode
  67. for y in range(1, H):
  68. for x in range(1, W):
  69. if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) < 255*4:
  70. out[y, x] = 0
  71. return out
  72. # Read image
  73. img = cv2.imread("../paojie.jpg").astype(np.float32)
  74. # Grayscale
  75. gray = BGR2GRAY(img)
  76. # Otsu's binarization
  77. otsu = otsu_binarization(gray)
  78. # Morphology - dilate
  79. erode_result = Morphology_Erode(otsu, Erode_time=2)
  80. dilate_result = Morphology_Dilate(otsu,Dil_time=2)
  81. # Save result
  82. cv2.imwrite("Black_and_white.jpg",otsu)
  83. cv2.imshow("Black_and_white",otsu)
  84. cv2.imwrite("erode_result.jpg", erode_result)
  85. cv2.imshow("erode_result", erode_result)
  86. cv2.imwrite("dilate_result.jpg", dilate_result)
  87. cv2.imshow("dilate_result",dilate_result)
  88. cv2.waitKey(0)
  89. cv2.destroyAllWindows()

三. 开/闭运算

先腐蚀后膨胀叫开运算(因为先腐蚀会分开物体,这样容易记住),其作用是:分离物体,消除小区域。
图像处理之形态学 - 图6
经验之谈:很多人对开闭运算的作用不是很清楚,但看上图↑,不用怕:如果我们的目标物体外面有很多无关的小区域,就用开运算去除掉;如果物体内部有很多小黑洞,就用闭运算填充掉。
为什么有了膨胀腐蚀还要开运算闭运算呢?其实开闭运算最重要的一点就是,可以保持物体原有大小。然后一个是消除物体内部孔洞的另一个是增强物体之间连接点的。

四.其他形态学操作

4.1 其他形态学操作

4.1.2 形态学梯度

膨胀图减去腐蚀图,dilation - erosion,这样会得到物体的轮廓:
图像处理之形态学 - 图7

4.2 基础形态学转换

4.2.1 腐蚀

cv2.erode(src, kernel, dst, anchor, iterations, borderType, borderValue)
src:输入图像
kernel:卷积核
dst:输出图像
anchor:核的基准点,默认为(-1, -1), 说明位于核的中心位置,基准点即kernel中与进行处理的像素点重合的点。
iterations:迭代次数
borderType:边界类型
borderValue:边界参数
腐蚀可以使目标区域范围“变小”,其实质造成图像的边界收缩,可以用来消除小且无意义的目标物。

4.2.3 膨胀

cv2.dilate(src, kernel, dst, anchor, iterations, borderType, borderValue)
同上
粗略地说,膨胀会使目标区域范围“变大”,将于目标区域接触的背景点合并到该目标物中,使目标边界向外部扩张。作用就是可以用来填补目标区域中某些空洞以及消除包含在目标区域中的小颗粒噪声。 膨胀也可以用来连接两个分开的物体。

4.2.4 高级形态学转换

cv2.morphologyEx(src, op, kernel, dst, anchor, iterations, borderType, borderValue)
同上
op:操作类型共5种

  • 开运算: cv2.MORPH_OPEN

    1. 先进性腐蚀再进行膨胀就叫做开运算。就像我们上面介绍的那样,它被用 来去除噪声。
  • 闭运算: cv2.MORPH_CLOSE

    1. 先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的小黑点。
  • 形态学梯度: cv2.MORPH_GRADIENT

    1. 结果看上去就像前景物体的轮廓。
  • 礼帽: cv2.MORPH_TOPHAT

    1. 原始图像与进行开运算之后得到的图像的差。
  • 黑帽: cv2.MORPH_BLACKHAT

    1. 进行闭运算之后得到的图像与原始图像的差。

它们与基础形态学转换之间的关系也可表示为:

Opening: dst = open(src, element) = dilate(erode(src, element), element)
Closing: dst = close{src, element) = erode(dilate(src, element), element)
Morphological gradient: dst = morph_grad(src, element) = dilate(src, element) - erode(src, element)
“Top hat”: dst = tophat(src, element) = src - open(src, element)
“Black hat”: dst = blackhat(src, element) = close(src, element) - src

五.形态学作用

膨胀与腐蚀能够实现以下作用:
1.消除噪声
2.分割出独立的图像元素,在图像中连接相邻的元素
3.寻找图像中的明显的极大值区域或者极小值区域
4.求出图像的梯度
需要注意之处: 腐蚀和膨胀都是对图像的白色部分(高亮部分)而言。膨胀是图像中的高亮部分进行膨胀,类似于领域扩张,效果图拥有比原图更大的高亮区域;腐蚀是原图的高亮部分被腐蚀,类似于领域被蚕食,效果图拥有比原图更小的高亮区域。
从数学的角度来说,膨胀和腐蚀操作就是将图像与核进行卷积,核可以是任意形状和大小的。


六. 参考内容:

  1. https://www.jianshu.com/p/ba2cec49c981
  2. https://www.cnblogs.com/yibeimingyue/p/10856439.html
  3. https://www.cnblogs.com/wojianxin/p/12542004.html
  4. https://blog.csdn.net/yukinoai/article/details/86762342

七. 版权声明:

未经作者允许,请勿随意转载抄袭,抄袭情节严重者,作者将考虑追究其法律责任,创作不易,感谢您的理解和配合!