关闭

学习OpenCV——一次颜色聚类

标签: iteratorfloatmergeimagec存储
3553人阅读 评论(0) 收藏 举报
分类:

1.首先区分三个通道,画出每个通道的直方图;

2.平滑直方图,像素值等于前后共七种颜色数量的平均值;

3.取波峰,波谷。(条件:颜色数亮s(i-2)<s(i-1)<s(i)>s(i+1)>s(i+2)或s(i-2)>s(i-1)>s(i)<s(i+1)<s(i+2)))

4.计算算有颜色的组合,并存入一个一维矩阵中;

5.颜色合并(利用map<int,int>);

6.把原图所有颜色与合并后的颜色计算距离,得出距离最近的合并颜色,在另一个原图大小的1通道矩阵中,记录相应位置颜色对应合并颜色的序号;

7.把原图序号相同的颜色加和,求平均值,就是类聚一次后的颜色。

8.把聚类后的颜色存入相应的序号的位置。

即为一次聚类后的结果,效果不很好。是由于聚类次数过少。

利用Kmean2算法,效果会很好。

 

#include "cv.h"
#include"highgui.h"
#include<map>
#include<vector>
#include<iostream>
using namespace std;
template<typename T>T sqr(T x){return x*x;}
CvMat* mat=0;
IplImage* image=0;
IplImage *histimg=cvCreateImage(cvSize(256,300),IPL_DEPTH_8U,3);
IplImage* DrawHist(map<int,int>colornum,int n);
map<int,int> Fine(CvMat* mat1u);

