OpenCV学习 kmeans实现图像分割
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距离时,一定要使样本的每一维数据归一化,不然的话由于样本的属性范围不同会导致错误的结果。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: 【OpenCV学习笔记 020】K-Means聚类算法介绍及实现
- 下一篇: 颜色聚类方法综述