基于K-MEANS聚类的胡萝卜纯色背景去除方法

所谓的聚类是指,将一个数据集中的某些方面相似的数据成员进行分类的过程,聚类就是一种发现这种内在结构的技术,聚类技术经常被称为无监督学习。k均值聚类是最著名的划分聚类算法,由于简洁和效率使得他成为所有聚类算法中最广泛使用的。给定一个数据点集合和需要的聚类数目k,k由用户指定,k均值算法根据某个距离函数反复把数据分入k个聚类中。

  1. k均值算法描述

先随机选取K个对象作为初始的聚类中心。然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。一旦全部对象都被分配了,每个聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是以下任何一个:

1)没有(或最小数目)对象被重新分配给不同的聚类。

2)没有(或最小数目)聚类中心再发生变化。

3)误差平方和局部最小。

而基于K均值的胡萝卜图像的分类,则是利用分类的思想,将目标区与背景区分成两类,所以,在此处将 K 的值,设置为 2;因为,是根据灰度值进行划分,则误差设置为1作为终止条件;

算法具体实现代码如下所示:

IplImage* img = cvCloneImage(m_sourceImage);
		IplImage* grayImage = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
		//IplImage* redImage = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);

		//cvSplit(img, NULL, NULL, redImage, NULL);

		cvCvtColor(img, grayImage, CV_RGB2GRAY);
		//IplImage* img = cvCreateImage(cvGetSize(m_sourceImage), IPL_DEPTH_8U, 1);
		//cvCvtColor(m_sourceImage, img, CV_RGB2GRAY);
		int total = img->height*img->width;
		int cluster_num = 2;
		CvMat *row = cvCreateMat(img->height, img->width, CV_32FC3);
		//cvConvert(redImage, row);
		cvConvert(img, row);//转一下类型!
		CvMat *clusters = cvCreateMat(total, 1, CV_32SC1);

// 		CvArr* cvReshapeMatND(const CvArr* arr,
// 			int sizeof_header, CvArr* header,
// 			int new_cn, int new_dims, int* new_sizes);
//
// 		arr :输入数组
// 		sizeof_header :输出头的大小,对于IplImage, CvMat 和 CvMatND 各种结构输出的头均是不同的.
// 		header:被添充的输出头.
// 		new_cn:新的通道数,如果new_cn = 0 则通道数保持原样
//		new_dims:新的维数.如果new_dims = 0 则维数保持原样。
// 			new_sizes
// 			新的维大小.只有当 new_dims = 1值被使用,因为要保持数组的总数一致,因此如果 new_dims = 1, new_sizes 是不被使用的

		cvReshape(row, row, 0, total);						//把图像转成数据矩阵,但注意实际数据未变,只是访问顺序变了。
		cvKMeans2(row, cluster_num, clusters, cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0));
		cvReshape(clusters, clusters, 0, img->width);		//聚类完的结果再reshape回来比较方便看~
		int i = 0, j = 0;
		CvScalar s;
		IplImage* resImg = cvCreateImage(cvSize(img->width, img->height), 8, 1);//生成用来显示结果的图像
		s = cvGet2D(img, i, j);

		vector <int> v1, v2;		//存放分类后的灰度值

		for (i = 0; i < img->height; i++)
		{
			for (j = 0; j < img->width; j++)
			{
				double val = cvGetReal2D(grayImage, i, j);

				if (clusters->data.i[i*img->width + j] == 0)
				{
					v1.push_back(val);				//处理完成后的图像的白色区域
					s.val[0] = 255;
 					cvSet2D(resImg, i, j, s);//注意循环顺序
				}
				else
				{
					v2.push_back(val);				//处理完成后的图像的黑色区域
					s.val[0] = 0;
					cvSet2D(resImg, i, j, s);
				}
			}
		}

		double thresh1 = accumulate(v1.begin(), v1.end(), 0) / v1.size();
		double thresh2 = accumulate(v2.begin(), v2.end(), 0) / v2.size();

		if (thresh2 > thresh1)		//如果黑色区域的灰度值均值大于白色区域
		{
			cvNot(resImg, resImg);	//图像取反
		}

		IplConvKernel *element = cvCreateStructuringElementEx(5, 5, 2, 2, CV_SHAPE_ELLIPSE);
		cvSmooth(resImg, resImg, CV_MEDIAN);
		cvErode(resImg, resImg, element, 1);
		cvDilate(resImg, resImg, element, 1);
		cvReleaseStructuringElement(&element);

		cvSaveImage("s2.jpg", m_sourceImage);
		cvSaveImage("b2.jpg", resImg);

		ShowImage(resImg, IDC_PIC2);

		int key = cvWaitKey(0);
		cvReleaseImage(&img);//记得释放内存
		cvReleaseImage(&resImg);
		cvReleaseMat(&row);
		cvReleaseMat(&clusters);

  上述代码,对图像的处理结果进行了校正,因为,K-Mean聚类,只是简单的将目标区与背景区进行分类,而不能明确的标记出目标区还是背景区,所以,根据经验,将灰度值均值较大的部分作为目标区;

而灰度值较小的部分标记为背景区;

以下为未校正图像与校正后图像的对比:

如上图所示:左侧图像为未做校正的处理效果,右侧图像为校正后的图像;

