K-Means的一些想法以及实现

作为测试,我使用的是二维平面坐标进行的。我们随机选取图片,使用OpenCV的Mat类对象读取图像文件中的数据,然后使用rand函数随机产生k(这里k值取决于输入)个二维坐标值。遍历整个图像像素位置,计算每个坐标相对于任意一个核心点之间的距离L^2(欧氏距离的平方,因为这样计算量会小一些),根据距离值对像素进行分类。当整个图像遍历一遍之后,我们有了一个初步的聚类,然而这个聚类是不好的,主要原因在于聚类的核心点是任意产生的(其原因是由于这个聚类方法是非监督的,我们对数据集和数据点是未知的)。我们需要对每一个数据集进行数据的修整。

 

1聚类前图像                                                                       2 初步聚类后

3最终聚类后图像 (647*580分辨率)

4 随机点的分布

这3个图,大概能说明K-Means聚类方法的一些原因和问题了。

在看这3个图的时候,请忽略图像的大小变化,关注图像内部的比例变化更好一些(根据距离进行聚类,因此可以忽略不计)。

我在做K-Means 的时候,为了展现效果,将不同的数据集采用不同色彩进行标注,每一个色区中有一个点,标定核心点的位置。

我们可以看出,图2的聚类不规则,3图作为最终聚类的形式,有较大的改观,从4图可以发现,一开始的随机点分布并不如3图当中如此排列有序,但是经过修正后,基本上比较规则,但是仍然不是完全四等分,其中主要原因之一,就是随机点的获取影响的聚类的效果,在我们采取的聚类对象中,可能会好一点,但是在别的距类对象中(数据分布及其不均匀,这样的数据量很大)可能比较糟糕。

#include<iostream>
#include<vector>
#include<string>
#include<cv.hpp>
using cv::Mat;
using cv::imread;
using cv::imshow;
using cv::imwrite;
using cv::waitKey;
using cv::cvtColor;
//using cv::Point2i;
using std::vector;
using std::string;
using std::cin;
using std::cout;
using std::endl;

//typedef Point2i Point;

struct Point
{
	int x;
	int y;
	unsigned int gray;
	unsigned int distance;
	double weight;
	Point()
	{
		x = 0;
		y = 0;
		gray = 0;
		distance = 0;
		weight = 0;
	}
	Point(int _x, int _y,unsigned int _gray=0,unsigned int _distance=0,int _weight=0) { x = _x; y = _y; gray =_gray; distance =_distance; weight = _weight; }
	Point(const Point&_point) { this->x = _point.x; this->y = _point.y; this->gray = _point.gray; this->distance = _point.distance; this->weight = _point.weight; }
	Point& operator=(const Point&_point) { this->x = _point.x; this->y = _point.y; this->gray = _point.gray; this->distance = _point.distance; this->weight = _point.weight; return *this; }

};

void dSort(vector<Point>*vec)
{
	vector<Point>::iterator fIt = vec->begin();

	for (; fIt != vec->end(); ++fIt)
	{
		for (vector<Point>::iterator sIt = fIt+1; sIt != vec->end(); ++sIt)
		{
			if (sIt->distance < fIt->distance)
			{

				Point tmp(*sIt);
				*sIt=*fIt;
				*fIt = tmp;
			}
		}

	}
	vector<Point>::iterator it = vec->begin();
	}

