精华内容
下载资源
问答
  • 超像素经典 SLIC 算法 python 实现
    千次阅读
    2020-02-10 09:17:50

    在这里插入图片描述

    摘要

    本文是研究生课程图像处理期末作业,内容是了解并入门超像素算法原理,主要介绍了超像素的评测标准,经典算法 SLIC,讨论了 SLIC 算法中的不足之处,以及 SLIC 的两个有效的改进算法 SEEDS 和 ETPS。
    文章内容见我的码云

    python3 代码

    运算速度慢但是便于理清 SLIC 算法的参考实现

    import math
    from skimage import io, color
    import numpy as np
    from tqdm import trange
    from tqdm import tqdm
    
    class Cluster(object):
        cluster_index = 1
    
        def __init__(self, h, w, l=0, a=0, b=0):
            self.update(h, w, l, a, b)
            self.pixels = []
            self.no = self.cluster_index
            Cluster.cluster_index += 1
    
        def update(self, h, w, l, a, b):
            self.h = h
            self.w = w
            self.l = l
            self.a = a
            self.b = b
    
        def __str__(self):
            return "{},{}:{} {} {} ".format(self.h, self.w, self.l, self.a, self.b)
    
        def __repr__(self):
            return self.__str__()
    
    
    class SLICProcessor(object):
        @staticmethod
        def open_image(path):
            """
            Return:
                3D array, row col [LAB]
            """
            rgb = io.imread(path)
            lab_arr = color.rgb2lab(rgb)
            return lab_arr
    
        @staticmethod
        def save_lab_image(path, lab_arr):
            """
            Convert the array to RBG, then save the image
            :param path:
            :param lab_arr:
            :return:
            """
            rgb_arr = color.lab2rgb(lab_arr)
            io.imsave(path, rgb_arr)
    
        def make_cluster(self, h, w):
            h = int(h)
            w = int(w)
            return Cluster(h, w,
                           self.data[h][w][0],
                           self.data[h][w][1],
                           self.data[h][w][2])
    
        def __init__(self, filename, K, M):
            self.K = K
            self.M = M
    
            self.data = self.open_image(filename)
            self.image_height = self.data.shape[0]
            self.image_width = self.data.shape[1]
            self.N = self.image_height * self.image_width
            self.S = int(math.sqrt(self.N / self.K))
    
            self.clusters = []
            self.label = {}
            self.dis = np.full((self.image_height, self.image_width), np.inf)
    
        def init_clusters(self):
            h = self.S // 2
            w = self.S // 2
            while h < self.image_height:
                while w < self.image_width:
                    self.clusters.append(self.make_cluster(h, w))
                    w += self.S
                w = self.S // 2
                h += self.S
    
        def get_gradient(self, h, w):
            if w + 1 >= self.image_width:
                w = self.image_width - 2
            if h + 1 >= self.image_height:
                h = self.image_height - 2
    
            gradient = self.data[h + 1][w + 1][0] - self.data[h][w][0] + \
                       self.data[h + 1][w + 1][1] - self.data[h][w][1] + \
                       self.data[h + 1][w + 1][2] - self.data[h][w][2]
            return gradient
    
        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
    
        def assignment(self):
            for cluster in tqdm(self.clusters):
                for h in range(cluster.h - 2 * self.S, cluster.h + 2 * self.S):
                    if h < 0 or h >= self.image_height: continue
                    for w in range(cluster.w - 2 * self.S, cluster.w + 2 * self.S):
                        if w < 0 or w >= self.image_width: continue
                        L, A, B = self.data[h][w]
                        Dc = math.sqrt(
                            math.pow(L - cluster.l, 2) +
                            math.pow(A - cluster.a, 2) +
                            math.pow(B - cluster.b, 2))
                        Ds = math.sqrt(
                            math.pow(h - cluster.h, 2) +
                            math.pow(w - cluster.w, 2))
                        D = math.sqrt(math.pow(Dc / self.M, 2) + math.pow(Ds / self.S, 2))
                        if D < self.dis[h][w]:
                            if (h, w) not in self.label:
                                self.label[(h, w)] = cluster
                                cluster.pixels.append((h, w))
                            else:
                                self.label[(h, w)].pixels.remove((h, w))
                                self.label[(h, w)] = cluster
                                cluster.pixels.append((h, w))
                            self.dis[h][w] = D
    
        def update_cluster(self):
            for cluster in self.clusters:
                sum_h = sum_w = number = 0
                for p in cluster.pixels:
                    sum_h += p[0]
                    sum_w += p[1]
                    number += 1
                _h = int(sum_h / number)
                _w = int(sum_w / number)
                cluster.update(_h, _w, self.data[_h][_w][0], self.data[_h][_w][1], self.data[_h][_w][2])
    
        def save_current_image(self, name):
            image_arr = np.copy(self.data)
            for cluster in self.clusters:
                for p in cluster.pixels:
                    image_arr[p[0]][p[1]][0] = cluster.l
                    image_arr[p[0]][p[1]][1] = cluster.a
                    image_arr[p[0]][p[1]][2] = cluster.b
                image_arr[cluster.h][cluster.w][0] = 0
                image_arr[cluster.h][cluster.w][1] = 0
                image_arr[cluster.h][cluster.w][2] = 0
            self.save_lab_image(name, image_arr)
    
        def iterate_10times(self):
            self.init_clusters()
            self.move_clusters()
            for i in trange(10):
                self.assignment()
                self.update_cluster()
                name = 'lenna_M{m}_K{k}_loop{loop}.png'.format(loop=i, m=self.M, k=self.K)
                self.save_current_image(name)
    
    
    if __name__ == '__main__':
        p = SLICProcessor('kemomimi.png', 500, 40)
        p.iterate_10times()
    
    

    将上面缓慢的循环体转化成 numpy 高速矩阵运算的参考实现,很有 python 优化计算的学习意义。
    作者原本是有一段合并不连续的超像素的函数( SLIC 可选的后期处理),发现并没有用到,就去掉了。

    # Aleena Watson
    # Final Project - Computer Vision Simon Niklaus
    # Winter 2018 - PSU
    
    import numpy as np
    import sys
    from skimage import io, color
    import tqdm
    
    # using algorithm in 3.2 apply image gradients as computed in eq2:
    # G(x,y) = ||I(x+1,y) - I(x-1,y)||^2+ ||I(x,y+1) - I(x,y-1)||^2
    
    # SLIC implements a special case of k-means clustering algorithm. 
    # Was recommended to use an off the shelf algorithm for clustering but
    # because this algorithm is based on this special case of k-means, 
    # I kept this implementation to stay true to the algorithm.
    
    def generate_pixels():
        indnp = np.mgrid[0:SLIC_height,0:SLIC_width].swapaxes(0,2).swapaxes(0,1)
        for i in tqdm.tqdm(range(SLIC_ITERATIONS)):
            SLIC_distances = 1 * np.ones(img.shape[:2])
            for j in range(SLIC_centers.shape[0]):
                x_low, x_high = int(SLIC_centers[j][3] - step), int(SLIC_centers[j][3] + step)
                y_low, y_high = int(SLIC_centers[j][4] - step), int(SLIC_centers[j][4] + step)
    
                if x_low <= 0:
                    x_low = 0
                #end
                if x_high > SLIC_width:
                    x_high = SLIC_width
                #end
                if y_low <=0:
                    y_low = 0
                #end
                if y_high > SLIC_height:
                    y_high = SLIC_height
                #end
    
                cropimg = SLIC_labimg[y_low : y_high , x_low : x_high]
                color_diff = cropimg - SLIC_labimg[int(SLIC_centers[j][4]), int(SLIC_centers[j][3])]
                color_distance = np.sqrt(np.sum(np.square(color_diff), axis=2))
    
                yy, xx = np.ogrid[y_low : y_high, x_low : x_high]
                pixdist = ((yy-SLIC_centers[j][4])**2 + (xx-SLIC_centers[j][3])**2)**0.5
    
                # SLIC_m is "m" in the paper, (m/S)*dxy
                dist = ((color_distance/SLIC_m)**2 + (pixdist/step)**2)**0.5
    
                distance_crop = SLIC_distances[y_low : y_high, x_low : x_high]
                idx = dist < distance_crop
                distance_crop[idx] = dist[idx]
                SLIC_distances[y_low : y_high, x_low : x_high] = distance_crop
                SLIC_clusters[y_low : y_high, x_low : x_high][idx] = j
            #end
    
            for k in range(len(SLIC_centers)):
                idx = (SLIC_clusters == k)
                colornp = SLIC_labimg[idx]
                distnp = indnp[idx]
                SLIC_centers[k][0:3] = np.sum(colornp, axis=0)
                sumy, sumx = np.sum(distnp, axis=0)
                SLIC_centers[k][3:] = sumx, sumy
                SLIC_centers[k] /= np.sum(idx)
            #end
        #end
    #end
    
    def display_contours(color):
        rgb_img = img.copy()
        is_taken = np.zeros(img.shape[:2], np.bool)
        contours = []
    
        for i in range(SLIC_width):
            for j in range(SLIC_height):
                nr_p = 0
                for dx, dy in [(-1,0), (-1,-1), (0,-1), (1,-1), (1,0), (1,1), (0,1), (-1,1)]:
                    x = i + dx
                    y = j + dy
                    if x>=0 and x < SLIC_width and y>=0 and y < SLIC_height:
                        if is_taken[y, x] == False and SLIC_clusters[j, i] != SLIC_clusters[y, x]:
                            nr_p += 1
                        #end
                    #end
                #end
    
                if nr_p >= 2:
                    is_taken[j, i] = True
                    contours.append([j, i])
                #end
            #end
        #end
        for i in range(len(contours)):
            rgb_img[contours[i][0], contours[i][1]] = color
        # for k in range(SLIC_centers.shape[0]):
        #     i,j = SLIC_centers[k][-2:]
        #     img[int(i),int(j)] = (0,0,0)
        #end
        io.imsave("SLIC_contours.jpg", rgb_img)
    
        return rgb_img
    #end
    
    def display_center():
        '''
        将超像素用聚类中心颜色代替
        '''
        import matplotlib.pyplot as plt
    
        lab_img = np.zeros([SLIC_height,SLIC_width,3]).astype(np.float64)
        for i in range(SLIC_width):
            for j in range(SLIC_height):
                k = int(SLIC_clusters[j, i])
                lab_img[j,i] = SLIC_centers[k][0:3]
        rgb_img = color.lab2rgb(lab_img)
        io.imsave("SLIC_centers.jpg",rgb_img)
        return (rgb_img*255).astype(np.uint8)
    
    def find_local_minimum(center):
        min_grad = 1
        loc_min = center
        for i in range(center[0] - 1, center[0] + 2):
            for j in range(center[1] - 1, center[1] + 2):
                c1 = SLIC_labimg[j+1, i]
                c2 = SLIC_labimg[j, i+1]
                c3 = SLIC_labimg[j, i]
                if ((c1[0] - c3[0])**2)**0.5 + ((c2[0] - c3[0])**2)**0.5 < min_grad:
                    min_grad = abs(c1[0] - c3[0]) + abs(c2[0] - c3[0])
                    loc_min = [i, j]
                #end
            #end
        #end
        return loc_min
    #end
    
    def calculate_centers():
        centers = []
        for i in range(step, SLIC_width - int(step/2), step):
            for j in range(step, SLIC_height - int(step/2), step):
                nc = find_local_minimum(center=(i, j))
                color = SLIC_labimg[nc[1], nc[0]]
                center = [color[0], color[1], color[2], nc[0], nc[1]]
                centers.append(center)
            #end
        #end
    
        return centers
    #end
    
    # global variables
    img = io.imread(sys.argv[1])
    print(img.max(),img.min())
    step = int((img.shape[0]*img.shape[1]/int(sys.argv[2]))**0.5)
    SLIC_m = int(sys.argv[3])
    SLIC_ITERATIONS = 4
    SLIC_height, SLIC_width = img.shape[:2]
    SLIC_labimg = color.rgb2lab(img)
    SLIC_distances = 1 * np.ones(img.shape[:2])
    SLIC_clusters = -1 * SLIC_distances
    SLIC_center_counts = np.zeros(len(calculate_centers()))
    SLIC_centers = np.array(calculate_centers())
    
    # main
    generate_pixels()
    calculate_centers()
    img_contours = display_contours([0.0, 0.0, 0.0])
    img_center = display_center()
    
    print(img,img_center,img_contours)
    result = np.hstack([img,img_contours,img_center])
    io.imsave("my_slic.jpg",result)
    
    更多相关内容
  • SLIC算法

    2021-09-06 16:05:09
    在介绍SLIC之前,先来介绍以下Lab颜色空间的介绍。 Lab色彩模型是由亮度(L)要素和与有关色彩的a,b要素组成,L的值由0(黑色)到100(白色),a表示从洋红色至绿色的范围(a为负值表示绿色而正值表示品红),b表示从黄色至...

    基础知识

    在介绍SLIC之前,先来介绍以下Lab颜色空间的介绍。

    Lab色彩模型是由亮度(L)要素和与有关色彩的a,b要素组成,L的值由0(黑色)到100(白色),a表示从洋红色至绿色的范围(a为负值表示绿色而正值表示品红),b表示从黄色至蓝色的范围(b为负值表示蓝色而正值表示黄色)。

    Lab颜色空间的优点:
    1)不像RGB和CMYK色彩空间,Lab颜色被设计来接近人类生理视觉。它致力于感知均匀性,它的L分量密切匹配人类亮度感知。因此可以被用来通过修改a和b分量的输出色阶来做精确的颜色平衡,或使用L分量来调整亮度对比。这些变换在RGB或CMYK种是困难的或不可能的。
    2)色域宽广。它不仅包含了RGB、CMYK的所有色域,还能表现他们不能表现得色彩。人的肉眼能感知的色彩,都能通过Lab模型表现出来。另外,Lab色彩模型的绝妙之处还在于它弥补了RGB色彩模型色彩分布不均的不足,因为RGB模型在蓝色到绿色之间的过渡色彩过多,而在绿色到红色之间又缺少黄色和其他色彩。
    3)Lab空间内的很多“颜色”超出了人类视觉的视域,因此纯粹是假想的;这些“颜色”不能在物理世界中再生。通过颜色管理软件,比如内置于图象编辑应用程序中的那些软件,可以选择最接近的色域内近似,在处理中变换亮度、彩度甚至色相。Dan Margulis称,在图象操作的多个步骤之间使用假想色是很有用的。

    算法思想

    SLIC算法时simple linear iterative cluster的简称,主要是将图像从RGB颜色空间转换到CIE-Lab颜色空间,对应每个像素的(L,a,b)颜色值和(x,y)坐标组成一个5维向量V[I,a,b,x,y],两个像素的相似性即可由他们的向量距离来度量,距离越大,相似性越小。

    该算法与K-means聚类算法思路类似,首先生成K个种子点,然后在每个种子点的周围空间里搜索距离该种子点最近的若干像素,将他们归为与该种子点一类,直到所有像素点都归类完毕。然后计算这K个超像素里所有像素点的平均向量值,重新得到K个聚类中心,然后再以这K个中心去搜索其周围与其最为相似的若干像素,所有像素都归类完重新得到K个超像素,更新聚类中心,在此迭代,如此反复直到收敛。

    具体算法步骤

    在这里插入图片描述
    1.初始化聚类中心:按照预先设定的超像素个数,在图像内均匀的分配聚类中心。如果图像有N个像素点,预分割为K个相同尺寸的超像素,那么每个超像素的大小为N/K,则相邻聚类中心的距离(步长)近似为 S = sqrt(N/K);
    2.在聚类中心的n×n邻域内重新选择聚类中心(一般n取3)。具体方法为:计算该邻域内所有像素点的梯度值,将聚类中心移动到该邻域内梯度最小的地方。这样做的目的是为了避免中心点落在梯度较大1的轮廓边界上,以免影响后续聚类效果;
    3.在每个聚类中心周围的邻域内为每个像素点分配类标签(即属于哪个聚类中心)。(期望的超像素尺寸为S×S,但其搜索范围为2S×2S);
    4.计算搜索点到聚类中心的距离度量(包括颜色距离和空间距离);
    在这里插入图片描述
    其中,d c c c代表颜色距离,d s s s代表空间距离,N s s s是类内最大空间距离,定义N s s s=sqrt(N/K),适用于每个聚类,最大颜色距离N c c c随图片不同而不同,也随聚类不同而不同,所以一般取一个固定常数(取值范围[1-40],一般取10)代替。最终的距离测度D‘如下:
    在这里插入图片描述
    由于每个像素点都会被多个种子点搜索到,所以每个像素点都会有一个与周围种子点的距离,取最小值对应的种子点作为该像素点的聚类中心。
    5.直到每个像素点聚类中心不再发生变化停止迭代(实践发现10次迭代绝大部分图片都可以得到较理想效果);
    6.增强连通性:经过上述迭代优化可能会出现出现多连通、超像素尺寸过小,单个超像素被切割为多个不连续超像素等等问题,而这些情况可以通过增强连通性来解决。主要思路在于:新建一张标记表,表内元素均为-1,按照“Z”型走向(从左到右、从上到下顺序)将不连续的超像素、尺寸过小超像素重新分配给临近的超像素,遍历果的像素点分配给相应的标签,直到所有点遍历完毕为止。

    SLIC主要优点

    1)生成的超像素如同细胞一般紧凑整齐,邻域特征比较容易表达。这样基于像素的方法可以比较容易的改造为基于超像素的方法。
    2)不仅可以分割彩色图,也可以兼容分割灰度图。
    3)需要设置的参数非常少,默认情况下只需要设置一个预分割的超像素的数量。
    4)相比其他的超像素分割方法,SLIC在运行速度、生成超像素的紧凑度、轮廓保持方面都比较理想。

    以下是论文中的效果图
    在这里插入图片描述

    自己实现的效果图:
    在这里插入图片描述

    展开全文
  • 本文是研究生课程图像处理期末作业,内容是了解并入门超像素算法原理,主要介绍了超像素的评测标准,经典算法 SLIC,讨论了 SLIC 算法中的不足之处,以及 SLIC 的两个有效的改进算法 SEEDS 和 ETPS。
  • SLIC.m为SLIC算法的实现 是一个function函数 FindAroundLine.m是用来将超像素块画边界线的function函数 SLIC.m和FindAroundLine.m都不用运行,把他放在和RunMe同一个路径下就行 注意在运行RunMe.m脚本时,要将...
  • 最简单的SLIC算法实现

    千次阅读 2021-11-20 14:25:00
    通过OpenCV实现SLIC超分辨率图像重建,极其简单,极其方便,道理浅显易懂。

    超像素由一系列位置相邻且颜色、亮度、纹理等特征相似的像素点组成的小区域。这些小区域大多保留了进一步进行图像分割的有效信息,且一般不会破坏图像中物体的边界信息,用少量的超像素代替大量像素表达图像特征,降低了图像处理的复杂度,一般作为分割算法的预处理步骤。

    SLIC算法生成的像素块相对紧凑,领域特征容易表达;同时需要设置调整的参数少,操作简单,速度快,对于图像的紧凑度、轮廓保持拥有很好的效果;兼容灰度图和彩色图的分割。

    代码如下:

    import cv2 as cv
    
    img = cv.imread("reba.jpg")
    # 初始化slic项,region_size设置分割图片尺寸大小 ruler设置平滑因子
    slic = cv.ximgproc.createSuperpixelSLIC(img,region_size=10, ruler=20.0)
    slic.iterate(10)    # 设置迭代次数,迭代次数相对来说越大越好
    mask_slic = slic.getLabelContourMask()  # 获取Mask,超像素边缘Mask==1
    mask_inv_slic = cv.bitwise_not(mask_slic)  # 对mask_slic进行逻辑取反运算
    img_slic = cv.bitwise_and(img, img, mask=mask_inv_slic)  # 在原图上绘制超像素边界
    cv.imshow("img_slic", img_slic)
    cv.waitKey(0)
    cv.imwrite('./SLIC.jpg', img_slic)
    cv.destroyAllWindows()
    
    

    运行结果如下:

    如果不懂代码可以尝试输出mask_slic和mask_inv_slic的图像,就明白了是怎么分割的了。

    代码如下:

    import cv2 as cv
    
    img = cv.imread("reba.jpg")
    # 初始化slic项,region_size设置分割图片尺寸大小 ruler设置平滑因子
    slic = cv.ximgproc.createSuperpixelSLIC(img,region_size=10, ruler=20.0)
    slic.iterate(10)    # 设置迭代次数,迭代次数相对来说越大越好
    mask_slic = slic.getLabelContourMask()  # 获取Mask,超像素边缘Mask==1
    
    # 显示mask_slic图像
    cv.imshow('mask_slic', mask_slic)
    cv.waitKey(0)
    cv.destroyAllWindows()
    mask_inv_slic = cv.bitwise_not(mask_slic)  # 对mask_slic进行逻辑取反运算
    
    # 显示mask_inv_slic图像
    cv.imshow('mask_inv_slic',mask_inv_slic)
    cv.waitKey(0)
    cv.destroyAllWindows()
    
    img_slic = cv.bitwise_and(img, img, mask=mask_inv_slic)  # 对边界和原图进行与运算,在原图上绘制超像素边界
    cv.imshow("img_slic", img_slic)
    cv.waitKey(0)
    cv.imwrite('./SLIC.jpg', img_slic)
    cv.destroyAllWindows()
    
    

    输出mask_slic图片如下:

     对mask_slic取反后的结果图片mask_inv_slic图像如下:

    其实在我理解OpenCV实现SLIC算法的过程就是先对图像绘制出分割图像,在进行逻辑运算绘制在原图上,对原图实现SLIC超分辨率重建算法。

    展开全文
  • SLIC算法.pptx

    2022-05-07 13:39:00
    SLIC算法.pptx
  • SLIC图像superpixel的C++代码
  • SLIC算法介绍及代码

    2016-02-14 14:54:56
    包括SLIC框架、相关论文介绍、关于SLIC的学习笔记、SLIC分割代码以及示例。
  • 超像素(SuperPixel),就是把原本多个像素点,组合成一个大的像素。...在超像素算法方面,SLIC Superpixels Compared to State-of-the-art Superpixel Methods这篇论文非常经典。论文中从算法效率,内存使用以...

    超像素(SuperPixel),就是把原本多个像素点,组合成一个大的像素。比如,原本的图片有二十多万个像素,用超像素处理之后,就只有几千个像素了。后面做直方图等处理就会方便许多。经常作为图像处理的预处理步骤。

    SuperPixel.png

    在超像素算法方面,SLIC Superpixels Compared to State-of-the-art Superpixel Methods这篇论文非常经典。论文中从算法效率,内存使用以及直观性比较了现有的几种超像素处理方法,并提出了一种更加实用,速度更快的算法——SLIC(simple linear iterative clustering),名字叫做简单的线性迭代聚类。其实是从k-means算法演化的,算法复杂度是O(n),只与图像的像素点数有关。

    这个算法突破性的地方有二:

    限制聚类时搜索的区域(2Sx2S),这样将k-means算法的复杂度降为常数。整个算法的复杂度为线性。

    计算距离时考虑LAB颜色和XY距离,5维。这样就把颜色和距离都考虑进去了。通过M可以调整颜色和距离的比重,灵活性强,超像素更加规则。

    SLIC算法原理

    整个算法的输入只有一个,即超像素的个数K。

    图片原有N个像素,要分割成K个像素,那么每个像素的大小是N/K。超像素之间的距离(即规则情况下超像素的边长)就是S=√N/K。

    我们的目标是使代价函数(cost function)最小。具体到本算法中,就是每个像素到所属的中心点的距离之和最小。

    首先,将K个超像素种子(也叫做聚类,即超像素的中心),均匀撒到图像的像素点上。

    一次迭代的第一步,对每个超像素的中心,2S范围内的所有像素点,判断他们是否属于这个超像素。这样之后,就缩短了像素点到超像素中心的距离。

    一次迭代的第二步,对每个超像素,将它的超像素中心移动到这个超像素的中点上。这样也缩短了像素点到超像素中心的距离。

    一般来说,迭代10是聚类效果和计算成本折中的次数。

    SLIC算法步骤

    撒种子。将K个超像素中心分布到图像的像素点上。

    微调种子的位置。以K为中心的3×3范围内,移动超像素中心到这9个点中梯度最小的点上。这样是为了避免超像素点落到噪点或者边界上。

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

    对每一个超像素中心x,它2S范围内的点:如果点到超像素中心x的距离(5维)小于这个点到它原来属于的超像素中心的距离,那么说明这个点属于超像素x。更新dis,更新label。

    对每一个超像素中心,重新计算它的位置。

    重复4 5 两步。

    伪代码(来自论文)

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    /∗Initialization∗/

    InitializeclustercentersCk=[lk,ak,bk,xk,yk]TbysamplingpixelsatregulargridstepsS.

    Moveclustercenterstothelowestgradientpositionina3×3neighborhood.

    Setlabell(i)=−1foreachpixeli.Setdistanced(i)=∞foreachpixeli.

    repeat

    /∗Assignment∗/

    foreachclustercenterCkdo

    foreachpixeliina2S×2SregionaroundCkdo

    ComputethedistanceDbetweenCkandi.

    ifD

    setd(i)=D

    setl(i)=k

    endif

    endfor

    endfor

    /∗Update∗/

    Computenewclustercenters.ComputeresidualerrorE.

    untilE≤threshold

    Python实现SLIC

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    97

    98

    99

    100

    101

    102

    103

    104

    105

    106

    107

    108

    109

    110

    111

    112

    113

    114

    115

    116

    117

    118

    119

    120

    121

    122

    123

    124

    125

    126

    127

    128

    129

    130

    131

    132

    133

    134

    135

    136

    137

    138

    139

    140

    141

    142

    143

    144

    145

    146

    147

    148

    149

    150

    151

    152

    153

    154

    155

    156

    157

    158

    159

    160

    161

    162

    importmath

    fromskimageimportio,color

    importnumpyasnp

    fromtqdmimporttrange

    classCluster(object):

    cluster_index=1

    def__init__(self,h,w,l=0,a=0,b=0):

    self.update(h,w,l,a,b)

    self.pixels=[]

    self.no=self.cluster_index

    self.cluster_index+=1

    defupdate(self,h,w,l,a,b):

    self.h=h

    self.w=w

    self.l=l

    self.a=a

    self.b=b

    def__str__(self):

    return"{},{}:{} {} {} ".format(self.h,self.w,self.l,self.a,self.b)

    def__repr__(self):

    returnself.__str__()

    classSLICProcessor(object):

    @staticmethod

    defopen_image(path):

    """

    Return:

    3D array, row col [LAB]

    """

    rgb=io.imread(path)

    lab_arr=color.rgb2lab(rgb)

    returnlab_arr

    @staticmethod

    defsave_lab_image(path,lab_arr):

    """

    Convert the array to RBG, then save the image

    """

    rgb_arr=color.lab2rgb(lab_arr)

    io.imsave(path,rgb_arr)

    defmake_cluster(self,h,w):

    returnCluster(h,w,

    self.data[h][w][0],

    self.data[h][w][1],

    self.data[h][w][2])

    def__init__(self,filename,K,M):

    self.K=K

    self.M=M

    self.data=self.open_image(filename)

    self.image_height=self.data.shape[0]

    self.image_width=self.data.shape[1]

    self.N=self.image_height*self.image_width

    self.S=int(math.sqrt(self.N/self.K))

    self.clusters=[]

    self.label={}

    self.dis=np.full((self.image_height,self.image_width),np.inf)

    definit_clusters(self):

    h=self.S/2

    w=self.S/2

    whileh

    whilew

    self.clusters.append(self.make_cluster(h,w))

    w+=self.S

    w=self.S/2

    h+=self.S

    defget_gradient(self,h,w):

    ifw+1>=self.image_width:

    w=self.image_width-2

    ifh+1>=self.image_height:

    h=self.image_height-2

    gradient=self.data[w+1][h+1][0]-self.data[w][h][0]+\

    self.data[w+1][h+1][1]-self.data[w][h][1]+\

    self.data[w+1][h+1][2]-self.data[w][h][2]

    returngradient

    defmove_clusters(self):

    forclusterinself.clusters:

    cluster_gradient=self.get_gradient(cluster.h,cluster.w)

    fordhinrange(-1,2):

    fordwinrange(-1,2):

    _h=cluster.h+dh

    _w=cluster.w+dw

    new_gradient=self.get_gradient(_h,_w)

    ifnew_gradient

    cluster.update(_h,_w,self.data[_h][_w][0],self.data[_h][_w][1],self.data[_h][_w][2])

    cluster_gradient=new_gradient

    defassignment(self):

    forclusterinself.clusters:

    forhinrange(cluster.h-2*self.S,cluster.h+2*self.S):

    ifh<0orh>=self.image_height:continue

    forwinrange(cluster.w-2*self.S,cluster.w+2*self.S):

    ifw<0orw>=self.image_width:continue

    L,A,B=self.data[h][w]

    Dc=math.sqrt(

    math.pow(L-cluster.l,2)+

    math.pow(A-cluster.a,2)+

    math.pow(B-cluster.b,2))

    Ds=math.sqrt(

    math.pow(h-cluster.h,2)+

    math.pow(w-cluster.w,2))

    D=math.sqrt(math.pow(Dc/self.M,2)+math.pow(Ds/self.S,2))

    ifD

    if(h,w)notinself.label:

    self.label[(h,w)]=cluster

    cluster.pixels.append((h,w))

    else:

    self.label[(h,w)].pixels.remove((h,w))

    self.label[(h,w)]=cluster

    cluster.pixels.append((h,w))

    self.dis[h][w]=D

    defupdate_cluster(self):

    forclusterinself.clusters:

    sum_h=sum_w=number=0

    forpincluster.pixels:

    sum_h+=p[0]

    sum_w+=p[1]

    number+=1

    _h=sum_h/number

    _w=sum_w/number

    cluster.update(_h,_w,self.data[_h][_w][0],self.data[_h][_w][1],self.data[_h][_w][2])

    defsave_current_image(self,name):

    image_arr=np.copy(self.data)

    forclusterinself.clusters:

    forpincluster.pixels:

    image_arr[p[0]][p[1]][0]=cluster.l

    image_arr[p[0]][p[1]][1]=cluster.a

    image_arr[p[0]][p[1]][2]=cluster.b

    image_arr[cluster.h][cluster.w][0]=0

    image_arr[cluster.h][cluster.w][1]=0

    image_arr[cluster.h][cluster.w][2]=0

    self.save_lab_image(name,image_arr)

    defiterate_10times(self):

    self.init_clusters()

    self.move_clusters()

    foriintrange(10):

    self.assignment()

    self.update_cluster()

    name='lenna_M{m}_K{k}_loop{loop}.png'.format(loop=i,m=self.M,k=self.K)

    self.save_current_image(name)

    if__name__=='__main__':

    p=SLICProcessor('Lenna.png',500,30)

    p.iterate_10times()

    效果如下:

    lenna_M30_K500_loop0.png

    Lenna图像在M=30,K=500时第一次迭代产生的超像素图。

    lenna_M30_K500_loop9.png

    Lenna图像在M=30,K=500时第10次迭代产生的超像素图。

    展开全文
  • 优化加权核K-means聚类初始中心点的SLIC算法.pdf
  • SLIC算法介绍与Python实现

    千次阅读 2019-04-27 17:04:00
    SLIC(simple linear iterative clustering)算法介绍与Python实现 本文转载自:https://blog.csdn.net/shinian1987/article/details/78618917 图像分割是图像处理,计算机视觉领域里非常基础,非常重要的一个...
  • SLIC算法理解(仅为个人笔记)

    千次阅读 2019-07-23 19:14:06
    MATLAB中有超像素分割算法superpixels函数,https://ww2.mathworks.cn/help/images/ref/superpixels.html?s_tid=doc_ta#bu1_lce-4,原理就是SLIC超像素分割。 1.SLIC超像素分割论文(翻译版) ...
  • VLFeat库中SLIC算法代码解读 原作者:Andrea Vedaldi
  • SLIC算法分割超像素原理及Python、C++

    千次阅读 2019-12-07 23:31:06
    超像素(SuperPixel),就是把原本多个像素点,组合成一个大的像素。...在超像素算法方面,SLIC Superpixels Compared to State-of-the-art Superpixel Methods这篇论文非常经典。论文中从算法效率,内...
  • 超像素SLIC算法源码阅读

    千次阅读 2019-04-30 15:48:50
    超像素SLIC算法源码阅读超像素SLIC算法源码阅读SLIC简介源码阅读实验结果 超像素SLIC算法源码阅读 SLIC简介 SLIC的全称Simple Linear Iterative Clustering,即简单线性迭代聚类,论文和代码链接如下: 论文传送...
  • 之前有关于SLIC Superpixel算法的个人理解请戳这里,这篇文章是对其改进算法Improved SLIC算法的理解。改进点: sigma filter 用来避免错误分割; 聚类结束后,会基于颜色相似度将小聚类融入临近的聚类中。 改进聚类...
  • python:超像素SLIC算法使用

    万次阅读 2018-07-01 21:45:33
    skimage作为图像处理库,包括多种图像分割算法。其中超像素slic目前表现较好,该部分代码如下。 from skimage.segmentation import slic,mark_boundaries from skimage import io import matplotlib.pyplot as plt ...
  • 简介:最近项目使用到了超像素分割,因此顺道研究了以下SLIC这一算法。超像素分割这类low-level vision问题已经在CVPR,ICCV这种顶级会议上逐渐销声匿迹,越来越流行的learning method渐渐占据了这些顶级会议90%的...
  • SLIC算法求superpixels的Windows软件,可自行设定superpixels的分割数目
  • 前言 像素风最早出现在8bit的电子游戏中,受制于电脑内存大小以及显示色彩单一, 只能使用少量像素来呈现内容,却成就了不少经典的像素游戏。随着内存容量与屏幕...什么是SLIC算法 像素画的绘制之所以不简单,是因
  • SLIC算法作为Superpixel中的聚类算法,简单高效,很多算法在预处理都会使用SLIC先对像素进行简单分类,方便之后的操作。
  • 其次结合图像的纹理特征提出了一种自适应K值方法,并对图像利用SLIC算法进行粗分割,描绘出乳腺肿块的初始轮廓;最后,利用GVF Snake算法加大对轮廓边缘信息的捕捉范围,进行细分割得到分割结果图。实验验证表明,该分割...
  • SLIC 算法

    2014-03-28 13:15:00
    读书笔记: http://blog.csdn.net/wishchin/article/details/17415785 转载于:https://www.cnblogs.com/muxiaoruo/p/3630438.html
  • 使用超像素的进行图像分割的matlab代码, 若体验良好可以给个好评
  • fast slic 算法

    千次阅读 2022-03-07 18:37:19
    fast slic算法,速度更快,性能更强的一种边缘检测算法
  • SLIC超像素分割算法的C++代码,代码来源于该算法创始人Radhakrishna Achanta网站,这里我们给出了对应的OpenCV Mat接口,代码在VS2012和OpenCV2.4.9版本下测试验证可行,其中附上SLIC的相关说明。
  • 这一篇文章主要介绍了SLIC算法的大致分析和理解,提供了源码,供大家复制下载。 目录 部分代码分析 1.RGB -> XYZ 大致分析: 详细代码: 2.RGB -> LAB 大致分析: 具体代码: 3.将一个图像中的全部点进行二次转化 ...
  • 一、算法步骤 1.将输入图像转化为CEILAB空间 2.输入k并计算出S: 3.创造一个以s为间距的网格 4.移动边缘的平均值 5.对图像中的每个像素在2s的邻域内进行搜索,并将该平均值分配给该像素 6.取分配给一个平均数的像素...
  • SLIC算法是simple linear iterative cluster的简称,该算法用来生成超像素(superpixel)。 目录 基本思想 实现SLIC算法 1.图像的预处理 2.初始化聚类中心 3.优化初始聚类中心 4.计算像素点与聚类中心的距离 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,472
精华内容 588
关键字:

slic算法