精华内容
下载资源
问答
  • 并行计算 Blog 02 —— SLIC代码的计算热点分析
    2021-11-25 15:05:08

    并行计算 Blog02 —— slic 代码的计算热点分析


    计时函数

    #include <chrono>
    
    auto startTime = Clock::now();
    // codes 
    auto endTime = Clock::now();
    auto compTime = chrono::duration_cast<chrono::microseconds>(endTime - startTime);
    cout <<  "Computing time=" << compTime.count()/1000 << " ms" << endl;
    

    我们在几个主要函数的首尾都加上这个计时模块,查看速度

    运行结果如下:

    
    DoRGBtoLABConversion time = 8030 ms
    
    DeleteEdges time = 365 ms
    
    PerturbSeeds time = 0 ms
    
    ***GetLABXYSeeds_ForGivenK time = 0 ms
    
    ***PerformSuperpixelSegmentation_VariableSandM time = 23257 ms
    
    EnforceLabelConnectivity time = 474 ms
    
    PerformSLICO_ForGivenK time = 32219 ms
    Computing time=32228 ms
    There are 0 points' labels are different from original file.
    
    --------------------------------
    Process exited after 33.29 seconds with return value 0
    请按任意键继续. . .
    
    
    DoRGBtoLABConversion time = 5105 ms
    
    DeleteEdges time = 231 ms
    
    PerturbSeeds time = 0 ms
    
    ***GetLABXYSeeds_ForGivenK time = 0 ms
    
    ***PerformSuperpixelSegmentation_VariableSandM time = 14787 ms
    
    EnforceLabelConnectivity time = 313 ms
    
    PerformSLICO_ForGivenK time = 20501 ms
    Computing time=20507 ms
    There are 0 points' labels are different from original file.
    
    --------------------------------
    Process exited after 20.93 seconds with return value 0
    请按任意键继续. . .
    

    第一个是编译运行的结果,第二个是连续运行几次后的结果。

    Q:运行时间的差距来源 ???

    通过运行结果可以看到调用函数的顺序以及主要的计算热点:
    核心优化点: SLIC::PerformSuperpixelSegmentation_VariableSandM
    更加的优化:预处理数据部分 DoRGBtoLABConversion


    代码结构

    // part 1 预处理图像色彩 样本耗时 5 ~ 8 秒 
    void void SLIC::RGB2XYZ(const int& sR, const int& sG, const int& sB,
    										double& X, double& Y, double& Z)
    void SLIC::RGB2LAB(const int& sR, const int& sG, const int& sB, 
    								double& lval, double& aval, double& bval)
    void SLIC::DoRGBtoLABConversion(const unsigned int*& ubuff,
    						double*& lvec, double*& avec, double*& bvec)
    
    // 检测 edge 
    void SLIC::DetectLabEdges(const double* lvec, const double* avec, const double* bvec,
    						const int& width, const int& height, vector<double>& edges)
    
    // 迭代种子
    void SLIC::PerturbSeeds(vector<double>& kseedsl, vector<double>& kseedsa, 
    						vector<double>& kseedsb, vector<double>& kseedsx,
    						vector<double>& kseedsy, const vector<double>& edges)
    
    // 获得种子	
    void SLIC::GetLABXYSeeds_ForGivenK(vector<double>& kseedsl, vector<double>& kseedsa,
    			vector<double>& kseedsb, vector<double>& kseedsx, vector<double>& kseedsy,
    			const int& K, const bool& perturbseeds, const vector<double>& edgemag)
    
    // 核心函数 程序的 60-70% 的时间消耗
    void SLIC::PerformSuperpixelSegmentation_VariableSandM(
    		vector<double>& kseedsl, vector<double>& kseedsa, vector<double>& kseedsb,
    		vector<double>& kseedsx, vector<double>& kseedsy, int* klabels,
    		const int& STEP, const int& NUMITR)
    
    // 加强边的关联性
    void SLIC::EnforceLabelConnectivity(
    	const int* labels,//input labels that need to be corrected to remove stray labels
    	const int& width,
    	const int& height,
    	int* nlabels,//new labels
    	int& numlabels,//the number of labels changes in the end if segments are removed
    	const int& K) //the number of superpixels desired by the user
    
    // 主要程序的入口
    void SLIC::PerformSLICO_ForGivenK(
    	const unsigned int*			ubuff,
    	const int					width,
    	const int					height,
    	int*						klabels,
    	int&						numlabels,
    	const int&					K,//required number of superpixels
    	const double&				m)//weight given to spatial distance
    
    代码流程:
    入口:
    slic.PerformSLICO_ForGivenK(img, width, height, labels, numlabels, m_spcount, m_compactness);
    进函数:
    void SLIC::PerformSLICO_ForGivenK(
    const unsigned int*			ubuff,
    const int					width,
    const int					height,
    int*						klabels,
    int&						numlabels,
    const int&					K, 	//required number of superpixels K = 20
    const double&				m)	//weight given to spatial distance  m=10.0
    -----------------------------------
    	// 1. 预处理成为 LABXY 向量
    	DoRGBtoLABConversion(ubuff, m_lvec, m_avec, m_bvec);
    	// 2. 检测边际  对应算法哪一块?
    	bool perturbseeds(true);
    	vector<double> edgemag(0);
    	if(perturbseeds) DetectLabEdges(m_lvec, m_avec, m_bvec, m_width, m_height, edgemag);
    	// 3. 获得迭代种子
    	GetLABXYSeeds_ForGivenK(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, K, perturbseeds, edgemag);
    		  	// 3.1 内部调用 Perturseeds
    			if(perturbseeds) 
    				PerturbSeeds(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, edgemag);
    
    	// 4. **核心部分  进行计算
    	int STEP = sqrt(double(sz)/double(K)) + 2.0;
    	//adding a small value in case the even the STEP size is too small.
    	PerformSuperpixelSegmentation_VariableSandM(kseedsl,kseedsa,kseedsb,kseedsx,kseedsy,klabels,STEP,10);
    	
    	// 5. 加强边的联系
    	numlabels = kseedsl.size();
    	int* nlabels = new int[sz];
    	EnforceLabelConnectivity(klabels, m_width, m_height, nlabels, numlabels, K);
    
    更多相关内容
  • slic实现代码

    2019-03-16 10:27:03
    实现slic代码 效果还行,可以试一下
  • 切片代码matlab C++ 代码来自 Chuan Yang、Lihe Zhang、Huchuan Lu、Xiang Ruan ...SLIC 超像素代码。 *注:论文中的结果是由MATLAB代码生成的。 此 c++ 代码的结果可能与 MATLAB 代码的结果有些不同。
  • python 自带slic代码分析

    千次阅读 热门讨论 2018-12-01 15:09:57
    一.python中的slic函数 def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=0, spacing=None, multichannel=True, convert2lab=None, enforce_connectivity=True, min_size_fact...

    一.python中的slic函数

    
    def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=0,
             spacing=None, multichannel=True, convert2lab=None,
             enforce_connectivity=True, min_size_factor=0.5, max_size_factor=3,
             slic_zero=False):
        """Segments image using k-means clustering in Color-(x,y,z) space.
    
        Parameters
        ----------
        image : 2D, 3D or 4D ndarray
            Input image, which can be 2D or 3D, and grayscale or multichannel
            (see `multichannel` parameter).
        n_segments : int, optional
            The (approximate) number of labels in the segmented output image.
        compactness : float, optional
            控制颜色和空间之间的平衡,约高越方块,和图关系密切,最好先确定指数级别,再微调
            Balances color proximity and space proximity. Higher values give
            more weight to space proximity, making superpixel shapes more
            square/cubic. In SLICO mode, this is the initial compactness.
            This parameter depends strongly on image contrast and on the
            shapes of objects in the image. We recommend exploring possible
            values on a log scale, e.g., 0.01, 0.1, 1, 10, 100, before
            refining around a chosen value.
        max_iter : int, optional
            最大k均值迭代次数
            Maximum number of iterations of k-means.
        sigma : float or (3,) array-like of floats, optional
            图像每个维度进行预处理时的高斯平滑核宽。若给定为标量值,则同一个值运用到各个维度。0意味
            着不平滑。如果“sigma”是标量的,并且提供了手动体素间距,则自动缩放它(参见注释部分)。
            Width of Gaussian smoothing kernel for pre-processing for each
            dimension of the image. The same sigma is applied to each dimension in
            case of a scalar value. Zero means no smoothing.
            Note, that `sigma` is automatically scaled if it is scalar and a
            manual voxel spacing is provided (see Notes section).
        spacing : (3,) array-like of floats, optional
            代表沿着图像每个维度的体素空间。默认情况下,slic假定均匀的空间(沿x,y,z轴相同的体素分辨
            率),这个参数控制在k均值聚类中各轴距离的权重
            The voxel spacing along each image dimension. By default, `slic`
            assumes uniform spacing (same voxel resolution along z, y and x).
            This parameter controls the weights of the distances along z, y,
            and x during k-means clustering.
        multichannel : bool, optional
            二进制参数,代表图像的最后一个轴代表多通道还是另一个空间维度
            Whether the last axis of the image is to be interpreted as multiple
            channels or another spatial dimension.
        convert2lab : bool, optional
            二进制参数,判断输入需要在分割之前转到LAB颜色空间。输入必须是RGB。当多通道参数为True,
            输入图片的通道数为3时,该参数默认为True
            Whether the input should be converted to Lab colorspace prior to
            segmentation. The input image *must* be RGB. Highly recommended.
            This option defaults to ``True`` when ``multichannel=True`` *and*
            ``image.shape[-1] == 3``.
        enforce_connectivity: bool, optional
            二进制参数,控制生成的分割块连接或不连接
            Whether the generated segments are connected or not
        min_size_factor: float, optional
            与分割目标数有关的要删去的最小分割块比率,(大概是小于长*宽*高/目标数量 的分割结果会被融
            合掉)
            Proportion of the minimum segment size to be removed with respect
            to the supposed segment size ```depth*width*height/n_segments```
        max_size_factor: float, optional
            最大融合比率上限
            Proportion of the maximum connected segment size. A value of 3 works
            in most of the cases.
        slic_zero: bool, optional
            不知所谓的零参数
            Run SLIC-zero, the zero-parameter mode of SLIC. [2]_
    
        Returns
        -------
        labels : 2D or 3D array
            Integer mask indicating segment labels.
    
        Raises
        ------
        ValueError
            If ``convert2lab`` is set to ``True`` but the last array
            dimension is not of length 3.
    
        Notes
        -----
        * If `sigma > 0`, the image is smoothed using a Gaussian kernel prior to
          segmentation.
    
        * If `sigma` is scalar and `spacing` is provided, the kernel width is
          divided along each dimension by the spacing. For example, if ``sigma=1``
          and ``spacing=[5, 1, 1]``, the effective `sigma` is ``[0.2, 1, 1]``. This
          ensures sensible smoothing for anisotropic images.
          如果有平滑参数sigma和体素空间参数spacing,那么空间体素参数会对平滑参数有平分的影响,比如                
          1/[5,1,1]=[0.2,1,1]
    
        * The image is rescaled to be in [0, 1] prior to processing.
          图像在预处理之前会被处理为[0,1]之间的标量
    
        * Images of shape (M, N, 3) are interpreted as 2D RGB images by default. To
          interpret them as 3D with the last dimension having length 3, use
          `multichannel=False`.
          (M,N,3)的图像默认为2维(RGB的图像),要想被理解为3维图需要设置多通道参数=False
    
        References
        ----------
        .. [1] Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi,
            Pascal Fua, and Sabine Süsstrunk, SLIC Superpixels Compared to
            State-of-the-art Superpixel Methods, TPAMI, May 2012.
        .. [2] http://ivrg.epfl.ch/research/superpixels#SLICO
    
        Examples
        --------
        >>> from skimage.segmentation import slic
        >>> from skimage.data import astronaut
        >>> img = astronaut()
        >>> segments = slic(img, n_segments=100, compactness=10)
    
        Increasing the compactness parameter yields more square regions:
    
        >>> segments = slic(img, n_segments=100, compactness=20)
    
        """
        ###############################################干正事啦
    
        image = img_as_float(image)
        is_2d = False
        #2D灰度图
        if image.ndim == 2:
            # 2D grayscale image
            image = image[np.newaxis, ..., np.newaxis]
            is_2d = True
    
        #比如2D RGB的图
        elif image.ndim == 3 and multichannel:
            # Make 2D multichannel image 3D with depth = 1
            image = image[np.newaxis, ...]
            is_2d = True
    
    
        #比如3D图
        elif image.ndim == 3 and not multichannel:
            # Add channel as single last dimension
            image = image[..., np.newaxis]
    
        #控制聚类时各轴权重
        if spacing is None:
            spacing = np.ones(3)
        elif isinstance(spacing, (list, tuple)):
            spacing = np.array(spacing, dtype=np.double)
    
        #高斯平滑
        if not isinstance(sigma, coll.Iterable):
            sigma = np.array([sigma, sigma, sigma], dtype=np.double)
            sigma /= spacing.astype(np.double)#有可能发生的体素除
        elif isinstance(sigma, (list, tuple)):
            sigma = np.array(sigma, dtype=np.double)
    
        #高斯滤波处
        if (sigma > 0).any():
            # add zero smoothing for multichannel dimension
            sigma = list(sigma) + [0]
            image = ndi.gaussian_filter(image, sigma)
    
        #多通道RGB图且需要转lab,用rab2lab即可实现
        if multichannel and (convert2lab or convert2lab is None):
            if image.shape[-1] != 3 and convert2lab:
                raise ValueError("Lab colorspace conversion requires a RGB image.")
            elif image.shape[-1] == 3:
                image = rgb2lab(image)
    
        depth, height, width = image.shape[:3]
    
        # initialize cluster centroids for desired number of segments
        #为实现目标分割块数,初始化聚类中心。
        #grid_* 相当于index
        #slices是根据目标数量分的块,有取整需要
        grid_z, grid_y, grid_x = np.mgrid[:depth, :height, :width]
        slices = regular_grid(image.shape[:3], n_segments)
        step_z, step_y, step_x = [int(s.step if s.step is not None else 1)
                                  for s in slices]
        segments_z = grid_z[slices]
        segments_y = grid_y[slices]
        segments_x = grid_x[slices]
    
        segments_color = np.zeros(segments_z.shape + (image.shape[3],))
        segments = np.concatenate([segments_z[..., np.newaxis],
                                   segments_y[..., np.newaxis],
                                   segments_x[..., np.newaxis],
                                   segments_color],
                                  axis=-1).reshape(-1, 3 + image.shape[3])
        segments = np.ascontiguousarray(segments)
    
        # we do the scaling of ratio in the same way as in the SLIC paper
        # so the values have the same meaning
        step = float(max((step_z, step_y, step_x)))
        ratio = 1.0 / compactness
    
        #我类个去,分割时方不方的骚操作
        image = np.ascontiguousarray(image * ratio)
    
        labels = _slic_cython(image, segments, step, max_iter, spacing, slic_zero)
    
        #把过小过小的处理一下
        if enforce_connectivity:
            segment_size = depth * height * width / n_segments
            min_size = int(min_size_factor * segment_size)
            max_size = int(max_size_factor * segment_size)
            labels = _enforce_label_connectivity_cython(labels,
                                                        min_size,
                                                        max_size)
    
        if is_2d:
            labels = labels[0]
    
        return labels

    二、注意事项

    1.要不要转化到LAB空间是可以调的,当然啦不转的结果就是方方正正的空间分割,和内容毫无关系,比如下图

    convert2lab or convert2lab is None  这段代码可以看出来,不传参数和传参数为True都是转到lab了,完美。

     

    2.分割结果比设置的少是因为做了一下后处理,调一下enforce_connectivity就变多啦,但不是一定分割结果和设置数量一样的。比如下图,设置分割20,参数设置为False结果为12块,参数设置为True就是3块

    分割目标数量恰当的话(比如100),是这样的:

     

    三、SLCI的使用

    from __future__ import division
    from skimage.segmentation import slic,mark_boundaries
    from skimage import io
    import matplotlib.pyplot as plt
    import numpy as np
    
    img = io.imread("imgs\style\DTD\\denoised_starry.jpg")
    print(img.shape)
    
    
    segments = slic(img, n_segments=100, compactness=20,enforce_connectivity=True,convert2lab=True)
    print(segments.shape)
    n_liantong=segments.max()+1
    print('n_liantong:',n_liantong)
    area=np.bincount(segments.flat)
    w,h=segments.shape
    print(area/(w*h))
    print((max(area/(w*h))),(min(area/(w*h))))
    
    out=mark_boundaries(img,segments)
    plt.subplot(111)
    plt.imshow(out)
    plt.show()

    四、参考一的代码做修改

    相对导入报错:

    ValueError: attempted relative import beyond top-level package

     

    调用关系需要做一下修改,

    原:

    from ..util import img_as_float, regular_grid
    from ..segmentation._slic import (_slic_cython,
                                      _enforce_label_connectivity_cython)
    from ..color import rgb2lab

    修改后:

    from skimage.util import img_as_float, regular_grid
    from skimage.segmentation._slic import (_slic_cython,
                                      _enforce_label_connectivity_cython)
    from skimage.color import rgb2lab

     

     

     

     

     

     

    展开全文
  • Python 自带slic代码分析

    千次阅读 2019-12-07 10:49:45
    一.python中的slic函数 def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=0, spacing=None, multichannel=True, convert2lab=None, enforce_connectivity=True, min_size_fac...

    一.python中的slic函数

     
    def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=0,
             spacing=None, multichannel=True, convert2lab=None,
             enforce_connectivity=True, min_size_factor=0.5, max_size_factor=3,
             slic_zero=False):
        """Segments image using k-means clustering in Color-(x,y,z) space.
        Parameters
        ----------
        image : 2D, 3D or 4D ndarray
            Input image, which can be 2D or 3D, and grayscale or multichannel
            (see `multichannel` parameter).
        n_segments : int, optional
            The (approximate) number of labels in the segmented output image.
        compactness : float, optional
            控制颜色和空间之间的平衡,约高越方块,和图关系密切,最好先确定指数级别,再微调
            Balances color proximity and space proximity. Higher values give
            more weight to space proximity, making superpixel shapes more
            square/cubic. In SLICO mode, this is the initial compactness.
            This parameter depends strongly on image contrast and on the
            shapes of objects in the image. We recommend exploring possible
            values on a log scale, e.g., 0.01, 0.1, 1, 10, 100, before
            refining around a chosen value.
        max_iter : int, optional
            最大k均值迭代次数
            Maximum number of iterations of k-means.
        sigma : float or (3,) array-like of floats, optional
            图像每个维度进行预处理时的高斯平滑核宽。若给定为标量值,则同一个值运用到各个维度。0意味
            着不平滑。如果“sigma”是标量的,并且提供了手动体素间距,则自动缩放它(参见注释部分)。
            Width of Gaussian smoothing kernel for pre-processing for each
            dimension of the image. The same sigma is applied to each dimension in
            case of a scalar value. Zero means no smoothing.
            Note, that `sigma` is automatically scaled if it is scalar and a
            manual voxel spacing is provided (see Notes section).
        spacing : (3,) array-like of floats, optional
            代表沿着图像每个维度的体素空间。默认情况下,slic假定均匀的空间(沿x,y,z轴相同的体素分辨
            率),这个参数控制在k均值聚类中各轴距离的权重
            The voxel spacing along each image dimension. By default, `slic`
            assumes uniform spacing (same voxel resolution along z, y and x).
            This parameter controls the weights of the distances along z, y,
            and x during k-means clustering.
        multichannel : bool, optional
            二进制参数,代表图像的最后一个轴代表多通道还是另一个空间维度
            Whether the last axis of the image is to be interpreted as multiple
            channels or another spatial dimension.
        convert2lab : bool, optional
            二进制参数,判断输入需要在分割之前转到LAB颜色空间。输入必须是RGB。当多通道参数为True,
            输入图片的通道数为3时,该参数默认为True
            Whether the input should be converted to Lab colorspace prior to
            segmentation. The input image *must* be RGB. Highly recommended.
            This option defaults to ``True`` when ``multichannel=True`` *and*
            ``image.shape[-1] == 3``.
        enforce_connectivity: bool, optional
            二进制参数,控制生成的分割块连接或不连接
            Whether the generated segments are connected or not
        min_size_factor: float, optional
            与分割目标数有关的要删去的最小分割块比率,(大概是小于长*宽*高/目标数量 的分割结果会被融
            合掉)
            Proportion of the minimum segment size to be removed with respect
            to the supposed segment size ```depth*width*height/n_segments```
        max_size_factor: float, optional
            最大融合比率上限
            Proportion of the maximum connected segment size. A value of 3 works
            in most of the cases.
        slic_zero: bool, optional
            不知所谓的零参数
            Run SLIC-zero, the zero-parameter mode of SLIC. [2]_
        Returns
        -------
        labels : 2D or 3D array
            Integer mask indicating segment labels.
        Raises
        ------
        ValueError
            If ``convert2lab`` is set to ``True`` but the last array
            dimension is not of length 3.
        Notes
        -----
        * If `sigma > 0`, the image is smoothed using a Gaussian kernel prior to
          segmentation.
        * If `sigma` is scalar and `spacing` is provided, the kernel width is
          divided along each dimension by the spacing. For example, if ``sigma=1``
          and ``spacing=[5, 1, 1]``, the effective `sigma` is ``[0.2, 1, 1]``. This
          ensures sensible smoothing for anisotropic images.
          如果有平滑参数sigma和体素空间参数spacing,那么空间体素参数会对平滑参数有平分的影响,比如                
          1/[5,1,1]=[0.2,1,1]
        * The image is rescaled to be in [0, 1] prior to processing.
          图像在预处理之前会被处理为[0,1]之间的标量
        * Images of shape (M, N, 3) are interpreted as 2D RGB images by default. To
          interpret them as 3D with the last dimension having length 3, use
          `multichannel=False`.
          (M,N,3)的图像默认为2维(RGB的图像),要想被理解为3维图需要设置多通道参数=False
        References
        ----------
        .. [1] Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi,
            Pascal Fua, and Sabine Süsstrunk, SLIC Superpixels Compared to
            State-of-the-art Superpixel Methods, TPAMI, May 2012.
        .. [2] http://ivrg.epfl.ch/research/superpixels#SLICO
        Examples
        --------
        >>> from skimage.segmentation import slic
        >>> from skimage.data import astronaut
        >>> img = astronaut()
        >>> segments = slic(img, n_segments=100, compactness=10)
        Increasing the compactness parameter yields more square regions:
        >>> segments = slic(img, n_segments=100, compactness=20)
        """
        ###############################################干正事啦
     
        image = img_as_float(image)
        is_2d = False
        #2D灰度图
        if image.ndim == 2:
            # 2D grayscale image
            image = image[np.newaxis, ..., np.newaxis]
            is_2d = True
     
        #比如2D RGB的图
        elif image.ndim == 3 and multichannel:
            # Make 2D multichannel image 3D with depth = 1
            image = image[np.newaxis, ...]
            is_2d = True
     
     
        #比如3D图
        elif image.ndim == 3 and not multichannel:
            # Add channel as single last dimension
            image = image[..., np.newaxis]
     
        #控制聚类时各轴权重
        if spacing is None:
            spacing = np.ones(3)
        elif isinstance(spacing, (list, tuple)):
            spacing = np.array(spacing, dtype=np.double)
     
        #高斯平滑
        if not isinstance(sigma, coll.Iterable):
            sigma = np.array([sigma, sigma, sigma], dtype=np.double)
            sigma /= spacing.astype(np.double)#有可能发生的体素除
        elif isinstance(sigma, (list, tuple)):
            sigma = np.array(sigma, dtype=np.double)
     
        #高斯滤波处
        if (sigma > 0).any():
            # add zero smoothing for multichannel dimension
            sigma = list(sigma) + [0]
            image = ndi.gaussian_filter(image, sigma)
     
        #多通道RGB图且需要转lab,用rab2lab即可实现
        if multichannel and (convert2lab or convert2lab is None):
            if image.shape[-1] != 3 and convert2lab:
                raise ValueError("Lab colorspace conversion requires a RGB image.")
            elif image.shape[-1] == 3:
                image = rgb2lab(image)
     
        depth, height, width = image.shape[:3]
     
        # initialize cluster centroids for desired number of segments
        #为实现目标分割块数,初始化聚类中心。
        #grid_* 相当于index
        #slices是根据目标数量分的块,有取整需要
        grid_z, grid_y, grid_x = np.mgrid[:depth, :height, :width]
        slices = regular_grid(image.shape[:3], n_segments)
        step_z, step_y, step_x = [int(s.step if s.step is not None else 1)
                                  for s in slices]
        segments_z = grid_z[slices]
        segments_y = grid_y[slices]
        segments_x = grid_x[slices]
     
        segments_color = np.zeros(segments_z.shape + (image.shape[3],))
        segments = np.concatenate([segments_z[..., np.newaxis],
                                   segments_y[..., np.newaxis],
                                   segments_x[..., np.newaxis],
                                   segments_color],
                                  axis=-1).reshape(-1, 3 + image.shape[3])
        segments = np.ascontiguousarray(segments)
     
        # we do the scaling of ratio in the same way as in the SLIC paper
        # so the values have the same meaning
        step = float(max((step_z, step_y, step_x)))
        ratio = 1.0 / compactness
     
        #我类个去,分割时方不方的骚操作
        image = np.ascontiguousarray(image * ratio)
     
        labels = _slic_cython(image, segments, step, max_iter, spacing, slic_zero)
     
        #把过小过小的处理一下
        if enforce_connectivity:
            segment_size = depth * height * width / n_segments
            min_size = int(min_size_factor * segment_size)
            max_size = int(max_size_factor * segment_size)
            labels = _enforce_label_connectivity_cython(labels,
                                                        min_size,
                                                        max_size)
     
        if is_2d:
            labels = labels[0]
     
        return labels
    

    二、注意事项

    1.要不要转化到LAB空间是可以调的,当然啦不转的结果就是方方正正的空间分割,和内容毫无关系,比如下图

    convert2lab or convert2lab is None  这段代码可以看出来,不传参数和传参数为True都是转到lab了,完美。

     

    2.分割结果比设置的少是因为做了一下后处理,调一下enforce_connectivity就变多啦,但不是一定分割结果和设置数量一样的。比如下图,设置分割20,参数设置为False结果为12块,参数设置为True就是3块

    分割目标数量恰当的话(比如100),是这样的:

     

    三、SLCI的使用

    from __future__ import division
    from skimage.segmentation import slic,mark_boundaries
    from skimage import io
    import matplotlib.pyplot as plt
    import numpy as np
     
    img = io.imread("imgs\style\DTD\\denoised_starry.jpg")
    print(img.shape)
     
     
    segments = slic(img, n_segments=100, compactness=20,enforce_connectivity=True,convert2lab=True)
    print(segments.shape)
    n_liantong=segments.max()+1
    print('n_liantong:',n_liantong)
    area=np.bincount(segments.flat)
    w,h=segments.shape
    print(area/(w*h))
    print((max(area/(w*h))),(min(area/(w*h))))
     
    out=mark_boundaries(img,segments)
    plt.subplot(111)
    plt.imshow(out)
    plt.show()
    

    四、参考一的代码做修改

    相对导入报错:

    ValueError: attempted relative import beyond top-level package

    调用关系需要做一下修改,

    原:

    1. from ..util import img_as_float, regular_grid

    2. from ..segmentation._slic import (_slic_cython,

    3. _enforce_label_connectivity_cython)

    4. from ..color import rgb2lab

    修改后:

    1. from skimage.util import img_as_float, regular_grid

    2. from skimage.segmentation._slic import (_slic_cython,

    3. _enforce_label_connectivity_cython)

    4. from skimage.color import rgb2lab

    展开全文
  • 在MATLAB下直接可运行,已调试通过,不是epfl网页里面要调用C++的程序。适合学习MATLAB的朋友。。。
  • 并行计算 Blog 01 SLIC 代码切分

    并行计算 Blog 01


    SLIC 代码切分


    1. 函数头
    #include <stdio.h>
    #include <cfloat>
    #include <cmath>
    #include <iostream>
    #include <fstream>
    #include "SLIC.h"
    #include <chrono>
    
    typedef chrono::high_resolution_clock Clock;
    
    // For superpixels
    const int dx4[4] = {-1,  0,  1,  0};
    const int dy4[4] = { 0, -1,  0,  1};
    //const int dx8[8] = {-1, -1,  0,  1, 1, 1, 0, -1};
    //const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1,  1};
    
    // For supervoxels
    const int dx10[10] = {-1,  0,  1,  0, -1,  1,  1, -1,  0, 0};
    const int dy10[10] = { 0, -1,  0,  1, -1, -1,  1,  1,  0, 0};
    const int dz10[10] = { 0,  0,  0,  0,  0,  0,  0,  0, -1, 1};
    
    • chono.h
      系统计时的头文件,计算效率
      https://blog.csdn.net/fengbingchun/article/details/73302364

    • dx4[], dy4[] superpixel 超像素的方向辅助数组

    • dx10[], dy10[] supervoxels 超体素(三维坐标的方向数组)


    1. SLIC 的类函数

    2.1 构造函数和析构函数

    这一部分注意 初始化的值,同时搞清楚使用的数据结构

    主要是 L, A, B 这三个维度的值

    一维作用:

    二维作用:

    // Construction/Destruction
    SLIC::SLIC()
    {
    	m_lvec = NULL;
    	m_avec = NULL;
    	m_bvec = NULL;
    
    	m_lvecvec = NULL;
    	m_avecvec = NULL;
    	m_bvecvec = NULL;
    }
    
    SLIC::~SLIC()
    {
    	if(m_lvec) delete [] m_lvec;
    	if(m_avec) delete [] m_avec;
    	if(m_bvec) delete [] m_bvec;
    
    	if(m_lvecvec)
    	{
    		for( int d = 0; d < m_depth; d++ ) delete [] m_lvecvec[d];
    		delete [] m_lvecvec;
    	}
    	if(m_avecvec)
    	{
    		for( int d = 0; d < m_depth; d++ ) delete [] m_avecvec[d];
    		delete [] m_avecvec;
    	}
    	if(m_bvecvec)
    	{
    		for( int d = 0; d < m_depth; d++ ) delete [] m_bvecvec[d];
    		delete [] m_bvecvec;
    	}
    }
    

    2.2 功能函数 RGB2XYZ 数据格式的转变

    参数转换的参数依据:?

    *加速:pow(double, double) 手写优化?

    void SLIC::RGB2XYZ(
    	const int&		sR,
    	const int&		sG,
    	const int&		sB,
    	double&			X,
    	double&			Y,
    	double&			Z)
    {
    	double R = sR/255.0;
    	double G = sG/255.0;
    	double B = sB/255.0;
    
    	double r, g, b;
    
    	if(R <= 0.04045)	r = R/12.92;
    	else				r = pow((R+0.055)/1.055,2.4);
    	if(G <= 0.04045)	g = G/12.92;
    	else				g = pow((G+0.055)/1.055,2.4);
    	if(B <= 0.04045)	b = B/12.92;
    	else				b = pow((B+0.055)/1.055,2.4);
    
    	X = r*0.4124564 + g*0.3575761 + b*0.1804375;
    	Y = r*0.2126729 + g*0.7151522 + b*0.0721750;
    	Z = r*0.0193339 + g*0.1191920 + b*0.9503041;
    }
    

    2.3 转换函数:RGB2LAB

    *加速点:依旧是浮点数的快速乘法

    //	RGB2LAB
    void SLIC::RGB2LAB(
    	const int& sR, const int& sG, const int& sB, 
    	double& lval, double& aval, double& bval)
    {
    
    	// sRGB to XYZ conversion
    	double X, Y, Z;
    	RGB2XYZ(sR, sG, sB, X, Y, Z);
    
    	// XYZ to LAB conversion
    	double epsilon = 0.008856;	//actual CIE standard
    	double kappa   = 903.3;		//actual CIE standard
    
    	double Xr = 0.950456;	//reference white
    	double Yr = 1.0;		//reference white
    	double Zr = 1.088754;	//reference white
    
    	double xr = X/Xr;
    	double yr = Y/Yr;
    	double zr = Z/Zr;
    
    	double fx, fy, fz;
    	if(xr > epsilon)	fx = pow(xr, 1.0/3.0);
    	else				fx = (kappa*xr + 16.0)/116.0;
    	if(yr > epsilon)	fy = pow(yr, 1.0/3.0);
    	else				fy = (kappa*yr + 16.0)/116.0;
    	if(zr > epsilon)	fz = pow(zr, 1.0/3.0);
    	else				fz = (kappa*zr + 16.0)/116.0;
    
    	lval = 116.0*fy-16.0;
    	aval = 500.0*(fx-fy);
    	bval = 200.0*(fy-fz);
    }
    

    2.4 功能函数:DoRGBtoLABConversion

    全图的 RGB to LAB 的格式转换

    rgb 24位, r 8bit g 8bit b 8bit 已经是位运算了

    *优化:new 分配空间可不可以优化

    ** 优化: RGB 拆成三个线程跑,ubuff 是const,只进行数据读

    //	DoRGBtoLABConversion
    //	For whole image: overlaoded floating point version
    void SLIC::DoRGBtoLABConversion(
    	const unsigned int*&		ubuff,
    	double*&					lvec,
    	double*&					avec,
    	double*&					bvec)
    {
    	int sz = m_width*m_height;
    	lvec = new double[sz];
    	avec = new double[sz];
    	bvec = new double[sz];
    
    	for( int j = 0; j < sz; j++ )
    	{
    		int r = (ubuff[j] >> 16) & 0xFF;
    		int g = (ubuff[j] >>  8) & 0xFF;
    		int b = (ubuff[j]      ) & 0xFF;
    
    		RGB2LAB( r, g, b, lvec[j], avec[j], bvec[j] );
    	}
    }
    

    2.5 核心功能函数:DetectLabEdges

    全图的扫描计算每一个点的梯度(除了最外部的一圈像素)

    对应论文中 : G(x, y) = ||I(x+1, y) - I(x-1, y)|| + ||I(x, y+1) - I(x, y-1)||

    //	DetectLabEdges
    void SLIC::DetectLabEdges(
    	const double*				lvec,
    	const double*				avec,
    	const double*				bvec,
    	const int&					width,
    	const int&					height,
    	vector<double>&				edges)
    {
    	int sz = width*height;
    
    	edges.resize(sz,0);
    	for( int j = 1; j < height-1; j++ )
    	{
    		for( int k = 1; k < width-1; k++ )
    		{
    			int i = j*width+k;
    
    			double dx = (lvec[i-1]-lvec[i+1])*(lvec[i-1]-lvec[i+1]) +
    						(avec[i-1]-avec[i+1])*(avec[i-1]-avec[i+1]) +
    						(bvec[i-1]-bvec[i+1])*(bvec[i-1]-bvec[i+1]);
    
    			double dy = (lvec[i-width]-lvec[i+width])*(lvec[i-width]-lvec[i+width]) +
    						(avec[i-width]-avec[i+width])*(avec[i-width]-avec[i+width]) +
    						(bvec[i-width]-bvec[i+width])*(bvec[i-width]-bvec[i+width]);
    
    			//edges[i] = (sqrt(dx) + sqrt(dy));
    			edges[i] = (dx + dy);
    		}
    	}
    }
    

    2.6 核心功能函数:PerturbSeeds

    功能:枚举每个当前的 超像素点,从 3 * 3 的范围中找到 G 值 (edges) 最小的迁移过去
    G 值在 2.5 中计算得到,图像不变则G值不变,即在计算过程中 G值是固定的。

    //	PerturbSeeds
    void SLIC::PerturbSeeds(
    	vector<double>&				kseedsl,
    	vector<double>&				kseedsa,
    	vector<double>&				kseedsb,
    	vector<double>&				kseedsx,
    	vector<double>&				kseedsy,
    	const vector<double>&		edges)
    {
    	const int dx8[8] = {-1, -1,  0,  1, 1, 1, 0, -1};
    	const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1,  1};
    	
    	int numseeds = kseedsl.size();
    
    	for( int n = 0; n < numseeds; n++ )
    	{
    		int ox = kseedsx[n];	//original x
    		int oy = kseedsy[n];	//original y
    		int oind = oy*m_width + ox;	// ind  --> index
    
    		int storeind = oind;
    		for( int i = 0; i < 8; i++ )
    		{
    			int nx = ox+dx8[i];	//new x
    			int ny = oy+dy8[i];	//new y
    
    			if( nx >= 0 && nx < m_width && ny >= 0 && ny < m_height)
    			{
    				int nind = ny*m_width + nx;
    				if( edges[nind] < edges[storeind])
    				{
    					storeind = nind;
    				}
    			}
    		}
    		if(storeind != oind)
    		{
    			kseedsx[n] = storeind % m_width;
    			kseedsy[n] = storeind / m_width;
    			kseedsl[n] = m_lvec[storeind];
    			kseedsa[n] = m_avec[storeind];
    			kseedsb[n] = m_bvec[storeind];
    		}
    	}
    }
    

    2.7 核心初始化函数:GetLABXYSeeds_ForGivenK、

    最初的 K 个超像素是如何选择的?
    就是在全图上直接画格子找出来,平均地去找。

    //	GetLABXYSeeds_ForGivenK
    // The k seed values are taken as uniform spatial pixel samples.
    void SLIC::GetLABXYSeeds_ForGivenK(
    	vector<double>&				kseedsl,
    	vector<double>&				kseedsa,
    	vector<double>&				kseedsb,
    	vector<double>&				kseedsx,
    	vector<double>&				kseedsy,
    	const int&					K,
    	const bool&					perturbseeds,
    	const vector<double>&		edgemag)
    {
    	int sz = m_width*m_height;
    	double step = sqrt(double(sz)/double(K));
    	int T = step;
    	int xoff = step/2;
    	int yoff = step/2;
    	
    	int n(0);int r(0);
    	for( int y = 0; y < m_height; y++ )
    	{
    		int Y = y*step + yoff;
    		if( Y > m_height-1 ) break;
    
    		for( int x = 0; x < m_width; x++ )
    		{
    			//int X = x*step + xoff;//square grid
    			int X = x*step + (xoff<<(r&0x1));//hex grid
    			if(X > m_width-1) break;
    
    			int i = Y*m_width + X;
    
    			//_ASSERT(n < K);
    			
    			//kseedsl[n] = m_lvec[i];
    			//kseedsa[n] = m_avec[i];
    			//kseedsb[n] = m_bvec[i];
    			//kseedsx[n] = X;
    			//kseedsy[n] = Y;
    			kseedsl.push_back(m_lvec[i]);
    			kseedsa.push_back(m_avec[i]);
    			kseedsb.push_back(m_bvec[i]);
    			kseedsx.push_back(X);
    			kseedsy.push_back(Y);
    			n++;
    		}
    		r++;
    	}
    
    	if(perturbseeds)
    	{
    		PerturbSeeds(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, edgemag);
    	}
    }
    

    2.8 核心函数:PerformSuperpixelSegmentation_VariableSandM

    功能:?

    //===========================================================================
    ///	PerformSuperpixelSegmentation_VariableSandM
    ///
    ///	Magic SLIC - no parameters
    ///
    ///	Performs k mean segmentation. It is fast because it looks locally, not
    /// over the entire image.
    /// This function picks the maximum value of color distance as compact factor
    /// M and maximum pixel distance as grid step size S from each cluster (13 April 2011).
    /// So no need to input a constant value of M and S. There are two clear
    /// advantages:
    ///
    /// [1] The algorithm now better handles both textured and non-textured regions
    /// [2] There is not need to set any parameters!!!
    ///
    /// SLICO (or SLIC Zero) dynamically varies only the compactness factor S,
    /// not the step size S.
    //===========================================================================
    
    
    void SLIC::PerformSuperpixelSegmentation_VariableSandM(
    	vector<double>&				kseedsl,
    	vector<double>&				kseedsa,
    	vector<double>&				kseedsb,
    	vector<double>&				kseedsx,
    	vector<double>&				kseedsy,
    	int*						klabels,
    	const int&					STEP,
    	const int&					NUMITR)
    {
    	int sz = m_width*m_height;
    	const int numk = kseedsl.size();
    	//double cumerr(99999.9);
    	int numitr(0);
    
    	//----------------
    	int offset = STEP;
    	if(STEP < 10) offset = STEP*1.5;
    	//----------------
    
    	vector<double> sigmal(numk, 0);
    	vector<double> sigmaa(numk, 0);
    	vector<double> sigmab(numk, 0);
    	vector<double> sigmax(numk, 0);
    	vector<double> sigmay(numk, 0);
    	vector<int> clustersize(numk, 0);
    	vector<double> inv(numk, 0);	//to store 1/clustersize[k] values
    	vector<double> distxy(sz, DBL_MAX);
    	vector<double> distlab(sz, DBL_MAX);
    	vector<double> distvec(sz, DBL_MAX);
    	vector<double> maxlab(numk, 10*10);	//THIS IS THE VARIABLE VALUE OF M, just start with 10
    	vector<double> maxxy(numk, STEP*STEP);	//THIS IS THE VARIABLE VALUE OF M, just start with 10
    
    	double invxywt = 1.0/(STEP*STEP);	//NOTE: this is different from how usual SLIC/LKM works
    
    	while( numitr < NUMITR )
    	{
    		//------
    		//cumerr = 0;
    		numitr++;
    		//------
    
    		distvec.assign(sz, DBL_MAX);
    		for( int n = 0; n < numk; n++ )
    		{
    			int y1 = max(0,			(int)(kseedsy[n]-offset));
    			int y2 = min(m_height,	(int)(kseedsy[n]+offset));
    			int x1 = max(0,			(int)(kseedsx[n]-offset));
    			int x2 = min(m_width,	(int)(kseedsx[n]+offset));
    
    			for( int y = y1; y < y2; y++ )
    			{
    				for( int x = x1; x < x2; x++ )
    				{
    					int i = y*m_width + x;
    					//_ASSERT( y < m_height && x < m_width && y >= 0 && x >= 0 );
    
    					double l = m_lvec[i];
    					double a = m_avec[i];
    					double b = m_bvec[i];
    
    					distlab[i] =	(l - kseedsl[n])*(l - kseedsl[n]) +
    									(a - kseedsa[n])*(a - kseedsa[n]) +
    									(b - kseedsb[n])*(b - kseedsb[n]);
    
    					distxy[i] =		(x - kseedsx[n])*(x - kseedsx[n]) +
    									(y - kseedsy[n])*(y - kseedsy[n]);
    
    					//------------------------------------------------------------------------
    					double dist = distlab[i]/maxlab[n] + distxy[i]*invxywt;	//only varying m, prettier superpixels
    					//double dist = distlab[i]/maxlab[n] + distxy[i]/maxxy[n];//varying both m and S
    					//------------------------------------------------------------------------
    					
    					if( dist < distvec[i] )
    					{
    						distvec[i] = dist;
    						klabels[i]  = n;
    					}
    				}
    			}
    		}
    		//-----------------------------------------------------------------
    		// Assign the max color distance for a cluster
    		//-----------------------------------------------------------------
    		if(0 == numitr)
    		{
    			maxlab.assign(numk,1);
    			maxxy.assign(numk,1);
    		}
    		{for( int i = 0; i < sz; i++ )
    		{
    			if(maxlab[klabels[i]] < distlab[i]) maxlab[klabels[i]] = distlab[i];
    			if(maxxy[klabels[i]] < distxy[i]) maxxy[klabels[i]] = distxy[i];
    		}}
    		//-----------------------------------------------------------------
    		// Recalculate the centroid and store in the seed values
    		//-----------------------------------------------------------------
    		sigmal.assign(numk, 0);
    		sigmaa.assign(numk, 0);
    		sigmab.assign(numk, 0);
    		sigmax.assign(numk, 0);
    		sigmay.assign(numk, 0);
    		clustersize.assign(numk, 0);
    
    		for( int j = 0; j < sz; j++ )
    		{
    			int temp = klabels[j];
    			//_ASSERT(klabels[j] >= 0);
    			sigmal[klabels[j]] += m_lvec[j];
    			sigmaa[klabels[j]] += m_avec[j];
    			sigmab[klabels[j]] += m_bvec[j];
    			sigmax[klabels[j]] += (j%m_width);
    			sigmay[klabels[j]] += (j/m_width);
    
    			clustersize[klabels[j]]++;
    		}
    
    		{for( int k = 0; k < numk; k++ )
    		{
    			//_ASSERT(clustersize[k] > 0);
    			if( clustersize[k] <= 0 ) clustersize[k] = 1;
    			inv[k] = 1.0/double(clustersize[k]);//computing inverse now to multiply, than divide later
    		}}
    		
    		{for( int k = 0; k < numk; k++ )
    		{
    			kseedsl[k] = sigmal[k]*inv[k];
    			kseedsa[k] = sigmaa[k]*inv[k];
    			kseedsb[k] = sigmab[k]*inv[k];
    			kseedsx[k] = sigmax[k]*inv[k];
    			kseedsy[k] = sigmay[k]*inv[k];
    		}}
    	}
    }
    

    2.9 辅助函数:SaveSuperpixelLabels2PPM

    将文件存为PPM格式,方便校验
    非功能重点,无需修改

    // 	SaveSuperpixelLabels2PGM
    //	Save labels to PGM in raster scan order.
    void SLIC::SaveSuperpixelLabels2PPM(
    	char*                           filename, 
    	int *                           labels, 
    	const int                       width, 
    	const int                       height)
    {
        FILE* fp;
        char header[20];
     
        fp = fopen(filename, "wb");
     
        // write the PPM header info, such as type, width, height and maximum
        fprintf(fp,"P6\n%d %d\n255\n", width, height);
     
        // write the RGB data
        unsigned char *rgb = new unsigned char [ (width)*(height)*3 ];
        int k = 0;
    	unsigned char c = 0;
        for ( int i = 0; i < (height); i++ ) {
            for ( int j = 0; j < (width); j++ ) {
    			c = (unsigned char)(labels[k]);
                rgb[i*(width)*3 + j*3 + 2] = labels[k] >> 16 & 0xff;  // r
                rgb[i*(width)*3 + j*3 + 1] = labels[k] >> 8  & 0xff;  // g
                rgb[i*(width)*3 + j*3 + 0] = labels[k]       & 0xff;  // b
    
    			// rgb[i*(width) + j + 0] = c;
                k++;
            }
        }
        fwrite(rgb, width*height*3, 1, fp);
    
        delete [] rgb;
     
        fclose(fp);
    }
    

    2.10 核心函数:EnforceLabelConnectivity

    功能:?

    //	EnforceLabelConnectivity
    //		1. finding an adjacent label for each new component at the start
    //		2. if a certain component is too small, assigning the previously found
    //		    adjacent label to this component, and not incrementing the label.
    
    void SLIC::EnforceLabelConnectivity(
    	const int*					labels,
    	//input labels that need to be corrected to remove stray labels
    	const int&					width,
    	const int&					height,
    	int*						nlabels,	//new labels
    	int&						numlabels,	
    	//the number of labels changes in the end if segments are removed
    	const int&					K) 
    	//the number of superpixels desired by the user
    {
    //	const int dx8[8] = {-1, -1,  0,  1, 1, 1, 0, -1};
    //	const int dy8[8] = { 0, -1, -1, -1, 0, 1, 1,  1};
    
    	const int dx4[4] = {-1,  0,  1,  0};
    	const int dy4[4] = { 0, -1,  0,  1};
    
    	const int sz = width*height;
    	const int SUPSZ = sz/K;
    	//nlabels.resize(sz, -1);
    	for( int i = 0; i < sz; i++ ) nlabels[i] = -1;
    	int label(0);
    	int* xvec = new int[sz];
    	int* yvec = new int[sz];
    	int oindex(0);
    	int adjlabel(0);//adjacent label
    	for( int j = 0; j < height; j++ )
    	{
    		for( int k = 0; k < width; k++ )
    		{
    			if( 0 > nlabels[oindex] )
    			{
    				nlabels[oindex] = label;
    				-
    				// Start a new segment
    				xvec[0] = k;
    				yvec[0] = j;
    	
    				// Quickly find an adjacent label for use later if needed
    				{for( int n = 0; n < 4; n++ )
    				{
    					int x = xvec[0] + dx4[n];
    					int y = yvec[0] + dy4[n];
    					if( (x >= 0 && x < width) && (y >= 0 && y < height) )
    					{
    						int nindex = y*width + x;
    						if(nlabels[nindex] >= 0) adjlabel = nlabels[nindex];
    					}
    				}}
    
    				int count(1);
    				for( int c = 0; c < count; c++ )
    				{
    					for( int n = 0; n < 4; n++ )
    					{
    						int x = xvec[c] + dx4[n];
    						int y = yvec[c] + dy4[n];
    
    						if( (x >= 0 && x < width) && (y >= 0 && y < height) )
    						{
    							int nindex = y*width + x;
    
    							if( 0 > nlabels[nindex] && labels[oindex] == labels[nindex] )
    							{
    								xvec[count] = x;
    								yvec[count] = y;
    								nlabels[nindex] = label;
    								count++;
    							}
    						}
    					}
    				}
    				
    				// If segment size is less then a limit, assign an
    				// adjacent label found before, and decrement label count.
    				if(count <= SUPSZ >> 2)
    				{
    					for( int c = 0; c < count; c++ )
    					{
    						int ind = yvec[c]*width+xvec[c];
    						nlabels[ind] = adjlabel;
    					}
    					label--;
    				}
    				label++;
    			}
    			oindex++;
    		}
    	}
    	numlabels = label;
    
    	if(xvec) delete [] xvec;
    	if(yvec) delete [] yvec;
    }
    

    2.11 核心函数: PerformSLICO_ForGivenK

    功能:

    //	PerformSLICO_ForGivenK
    // Zero parameter SLIC algorithm for a given number K of superpixels.
    void SLIC::PerformSLICO_ForGivenK(
    	const unsigned int*			ubuff,
    	const int					width,
    	const int					height,
    	int*						klabels,
    	int&						numlabels,
    	const int&					K,//required number of superpixels
    	const double&				m)//weight given to spatial distance
    {
    	vector<double> kseedsl(0);
    	vector<double> kseedsa(0);
    	vector<double> kseedsb(0);
    	vector<double> kseedsx(0);
    	vector<double> kseedsy(0);
    
    	//--------------------------------------------------
    	m_width  = width;
    	m_height = height;
    	int sz = m_width*m_height;
    	//--------------------------------------------------
    	//if(0 == klabels) klabels = new int[sz];
    	for( int s = 0; s < sz; s++ ) klabels[s] = -1;
    	//--------------------------------------------------
    	if(1)//LAB
    	{
    		DoRGBtoLABConversion(ubuff, m_lvec, m_avec, m_bvec);
    	}
    	else//RGB
    	{
    		m_lvec = new double[sz]; m_avec = new double[sz]; m_bvec = new double[sz];
    		for( int i = 0; i < sz; i++ )
    		{
    			m_lvec[i] = ubuff[i] >> 16 & 0xff;
    			m_avec[i] = ubuff[i] >>  8 & 0xff;
    			m_bvec[i] = ubuff[i]       & 0xff;
    		}
    	}
    	//--------------------------------------------------
    
    	bool perturbseeds(true);
    	vector<double> edgemag(0);
    	if(perturbseeds) DetectLabEdges(m_lvec, m_avec, m_bvec, m_width, m_height, edgemag);
    	GetLABXYSeeds_ForGivenK(kseedsl, kseedsa, kseedsb, kseedsx, kseedsy, K, perturbseeds, edgemag);
    
    	int STEP = sqrt(double(sz)/double(K)) + 2.0;//adding a small value in the even the STEP size is too small.
    	PerformSuperpixelSegmentation_VariableSandM(kseedsl,kseedsa,kseedsb,kseedsx,kseedsy,klabels,STEP,10);
    	numlabels = kseedsl.size();
    
    	int* nlabels = new int[sz];
    	EnforceLabelConnectivity(klabels, m_width, m_height, nlabels, numlabels, K);
    	{for(int i = 0; i < sz; i++ ) klabels[i] = nlabels[i];}
    	if(nlabels) delete [] nlabels;
    }
    

    以上为 SLIC 的算法主体


    3.1 辅助函数: LoadPPM

    非重点

    // Load PPM file
    void LoadPPM(char* filename, unsigned int** data, int* width, int* height)
    {
        char header[1024];
        FILE* fp = NULL;
        int line = 0;
     
        fp = fopen(filename, "rb");
     
        // read the image type, such as: P6
        // skip the comment lines
        while (line < 2) {    
            fgets(header, 1024, fp);
            if (header[0] != '#') {
                ++line;
            }
        }
        // read width and height
        sscanf(header,"%d %d\n", width, height);
     
        // read the maximum of pixels
        fgets(header, 20, fp);
     
        // get rgb data
        unsigned char *rgb = new unsigned char [ (*width)*(*height)*3 ];
        fread(rgb, (*width)*(*height)*3, 1, fp);
    
        *data = new unsigned int [ (*width)*(*height)*4 ];
        int k = 0;
        for ( int i = 0; i < (*height); i++ ) {
            for ( int j = 0; j < (*width); j++ ) {
                unsigned char *p = rgb + i*(*width)*3 + j*3;
                                          // a ( skipped )
                (*data)[k]  = p[2] << 16; // r
                (*data)[k] |= p[1] << 8;  // g
                (*data)[k] |= p[0];       // b
                k++;
            }
        }
    
        // ofc, later, you'll have to cleanup
        delete [] rgb;
     
        fclose(fp);
    }
    

    2.11-2 辅助函数:CheckLabelswithPPM

    非重点

    // Load PPM file
    int CheckLabelswithPPM(char* filename, int* labels, int width, int height)
    {
        char header[1024];
        FILE* fp = NULL;
        int line = 0, ground = 0;
     
        fp = fopen(filename, "rb");
     
        // read the image type, such as: P6
        // skip the comment lines
        while (line < 2) {    
            fgets(header, 1024, fp);
            if (header[0] != '#') {
                ++line;
            }
        }
        // read width and height
    	int w(0);
    	int h(0);
        sscanf(header,"%d %d\n", &w, &h);
    	if (w != width || h != height) return -1;
     
        // read the maximum of pixels
        fgets(header, 20, fp);
     
        // get rgb data
        unsigned char *rgb = new unsigned char [ (w)*(h)*3 ];
        fread(rgb, (w)*(h)*3, 1, fp);
    
        int num = 0, k = 0;
        for ( int i = 0; i < (h); i++ ) {
            for ( int j = 0; j < (w); j++ ) {
                unsigned char *p = rgb + i*(w)*3 + j*3;
                                      // a ( skipped )
                ground  = p[2] << 16; // r
                ground |= p[1] << 8;  // g
                ground |= p[0];       // b
                
    			if (ground != labels[k])
    				num++;
    
    			k++;
            }
        }
    
        // ofc, later, you'll have to cleanup
        delete [] rgb;
        fclose(fp);
    	return num;
    }
    

    主函数

    int main (int argc, char **argv)
    {
    	unsigned int* img = NULL;
    	int width(0);
    	int height(0);
    
    	LoadPPM((char *)"input_image.ppm", &img, &width, &height);
    	if (width == 0 || height == 0) return -1;
    
    	int sz = width*height;
    	int* labels = new int[sz];
    	int numlabels(0);
    	SLIC slic;
    	int m_spcount;
    	double m_compactness;
    	m_spcount = 200;
    	m_compactness = 10.0;
        auto startTime = Clock::now();
    	slic.PerformSLICO_ForGivenK(img, width, height, labels, numlabels, m_spcount, m_compactness);//for a given number K of superpixels
        auto endTime = Clock::now();
        auto compTime = chrono::duration_cast<chrono::microseconds>(endTime - startTime);
        cout <<  "Computing time=" << compTime.count()/1000 << " ms" << endl;
    
    	int num = CheckLabelswithPPM((char *)"check.ppm", labels, width, height);
    	if (num < 0) {
    		cout <<  "The result for labels is different from output_labels.ppm." << endl;
    	} else {
    		cout <<  "There are " << num << " points' labels are different from original file." << endl;
    	}
    	
    	slic.SaveSuperpixelLabels2PPM((char *)"output_labels.ppm", labels, width, height);
    	if(labels) delete [] labels;
    	
    	if(img) delete [] img;
    
    	return 0;
    }
    
    展开全文
  • SLIC超像素分割MATLAB代码SLIC 超像素 该存储库提供了带有 Python 和 Matlab 接口的简单线性迭代聚类 (SLIC) 算法的代码。 在这两种情况下,都提供了一个演示文件,应该很容易使用。 这两个版本都可以为灰色、彩色...
  • SLIC超像素分割代码

    2018-05-12 14:45:36
    代码为C代码、需编译成MATLAB可执行文件后使用。经本人使用验证有效。。有问题的可以私信。。该代码确定可以实现相应的功能。。
  • 给定K个超像素的SLIC算法 具体代码: 完整代码 SLIC.cpp SLIC.h 运行结果: 部分代码分析 1.RGB -> XYZ 大致分析: 详细代码: void SLIC::RGB2XYZ( const int& sR, const int& sG, const int& sB, double& ...
  • SLIC超像素分割算法MATLAB算法代码实现,超像素分割关键代码形式

空空如也

空空如也

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

slic代码