//CvMat* Merge(CvMat* Fine,int FineNum);
int main()
{
	image=cvLoadImage("D:/7.jpg",1);
	cvNamedWindow("Show",1);
	cvShowImage("Show",image);
	IplImage *hist0=0;//cvCreateImage(cvSize(300,300),IPL_DEPTH_8U,1);
	IplImage *hist1=0;//cvCreateImage(cvSize(300,300),IPL_DEPTH_8U,1);
	CvMat* r=cvCreateMat(image->height,image->width,CV_8UC1);
	CvMat* g=cvCreateMat(image->height,image->width,CV_8UC1);
	CvMat* b=cvCreateMat(image->height,image->width,CV_8UC1);
	CvMat* rgb=cvCreateMat(image->height,image->width,CV_32FC3);
	CvMat* result=cvCreateMat(image->height,image->width,CV_32FC3);
	CvMat* result00=cvCreateMat(image->height,image->width,CV_8UC3);
	cvConvertScale(image,rgb,1.0/255);
	cvSplit(image,r,g,b,NULL);
	map<int,int>fine_r=Fine(r);
	map<int,int>fine_g=Fine(g);
	map<int,int>fine_b=Fine(b);

	int FineNum=fine_r.size()*fine_g.size()*fine_b.size();
	cout<<"FineNum: "<<FineNum<<endl;
	CvMat* Fine=cvCreateMat(1,FineNum,CV_32FC3);
	//vector<CvScalar>avg;////////////////////////////
	int i=0;
	for(map<int,int>::iterator it0=fine_r.begin();it0!=fine_r.end();it0++){
		for(map<int,int>::iterator it1=fine_g.begin();it1!=fine_g.end();it1++){
			float* f=(float*)(Fine->data.ptr);
			for(map<int,int>::iterator it2=fine_b.begin();it2!=fine_b.end();it2++)
			{
				f[3*i]=(float)it0->first/255;
				f[3*i+1]=(float)it1->first/255;
				f[3*i+2]=(float)it2->first/255;
				i++;
			}
		}
	}

	//CvMat* Fine2=0;
	//Fine2=Merge(Fine,FineNum);
		vector<pair<int,int>>merge;
	float* f1=(float*)(Fine->data.ptr);
	float* f2=(float*)(Fine->data.ptr);
	for(int m=0;m<FineNum;m++)
	{
		
		for(int n=m+1;n<FineNum;n++)
		{
			float d=sqr(f1[3*m]-f2[3*n])+sqr(f1[3*m+1]-f2[3*n+1])+sqr(f1[3*m+2]-f2[3*n+2]);
			if(d<=0.1){
				merge.push_back(make_pair(m,n));
			}

		}
	}
	cout<<"merge:"<<merge.size()<<endl;
	//Fine1中存储把颜色距离平方小于0.05的元素合并后的结果,结果存在第一个元素位置,第二个位置置零
	CvMat* Fine1=cvCreateMat(1,FineNum,CV_32FC3);
	float* F1=(float*)(Fine1->data.ptr);
	for(vector<pair<int,int>>::iterator iter=merge.begin();iter!=merge.end();iter++)
	{
		if(F1[3*(iter->first)]!=0)
		{
			F1[3*(iter->first)]=(f1[3*(iter->first)]+f1[3*(iter->second)])/2;
			F1[3*(iter->first)+1]=(f1[3*(iter->first)+1]+f1[3*(iter->second)+1])/2;
			F1[3*(iter->first)+2]=(f1[3*(iter->first)+2]+f1[3*(iter->second)+2])/2;
			F1[3*(iter->second)]=0;
			F1[3*(iter->second)+1]=0;
			F1[3*(iter->second)+2]=0;
			f1[3*(iter->second)]=0;
			f1[3*(iter->second)+1]=0;
			f1[3*(iter->second)+2]=0;
		}
		else
			{
				F1[3*(iter->first)]=f1[3*(iter->first)];
				F1[3*(iter->first)+1]=f1[3*(iter->first)+1];
				F1[3*(iter->first)+2]=f1[3*(iter->first)+2];
			}
	}
	
	//求Fine1中非零元素个数
	int no=0;
	for(int m=0;m<FineNum;m++)
	{
		if(F1[m]!=0)
			no++;
	}
	cout<<"Not Zore Num:"<<no<<endl;
	//Fine2中存储merge后Fine1中的非零元素
	CvMat* Fine2=cvCreateMat(1,no*3,CV_32FC1);
	float* F2=(float*)(Fine2->data.ptr);
	for(int m=0;m<FineNum;m++)
	{
		if(F1[m]!=0)
		{
			*F2=F1[m];
			F2++;
		}

	}
	cout<<"F2_Width: "<<Fine2->width<<endl;

	
	//int no=Fine2->width;

	CvMat* id =cvCreateMat(image->height,image->width,CV_32SC1);
	for(int r=0;r<rgb->rows;r++){
		int* idx=(int*)(id->data.ptr+r*id->step);
		float* rgbData=(float*)(rgb->data.ptr+r*rgb->step);
		for(int c=0;c<rgb->cols;c++,idx++){
			
			float D=200000;
			int t=0;
			float* f=(float*)(Fine2->data.ptr);
			for(int i=0;i<no;i++){
				float dist=sqr(rgbData[3*c]-f[3*i])+sqr(rgbData[3*c+1]-f[3*i+1])+sqr(rgbData[3*c+2]-f[3*i+2]);
				if(dist<D){
					D=dist;
					t=i;
				}
				*idx=t;
			}

		}
	}
	//vector<CvScalar>avg1;//////////////////////
	CvMat *colorNum= cvCreateMat(1,no, CV_32SC1);
	cvZero(Fine2);
	cvZero(colorNum);

	float* f=(float*)(Fine2->data.ptr);
	
	int* num1=(int*)(colorNum->data.ptr);
	for(int r=0;r<rgb->rows;r++){
		int* idx=(int*)(id->data.ptr+r*id->step);
		float* rgbData=(float*)(rgb->data.ptr+r*rgb->step);
 		for(int c=0;c<rgb->cols;c++){

			f[3*idx[c]]+=rgbData[3*c];
			f[3*idx[c]+1]+=rgbData[3*c+1];
			f[3*idx[c]+2]+=rgbData[3*c+2];
			num1[*idx]++;
		}
	}
	for(int i=0;i<no;i++)
	{
		f[3*i]/=num1[i];
		f[3*i+1]/=num1[i];
		f[3*i+2]/=num1[i];
	}
	for(int r=0;r<rgb->rows;r++){
		int* idx=(int*)(id->data.ptr+r*id->step);
		float* resultData=(float*)(result->data.ptr+r*result->step);
		for(int c=0;c<rgb->cols;c++,idx++)
		{
			//CvScalar avg1;
			resultData[3*c]=f[3*(*idx)];
			resultData[3*c+1]=f[3*(*idx)+1];
			resultData[3*c+2]=f[3*(*idx)+2];
			//cvSet2D(result,r,c,avg1);
		}
	}
	//cvConvertScale(result,result00,255);
	
	cvNamedWindow("Result",1);
	cvShowImage("Result",result);
	//cvSaveImage("D:/test/out_C-mean量化颜色(峰&谷,直接合并)+(d小于0.1)merge颜色/9.jpg",result00);
	cvWaitKey(0);
}

