【OpenCv3】 VS C++ (五):SLIC超像素分割算法

article/2025/10/1 7:27:34

下一节地址:https://blog.csdn.net/qq_40515692/article/details/102788157
OpenCv专栏:https://blog.csdn.net/qq_40515692/article/details/102885061

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

这一节讲的是用C++实现超像素,下一节讲在超像素基础上用Kmeans分类进行分割,代码先根据超像素SLIC算法编写,后参考github的代码优化了一些地方,然后根据老师说的有更改了一些地方,欢迎大家一起讨论。

题目如下:
在这里插入图片描述
简单解法(HSV 直方图阈值)如下(至于为什么不用Matlab了,因为作为C系程序员,写c++真滴好爽呀):
https://blog.csdn.net/qq_40515692/article/details/102749271

这一节先讲SLIC超像素算法,下一节讲在超像素基础上用Kmeans分类进行分割,参考博客如下:
https://www.jianshu.com/p/d0ef931b3ddf
https://blog.csdn.net/duyue3052/article/details/82149877

效果如下(虽然还是有些可以更好的地方,但是可以看到已经分得很不错了,当然还有缺陷更少的算法可以更加好的分割比如像素点较少的蓝色线等的算法),完整代码附在下一节了:
在这里插入图片描述
在这里插入图片描述

一、分析

在写较复杂的程序时,前期的百度、google参考别人思路、考虑算法的步骤十分关键,甚至应该用一半实现代码以上的时间。

  • 为什么使用超像素?

如果看了之前的颜色阈值分割程序就会发现,之前的阈值分割没有考虑更高维的颜色数据,更重要的是没有利用各个像素点的位置信息(比如相邻的像素点更有可能属于一张分割图片),所以我们使用超像素算法,在保留图像像素的位置、颜色信息的同时,简化问题。

  • 超像素示意图:
    在这里插入图片描述
    这里贴出SLIC的步骤:
  1. 撒种子。将K个超像素中心分布到图像的像素点上。(这里我的实现里面直接先根据图像大小和超像素的数目,均匀发布)

  2. 微调种子的位置。以K为中心的3×3范围内,移动超像素中心到这9个点中梯度最小的点上。这样是为了避免超像素点落到噪点或者边界上。(这里我也进行了实现,但是对于最终结果貌似没有太大影响,篇幅有限就不进行讲解)

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

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

  5. 对每一个超像素中心,重新计算它的位置(根据的是属于该超像素的所有像素的位置中心)以及其LAB值(马上会讲)。

    重复4 5 两步。

其中关键的4,5步其实用到了kmeans算法的思想,如下图所示,假设有两个超像素点(红点、蓝点),一系列像素点(绿色),首先对每个像素点计算应该归属与哪一个超像素点、分类(如图片b、c所示)。

然后进行第五步计算中心,让超像素移动到中心,不断重复,最终成功划分。

但是应注意实际的SLIC算法和kmeans算法有区别,为了加快计算速度,在进行第4步时只计算了超像素中心有限范围内的点。(这是我实现算法时的理解,如果有误希望指出)

需要注意的是这里的“距离”可以是多维的数据距离,而不一定是比如像素之间的row、col之间的距离(比如RGB的欧式距离等)。

在这里插入图片描述

  • 然后就需要考虑如何针对一张图像,度量”距离“?

这里先简单介绍LAB色彩空间。Lab色彩模型是由亮度(L)和有关色彩的a, b三个要素组成。L表示亮度(Luminosity),L的值域由0(黑色)到100(白色)。a表示从洋红色至绿色的范围(a为负值指示绿色而正值指示品红),b表示从黄色至蓝色的范围(b为负值指示蓝色而正值指示黄色)。

Lab色彩模型的绝妙之处还在于它弥补了RGB色彩模型色彩分布不均的不足,因为RGB模型在蓝色到绿色之间的过渡色彩过多,而在绿色到红色之间又缺少黄色和其他色彩。如果我们想在数字图形的处理中保留尽量宽阔的色域和丰富的色彩,最好选择Lab。

然后就是如何计算”距离“,距离计算方法如下,其中,dc代表颜色距离,ds代表空间距离,Ns是类内最大空间距离,Nc为最大的颜色距离:

