形态学滤波#

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

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

  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 0x7f115dac0c50>

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

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()

腐蚀#

形态学 erosion 将像素 (i, j) 设置为以 (i, j) 为中心的邻域中所有像素的最小值。传递给 erosion 的结构元素 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

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

膨胀#

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

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

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

开运算#

图像的形态学 opening 定义为腐蚀后跟膨胀。开运算可以去除小的亮斑(即“盐”)并连接小的暗裂纹。

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

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

闭运算#

图像的形态学 closing 定义为膨胀后跟腐蚀。闭运算可以去除小的暗斑(即“胡椒”)并连接小的亮裂纹。

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

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 形态学处理教程

2. 奥克兰大学形态学图像处理教程

  1. https://en.wikipedia.org/wiki/Mathematical_morphology

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

由 Sphinx-Gallery 生成图库