形态学滤波#

形态学图像处理是一组与图像中特征的形状或形态相关的非线性操作,例如边界、骨架等。在任何给定的技术中,我们使用一个称为结构元素的小形状或模板来探测图像,该结构元素定义了围绕像素的感兴趣区域或邻域。

在本文件中,我们概述了以下基本形态学操作:

  1. 侵蚀

  2. 膨胀

  3. 打开

  4. 关闭

  5. 白色礼帽

  6. 黑色礼帽

  7. 骨架化

  8. 凸包

要开始,让我们使用 io.imread 加载一张图像。请注意,形态学函数仅适用于灰度或二值图像,因此我们设置 as_gray=True

import matplotlib.pyplot as plt
from skimage import data
from skimage.util import img_as_ubyte

orig_phantom = img_as_ubyte(data.shepp_logan_phantom())
fig, ax = plt.subplots()
ax.imshow(orig_phantom, cmap=plt.cm.gray)
plot morphology
<matplotlib.image.AxesImage object at 0x17462ac10>

让我们也定义一个用于绘制比较的便利函数:

def plot_comparison(original, filtered, filter_name):
    fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(8, 4), sharex=True, sharey=True)
    ax1.imshow(original, cmap=plt.cm.gray)
    ax1.set_title('original')
    ax1.set_axis_off()
    ax2.imshow(filtered, cmap=plt.cm.gray)
    ax2.set_title(filter_name)
    ax2.set_axis_off()

侵蚀#

形态学 腐蚀 将像素 (i, j) 设置为以 (i, j) 为中心的邻域内所有像素的 最小值 。结构元素 footprint 传递给 腐蚀 是一个布尔数组,描述了这个邻域。下面,我们使用 disk 创建一个圆形结构元素,这在接下来的大多数示例中都会用到。

from skimage.morphology import erosion, dilation, opening, closing, white_tophat  # noqa
from skimage.morphology import black_tophat, skeletonize, convex_hull_image  # noqa
from skimage.morphology import disk  # noqa

footprint = disk(6)
eroded = erosion(orig_phantom, footprint)
plot_comparison(orig_phantom, eroded, 'erosion')
original, erosion

注意随着我们增加圆盘的大小,图像的白色边界是如何消失或被侵蚀的。还要注意中心两个黑色椭圆的大小增加,以及图像下部三个浅灰色斑块的消失。

膨胀#

形态学 膨胀 将位于 (i, j) 的像素设置为 以 (i, j) 为中心的邻域内所有像素的最大值 。膨胀会扩大明亮的区域并缩小暗的区域。

dilated = dilation(orig_phantom, footprint)
plot_comparison(orig_phantom, dilated, 'dilation')
original, dilation

注意图像的白色边界如何随着我们增加圆盘的大小而变厚,或者说膨胀。同时注意中心两个黑色椭圆的大小减小,以及中心浅灰色圆圈和图像下半部分三个斑块的加厚。

打开#

图像上的形态学 opening 定义为 腐蚀后跟膨胀 。Opening 可以去除小的亮点(即“盐”)并连接小的暗裂缝。

opened = opening(orig_phantom, footprint)
plot_comparison(orig_phantom, opened, 'opening')
original, opening

由于 opening 图像操作从腐蚀操作开始,小于结构元素的亮区域将被移除。随后的膨胀操作确保大于结构元素的亮区域保留其原始大小。注意中心的光暗形状如何保持其原始厚度,但底部的3个较亮斑块被完全腐蚀。外部的白色环突出了尺寸依赖性:比结构元素薄的环部分被完全擦除,而顶部较厚的区域保留其原始厚度。

关闭#

图像上的形态学 闭合 被定义为 膨胀后跟腐蚀 。闭合可以去除小暗点(即“胡椒”)并连接小的明亮裂缝。

为了更清楚地说明这一点,让我们在白色边框上添加一个小裂缝:

phantom = orig_phantom.copy()
phantom[10:30, 200:210] = 0

closed = closing(phantom, footprint)
plot_comparison(phantom, closed, 'closing')
original, closing

由于 closing 图像操作从膨胀操作开始,小于结构元素的暗区域会被移除。随后的膨胀操作确保大于结构元素的暗区域保留其原始大小。注意底部白色椭圆如何因膨胀而连接,但其他暗区域保留其原始大小。还要注意我们添加的裂缝如何大部分被移除。

白色礼帽#

图像的 white_tophat 定义为 图像减去其形态学开运算 。此操作返回图像中比结构元素小的亮点。

为了让事情变得有趣,我们会在图像中添加亮斑和暗斑:

phantom = orig_phantom.copy()
phantom[340:350, 200:210] = 255
phantom[100:110, 200:210] = 0

w_tophat = white_tophat(phantom, footprint)
plot_comparison(phantom, w_tophat, 'white tophat')
original, white tophat

如你所见,10像素宽的白色方块被高亮显示,因为它比结构元素小。此外,椭圆周围的大部分细白边被保留,因为它们比结构元素小,但顶部的较厚区域消失了。

黑色礼帽#

图像的 black_tophat 定义为其形态学 闭运算减去原始图像 。此操作返回图像中 小于结构元素的暗斑

b_tophat = black_tophat(phantom, footprint)
plot_comparison(phantom, b_tophat, 'black tophat')
original, black tophat

如你所见,10像素宽的黑色方块被高亮显示,因为它比结构元素小。

二重性

正如你应该注意到的,这些操作中的许多只是另一个操作的逆操作。这种对偶性可以总结如下:

  1. 侵蚀 <-> 膨胀

  2. 打开 <-> 关闭

  3. 白色礼帽 <-> 黑色礼帽

骨架化#

细化用于将二值图像中的每个连通分量减少为一个 单像素宽的骨架 。需要注意的是,这仅在二值图像上执行。

horse = data.horse()

sk = skeletonize(horse == 0)
plot_comparison(horse, sk, 'skeletonize')
original, skeletonize

顾名思义,这项技术通过连续应用细化操作,将图像细化到1像素宽的骨架。

凸包#

convex_hull_image包含在包围输入图像中所有白色像素的最小凸多边形内的像素集合。再次注意,这也是在二值图像上执行的。

hull1 = convex_hull_image(horse == 0)
plot_comparison(horse, hull1, 'convex hull')
original, convex hull

如图所示,convex_hull_image 给出了覆盖图像中白色或True部分的最小多边形。

如果我们向图像中添加一个小颗粒,我们可以看到凸包如何适应以包围该颗粒:

horse_mask = horse == 0
horse_mask[45:50, 75:80] = 1

hull2 = convex_hull_image(horse_mask)
plot_comparison(horse_mask, hull2, 'convex hull')
original, convex hull

附加资源#

1. MathWorks tutorial on morphological processing

2. Auckland university’s tutorial on Morphological Image Processing

  1. https://en.wikipedia.org/wiki/数学形态学

脚本总运行时间: (0 分钟 0.711 秒)

由 Sphinx-Gallery 生成的图库