在这里插入图片描述

二、读取图片,完成大致框架

第一步还是先包含头文件,还有定义需要用到的变量,需要配置opencv,在VS上的配置可以参考:
https://blog.csdn.net/qq_40515692/article/details/81042303

#include <opencv2/opencv.hpp>
#include <iostream>  using namespace cv;
using namespace std;#define sqrtK 128		// 超像素个数128*128
#define sqrtN 512		// 图像格式512*512int label[sqrtN][sqrtN];		// 图像各像素点归属
int dis[sqrtN][sqrtN];			// 图像各像素点距离struct cluster{int row, col, l, a, b;
};
cluster clusters[sqrtK*sqrtK];		// 存储超像素的像素坐标

我们先定义好大致框架,首先是读取图片,转换为LAB色彩空间,然后把上面提到的步骤分步定义为函数。

int main(){// 注意修改文件位置Mat src = imread("C:\\Users\\ttp\\Desktop\\map.bmp"), lab;// resize图片并滤波resize(src, src, Size(sqrtN, sqrtN));// GaussianBlur(src, src, Size(3, 3), 1, 1);// 得到Lab色彩空间,需要注意的是:// 1.opencv里面默认为BGR排列方式// 2.LAB通道范围取决于转换前的通道范围,这样其实也方便处理// 	例如:开始是0-255,转换后也是0-255,而不是LAB规定的[127,-128]cvtColor(src, lab, CV_BGR2Lab);int N = sqrtN * sqrtN;			// 像素总数 512*512int K = sqrtK * sqrtK;			// 超像素个数 128*128int S = sqrt(N / K);			// 相邻种子点距离(超像素边长) 4// 1.初始化像素init_clusters(lab,S);cout << "1-初始化像素-完成\n";// 2.微调种子的位置 貌似好一点,没有太大区别// 所以这里就直接注释了// move_clusters(lab);// cout << "2-微调种子的位置-完成\n";for (int i = 0; i < 5; i++) {// 3.4.初始化数据update_pixel(lab, 2*S);cout << "3-初始化数据-完成\n";// 5.让超像素位于正中间updaye_clusters(lab);cout << "4-让超像素位于正中间-完成\n";// -------------------这两个函数主要是帮助显示结果的// 6.标识超像素draw_clusters(src.clone());cout << "5-标识超像素-完成\n";// 7.绘制超像素结果图final_draw(lab, lab.clone());cout << "6-绘制超像素结果图-完成\n";// opencv的函数,每1000ms更新一下,动态显示图片waitKey(1000);// -----------------------------------------------}imshow("原图", src);waitKey(0);
}

三、各函数实现

1.init_clusters函数

init_clusters函数就是我们的第一步了,传入的参数为lab的色彩空间和S。

需要注意的是opencv里面Mat类的赋值并不是直接把Mat的数据全部拷贝一份赋值。
而是类似于C++的引用赋值(比如:Mat a,b; b=a; 改变b也会改变a)。
如果想赋值得到一个全新的图像矩阵,可以使用b=a.clone();这种方式。
所以这里就直接传lab了,效率应该不会低。

fill函数用于对一段空间赋值,这里即将矩阵dis赋-1。(在非opencv程序也可以使用)

void init_clusters(const Mat lab,int S) {// 初始化每一个超像素的坐标for (int i = 0; i < sqrtK; i++) {int temp_row = S / 2 + i * S;for (int j = 0; j < sqrtK; j++) {clusters[i * sqrtK + j].row = temp_row;clusters[i * sqrtK + j].col = S / 2 + j * S;// cout << clusters[i * sqrtK + j].row << "\t" << clusters[i * sqrtK + j].col // << "\t" << clusters[i * sqrtK + j].h << endl;}}// 初始化每一个像素的label(即属于哪一个超像素)for (int i = 0; i < sqrtN; i++) {int cluster_row = i / S;for (int j = 0; j < sqrtN; j++) {label[i][j] = cluster_row * sqrtK + j / S;// cout << cluster_row * sqrtK + j / S << endl;}}// 像素与超像素的距离先假设为-1fill(dis[0], dis[0] + (sqrtN * sqrtN), -1);
}

