学习OpenCV——一次颜色聚类

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算法,效果会很好。

 

  1. #include "cv.h"  
  2. #include"highgui.h"  
  3. #include<map>  
  4. #include<vector>  
  5. #include<iostream>  
  6. using namespace std;  
  7. template<typename T>T sqr(T x){return x*x;}  
  8. CvMat* mat=0;  
  9. IplImage* image=0;  
  10. IplImage *histimg=cvCreateImage(cvSize(256,300),IPL_DEPTH_8U,3);  
  11. IplImage* DrawHist(map<int,int>colornum,int n);  
  12. map<int,int> Fine(CvMat* mat1u);  
  13.   
  14. //CvMat* Merge(CvMat* Fine,int FineNum);  
  15. int main()  
  16. {  
  17.     image=cvLoadImage("D:/7.jpg",1);  
  18.     cvNamedWindow("Show",1);  
  19.     cvShowImage("Show",image);  
  20.     IplImage *hist0=0;//cvCreateImage(cvSize(300,300),IPL_DEPTH_8U,1);  
  21.     IplImage *hist1=0;//cvCreateImage(cvSize(300,300),IPL_DEPTH_8U,1);  
  22.     CvMat* r=cvCreateMat(image->height,image->width,CV_8UC1);  
  23.     CvMat* g=cvCreateMat(image->height,image->width,CV_8UC1);  
  24.     CvMat* b=cvCreateMat(image->height,image->width,CV_8UC1);  
  25.     CvMat* rgb=cvCreateMat(image->height,image->width,CV_32FC3);  
  26.     CvMat* result=cvCreateMat(image->height,image->width,CV_32FC3);  
  27.     CvMat* result00=cvCreateMat(image->height,image->width,CV_8UC3);  
  28.     cvConvertScale(image,rgb,1.0/255);  
  29.     cvSplit(image,r,g,b,NULL);  
  30.     map<int,int>fine_r=Fine(r);  
  31.     map<int,int>fine_g=Fine(g);  
  32.     map<int,int>fine_b=Fine(b);  
  33.   
  34.     int FineNum=fine_r.size()*fine_g.size()*fine_b.size();  
  35.     cout<<"FineNum: "<<FineNum<<endl;  
  36.     CvMat* Fine=cvCreateMat(1,FineNum,CV_32FC3);  
  37.     //vector<CvScalar>avg;  
  38.     int i=0;  
  39.     for(map<int,int>::iterator it0=fine_r.begin();it0!=fine_r.end();it0++){  
  40.         for(map<int,int>::iterator it1=fine_g.begin();it1!=fine_g.end();it1++){  
  41.             float* f=(float*)(Fine->data.ptr);  
  42.             for(map<int,int>::iterator it2=fine_b.begin();it2!=fine_b.end();it2++)  
  43.             {  
  44.                 f[3*i]=(float)it0->first/255;  
  45.                 f[3*i+1]=(float)it1->first/255;  
  46.                 f[3*i+2]=(float)it2->first/255;  
  47.                 i++;  
  48.             }  
  49.         }  
  50.     }  
  51.   
  52.     //CvMat* Fine2=0;  
  53.     //Fine2=Merge(Fine,FineNum);  
  54.         vector<pair<int,int>>merge;  
  55.     float* f1=(float*)(Fine->data.ptr);  
  56.     float* f2=(float*)(Fine->data.ptr);  
  57.     for(int m=0;m<FineNum;m++)  
  58.     {  
  59.           
  60.         for(int n=m+1;n<FineNum;n++)  
  61.         {  
  62.             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]);  
  63.             if(d<=0.1){  
  64.                 merge.push_back(make_pair(m,n));  
  65.             }  
  66.   
  67.         }  
  68.     }  
  69.     cout<<"merge:"<<merge.size()<<endl;  
  70.     //Fine1中存储把颜色距离平方小于0.05的元素合并后的结果,结果存在第一个元素位置,第二个位置置零  
  71.     CvMat* Fine1=cvCreateMat(1,FineNum,CV_32FC3);  
  72.     float* F1=(float*)(Fine1->data.ptr);  
  73.     for(vector<pair<int,int>>::iterator iter=merge.begin();iter!=merge.end();iter++)  
  74.     {  
  75.         if(F1[3*(iter->first)]!=0)  
  76.         {  
  77.             F1[3*(iter->first)]=(f1[3*(iter->first)]+f1[3*(iter->second)])/2;  
  78.             F1[3*(iter->first)+1]=(f1[3*(iter->first)+1]+f1[3*(iter->second)+1])/2;  
  79.             F1[3*(iter->first)+2]=(f1[3*(iter->first)+2]+f1[3*(iter->second)+2])/2;  
  80.             F1[3*(iter->second)]=0;  
  81.             F1[3*(iter->second)+1]=0;  
  82.             F1[3*(iter->second)+2]=0;  
  83.             f1[3*(iter->second)]=0;  
  84.             f1[3*(iter->second)+1]=0;  
  85.             f1[3*(iter->second)+2]=0;  
  86.         }  
  87.         else  
  88.             {  
  89.                 F1[3*(iter->first)]=f1[3*(iter->first)];  
  90.                 F1[3*(iter->first)+1]=f1[3*(iter->first)+1];  
  91.                 F1[3*(iter->first)+2]=f1[3*(iter->first)+2];  
  92.             }  
  93.     }  
  94.       
  95.     //求Fine1中非零元素个数  
  96.     int no=0;  
  97.     for(int m=0;m<FineNum;m++)  
  98.     {  
  99.         if(F1[m]!=0)  
  100.             no++;  
  101.     }  
  102.     cout<<"Not Zore Num:"<<no<<endl;  
  103.     //Fine2中存储merge后Fine1中的非零元素  
  104.     CvMat* Fine2=cvCreateMat(1,no*3,CV_32FC1);  
  105.     float* F2=(float*)(Fine2->data.ptr);  
  106.     for(int m=0;m<FineNum;m++)  
  107.     {  
  108.         if(F1[m]!=0)  
  109.         {  
  110.             *F2=F1[m];  
  111.             F2++;  
  112.         }  
  113.   
  114.     }  
  115.     cout<<"F2_Width: "<<Fine2->width<<endl;  
  116.   
  117.       
  118.     //int no=Fine2->width;  
  119.   
  120.     CvMat* id =cvCreateMat(image->height,image->width,CV_32SC1);  
  121.     for(int r=0;r<rgb->rows;r++){  
  122.         int* idx=(int*)(id->data.ptr+r*id->step);  
  123.         float* rgbData=(float*)(rgb->data.ptr+r*rgb->step);  
  124.         for(int c=0;c<rgb->cols;c++,idx++){  
  125.               
  126.             float D=200000;  
  127.             int t=0;  
  128.             float* f=(float*)(Fine2->data.ptr);  
  129.             for(int i=0;i<no;i++){  
  130.                 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]);  
  131.                 if(dist<D){  
  132.                     D=dist;  
  133.                     t=i;  
  134.                 }  
  135.                 *idx=t;  
  136.             }  
  137.   
  138.         }  
  139.     }  
  140.     //vector<CvScalar>avg1;//  
  141.     CvMat *colorNum= cvCreateMat(1,no, CV_32SC1);  
  142.     cvZero(Fine2);  
  143.     cvZero(colorNum);  
  144.   
  145.     float* f=(float*)(Fine2->data.ptr);  
  146.       
  147.     int* num1=(int*)(colorNum->data.ptr);  
  148.     for(int r=0;r<rgb->rows;r++){  
  149.         int* idx=(int*)(id->data.ptr+r*id->step);  
  150.         float* rgbData=(float*)(rgb->data.ptr+r*rgb->step);  
  151.         for(int c=0;c<rgb->cols;c++){  
  152.   
  153.             f[3*idx[c]]+=rgbData[3*c];  
  154.             f[3*idx[c]+1]+=rgbData[3*c+1];  
  155.             f[3*idx[c]+2]+=rgbData[3*c+2];  
  156.             num1[*idx]++;  
  157.         }  
  158.     }  
  159.     for(int i=0;i<no;i++)  
  160.     {  
  161.         f[3*i]/=num1[i];  
  162.         f[3*i+1]/=num1[i];  
  163.         f[3*i+2]/=num1[i];  
  164.     }  
  165.     for(int r=0;r<rgb->rows;r++){  
  166.         int* idx=(int*)(id->data.ptr+r*id->step);  
  167.         float* resultData=(float*)(result->data.ptr+r*result->step);  
  168.         for(int c=0;c<rgb->cols;c++,idx++)  
  169.         {  
  170.             //CvScalar avg1;  
  171.             resultData[3*c]=f[3*(*idx)];  
  172.             resultData[3*c+1]=f[3*(*idx)+1];  
  173.             resultData[3*c+2]=f[3*(*idx)+2];  
  174.             //cvSet2D(result,r,c,avg1);  
  175.         }  
  176.     }  
  177.     //cvConvertScale(result,result00,255);  
  178.       
  179.     cvNamedWindow("Result",1);  
  180.     cvShowImage("Result",result);  
  181.     //cvSaveImage("D:/test/out_C-mean量化颜色(峰&谷,直接合并)+(d小于0.1)merge颜色/9.jpg",result00);  
  182.     cvWaitKey(0);  
  183. }  
  184.   
  185. map<int,int> Fine(CvMat* mat1u)  
  186. {  
  187.     map<int,int>colornum1;  
  188.     IplImage *hist0=0;//cvCreateImage(cvSize(300,300),IPL_DEPTH_8U,1);  
  189.     IplImage *hist1=0;//cvCreateImage(cvSize(300,300),IPL_DEPTH_8U,1);  
  190.     for(int i=0;i<mat1u->rows;i++)  
  191.     {  
  192.         for(int j=0;j<mat1u->cols;j++)  
  193.         {  
  194.             int color=(int)(cvGetReal2D(mat1u,i,j));  
  195.             ++colornum1[color];  
  196.         }  
  197.     }  
  198.   
  199.     int n=colornum1.size();  
  200.     /* 
  201.     colornum1[0]=0; 
  202.     colornum1[1]=0; 
  203.     colornum1[2]=0; 
  204.     colornum1[n-3]=0; 
  205.     colornum1[n-1]=0; 
  206.     colornum1[n-2]=0; 
  207.     */  
  208.     cout<<"ColorNum:"<<n<<endl;  
  209.     hist0=DrawHist(colornum1,n);  
  210.     cvNamedWindow("Hist0",1);  
  211.     cvShowImage("Hist0",hist0);  
  212.     //平滑  
  213.     vector<pair<intint>> num1;  
  214.     for( map<int,int>::iterator iter=colornum1.begin();iter!=colornum1.end();iter++)  
  215.     {  
  216.         num1.push_back(pair<int,int>(iter->first,iter->second));  
  217.     }  
  218.   
  219.   
  220.     for(vector<pair<int,int>>::size_type i=3;i!=n-4;i++)  
  221.     {  
  222.         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);  
  223.         colornum1[num1[i].first]=n;  
  224.     }  
  225.     hist1=DrawHist(colornum1,n);  
  226.   
  227.       
  228.     num1.clear();  
  229.     for( map<int,int>::iterator iter=colornum1.begin();iter!=colornum1.end();iter++)  
  230.     {  
  231.         num1.push_back(pair<int,int>(iter->first,iter->second));  
  232.     }  
  233.     map<int,int>merge1;  
  234.     map<int,int>merge2;  
  235.     int j=0;  
  236.     for(vector<pair<int,int>>::size_type i=3;i!=n-4;i++)  
  237.     {  
  238.         if((num1[i-2].second<num1[i-1].second&&num1[i-1].second<num1[i].second   
  239.             && num1[i].second>num1[i+1].second&& num1[i+1].second>num1[i+2].second  
  240.             ||num1[i-2].second>num1[i-1].second&&num1[i-1].second>num1[i].second   
  241.             && num1[i].second<num1[i+1].second&& num1[i+1].second<num1[i+2].second)  
  242.             &&num1[i-1].second!=0&&num1[i-2].second!=0&&num1[i-3].second!=0  
  243.             &&num1[i+1].second!=0&&num1[i+2].second!=0&&num1[i+3].second!=0)  
  244.             {  
  245.                           
  246.                 merge1[i]=num1[i].second;  
  247.                 cout<<num1[i].first<<": "<<num1[i].second<<endl;  
  248.               
  249.                   
  250.             }  
  251.     }  
  252.       
  253.   
  254.     //同一通道上颜色距离小于32的删除  
  255.   
  256.     vector<pair<intint>> num3;  
  257.     for( map<int,int>::iterator iter=merge1.begin();iter!=merge1.end();iter++)  
  258.     {  
  259.         num3.push_back(pair<int,int>(iter->first,iter->second));  
  260.     }  
  261.   
  262.     vector<pair<int,int>>::iterator it3,it2;  
  263.     it2=num3.begin();  
  264.     it3=num3.begin();  
  265.     ++it3;  
  266.     while(it3!=num3.end())  
  267.     {  
  268.         if(abs(it2->first-it3->first)<32)  
  269.         {  
  270.             it3=num3.erase(it3);  
  271.         }  
  272.         else  
  273.         {  
  274.             it2=it3;  
  275.             it3++;  
  276.         }  
  277.     }  
  278.   
  279.   
  280.     int m3=num3.size();  
  281.     cout<<"merge color num:"<<m3<<endl;  
  282.       
  283.     for(vector<pair<int,int>>::size_type i=0;i!=m3;i++)  
  284.     {  
  285.         cout<<num3[i].first<<endl;  
  286.         merge2[num3[i].first]=num3[i].second;  
  287.     }  
  288.       
  289. /  
  290.     for( map<int,int>::iterator iter=merge2.begin();iter!=merge2.end();iter++)  
  291.     {  
  292.         int x=iter->first;  
  293.         double y=iter->second;  
  294.         int h=(int)(300-0.1*y);  
  295.         cvCircle(hist1,cvPoint(x,h),1,CV_RGB(255,0,0),-1);  
  296.     }  
  297.   
  298.     cvNamedWindow("Hist1",1);  
  299.     cvShowImage("Hist1",hist1);  
  300.     cvWaitKey(0);  
  301.     return merge2;  
  302. }  
  303. IplImage* DrawHist(map<int,int>colornum,int n)  
  304. {  
  305.     cvZero(histimg);  
  306.     int bin_w=1;  
  307.       
  308.     double bin_h=(double)300/3000;  
  309.   
  310.     for(map<int,int>::iterator it=colornum.begin();it!=colornum.end();it++)  
  311.     {  
  312.         double val =(double) (it->second*bin_h );  
  313.         CvScalar color = CV_RGB(255,255,0); //(hsv2rgb(i*180.f/hdims);  
  314.         cvLine( histimg, cvPoint(it->first*bin_w,300),  
  315.             cvPoint((it->first)*bin_w,(int)(300-val)),color, 1, 8, 0 );  
  316.     }  
  317.     return histimg;  
  318.       
  319. }  
  320. <img src="http://hi.csdn.net/attachment/201203/23/0_1332479095dNOm.gif" alt="">  
  1.   
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值