图像分割是图像处理,计算机视觉领域里非常基础,非常重要的一个应用。今天介绍一种高效的分割算法,即 simple linear iterative clustering (SLIC) 算法,顾名思义,这是一种简单的迭代聚类算法,这个算法发表于 2012 年的 PAMI 上。
SLIC 算法有几个关键点,
1: 图像分割块的初始化,每一个图像块都是一个聚类,聚类的中心称为 superpixel,聚类的个数
2:聚类中心的初始化,在划分好的图像块里,随机采样一个点作为聚类的中心,为了避免采样的初始点是噪声或者是在边缘部分,算法做了一点变化,在采样点附近
3: 计算像素点到聚类中心的距离,图像分好块,选择好了每一个图像块的聚类中心,接下来就是计算图像中每一个像素点离聚类中心的距离了,这里与通常的聚类算法不一样,一般的聚类算法会计算像素点离每一个聚类中心的距离,换句话说,每一个聚类中心都要和所有的像素点计算距离,这个明显是费时,而且也是没有必要的,SLIC 算法简化了这一步,只计算每个聚类中心周围
为了可以衡量距离,这个算法考虑了 空间距离 和 颜色距离 两种:
算法最后衡量距离的形式如下所示:
在 CIELAB 颜色空间中,论文中提到 m 的取值范围大概是 [1, 40]
4:重新聚类,计算完距离之后,每一个像素点都会更新自己所属的图像块,将同一个图像块的像素点取平均,得到新的聚类中心,然后再重复前面的步骤,直到两次聚类中心的距离小于某个阈值。算法的流程图如下所示:
给出一段Python 的代码:
# import the necessary packages
from skimage.segmentation import slic
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float
from skimage import io
import matplotlib.pyplot as plt
# load the image and convert it to a floating point data type
image = img_as_float(io.imread("image.jpg"))
# loop over the number of segments
for numSegments in (100, 200, 300):
# apply SLIC and extract (approximately) the supplied number
# of segments
segments = slic(image, n_segments = numSegments, sigma = 5)
# show the output of SLIC
fig = plt.figure("Superpixels -- %d segments" % (numSegments))
ax = fig.add_subplot(1, 1, 1)
ax.imshow(mark_boundaries(image, segments))
plt.axis("off")
# show the plots
plt.show()