由于此方法只是简单的根据图像的灰度值对图像进行二值化,所以,很难对复杂背景的图像进行分割;相关的算法,在以后的学习中再进行完善与补充。

时间: 2024-11-03 22:33:39

基于K-MEANS聚类的胡萝卜纯色背景去除方法的相关文章

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

基于大数据聚类社群的作弊用户发现方法

前面的文章中我们讲道,像趣头条类的APP对于收徒和阅读行为给予用户现金奖励的方式势必会受到大量羊毛党黑产的注意,其实单个用户能薅到的钱是没有多少的,为了达到利益最大化,黑产肯定会利用各种手段构建大量账号来薅APP运营企业的羊毛,因为收徒的奖励远高于阅读,所以赚取收徒奖励就成了最严重的薅羊毛手段.前文提到为了更好的识别出这些异常用户,我们利用用户的师徒关系构建连通图,把同一个连通图上的用户视为一个社群,利用Spark Grahpx实现了一个简单高效的社群发现功能.具体内容可以查看上一篇文章<基于S

Windows7只能设置纯色背景解决方法

解决设置设置纯色图片,不能设置其他背景图片的方法. 比如这样的. 首先找到这个目录 C:\Users\(这个位置填写你的电脑用户名)\AppData\Roaming\Microsoft\Windows\Themes,(Users也有可能是中文名——用户) 把他删除,如果删除成功则就OK了,重新设置一些背景图片即可. 如果没有成功,提示文件正在打开,无法进行操作,则需要以下操作. 进入个性化页面,切换主题为windows经典 切换之后,即可删除 Themes文件夹. 原文地址:https://ww

R与数据分析旧笔记(十五) 基于有代表性的点的技术:K中心聚类法

基于有代表性的点的技术:K中心聚类法 基于有代表性的点的技术:K中心聚类法 算法步骤 随机选择k个点作为"中心点" 计算剩余的点到这个k中心点的距离,每个点被分配到最近的中心点组成聚簇 随机选择一个非中心点,用它代替某个现有的中心点,计算这个代换的总代价S 如果S<0,则用代替,形成新的k个中心点集合 重复2,直至中心点集合不发生变化 K中心法的实现:PAM PAM使用离差平方和来计算成本S(类似于ward距离的计算) R语言的cluster包实现了PAM K中心法的优点:对于&

k均值聚类

目录 一.k均值简介 二.应用简介 三.算法 四.选择合适的K 五.具体实例 一.k均值简介 K均值聚类是一种无监督学习,对未标记的数据(即没有定义类别或组的数据)进行分类. 该算法的目标是在数据中找到由变量K标记的组.该算法迭代地工作基于所提供的特征,将每个数据点分配给K个组中的一个. 基于特征相似性对数据点进行聚类. K均值聚类算法的结果是: 1.K簇的质心,可用于标记新数据 2.训练数据的标签(每个数据点分配给一个集群) 二.应用简介 K均值聚类算法用于查找未在数据中明确标记的组.这可用于

K均值聚类和DBSCAN介绍

K均值(K-means)聚类 问题定义:给定数据$\vec{x}_1,\vec{x}_2,\cdots,\vec{x}_n$,将它们分到不同的$K$个簇(cluster)中.定义$\vec{c}=(c_1,c_2,\cdots,c_n),\text{ }c_i\in\{1,2,\cdots,K\}$,$c_i=k$表示$\vec{x}_i$被分到了第$k$个簇中.定义$\vec{\mu}_k$为第$k$个簇的中心(centroid),$k=1,2,\cdots,K$.K-means是一种基于距离

基于密度的聚类之Dbscan算法

一.算法概述 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一个比较有代表性的基于密度的聚类算法.与划分和层次聚类方法不同,它将簇定义为密度相连的点的最大集合,能够把具有足够高密度的区域划分为簇,并可在噪声的空间数据库中发现任意形状的聚类(笔者认为是因为他不是基于距离的,基于距离的发现的是球状簇). 该算法利用基于密度的聚类的概念,即要求聚类空间中的一定区域内所包含对象(点或其他空间对象)的数目不小于某一给

机器学习实战5:k-means聚类:二分k均值聚类+地理位置聚簇实例

k-均值聚类是非监督学习的一种,输入必须指定聚簇中心个数k.k均值是基于相似度的聚类,为没有标签的一簇实例分为一类. 一 经典的k-均值聚类 思路: 1 随机创建k个质心(k必须指定,二维的很容易确定,可视化数据分布,直观确定即可): 2 遍历数据集的每个实例,计算其到每个质心的相似度,这里也就是欧氏距离:把每个实例都分配到距离最近的质心的那一类,用一个二维数组数据结构保存,第一列是最近质心序号,第二列是距离: 3 根据二维数组保存的数据,重新计算每个聚簇新的质心: 4 迭代2 和 3,直到收敛

k-均值聚类算法;二分k均值聚类算法

根据<机器学习实战>一书第十章学习k均值聚类算法和二分k均值聚类算法,自己把代码边敲边理解了一下,修正了一些原书中代码的细微差错.目前代码有时会出现如下4种报错信息,这有待继续探究和完善. 报错信息: Warning (from warnings module): File "F:\Python2.7.6\lib\site-packages\numpy\core\_methods.py", line 55 warnings.warn("Mean of empty