map<int,int> Fine(CvMat* mat1u)
{
	map<int,int>colornum1;
	IplImage *hist0=0;//cvCreateImage(cvSize(300,300),IPL_DEPTH_8U,1);
	IplImage *hist1=0;//cvCreateImage(cvSize(300,300),IPL_DEPTH_8U,1);
	for(int i=0;i<mat1u->rows;i++)
	{
		for(int j=0;j<mat1u->cols;j++)
		{
			int color=(int)(cvGetReal2D(mat1u,i,j));
			++colornum1[color];
		}
	}

	int n=colornum1.size();
	/*
	colornum1[0]=0;
	colornum1[1]=0;
	colornum1[2]=0;
	colornum1[n-3]=0;
	colornum1[n-1]=0;
	colornum1[n-2]=0;
	*/
	cout<<"ColorNum:"<<n<<endl;
	hist0=DrawHist(colornum1,n);
	cvNamedWindow("Hist0",1);
	cvShowImage("Hist0",hist0);
	//平滑
	vector<pair<int, int>> num1;
	for( map<int,int>::iterator iter=colornum1.begin();iter!=colornum1.end();iter++)
	{
		num1.push_back(pair<int,int>(iter->first,iter->second));
	}


	for(vector<pair<int,int>>::size_type i=3;i!=n-4;i++)
	{
		int n=(int)((num1[i-3].second+num1[i-2].second+num1[i-1].second+num1[i].second+num1[i+1].second+num1[i+2].second+num1[i+3].second)/7);
		colornum1[num1[i].first]=n;
	}
	hist1=DrawHist(colornum1,n);

	
	num1.clear();
	for( map<int,int>::iterator iter=colornum1.begin();iter!=colornum1.end();iter++)
	{
		num1.push_back(pair<int,int>(iter->first,iter->second));
	}
	map<int,int>merge1;
	map<int,int>merge2;
	int j=0;
	for(vector<pair<int,int>>::size_type i=3;i!=n-4;i++)
	{
		if((num1[i-2].second<num1[i-1].second&&num1[i-1].second<num1[i].second 
			&& num1[i].second>num1[i+1].second&& num1[i+1].second>num1[i+2].second
			||num1[i-2].second>num1[i-1].second&&num1[i-1].second>num1[i].second 
			&& num1[i].second<num1[i+1].second&& num1[i+1].second<num1[i+2].second)
			&&num1[i-1].second!=0&&num1[i-2].second!=0&&num1[i-3].second!=0
			&&num1[i+1].second!=0&&num1[i+2].second!=0&&num1[i+3].second!=0)
			{
						
				merge1[i]=num1[i].second;
				cout<<num1[i].first<<": "<<num1[i].second<<endl;
			
				
			}
	}
	
////////////////////////////////////////////////////////////////////////////////////
	//同一通道上颜色距离小于32的删除

	vector<pair<int, int>> num3;
	for( map<int,int>::iterator iter=merge1.begin();iter!=merge1.end();iter++)
	{
		num3.push_back(pair<int,int>(iter->first,iter->second));
	}

	vector<pair<int,int>>::iterator it3,it2;
	it2=num3.begin();
	it3=num3.begin();
	++it3;
	while(it3!=num3.end())
	{
		if(abs(it2->first-it3->first)<32)
		{
			it3=num3.erase(it3);
		}
		else
		{
			it2=it3;
			it3++;
		}
	}


	int m3=num3.size();
	cout<<"merge color num:"<<m3<<endl;
	
	for(vector<pair<int,int>>::size_type i=0;i!=m3;i++)
	{
		cout<<num3[i].first<<endl;
		merge2[num3[i].first]=num3[i].second;
	}
	
/////////////////////////////////////////////////////////////////////////////////////////////
	for( map<int,int>::iterator iter=merge2.begin();iter!=merge2.end();iter++)
	{
		int x=iter->first;
		double y=iter->second;
		int h=(int)(300-0.1*y);
		cvCircle(hist1,cvPoint(x,h),1,CV_RGB(255,0,0),-1);
	}

	cvNamedWindow("Hist1",1);
	cvShowImage("Hist1",hist1);
	cvWaitKey(0);
	return merge2;
}
IplImage* DrawHist(map<int,int>colornum,int n)
{
	cvZero(histimg);
	int bin_w=1;
	
	double bin_h=(double)300/3000;

	for(map<int,int>::iterator it=colornum.begin();it!=colornum.end();it++)
	{
 		double val =(double) (it->second*bin_h );
        CvScalar color = CV_RGB(255,255,0); //(hsv2rgb(i*180.f/hdims);
        cvLine( histimg, cvPoint(it->first*bin_w,300),
			cvPoint((it->first)*bin_w,(int)(300-val)),color, 1, 8, 0 );
	}
    return histimg;
	
}


 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1246707次
    • 积分:14500
    • 等级:
    • 排名:第816名
    • 原创:177篇
    • 转载:67篇
    • 译文:5篇
    • 评论:1177条
    博主描述
    小硕一枚,目前从业方向:基于交互式设备的应用研发,主要关注:Kinect、LeapMotion、Oculus等交互式设备或可穿戴设备 ;希望和大家交流,共同提高。大家如果对文章有什么问题,发邮件可能无法及时回复,请直接在文章评论栏留言。本人微博:

     小熊不去实验室

    博客专栏
    文章分类
    Tech Blog 1
    最新评论