2.update_pixel函数

首先我们还是实现距离计算函数吧,这个函数传入参数为lab,clusters_index表示超像素的索引,
i,j表示像素的横纵坐标。

lab.at(row,col)属于opencv里面的写法,用于访问矩阵lab在坐标(row,col)的值
Vec3b表示3通道,每个通道为uchar类型(0-255)。为什么是Vec3b,参考完成大致框架里面的代码注释。

代码和上面的公式几乎没区别(权重取得有点随意)。

inline int get_distance(const Mat lab,int clusters_index,int i,int j) {int dl = clusters[clusters_index].l - lab.at<Vec3b>(i, j)[0];int da = clusters[clusters_index].a - lab.at<Vec3b>(i, j)[1];int db = clusters[clusters_index].b - lab.at<Vec3b>(i, j)[2];int dx = clusters[clusters_index].row - i;int dy = clusters[clusters_index].col - j;int h_distance = dl * dl + da * da + db * db;int xy_distance = dx * dx + dy * dy;//cout << h_distance << "\t" << xy_distance * 100 << endl;return h_distance + xy_distance * 100;
}

然后就可以完成update_pixel函数了

void update_pixel(const Mat lab,int s) {for (int i = 0; i < sqrtK * sqrtK; i++) {	// 对于每一个超像素int clusters_x = clusters[i].row;int clusters_y = clusters[i].col;for (int x = -s; x <= s; x++) {			// 在它周围-s到s的范围内for (int y = -s; y <= s; y++) {int now_x = clusters_x + x;int now_y = clusters_y + y;if (now_x < 0 || now_x >= sqrtN || now_y < 0 || now_y >= sqrtN)continue;int new_dis = get_distance(lab, i, now_x, now_y);// 如果为-1(还没有更新过)或者新的距离更小,就更换当前像素属于的超像素if (dis[now_x][now_y] > new_dis || dis[now_x][now_y] == -1) {dis[now_x][now_y] = new_dis;label[now_x][now_y] = i;}}}}
}

3. updaye_clusters函数

这个函数就是根据当前超像素的所有归属像素来更新位置。

需要注意的是C++用new申请空间时后面加上()会自动初始化申请的空间。
还有就是记得delete

void updaye_clusters(const Mat lab) {int *sum_count = new int[sqrtK * sqrtK]();int *sum_i = new int[sqrtK * sqrtK]();int *sum_j = new int[sqrtK * sqrtK](); int* sum_l = new int[sqrtK * sqrtK]();int* sum_a = new int[sqrtK * sqrtK]();int* sum_b = new int[sqrtK * sqrtK]();for (int i = 0; i < sqrtN; i++) {for (int j = 0; j < sqrtN; j++) {sum_count[label[i][j]]++;sum_i[label[i][j]] += i;sum_j[label[i][j]] += j; sum_l[label[i][j]] += lab.at<Vec3b>(i, j)[0];sum_a[label[i][j]] += lab.at<Vec3b>(i, j)[1];sum_b[label[i][j]] += lab.at<Vec3b>(i, j)[2];}}for (int i = 0; i < sqrtK * sqrtK; i++) {if (sum_count[i] == 0) {continue;}clusters[i].row = round(sum_i[i] / sum_count[i]);clusters[i].col = round(sum_j[i] / sum_count[i]); clusters[i].l = round(sum_l[i] / sum_count[i]);clusters[i].a = round(sum_a[i] / sum_count[i]);clusters[i].b = round(sum_b[i] / sum_count[i]);}delete[] sum_count;delete[] sum_i;delete[] sum_j;delete[] sum_l;delete[] sum_a;delete[] sum_b;
}

4. 显示函数

OK, 到了这一步其实算法已经完成了。我们在实现一下用于显示的函数吧。draw_clusters函数就是画出每一个超像素点,final_draw函数就是绘制一张超像素分割图。

void draw_clusters(const Mat copy) {for (int index = 0; index < sqrtK * sqrtK; index++) {Point p(clusters[index].row, clusters[index].col);circle(copy, p, 1, Scalar(0, 0, 255), 1);  // 画半径为1的圆(画点)}imshow("超像素示意图", copy);
}void final_draw(const Mat lab,Mat copy) {for (int i = 0; i < sqrtN; i++) {for (int j = 0; j < sqrtN; j++) {int index = label[i][j];copy.at<Vec3b>(i, j)[0] = lab.at<Vec3b>(clusters[index].row, clusters[index].col)[0];copy.at<Vec3b>(i, j)[1] = lab.at<Vec3b>(clusters[index].row, clusters[index].col)[1];copy.at<Vec3b>(i, j)[2] = lab.at<Vec3b>(clusters[index].row, clusters[index].col)[2];}}cvtColor(copy, copy, CV_Lab2BGR);imshow("分割图", copy);
}

最后效果如下:

在这里插入图片描述


2020 7.3更新:

完成了超像素框绘制的功能,这里给出汇总代码:

#include <opencv2/opencv.hpp>
#include <iostream>  using namespace cv;
using namespace std;#define sqrtK 32		// 超像素个数32*32
#define sqrtN 512		// 图像格式512*512int label[sqrtN][sqrtN];		// 图像各像素点归属
int dis[sqrtN][sqrtN];			// 图像各像素点距离struct cluster {int row, col, l, a, b;
};
cluster clusters[sqrtK * sqrtK];		// 存储超像素的像素坐标、颜色/*** 初始化每一个超像素的坐标* 初始化每一个像素的label(即属于哪一个超像素)* 像素与超像素的距离先假设为-1
*/
void init_clusters(const Mat lab, int S) {for (int i = 0; i < sqrtK; i++) {int temp_row = S / 2 + i * S;for (int j = 0; j < sqrtK; j++) {clusters[i * sqrtK + j].row = temp_row;clusters[i * sqrtK + j].col = S / 2 + j * S;}}for (int i = 0; i < sqrtN; i++) {int cluster_row = i / S;for (int j = 0; j < sqrtN; j++) {label[i][j] = cluster_row * sqrtK + j / S;}}fill(dis[0], dis[0] + (sqrtN * sqrtN), -1);
}inline int get_distance(const Mat lab, int clusters_index, int i, int j) {int dl = clusters[clusters_index].l - lab.at<Vec3b>(i, j)[0];int da = clusters[clusters_index].a - lab.at<Vec3b>(i, j)[1];int db = clusters[clusters_index].b - lab.at<Vec3b>(i, j)[2];int dx = clusters[clusters_index].row - i;int dy = clusters[clusters_index].col - j;int h_distance = dl * dl + da * da + db * db;int xy_distance = dx * dx + dy * dy;//cout << h_distance << "\t" << xy_distance * 100 << endl;return h_distance + xy_distance * 100;
}void update_pixel(const Mat lab, int s) {for (int i = 0; i < sqrtK * sqrtK; i++) {	// 对于每一个超像素int clusters_x = clusters[i].row;int clusters_y = clusters[i].col;for (int x = -s; x <= s; x++) {			// 在它周围-s到s的范围内for (int y = -s; y <= s; y++) {int now_x = clusters_x + x;int now_y = clusters_y + y;if (now_x < 0 || now_x >= sqrtN || now_y < 0 || now_y >= sqrtN)continue;int new_dis = get_distance(lab, i, now_x, now_y);// 如果为-1(还没有更新过)或者新的距离更小,就更换当前像素属于的超像素if (dis[now_x][now_y] > new_dis || dis[now_x][now_y] == -1) {dis[now_x][now_y] = new_dis;label[now_x][now_y] = i;}}}}
}void updaye_clusters(const Mat lab) {int* sum_count = new int[sqrtK * sqrtK]();int* sum_i = new int[sqrtK * sqrtK]();int* sum_j = new int[sqrtK * sqrtK]();int* sum_l = new int[sqrtK * sqrtK]();int* sum_a = new int[sqrtK * sqrtK]();int* sum_b = new int[sqrtK * sqrtK]();for (int i = 0; i < sqrtN; i++) {for (int j = 0; j < sqrtN; j++) {sum_count[label[i][j]]++;sum_i[label[i][j]] += i;sum_j[label[i][j]] += j;sum_l[label[i][j]] += lab.at<Vec3b>(i, j)[0];sum_a[label[i][j]] += lab.at<Vec3b>(i, j)[1];sum_b[label[i][j]] += lab.at<Vec3b>(i, j)[2];}}for (int i = 0; i < sqrtK * sqrtK; i++) {if (sum_count[i] == 0) {continue;}clusters[i].row = round(sum_i[i] / sum_count[i]);clusters[i].col = round(sum_j[i] / sum_count[i]);clusters[i].l = round(sum_l[i] / sum_count[i]);clusters[i].a = round(sum_a[i] / sum_count[i]);clusters[i].b = round(sum_b[i] / sum_count[i]);}delete[] sum_count;delete[] sum_i;delete[] sum_j;delete[] sum_l;delete[] sum_a;delete[] sum_b;
}void draw_clusters(const Mat copy) {for (int index = 0; index < sqrtK * sqrtK; index++) {Point p(clusters[index].row, clusters[index].col);circle(copy, p, 1, Scalar(0, 0, 255), 1);  // 画半径为1的圆(画点)}imshow("超像素示意图", copy);
}void final_draw(const Mat lab, Mat copy) {for (int i = 0; i < sqrtN; i++) {for (int j = 0; j < sqrtN; j++) {int index = label[i][j];copy.at<Vec3b>(i, j)[0] = lab.at<Vec3b>(clusters[index].row, clusters[index].col)[0];copy.at<Vec3b>(i, j)[1] = lab.at<Vec3b>(clusters[index].row, clusters[index].col)[1];copy.at<Vec3b>(i, j)[2] = lab.at<Vec3b>(clusters[index].row, clusters[index].col)[2];}}cvtColor(copy, copy, CV_Lab2BGR);imshow("分割图", copy);
}void draw_edge(const Mat lab, Mat copy) {// 这里的代码和上面的函数几乎一样,都是同标签的绘制相应的超像素颜色,因为方便用户自己选用绘制函数所以没有调用上面的函数for (int i = 0; i < sqrtN; i++) {for (int j = 0; j < sqrtN; j++) {int index = label[i][j];copy.at<Vec3b>(i, j)[0] = lab.at<Vec3b>(clusters[index].row, clusters[index].col)[0];copy.at<Vec3b>(i, j)[1] = lab.at<Vec3b>(clusters[index].row, clusters[index].col)[1];copy.at<Vec3b>(i, j)[2] = lab.at<Vec3b>(clusters[index].row, clusters[index].col)[2];}}// 这里的思路是4个方向,一旦有标签不同,就设置为黑色static int X[] = { 0,0,-1,1 };static int Y[] = { 1,-1,0,0 };cvtColor(copy, copy, CV_Lab2BGR); // 改成BGR,方便后面设置边框的颜色。for (int i = 0; i < sqrtN; i++) {for (int j = 0; j < sqrtN; j++) {int index = label[i][j];for (int k = 0; k < 4; k++) {if (index != label[i + X[k]][j + X[k]])copy.at<Vec3b>(i, j)[0] = copy.at<Vec3b>(i, j)[1] = copy.at<Vec3b>(i, j)[2] = 0;}}}imshow("超像素边界", copy);
}int main() {// 注意修改文件位置Mat src = imread("C:\\Users\\ttp\\Desktop\\map.bmp"), lab;// resize图片并高斯滤波(可选)resize(src, src, Size(sqrtN, sqrtN));// GaussianBlur(src, src, Size(3, 3), 1, 1);/**得到Lab色彩空间,需要注意的是:1.opencv里面默认为BGR排列方式2.LAB通道范围取决于转换前的通道范围,这样其实也方便处理例如:开始是0-255,转换后也是0-255,而不是LAB规定的[127,-128]*/cvtColor(src, lab, CV_BGR2Lab);int N = sqrtN * sqrtN;			// 像素总数 512*512int K = sqrtK * sqrtK;			// 超像素个数 128*128int S = sqrt(N / K);			// 相邻种子点距离(超像素边长) 4// 1.初始化像素init_clusters(lab, S);cout << "1-初始化像素-完成\n";// 2.微调种子的位置 貌似好一点,没有太大区别,所以这里就直接省略了for (int i = 0; i < 5; i++) {// 3.4.初始化数据update_pixel(lab, 2 * S);cout << "3-初始化数据-完成\n";// 5.让超像素位于正中间updaye_clusters(lab);cout << "4-让超像素位于正中间-完成\n";// -------------------这两个函数主要是帮助显示结果的// 6.标识超像素draw_clusters(src.clone());cout << "5-标识超像素-完成\n";// 7.绘制超像素结果图final_draw(lab, lab.clone());cout << "6-绘制超像素结果图-完成\n";draw_edge(lab, lab.clone());// opencv的函数,每1000ms更新一下,动态显示图片waitKey(30);// -----------------------------------------------}imshow("原图", src);waitKey(0);
}

运行结果:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


http://chatgpt.dhexx.cn/article/khHQJcBj.shtml

相关文章

superpixels(超像素)

superpixels(超像素&#xff09; 1.理解&#xff1a; 超像素不是在普通的像素基础上继续微观细分&#xff0c;超像素是一系列像素的集合&#xff0c;这些像素具有类似的颜色、纹理等特征&#xff0c;距离也比较近。其中超像素比较常用的一种方法是SLIC Semantic Segmentatio…

Seeds超像素分割

#%% SEED超像素分割 import cv2 import numpy as np import imageio # print(dir(cv2.ximgproc))img imageio.imread(rE:\Vaihingen\data\orginalimages\top_mosaic_09cm_area31.tif)[:,:,::-1] converted_img cv2.cvtColor(img, cv2.COLOR_BGR2HSV)# print(type(img_feature…

Python实现超像素分割

目录 一、什么是超像素&#xff1f;二、超像素具有哪些特点&#xff1f;三、Simple Linear Iterative Clustering (SLIC)算法实现步骤四、SLIC算法代码实现五、效果展示和分析六、基于超像素的边缘检测代码七、基于超像素的边缘检测效果展示与分析八、思维扩展参考资料注意事项…

基于Matlab的SLIC超像素分割算法分析

SLIC超像素分割算法分析 1&#xff1a;导入原始照片&#xff0c;初始化聚类中心&#xff0c;按照设定的超像素个数&#xff0c;在图像内均匀的分配聚类中心。假设图片总共有 N 个像素点&#xff0c;预分割为 s 个相同尺寸的超像素&#xff0c;那么每个超像素的大小为N/ s &…

超像素分割算法————综述

参考&#xff1a;超像素—学习笔记 什么是超像素&#xff1f;评价标准&#xff1f;SLIC、SEED、ETPS算法 比较的指标&#xff1a;图像边界的粘附性、算法速度、存储效率、分割性能 超像素算法&#xff1a;将像素组合成感知有意义的原子区域( atomic regions)&#xff0c;其可…

超像素分割 SLIC算法 使用示例

参考博客 介绍超像素分割 & SLIC算法 SLIC超像素分割详解&#xff08;一&#xff09;&#xff1a;简介_计算机视觉life的博客-CSDN博客_slic超像素分割 机器学习&#xff1a;simple linear iterative clustering (SLIC) 算法_Matrix_11的博客-CSDN博客_简单线性迭代聚类…

图像处理: 超像素(superpixels)分割 SLIC算法

原理 超像素概念是2003年Xiaofeng Ren提出和发展起来的图像分割技术&#xff0c;是指具有相似纹理、颜色、亮度等特征的相邻像素构成的有一定视觉意义的不规则像素块。它利用像素之间特征的相似性将像素分组,用少量的超像素代替大量的像素来表达图片特征,很大程度上降低了图像…

超像素SLIC算法源码阅读

超像素SLIC算法源码阅读 超像素SLIC算法源码阅读SLIC简介源码阅读实验结果其他超像素算法对比 超像素SLIC算法源码阅读 SLIC简介 SLIC的全称Simple Linear Iterative Clustering&#xff0c;即简单线性迭代聚类&#xff0c;论文和代码链接如下&#xff1a; 论文传送门&#x…

python 超像素分割

SILC算法超像素分割&#xff08;源码实现&#xff09; 主体代码来自github.com/laixintao/slic-python-implementation 原代码中只有分割之后的小方块 即1.png 没有明显边界 没有继续进行图像分割 源码修改&#xff1a; 1.向Cluster类添加了label属性&#xff0c;以便于标记…

超像素分割学习笔记

学习目标 掌握超像素分割的原理、超像素分割方法的推导过程以及实现方法 1.1 超像素 超像素是指将具有相似纹理、颜色、亮度等特征的相邻像素聚合成某一个像素块&#xff0c;结合超像素的思想&#xff0c;这样可以使少量的像素块代替原本大量的像素。 目前超像素广泛应用于图…

SLIC超像素算法

原文出自&#xff1a;https://blog.csdn.net/Fighting_Dreamer/article/details/77170859 SLIC与目前最优超像素算法的比较 Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi, Pascal Fua, and Sabine Susstrunk 摘要 近年来&#xff0c;计算机视觉应用越来…

超像素池化全监督语义分割

Efficient semantic image segmentation with superpixel pooling 摘要 在这项工作中&#xff0c;我们评估了超像素池化层在深层网络结构中用于语义分割的应用。超像素池化是一种灵活有效的方法&#xff0c;可以替代其他包含空z间先验信息的池策略。我们提出了一个简单而高效…

SLIC超像素分割算法

SLIC超像素分割算法 《SLIC Superpixels》 摘要 超像素在计算机视觉应用中越来越受欢迎。然而&#xff0c;很少有算法能够输出所需数量的规则、紧凑的超级像素&#xff0c;并且计算开销低。我们介绍了一种新的算法&#xff0c;将像素聚类在组合的五维颜色和图像平面空间中&a…

matlab 超像素合并,超像素区域合并

应广大学术同行的请求,将以往研究的一些代码进行整理,特发布一个学术版本的小软件工具:SuperpixelMerge, 基本功能:实现超像素的区域合并 参数说明:共7个参数,分别为图像路径、超像素分割标记图像路径、输出结果路径、合并准则、合并后区域个数、形状参数、紧凑度参数。详…

超像素—学习笔记

文章目录 概念超像素判别条件超像素初始化的方法超像素算法SLIC算法 参考资料 概念 超像素由一系列位置相邻且颜色、亮度、纹理等特征相似的像素点组成的小区域。这些小区域大多保留了进一步进行图像分割的有效信息&#xff0c;且一般不会破坏图像中物体的边界信息。 超像素是…

超像素采样网络(英伟达)

Superpixel Sampling Networks 摘要 超像素为图像数据提供了一种高效的低/中层次的表示&#xff0c;大大减少了后续视觉任务的图像基元数量。现有的超像素算法是不可微的&#xff0c;这使得它们很难集成到其他端到端可训练的深度神经网络中。我们开发了一种新的超像素采样可微…

超像素、语义分割、实例分割、全景分割

图像分割&#xff08;Image segmentation&#xff09;就是根据某些规则把图像中的像素分成不同的部分&#xff08;打上不同的标签&#xff09;。 1. 超像素&#xff08;superpixels&#xff09; 超像素并不是在普通的像素基础上继续像微观细分&#xff0c;恰恰相反的是&#…

超像素

《超像素》   超像素是一种以聚类思想为初衷的方法&#xff0c;目的是为了对较大像素的图像进行区域划分&#xff0c;来帮助理解&#xff0c;本文介绍了一个开源项目在火灾检测场景使用超像素&#xff0c;比较巧妙&#xff0c;虽然效果不是很理想&#xff0c;但是提供了一个…

超像素学习笔记(1)——概念及判别条件

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、超像素的概念二、超像素判别条件&#xff1a;一般参考三个指标1.Undersegmentation Error&#xff08;UE&#xff09;——欠分割误差2.Boundary Recall&…

超像素(superpixel)——SLIC和深度学习法

定义 可以理解成在图像上做的聚类问题。超像素的做法是将感知上相似的像素组在一起&#xff0c;称为一个超像素&#xff0c;以此来提供图像数据的紧凑表示。然后在后续的处理&#xff0c;处理单位就变成了超像素&#xff0c;而不是我们常用的像素。 一般超像素的结果可以为下…