K-means之C++及OpenCV实现
来源:互联网 发布:怎样修改淘宝卖家地址 编辑:程序博客网 时间:2024/04/30 01:19
这个算法的步骤如下:
1.随机选取样本中的K个点作为聚类中心
2.计算所有样本到各个聚类中心的距离,将每个样本规划在最近的聚类中
3.计算每个聚类中所有样本的中心,并将新的中心代替原来的中心
4.检查新老聚类中心的距离,如果距离超过规定的阈值,则重复2-4,直到小于阈值
那么,现在,我实现的程序的步骤也是按照上面一步一步来的,
为了方便,我直接在平面上随机产生n个点,选取前K个点作为聚类中心,
距离就定义为平面上的欧式距离,
然后为了形象化地观察过程和结果,我将过程以图像的方式显示。
代码如下:
首先是主体:
然后是其他函数的实现:判断是否是需要的:
显示结果:
看下效果:
而通过几次运行和观察,阈值不必取的很小,首先是迭代次数越来越多,时间越来越长,但结果差别却是越来越小,即,到几次迭代之后就能取得好的效果了,再迭代下去取的结果跟原来相差不大。
const int nClusters = 4;//这是Kmeans算法的一个缺点,在聚类之前需要指定类别个数
int _tmain(int argc, _TCHAR* argv[])
{
Mat src;
src = imread("E:\\bad\\belt (1).jpeg");
imshow("original", src);
blur(src, src, Size(11,11));//使用blur对图像进行平滑处理,这种方法就是最简单的求平均数
//size:定义滤波器的大小
imshow("blurred", src);
//p是特征矩阵,每行表示一个特征,每个特征对应src中每个像素点的(x,y,r,g,b共5维)
Mat p = Mat::zeros(src.cols*src.rows, 5, CV_32F); //初始化全0矩阵(行和列还有类型)
//所有元素行,5列的矩阵
Mat bestLabels, centers, clustered;
vector<Mat> bgr; //定义一个Mat向量容器保存拆分后的数据
split(src, bgr); //分隔出src的三个通道
for(int i=0; i<src.cols*src.rows; i++)
{
p.at<float>(i,0) = (i/src.cols) / src.rows; // p.at<uchar>(y,x) 相当于 p->Imagedata[y *p->widthstep + x], p是8位uchar
p.at<float>(i,1) = (i%src.cols) / src.cols; // p.at<float>(y,x) 相当于 p->Imagedata[y *p->widthstep + x], p是32位float
p.at<float>(i,2) = bgr[0].data[i] / 255.0;
p.at<float>(i,3) = bgr[1].data[i] / 255.0;
p.at<float>(i,4) = bgr[2].data[i] / 255.0;
}
//计算时间
double t = (double)cvGetTickCount();//GetTickcount函数:它返回从操作系统启动到当前所经的计时周期数
//kmeans聚类,每个样本的标签保存在bestLabels中
kmeans(p, nClusters, bestLabels,
TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0),
3, KMEANS_PP_CENTERS, centers);
t = (double)cvGetTickCount() - t;
float timecost = t/(cvGetTickFrequency()*1000);//getTickFrequency函数:返回每秒的计时周期数
//给每个类别赋颜色,其值等于每个类第一个元素的值
Vec3b colors[nClusters];//Vec3b 是定义一个uchar类型的数组长度为3
bool colormask[nClusters];
memset(colormask, 0, nClusters*sizeof(bool));//将colormask中前nClusters*sizeof(bool)个字节用0替换并返回colormask
//memset:作用是在一段内存块中填充某个给定的值,
//它是对较大的结构体或数组进行清零操作的一种最快方法
int count = 0;
for(int i=0; i<src.cols*src.rows; i++)
{
int clusterindex = bestLabels.at<int>(i,0);
for (int j=0; j<nClusters; j++)
{
if(j == clusterindex && colormask[j] == 0)
{
int y = i/src.cols;
int x = i%src.cols;
colors[j] = src.at<Vec3b>(y,x);
colormask[j] = 1;
count++;
break;
}
}
if(nClusters == count)break;
}
//显示聚类结果
clustered = Mat(src.rows, src.cols, CV_8UC3);
for(int i=0; i<src.cols*src.rows; i++)
{
int y = i/src.cols;
int x = i%src.cols;
int clusterindex = bestLabels.at<int>(i,0);
clustered.at<Vec3b>(y, x) = colors[clusterindex];
}
imshow("clustered", clustered);
cvWaitKey(0);
- K-means之C++及OpenCV实现
- K-means之C++及OpenCV实现
- k-means算法及opencv实现
- k-means算法及opencv实现
- k-means算法及opencv实现
- K-means算法及OpenCV实现
- K-means C实现
- k-means聚类及C代码实现
- 【Machine Learning】K-means算法及C语言实现
- c实现K-means算法
- k-means/k-means++算法的笔记及scala实现
- 【OpenCV学习笔记 020】K-Means聚类算法介绍及实现
- k-means(k均值聚类)算法介绍及实现(c++)
- k-means(k均值聚类)算法介绍及实现(c++)
- C均值算法(K-means)在opencv中实现图像分割(抠图)
- OpenCV k-means聚类
- opencv k-means
- K-means原理及Matlab实现
- Linux运维第二十二讲
- struts2使用html的布局
- 设计一个一百亿的计算器
- Ceph源码分析之Async模块:1、异步通信核心模块EventCenter+Epoll
- 性能优化:使用SparseArray和ArrayMap代替HashMap
- K-means之C++及OpenCV实现
- UVa 12435
- C++利用vector容器实现最大最小元问题
- make your own phpstorm epa
- Something about Telephone Interview
- 21 Essential JavaScript Interview Questions
- 博客
- L3-003. 社交集群-图的连通分支数&&并查集-天梯赛练习题
- Oracle PL/SQL开发基础(第二弹:使用数据字典视图查看表约束)