-
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代码 效果还行,可以试一下 -
slic代码matlab-ranking_saliency:c++codeforpaper"saliencydetectionviagraph
2021-06-02 20:16:43切片代码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
调用关系需要做一下修改,
原:
-
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
-
-
SLIC超像素 MATLAB经典程序 直接可用
2018-03-30 08:06:30在MATLAB下直接可运行,已调试通过,不是epfl网页里面要调用C++的程序。适合学习MATLAB的朋友。。。 -
并行计算 Blog 01 —— SLIC代码切分
2021-11-23 16:13:57并行计算 Blog 01 SLIC 代码切分并行计算 Blog 01
SLIC 代码切分
- 函数头
#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 超体素(三维坐标的方向数组)
- 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:SLIC
2021-06-17 01:29:54SLIC超像素分割MATLAB代码SLIC 超像素 该存储库提供了带有 Python 和 Matlab 接口的简单线性迭代聚类 (SLIC) 算法的代码。 在这两种情况下,都提供了一个演示文件,应该很容易使用。 这两个版本都可以为灰色、彩色... -
SLIC超像素分割代码
2018-05-12 14:45:36源代码为C代码、需编译成MATLAB可执行文件后使用。经本人使用验证有效。。有问题的可以私信。。该代码确定可以实现相应的功能。。 -
并行计算 SLIC超像素算法(二) 代码分析
2021-10-21 10:06:15给定K个超像素的SLIC算法 具体代码: 完整代码 SLIC.cpp SLIC.h 运行结果: 部分代码分析 1.RGB -> XYZ 大致分析: 详细代码: void SLIC::RGB2XYZ( const int& sR, const int& sG, const int& sB, double& ... -
SLIC超像素matlab代码实现.zip
2019-08-09 11:21:04SLIC超像素分割算法MATLAB算法代码实现,超像素分割关键代码形式