分割和超像素算法比较#

此示例比较了四种流行的低级图像分割方法。由于难以获得良好的分割结果,并且“良好”的定义通常取决于应用,因此这些方法通常用于获得过度分割,也称为超像素。这些超像素随后作为更复杂的算法(例如条件随机场 (CRF))的基础。

Felzenszwalb 的高效基于图的分割#

这种快速的二维图像分割算法,在 [1] 中提出,在计算机视觉领域很流行。该算法只有一个 scale 参数,它会影响段的大小。实际的段大小和数量可能差异很大,具体取决于局部对比度。

Quickshift 图像分割#

Quickshift 是一种相对较新的二维图像分割算法,基于核化均值漂移的近似。因此,它属于局部模式搜索算法家族,并应用于包含颜色信息和图像位置的 5D 空间 [2]

Quickshift 的优点之一是它实际上可以同时在多个尺度上计算分层分割。

Quickshift 具有两个主要参数:sigma 控制局部密度近似的尺度,max_dist 选择生成的层次分割中的一个级别。还有一个颜色空间距离和图像空间距离之间的权衡,由 ratio 给出。

SLIC - 基于 K-Means 的图像分割#

此算法仅在颜色信息和图像位置的 5d 空间中执行 K-means,因此与 quickshift 密切相关。由于聚类方法更简单,因此非常高效。对于此算法,在 Lab 颜色空间中工作以获得良好的结果至关重要。该算法迅速发展,现在被广泛使用。有关详细信息,请参见 [3]compactness 参数权衡颜色相似性和邻近性,就像 Quickshift 一样,而 n_segments 选择 kmeans 的中心数量。

梯度图像的紧凑分水岭分割#

分水岭算法不是将彩色图像作为输入,而是需要一个灰度梯度图像,其中明亮的像素表示区域之间的边界。该算法将图像视为一个景观,其中明亮的像素形成高峰。然后从给定的标记开始淹没该景观,直到不同的洪水盆地相遇在山峰处。每个不同的盆地然后形成一个不同的图像段。 [4]

与 SLIC 一样,还有一个额外的紧凑性参数,它使标记难以淹没远处的像素。这使得分水岭区域形状更规则。 [5]

Felzenszwalbs's method, SLIC, Quickshift, Compact watershed
Felzenszwalb number of segments: 194
SLIC number of segments: 196
Quickshift number of segments: 695
Watershed number of segments: 256

import matplotlib.pyplot as plt
import numpy as np

from skimage.data import astronaut
from skimage.color import rgb2gray
from skimage.filters import sobel
from skimage.segmentation import felzenszwalb, slic, quickshift, watershed
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float

img = img_as_float(astronaut()[::2, ::2])

segments_fz = felzenszwalb(img, scale=100, sigma=0.5, min_size=50)
segments_slic = slic(img, n_segments=250, compactness=10, sigma=1, start_label=1)
segments_quick = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5)
gradient = sobel(rgb2gray(img))
segments_watershed = watershed(gradient, markers=250, compactness=0.001)

print(f'Felzenszwalb number of segments: {len(np.unique(segments_fz))}')
print(f'SLIC number of segments: {len(np.unique(segments_slic))}')
print(f'Quickshift number of segments: {len(np.unique(segments_quick))}')
print(f'Watershed number of segments: {len(np.unique(segments_watershed))}')

fig, ax = plt.subplots(2, 2, figsize=(10, 10), sharex=True, sharey=True)

ax[0, 0].imshow(mark_boundaries(img, segments_fz))
ax[0, 0].set_title("Felzenszwalbs's method")
ax[0, 1].imshow(mark_boundaries(img, segments_slic))
ax[0, 1].set_title('SLIC')
ax[1, 0].imshow(mark_boundaries(img, segments_quick))
ax[1, 0].set_title('Quickshift')
ax[1, 1].imshow(mark_boundaries(img, segments_watershed))
ax[1, 1].set_title('Compact watershed')

for a in ax.ravel():
    a.set_axis_off()

plt.tight_layout()
plt.show()

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

由 Sphinx-Gallery 生成的图库