void Weight(vector<Point>*vec,double alpha,double beta,double theta)
{
	if (vec->empty())
	{
		cout << "container is empty" << endl;
		return;
	}
	cout << "start sort" << endl;
	dSort(vec);
	cout << "end sort" << endl;
	double cscore = 0.0;
	double dscore = 0.0;
	vector<Point>::iterator it = vec->begin();
	for (; it != vec->end(); ++it)
	{
		dscore = (1 / (sqrt(2 * 3.14159)*beta))*(exp((it - vec->begin())*(it - vec->begin()) / (2 * beta*beta)));
		//cout << dscore << endl;
		dscore *= it->distance;
		cscore = (1 / (sqrt(2 * 3.14159)*theta))*(exp((it - vec->begin())*(it - vec->begin()) / (2 * theta*theta)));
		cscore *= it->gray;
		it->weight = double(alpha*it->distance) + double((1 - alpha)*it->gray);
	//	cout << "weight=" << it->weight << endl;
	}
	cout << "after weight" << endl;

}
 int squareDistance(const Point& p1, const Point &p2)
{
	//cout <<"s"<<p1.x << "," << p1.y <<"   "<<p2.x<<","<<p2.y<<endl;

	return ((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
 int colorGap(Mat mat,const Point&p1, const Point&p2)
{
//	cout << "c" << p1.x << "," << p1.y << "   " << p2.x << "," << p2.y<<endl;
	//cout<<"gap="<< abs(mat.at<uchar>(p1.x, p1.y) - mat.at<uchar>(p2.x, p2.y));

	return abs(mat.at<uchar>(p1.x, p1.y) - mat.at<uchar>(p2.x, p2.y));
}

const Point & findCentre( vector<Point>&vec)
{
	cout << "start centre" << endl;
	vector<Point>::iterator it = vec.begin();
	int	xall = 0;
	int yall = 0;
	int weight = 0;
	for (; it != vec.end(); ++it)
	{
		xall+= it->x;
		yall += it->y;
	}
	weight=vec.size();
//	cout << xall << ‘\t‘ << yall << ‘\t‘ << weight <<‘\t‘<<xall/weight<<endl;
	cout << "end centre" << endl;
	Point t(xall / weight, yall / weight);
	cout << t.x <<‘\t‘<< t.y << endl;
	vec.clear();
	//cout << "xall=" << xall << "yall=" << yall << "weight=" << weight <<"xall/weight="<<xall/weight<<"yall/weight="<<yall/weight<< endl;
	return t;
}

bool stopCondition(int num, Point*pt, vector<Point>*vec)
{
	bool flag = 1;
	for (int i = 0; i != num; ++i)
	{
		if (pt[i].x == vec[i].begin()->x&&pt[i].y == vec[i].begin()->y)
			flag = flag & 1;
		else
			flag = flag & 0;
	}
	return flag;
}

void getPoint(Mat mat, vector<Point> *vec, int num = 5)
{
	unsigned int Min = mat.rows*mat.rows + mat.cols*mat.cols;
	int pos = 0;
	for (int i = 0; i != mat.rows; ++i)
	{
		for (int j = 0; j != mat.cols; ++j)
		{
			Min = mat.rows*mat.rows + mat.cols*mat.cols;
			pos = 0;
			for (int k = 0; k != num; ++k)
			{
				Point tmp = *vec[k].begin();
				if ((Min > squareDistance(Point(i, j), tmp)))//&&squareDistance(Point(i, j), tmp)<=l_gap)
				{

					Min = squareDistance(Point(i, j), tmp);
					pos = k;
				}
			}
			Point tmp(i, j, colorGap(mat, Point(i, j), vec[pos].front()), Min, 0);
			vec[pos].push_back(tmp);
		}
	}
}

void K_Means(Mat&mat,vector<Point> *vec, int num = 5, double alpha = 0.5,int amp=10,int l_gap=20,int c_gap=30,double threshold=0.5 )
{

	int amplitude = 15;
	if (mat.empty())
	{
		cout << "please input the Mat" << endl;
		return;
	}
	Point*start = new Point[num];
	for (int i = 0; i != num; ++i)
    start[i] = Point(0, 0);

    for (int i = 0; i != num; ++i)
    {
        vec[i].push_back(Point(rand() % mat.rows, rand() % mat.cols));
		cout << vec[i].front().x << "," << vec[i].front().y << endl;
	}

	while (!stopCondition(num, start, vec))
	{

		cout << "________________________" << endl;
		for (int i = 0; i != num; ++i)
		{
			cout << "start" << start[i].x << ‘\t‘ << start[i].y << endl;
			cout << "vec" << vec[i].begin()->x << ‘\t‘ << vec[i].begin()->y << endl;
		}
		cout << "_____________________________" << endl;

		for (int i = 0; i != num; ++i)
		{
			start[i] = vec[i].front();
		}
		amplitude = 0;
		getPoint(mat, vec, num);
		cout << "get the weight and centre" << endl;
		for (int x = 0; x != num; ++x)
		{
			cout << "num=" << x << endl;
			//	Weight(&vec[x], 0.5, 0.4, 0.4);
			Point t(findCentre(vec[x]));
			//*vec[x].begin() = t;
			vec[x].push_back(t);
			cout << vec[x].begin()->x << vec[x].begin()->y << endl;
		}
	}
	            getPoint(mat, vec, num);
				cout << "paint" << endl;
				/*
				for (int i = 0; i != num; ++i)
				{
					double allweight = 0.0;
					vector<Point>::iterator it = vec[i].begin();
					for (; it != vec[i].end(); ++it)
						allweight += it->weight;
					it = vec[i].begin();
					double aveweight = allweight / (vec[i].size());
					*/
					/*
					for (int i = 0; i != mat.rows; ++i)
						for (int j = 0; j != mat.cols; ++j)
							mat.at<uchar>(i, j) = 255;
							*/

				for (int i = 0; i != num;++i)
				{
					vector<Point>::iterator it = vec[i].begin();
					for (; it != vec[i].end(); ++it)
					{
							mat.at<uchar>(it->x, it->y) = 50 + i * 30;
					}
					mat.at<uchar>(vec[i].front().x, vec[i].front().y) = 0;

				}

}

int main()
{
	int number = 0;
	vector<Point> *vec;
	cin >> number;
	vec = new vector<Point>[number];
//	for (int i = 0; i != numbe)
	Mat mat =imread("2.jpg");
	cvtColor(mat, mat, CV_BGR2GRAY);
	K_Means(mat, vec,number);
	imshow("1", mat);
	//imwrite(string("2.jpg"), mat);
	waitKey(0);
}

  代码格式杂乱无章,作为自己的笔记,先这么凑合吧,等把这个K-Means联合color因子的算法完全写出来,再进行调整也不晚。

这些代码中,其中Weight函数中提出了色彩+距离权重的计算,我们使用两个不同参数的高斯函数进行权重的规约(将数据按照距离进行排序,由小到大。距离越大,相对于高斯函数的中轴越远,将这个距离带入高斯函数中,最终权值较小)。色彩+距离这两个因子使用一个参数进行调节,控制这两个因子在权重中所占比率的大小,这样我感觉效果会好一些。

时间: 2024-08-03 11:54:13

K-Means的一些想法以及实现的相关文章

软件——机器学习与Python,聚类,K——means

K-means是一种聚类算法: 这里运用k-means进行31个城市的分类 城市的数据保存在city.txt文件中,内容如下: BJ,2959.19,730.79,749.41,513.34,467.87,1141.82,478.42,457.64TianJin,2459.77,495.47,697.33,302.87,284.19,735.97,570.84,305.08HeBei,1495.63,515.90,362.37,285.32,272.95,540.58,364.91,188.63

k means聚类过程

k-means是一种非监督 (从下图0 当中我们可以看到训练数据并没有标签标注类别)的聚类算法 0.initial 1.select centroids randomly 2.assign points 3.update centroids 4.reassign points 5.update centroids 6.reassign points 7.iteration reference: https://www.naftaliharris.com/blog/visualizing-k-me

python实现k近邻

k近邻分类器大概想法是  在已知许多样本分好类的情况下,给定一个新样本i, 计算得到与i最接近的k个样本,那么假设这k个样本为a1, a2, ... , ak ,总共五个类别{1,2,3,4,5}, 其中就有{a1:3, a2:4, a3:1, ... ,  ak:2},a1 所对的值3 就为它的类别,现在如果在这个k个样本里,属于类别3 的样本最多,那么我们就可以把样本i 归为类别3 现在来用python 简单实现下这个分类器 首先定义一下数据集结构 数据矩阵 X_train表示训练样本矩阵,

快速查找无序数组中的第K大数?

1.题目分析: 查找无序数组中的第K大数,直观感觉便是先排好序再找到下标为K-1的元素,时间复杂度O(NlgN).在此,我们想探索是否存在时间复杂度 < O(NlgN),而且近似等于O(N)的高效算法. 还记得我们快速排序的思想麽?通过“partition”递归划分前后部分.在本问题求解策略中,基于快排的划分函数可以利用“夹击法”,不断从原来的区间[0,n-1]向中间搜索第k大的数,大概搜索方向见下图: 2.参考代码: 1 #include <cstdio> 2 3 #define sw

当我们在谈论kmeans(3)

本系列意在长期连载分享,内容上可能也会有所删改: 因此如果转载,请务必保留源地址,非常感谢! 博客园:http://www.cnblogs.com/data-miner/(暂时公式显示有问题) 其他:建设中- 当我们在谈论kmeans:论文概述(2) 算法历程 2001年 在Estlick, Mike, et al. "Algorithmic transformations in the implementation of K- means clustering on reconfigurabl

机器学习十大算法(二)

文章来源:https://www.dezyre.com/article/top-10-machine-learning-algorithms/202 本人自行翻译,如有错误,还请指出.后续会继续补充实例及代码实现. 3.机器学习算法概述 3.1 朴素贝叶斯分类器算法 手动分类网页,文档,电子邮件或任何其他冗长的文本注释将是困难且实际上不可能的. 这是朴素贝叶斯分类器机器学习算法来解决. 分类器是从可用类别之一分配总体的元素值的函数. 例如,垃圾邮件过滤是朴素贝叶斯分类器算法的流行应用程序. 此处

UVA 11019 Matrix Matcher 二维的字符串匹配 ac自动机

只要把每行的模版串插到ac自动机,然后匹配行,每次匹配成功,那一行对应的字符矩阵的左上角的计数器+1,最后统计下计数器矩阵有多少个左上角是行数的就可以了. 思路很简单,但想法很好,但要注意模版上有两行是一样的,插入到ac自动机的时候会插到同一个结点上,为了区分,我还是谨慎地开了个vector,然后1A了. #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,s

Apache Spark RDD(Resilient Distributed Datasets)论文

Spark RDD(Resilient Distributed Datasets)论文 概要 1: 介绍 2: Resilient Distributed Datasets(RDDs) 2.1 RDD 抽象 2.2 Spark 编程接口 2.2.1 例子 – 监控日志数据挖掘 2.3 RDD 模型的优势 2.4 不适合用 RDDs 的应用 3 Spark 编程接口 3.1 Spark 中 RDD 的操作 3.2 举例应用 3.2.1 线性回归 3.2.2 PageRank 4 表达 RDDs 5

转载:日志分析

MARK 日志分析: http://blog.csdn.net/pkueecser/article/details/9569251 大数据应用--系统监控与日志分析PPT http://wenku.baidu.com/link?url=8CJ-URMjVTVaw3GM1AZ2w9A7V0CIeRz3dx7xvysILLk6IdWpJGT889gQ7-824G4hAK-T2tdqZY1Lo6CEN1hgqHQNlHhVFykWJ_9XQW6EN5K ============= 日志在计算机系统中是

k-means聚类学习

4.1.摘要 在前面的文章中,介绍了三种常见的分类算法.分类作为一种监督学习方法,要求必须事先明确知道各个类别的信息,并且断言所有待分类项都有一个类别与之对应.但是很多时候上述条件得不到满足,尤其是在处理海量数据的时候,如果通过预处理使得数据满足分类算法的要求,则代价非常大,这时候可以考虑使用聚类算法.聚类属于无监督学习,相比于分类,聚类不依赖预定义的类和类标号的训练实例.本文首先介绍聚类的基础——距离与相异度,然后介绍一种常见的聚类算法——k均值和k中心点聚类,最后会举一个实例:应用聚类方法试