形态滤波

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

在本文档中,我们概述了以下基本的形态运算:

  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
from skimage import io

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

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

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.axis('off')
    ax2.imshow(filtered, cmap=plt.cm.gray)
    ax2.set_title(filter_name)
    ax2.axis('off')

侵蚀

形态 erosion 将(i,j)处的像素设置为 在以(i,j)为中心的邻域中的所有像素上的最小值 。结构元素, selem ,传递给 erosion 是描述此邻域的布尔数组。下面,我们使用 disk 创建圆形结构元素,我们在下面的大多数示例中都使用了该元素。

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

selem = disk(6)
eroded = erosion(orig_phantom, selem)
plot_comparison(orig_phantom, eroded, 'erosion')
original, erosion
请注意图像的白色边界是如何消失或被侵蚀的

增加磁盘的大小。还请注意,图像中央的两个黑色椭圆的大小增加了,而图像下部的3个浅灰色斑块消失了。

扩张

形态 dilation 将(i,j)处的像素设置为 以(i,j)为中心的邻域中的所有像素的最大值 。扩张会放大亮区,缩小暗区。

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

请注意,随着磁盘大小的增加,图像的白色边界如何变厚或变大。还可以注意到中心的两个黑色椭圆形的尺寸减小,以及中心的浅灰色圆圈和图像下部的3个补丁变厚。

打开

形态 opening 在图像上被定义为 先是侵蚀然后是膨胀 。开口可以去除小亮点(即“盐”),并连接小的黑色裂缝。

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

因为 opening 图像从侵蚀操作开始,光区域是 更小的 则结构元素被移除。接下来的扩张操作确保了 更大 则结构元素保持其原始大小。注意中心的浅色和深色形状的原始厚度,但底部的3个较浅的补丁完全被侵蚀。外部的白色环突出了尺寸相关性:环的比结构元素薄的部分被完全擦除,而顶部较厚的区域保持其原始厚度。

结业

形态 closing 在图像上被定义为 先膨胀后侵蚀 。闭合可以去除小黑点(即“胡椒”),并连接小的明亮裂缝。

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

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

closed = closing(phantom, selem)
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, selem)
plot_comparison(phantom, w_tophat, 'white tophat')
original, white tophat

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

黑色大礼帽

这个 black_tophat 定义为图像的形态 关闭时不带原始图像 。此操作返回 图像中比结构元素小的暗点

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

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

Duality

正如您应该注意到的,这些操作中的许多操作只是与另一个操作相反。这种二元性可以概括为:

  1. 侵蚀<->膨胀

  2. 打开<->关闭

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

框架化

细化用于将二值图像中的每个连通分量减少到 single-pixel wide skeleton 。重要的是要注意,这只在二进制图像上执行。

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的最小多边形。

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

import numpy as np

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/Mathematical_morphology

脚本的总运行时间: (0分0.954秒)

Gallery generated by Sphinx-Gallery