SLIC算法分割超像素原理及Python实现

为了从NYU数据集中得到分割标签,尝试用12年的SLIC算法,加上以关节点为中心的分割结果。

  • SLIC

原始链接

整个算法的输入只有一个,即超像素的个数K。图片原有N个像素,要分割成K个像素,那么每个像素的大小是N/K。超像素之间的距离(即规则情况下超像素的边长)就是S=√N/K。我们的目标是使代价函数(cost function)最小。具体到本算法中,就是每个像素到所属的中心点的距离之和最小。

SLIC算法步骤

  1. 撒种子。将K个超像素中心分布到图像的像素点上。
  2. 微调种子的位置。以K为中心的3×3范围内,移动超像素中心到这9个点中梯度最小的点上。这样是为了避免超像素点落到噪点或者边界上。
  3. 初始化数据。取一个数组label保存每一个像素点属于哪个超像素。dis数组保存像素点到它属于的那个超像素中心的距离。
  4. 对每一个超像素中心x,它2S范围内的点:如果点到超像素中心x的距离(5维)小于这个点到它原来属于的超像素中心的距离,那么说明这个点属于超像素x。更新dis,更新label。
  5. 对每一个超像素中心,重新计算它的位置。
  6. 重复4 5 两步。

代码阅读

(1)先创建一个对象p

  • 图片存储在data中
  • N是像素数量
  • K是超像素数量
  • S是超像素边长(以像素为单位)
  • dis存储每个像素与超像素的距离

SLIC算法分割超像素原理及Python实现_第1张图片

值得注意的是这里用到了Lab颜色空间,data中存储图像时做了一个RGB到Lab的转换Lab

SLIC算法分割超像素原理及Python实现_第2张图片

(2)执行初始化init_clusters()

将K个超像素中心分布到图像的像素点上,在clusters中存储超像素的像素坐标和像素值。

    def make_cluster(self, h, w):
        return Cluster(h, w,
                       self.data[h][w][0],
                       self.data[h][w][1],
                       self.data[h][w][2])

前两个是坐标,后面是该点的RGB像素值

SLIC算法分割超像素原理及Python实现_第3张图片

(3)微调种子的位置——执行move_clusters

    def move_clusters(self):
        for cluster in self.clusters:
            cluster_gradient = self.get_gradient(cluster.h, cluster.w)
            for dh in range(-1, 2):
                for dw in range(-1, 2):
                    _h = cluster.h + dh
                    _w = cluster.w + dw
                    new_gradient = self.get_gradient(_h, _w)
                    if new_gradient < cluster_gradient:
                        cluster.update(_h, _w, self.data[_h][_w][0], self.data[_h][_w][1], self.data[_h][_w][2])
                        cluster_gradient = new_gradient

(4)初始化数据。取一个数组label保存每一个像素点属于哪个超像素。dis数组保存像素点到它属于的那个超像素中心的距离。(十分耗时)

首先从clusters中取出一个超像素

上下左右画一个边长为超像素4倍的正方形(越界的排除)

对于正方形中的每个像素点,计算一个基于3+2维向量的距离

如果距离小于dis矩阵中保存的该像素点到对应超像素的距离

  • 更新dis矩阵中的值。
  • 更新label矩阵,保存该点的超像素
  • 在超像素数组中保存该点

SLIC算法分割超像素原理及Python实现_第4张图片

(5)对于每个超像素,遍历所有属于这个超像素的像素点,让超像素位于正中间。

你可能感兴趣的:(机器学习)