OpenCV学习 kmeans实现图像分割

7 篇文章 0 订阅
3 篇文章 0 订阅

using namespace std;
using namespace cv;
int main()
{
	const int MAX_CLUSTERS = 5;
	Vec3b colorTab[] =
	{
		Vec3b(0, 0, 255),
		Vec3b(0, 255, 0),
		Vec3b(255, 100, 100),
		Vec3b(255, 0, 255),
		Vec3b(0, 255, 255)
	};
	Mat data, labels;
	Mat pic = imread("C:/Users/dell/Desktop/1.jpg");
	for (int i = 0; i < pic.rows; i++)
	for (int j = 0; j < pic.cols; j++)
	{
		Vec3b point = pic.at<Vec3b>(i, j);
		Mat tmp = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
		data.push_back(tmp);
	}

	//根据浏览图片,确定k=3
	kmeans(data, 4, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0),
		3, KMEANS_RANDOM_CENTERS);

	int n = 0;
	//显示聚类结果,不同的类别用不同的颜色显示
	for (int i = 0; i < pic.rows; i++)
	for (int j = 0; j < pic.cols; j++)
	{
		int clusterIdx = labels.at<int>(n);
		pic.at<Vec3b>(i, j) = colorTab[clusterIdx];
		n++;
	}
	imshow("pic", pic);
	waitKey(0);

	return 0;
}

基本算法步骤:
初始化:从 n个数据对象任意选择 k 个对象作为初始聚类中心;
迭代:
    1. 根据每个聚类对象的均值(中心对象),计算每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行分类;
    2. 由新的分类数据,重新计算每个(有变化)聚类的均值(中心对象);
    3. 计算标准测度函数,当满足一定条件,如函数收敛时,则算法终止;如果条件不满足则循环执行。如opencv中,每次迭代,最大的聚类中心位移max_center_shift < criteria.epsilon小于精度要求时,就结束迭代。以及迭代次数超过设定的最大值时,也结束 iter >= criteria.maxCount。
结束。计算方差,及labels每个对象的分类结果,返回。
算法的时间复杂度上界为O(n*k*t), 其中t是迭代次数。属于非监督学习方法。
OpenCV中增加了参数:
attempts:使用不同的初始化条件,进行分类的次数
flag: KMEANS_RANDOM_CENTERS, KMEANS_PP_CENTERS, KMEANS_USE_INITIAL_LABELS
        kmeans算法的2个缺点:第一是必须人为指定所聚的类的个数k;第二是如果使用欧式距离来衡量相似度的话,可能会得到错误的结果,因为没有考虑到属性的重要性和相关性。为了减少这种错误,在使用kmeans距离时,一定要使样本的每一维数据归一化,不然的话由于样本的属性范围不同会导致错误的结果。
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值