基于Kmeans聚类算法实现图像分割(从原理开始实现)

一、Kmeans聚类算法基本原理
K-Means算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本集划分为K个簇。让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大。
以彩色图像为例:基于彩色图像的RGB三通道为xyz轴建立空间直角坐标系,那么一副图像上的每个像素点与该空间直角坐标系建立了一 一映射(双射)的关系。
从空间直角坐标系中随机取 k 个点,作为 k 个簇的各自的中心。计算所有像素点到k个簇心的距离,并将所有像素点划分至与其距离最小的簇类。自此聚类完成。其中,距离定义为欧氏距离:
在这里插入图片描述
其中r,g,b分别表示红绿蓝三通道,r1,g1,b1为彩色图片中某像素点;r0,g0,b0表示某簇类的簇心。
二、基于Kmeans图像分割算法流程
Note:彩色图像的操作是基于一个三维空间
1、加载图像,获取图像的所有像素点并将其转换为样本数据。
2、开始迭代
a)、初始化簇心坐标。
a)、更新簇心坐标,遍历样本数据中的数据点并计算数据点与所有簇心的距离。对于某数据点计算得到的与所有簇类的欧氏距离中,取欧氏距离最小所对应的簇类作为该数据点对应的类。
c)、计算更新后的簇心坐标与更新前的簇心坐标的均方误差。若均方误差仍大于某阈值,则重复b),反之结束迭代。
Kmeans的详细算法流程参考博文:
https://www.cnblogs.com/pinard/p/6164214.html
三、代码主函数部分
1、加载图片

	Mat src, dst;
	src = imread("J20.jpg");
	namedWindow("输入图像", WINDOW_AUTOSIZE);
	imshow("输入图像", src);

2、初始化颜色(图像分割后需要上色)

	Scalar colorTab[] = {
   
		Scalar(0,0,255),
		Scalar(0,255,0),
		Scalar(255,0,0),
		Scalar(0,255,255),
		Scalar(255,0,255),
	};

3、初始化簇类数,并将所有的像素点全部转换为样本数据

	int sampleCount = width*height;
	int clusterCount = 5;
	Mat points(sampleCount, dims, CV_32F, Scalar(10));
	//将彩色图像的像素点转换为样本数据
	int index = 0;
	for (int row = 0; row < height; row++)
	{
   
		for (int col = 0; col < width; col++)
		{
   
			index = row*width + col;
			Vec3b bgr = src.at<Vec3b>(row, col);
			points.at<float>(index, 0) = static_cast<int>(bgr[0]);//b
			points.at<float>(index, 1) = static_cast<int>(bgr[1]);//g
			points.at<float>(index, 2) = static_cast<int>(bgr[2]);//r
		}
	}

4、利用Kmeans算法对样本数据分类

	centers, feature = Kmeans(points, clusterCount, sampleCount);

5、
显示图像分割后的结果

	//显示图像分割结果
	Mat result = Mat::zeros(src.size(), src.type());
	int index1 = 0;
	for (int row = 0; row < height; row++)
	{
   
		for (int col = 0; col < width; col++)
		{
   
			index1 = row*width + col;
			int label = feature.at<float>(index1, 3);
			result.at<Vec3b>(row, col)[0] = colorTab[label][0];
			result.at<Vec3b>(row, col)[1] = colorTab[label][1];
			result.at<Vec3b>(row, col)[2] = colorTab[label][2];
		}
	}
	imshow("基于Kmeans聚类的图像分割", result);

四、代码子函数部分
1、初始化聚类中心

	//初始化簇心
	Mat centers = Mat::zeros(clusterCount, 1, CV_32FC3);//4行3列
	centers.at<float>(0, 0) = 150;
	centers.at<float>(0, 1) = 180;
	centers.at<float>(0, 2) = 200;

	centers.at<float>(1, 0) = 20;
	centers.at<float>(
  • 33
    点赞
  • 209
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值