前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >K-means算法及OpenCV实现

K-means算法及OpenCV实现

作者头像
chaibubble
发布2022-05-07 09:35:57
6600
发布2022-05-07 09:35:57
举报
文章被收录于专栏:深度学习与计算机视觉

K-means算法MacQueen在1967年提出的,是最简单与最常见数据分类方法之一并且最为一种常见数据分析技术在机器学习、数据挖掘、模式识别、图像分析等领域都用应用。从机器学习的角度看,K-means属于一种无监督的机器学习方法。无监督学习(Unsupervised Learning)简单的说就是在不给定正确答案(标签)的情况下,在数据中找到一些相似的特征用以分析(分类)数据的方法。而在K-means算法解决图像的问题中,就是在对图像的像素点进行分类,达到图像分割的目的。

K-means算法流程:

这里写图片描述
这里写图片描述

(1)K-means初始聚类中心的确定:初始的K个分类中每个分类的中心点选择,K-Means算法支持随机选择,人工指定与中心化算法三种方式。 (2)如何判断收敛:

这里写图片描述
这里写图片描述

其中i表示第i个数据点,j表示第j个聚类中心,

这里写图片描述
这里写图片描述

表示第i个数据点的数据,

这里写图片描述
这里写图片描述

表示第j个聚类中心的值。所以RSS表征的意义为:被归于一类的数据点距离与它对应的聚类中心的差值的平方和。K-means聚类算法依靠两次聚类后RSS的差值是否小于设定的阈值判断是否达到收敛。 (3)如何表征像素点(数据点)的特征: 多维数据支持,多数时候我们要分类的特征对象的描述数据不止一个数据特征,而是一个特征向量来表示,OpenCV中通过Mat对象构建实现对多维数据KMeans分类支持。

K-means的OpenCV实现:

函数定义:

代码语言:javascript
复制
CV_EXPORTS_W double kmeans( 
InputArray data, 
int K, 
CV_OUT InputOutputArray bestLabels,
TermCriteria criteria, 
int attempts,
int flags, 
OutputArray centers=noArray() );

第一个参数:表示输入的数据集合,可以一维或者多维数据,类型是Mat类型,比如Mat points(count, 2, CV_32F)表示数据集合是二维,浮点数数据集; 第二个参数:表示分类的数目,K=2时即表示二分类; 第三个参数:表示计算之后各个数据点的最终的分类索引,是一个INT类型的Mat对象; 第四个参数:表示算法终止的条件,达到最大循环数目或者指定的精度阈值算法就停止继续分类迭代计算; 第五个参数:表示为了获得最佳的分类效果,算法要不同的初始分类尝试次数; 第六个参数:表示表示选择初始中心点选择方法用哪一种方法: KMEANSRANDOMCENTERS 表示随机选择中心点 KMEANSPPCENTERS 基于中心化算法选择 KMEANSUSEINITIAL_LABELS第一次分类中心点用输入的中心点; 第七个参数:表示输出的每个分类的中心点数据;

代码语言:javascript
复制
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
	Mat SrcImage = imread("1.jpg");
	imshow("原图", SrcImage);
	int width = SrcImage.cols;
	int height = SrcImage.rows;
	int dims = SrcImage.channels();
	int sampleCount = width*height;
	int clusterCount = 2;
	Mat points(sampleCount, dims, CV_32F, Scalar(10));
	Mat labels;
	Mat centers(clusterCount, 1, points.type());
	int index = 0;
	for (int row = 0; row < height; row++) {
		for (int col = 0; col < width; col++) {
			index = row*width + col;
			Vec3b rgb = SrcImage.at<Vec3b>(row, col);
			points.at<float>(index, 0) = static_cast<int>(rgb[0]);
			points.at<float>(index, 1) = static_cast<int>(rgb[1]);
			points.at<float>(index, 2) = static_cast<int>(rgb[2]);
		}
	}
	TermCriteria criteria = TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0);
	kmeans(points, clusterCount, labels, criteria, 3, KMEANS_PP_CENTERS, centers);
	Mat result = Mat::zeros(SrcImage.size(), CV_8UC3);
	for (int row = 0; row < height; row++) {
		for (int col = 0; col < width; col++) {
			index = row*width + col;
			int label = labels.at<int>(index, 0);
			if (label == 1) {
				result.at<Vec3b>(row, col)[0] = 0;
				result.at<Vec3b>(row, col)[1] = 0;
				result.at<Vec3b>(row, col)[2] = 0;
			}
			else if (label == 0) {
				result.at<Vec3b>(row, col)[0] = 255;
				result.at<Vec3b>(row, col)[1] = 255;
				result.at<Vec3b>(row, col)[2] = 255;
			}
		}
	}
	imshow("聚类结果", result);
	waitKey(0);
	return 0;
}

结果:

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-04-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档