[opencv]K-means聚类算法分割图像

1.K-means算法

K-means是一种经典的无监督聚类算法。

算法原理:
(1)从N个数据对象中取K个点作为聚类中心。
(2)计算N个数据对象到各个聚类中心的距离,将N个数据对象划分到距离最近的中心,形成K个聚类。
(3)计算每个聚类的中心,将新的中心代替原来的中心。
(4)检查新老聚类中心的距离,重复(2)-(3)直到距离小于规定阈值。

2.opencv函数

cvKMeans2(const CvArr* samples, int nclusters, CvArr* labels, CvTermCriteria criteria, int attempts=1, CvRNG*rng=0, int flags=0, CvArr* centers=0, double* compactness=0)

kmeans(InputArray samples, int clusterCount, InputOutputArray labels, TermCriteria criteria, int attempts, int flags, OutputArray centers=noArray() )

Parameters:
  • samples – Floating-point matrix of input samples, one row per sample.
  • clusterCount – Number of clusters to split the set by.
  • labels – Input/output integer array that stores the cluster indices for every sample.
  • criteria – The algorithm termination criteria, that is, the maximum number of iterations and/or the desired accuracy. The accuracy is specified as criteria.epsilon. As soon as each of the cluster centers moves by less than criteria.epsilon on some iteration, the algorithm stops.
  • attempts – Flag to specify the number of times the algorithm is executed using different initial labelings. The algorithm returns the labels that yield the best compactness (see the last function parameter).
  • flags –

    Flag that can take the following values:

    • KMEANS_RANDOM_CENTERS Select random initial centers in each attempt.
    • KMEANS_PP_CENTERS Use kmeans++ center initialization by Arthur and Vassilvitskii [Arthur2007].
    • KMEANS_USE_INITIAL_LABELS During the first (and possibly the only) attempt, use the user-supplied labels instead of computing them from the initial centers. For the second and further attempts, use the random or semi-random centers. Use one of KMEANS_*_CENTERS flag to specify the exact method.
  • centers – Output matrix of the cluster centers, one row per each cluster center.
sample

输入样本的浮点矩阵,每个样本一行

clusterCount

给定的聚类数目 

labels

输出整数向量:每个样本对应的类别标识 

criteria

迭代终止条件:迭代最大次数和精度

attempts

运行K-means的次数,取结果最好的聚类为最终聚类,和flags一起使用

flags

KMEANS_RANDOM_CENTERS 每次尝试选取随机初始化中心

KMEANS_PP_CENTERS  使用Arthur and Vassilvitskii算法进行中心初始化

KMEANS_USE_INITIAL_LABELS使用用户自定义初始点

3.实现

处理图像:


将图像的颜色数据进行K-means聚类,这里有黑、白、红三色,所以分为3类进行效果测试。

将图像每个像素三通道值按行存给样本samples。

	for (int i = 0; i < img->width;i++)
	{
		for (int j = 0; j < img->height;j++)
		{
			CvScalar s;
			s.val[0] = (float)cvGet2D(img, j, i).val[0];
			s.val[1] = (float)cvGet2D(img, j, i).val[1];
			s.val[2] = (float)cvGet2D(img, j, i).val[2];
			cvSet2D(samples,k++,0,s);
		}
	}
nCluster定义为3。

进行K-means聚类分析

	cvKMeans2(samples,nCluster,clusters,cvTermCriteria(CV_TERMCRIT_ITER,100,1.0));
保存结果给clusters,这里是根据图像坐标对应颜色的聚类结果分别标志为0,1,2。

测试分类效果:

将图像基于聚类标签结果进行提取。

(1)提取标签0

	k = 0;
	int val = 0;

	for (int i = 0; i < img->width;i++)
	{
		for (int j = 0; j < img->height;j++)
		{
			val = (int)clusters->data.i[k++];

			CvScalar s1;
			if (val == 0)
			{
				s1.val[0] = 255;
			}
			else
			{
				s1.val[0] = 0;
			}
			cvSet2D(bin,j,i,s1);
		}
	}
将图像基于bin进行mask复制,显示标签0对应的区域

	cvThreshold(bin,bin,200,255,CV_THRESH_BINARY);
	IplImage *img1=cvCreateImage(cvSize(img->width,img->height),img->depth,img->nChannels);
	cvCopy(img,img1,bin);
	cvShowImage("原图", img);
	cvShowImage("bin",bin);
	cvShowImage("聚类图像",img1);
	cvWaitKey(0);

得到图像效果如下:



(2)提取标签1

将val改为1,得到图像效果如下:



(3)提取标签2

将val改为2,得到图像效果如下:









评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值