模糊聚類算法(FCM)


 伴隨着模糊集理論的形成、發展和深化,RusPini率先提出模糊划分的概念。以此為起點和基礎,模糊聚類理論和方法迅速蓬勃發展起來。針對不同的應用,人們提出了很多模糊聚類算法,比較典型的有基於相似性關系和模糊關系的方法、基於模糊等價關系的傳遞閉包方法、基於模糊圖論的最大支撐樹方法,以及基於數據集的凸分解、動態規划和難以辨別關系等方法。然而,上述方法均不能適用於大數據量的情況,難以滿足實時性要求較高的場合,因此實際應用並不廣泛。

模糊聚類分析按照聚類過程的不同大致可以分為三大類:

(1)基於模糊關系的分類法:其中包括譜系聚類算法(又稱系統聚類法)、基於等價關系的聚類算法、基於相似關系的聚類算法和圖論聚類算法等等。它是研究比較早的一種方法,但是由於它不能適用於大數據量的情況,所以在實際中的應用並不廣泛。

(2)基於目標函數的模糊聚類算法:該方法把聚類分析歸結成一個帶約束的非線性規划問題,通過優化求解獲得數據集的最優模糊划分和聚類。該方法設計簡單、解決問題的范圍廣,還可以轉化為優化問題而借助經典數學的非線性規划理論求解,並易於計算機實現。因此,隨着計算機的應用和發展,基於目標函數的模糊聚類算法成為新的研究熱點。

(3)基於神經網絡的模糊聚類算法:它是興起比較晚的一種算法,主要是采用競爭學習算法來指導網絡的聚類過程。

 

在介紹算法之前,先介紹下模糊集合的知識。

HCM聚類算法

        首先說明隸屬度函數的概念。隸屬度函數是表示一個對象x 隸屬於集合A 的程度的函數,通常記做μA(x),其自變量范圍是所有可能屬於集合A 的對象(即集合A 所在空間中的所有點),取值范圍是[0,1],即0<=μA(x),μA(x)<=1。μA(x)=1 表示x 完全隸屬於集合A,相當於傳統集合概念上的x∈A。一個定義在空間X={x}上的隸屬度函數就定義了一個模糊集合A,或者叫定義在論域X={x}上的模糊子集A’。對於有限個對象x1,x2,……,xn 模糊集合A’可以表示為:

        有了模糊集合的概念,一個元素隸屬於模糊集合就不是硬性的了,在聚類的問題中,可以把聚類生成的簇看成模糊集合,因此,每個樣本點隸屬於簇的隸屬度就是[0,1]區間里面的值。

 

再接下來要講FCM算法不得不先講一下HCM算法

硬C-均值(HCM)算法是實現數據集J硬C划分的經典算法之一,也是最受歡迎的算法之一。它能夠把數據集X分成C個超橢球結構的聚類。HCM算法把傳統的聚類問題歸結為如下的非線性數學規划問題:


其中U=(uij)cxn為硬C-划分矩陣,V=(v1,v2,,,vc)為C個聚類中心,||·||代碼歐式距離。

HCM算法的具體流程如下:

初始化:指定聚類類別數C,2<=C<=n,n是數據個數,設定迭代停止閾值Ɛ,初始化聚類中心V0,設置迭代計數器b=0;

步驟一:根據下面的公式計算或更新划分矩陣U


步驟二:根據下面公式更新聚類中心V(b+1)


步驟三:如果||Vb – V(b+1)||< Ɛ,則算法停止並輸出划分矩陣和聚類中心V,否則令b=b+1,轉向執行步驟一

FCM聚類算法

Dunn按照RusPini定義的模糊划分的概念,把HCM算法擴展到模糊划分領域。Dunn對每個樣本與每個聚類中心的距離用其隸屬度平方加權,從而把類內誤差平方和目標函數J1擴展為類內加權誤差平方和函數J2:


Bezdek又將Dunn的目標函數推廣為更普遍的形式,給出了基於目標函數的模糊聚類更一般的描述。


其中,m∈[1,+∞)稱為加權指數,又稱作平滑參數。盡管從數學角度看,m的出現不自然,但如果不對隸屬度加權,從HCM算法到FCM算法的推廣將是無效的。

FCM算法的具體流程如下:

初始化:指定聚類類別數C,2<=C<=n,n是數據個數,設定迭代停止閾值Ɛ,初始化聚類中心V0,設置迭代計數器b=0;

步驟一:根據下面的公式計算或更新划分矩陣U


步驟二:根據下面公式更新聚類中心V(b+1)


步驟三:如果||Vb – V(b+1)||< Ɛ,則算法停止並輸出划分矩陣和聚類中心V,否則令b=b+1,轉向執行步驟一


FCM算法流程圖

FCM算法是目前比較流行的一種模糊聚類算法,究其原因大致有以下幾個方面:首先,模糊C—均值泛函Jm仍是傳統硬C一均值泛函J1的自然推廣;硬C一均值泛函J1是一個應用十分廣泛的聚類准則,對其在理論上的研究己經相當完善,這就為Jm的研究提供了良好的條件;數學上看,Jm與RS的希爾伯特空間結構(正交投影和均方逼近理論)有密切的關系,因此比其它泛函有更深厚的數學基礎;最后,也是最重要的是該目標函數不僅在許多領域獲得了非常成功的應用,而且以FCM算法為基礎,人們提出的基於其它原型的模糊聚類算法,形成了一大批FCM類型的算法:如模糊C一線(FCL)、模糊C一面(FCP)等聚類算法,分別實現了對呈線狀、超平面狀結構模式子集(或聚類)的檢測。

FCM算法應用到顏色遷移中

        錢小燕等人將聚類算法應用到色彩遷移中,提出了一種基於圖像模糊顏色聚類的自適應色彩遷移算法。該算法首先將源圖像和目標圖像分別轉換到lαβ顏色空間:利用FCM 算法把源圖像和目標圖像划分為具有不同顏色特征的聚類,然后分析圖像中的顏色特征:分別算出每個域的匹配權值,對每個目標圖像的匹配權值,從源圖像中選取一個最接近域作為最佳匹配域;最后根據目標圖像各聚類域與源圖像中的匹配域之間的關系,引入隸屬度因子,兩個域的處理結果分別進行加權平均,獲得色彩遷移結果。使用FCM的思想對圖像進行聚類域划分的思路是:設准備處理圖像I的大小是S×H,即對顏色聚類顏色分析的個數是N,N = S×H,則圖像I可表示成集合,I={p1 ,p2 ...,pn }。圖像被分為c類,每個類的聚類中心為V={v1,v2 ...,vc },用uik表示像素pk隸屬於聚類中心Vi的隸屬度,定義圖像的隸屬度矩陣U。具體算法如下:

步驟一:把源圖像和目標圖像分別從RGB轉換到lαβ空間。

步驟二:確定待處理圖像聚類域個數c,然后初始化聚類中心。假設加權指數m=2,設定處理的最大迭代次數為50。

步驟三:當迭代次數小於50 時,根據初始化聚類中心計算隸屬度矩陣。如果pk≠vi,則對於所有的vi ( i=1,2,...,C ),利用下式計算隸屬度矩陣。


其中,i =1,2,...C; j =1,2,...N

如果,pk=vi,,k =1,2,...N則


其中,dik為第k個元素到第i 個聚類中心的距離,定義在lαβ下的歐式距離。


步驟四:對圖像聚類划分。圖像的隸屬度矩陣中,從每列選擇隸屬度最大的點作為相對應點的歸屬域,並重新計算聚類中心。

步驟五:對收斂情況進行檢查。若||Vi – V’i||<Σ,則立即停止迭代;否則一直迭代計算步驟三與步驟四。

步驟六:對聚類域進行匹配。使用FCM 后,對每一個聚類域分別設置一個匹配權值參數w,當目標圖像是灰度圖像時,w為聚類域的亮度均值;當目標圖像為彩色圖像時,w 是聚類域3 個通道標准差的加權平均值。

步驟七:色彩遷移。為了保持通用性,假定目標圖像中元素pi的歸屬域與源圖像中聚類域h 是匹配域,利用下式獲得各個通道的新值:


FCM算法效果圖

[cpp]  view plain  copy
  1. BOOL TranFCM(LPBYTE lpDIBBits, LONG lmageWidth, LONG lmageHeight,LPBYTE lpDIBBits2, LONG lmageWidth2, LONG lmageHeight2,LPBYTE lpDIBBits3)  
  2. {  
  3.     int classnum=2;  
  4.     int m=2;  
  5.     int i,j,k,nindex;  
  6.     double l,a,b;  
  7.     double* belong=new double[lmageWidth*lmageHeight*classnum];  
  8.     double* belong2=new double[lmageWidth2*lmageHeight2*classnum];  
  9.     double* center=new double[classnum*3];  
  10.     double* center2=new double[classnum*3];  
  11.     int* clustermap=new int[classnum];  
  12.     double suml,suma,sumb;  
  13.     FCMCluster(lpDIBBits,lmageWidth,lmageHeight,belong,center,classnum,m);  
  14.     FCMCluster(lpDIBBits2,lmageWidth2,lmageHeight2,belong2,center2,classnum,m);  
  15.       
  16.     double* vl=new double[classnum];  
  17.     double* va=new double[classnum];  
  18.     double* vb=new double[classnum];  
  19.     double* vl2=new double[classnum];  
  20.     double* va2=new double[classnum];  
  21.     double* vb2=new double[classnum];  
  22.     for(i=0;i<classnum;i++)  
  23.     {  
  24.         BYTE distance=255;  
  25.         int map=-1;  
  26.         BYTE r,g,b,r2,g2,b2;  
  27.         for(j=0;j<classnum;j++)  
  28.         {  
  29.             LabToRgb(center[i*3+0],center[i*3+1],center[i*3+2],r,g,b);  
  30.             LabToRgb(center2[j*3+0],center2[j*3+1],center2[j*3+2],r2,g2,b2);  
  31.             BYTE dis=abs(RgbToGray(r,g,b)-RgbToGray(r2,g2,b2));  
  32.             if (distance>dis) {distance=dis;map=j;}  
  33.         }  
  34.         clustermap[i]=map;  
  35.     }  
  36.     //TranColor(belong,belong2,center,center2);  
  37.     //求各聚類域的標准差  
  38.   
  39.     //求結果圖像的lab  
  40.     for(j = 0;j <lmageHeight; j++)  
  41.     {  
  42.         for(i = 0; i <lmageWidth; i++)  
  43.         {     
  44.             nindex=((lmageHeight-j-1)*lmageWidth+i);  
  45.             suml=suma=sumb=0;  
  46.             RgbToLab(lpDIBBits[nindex*3+2],lpDIBBits[nindex*3+1],lpDIBBits[nindex*3+0],l,a,b);  
  47.             for(k=0;k<classnum;k++)  
  48.             {  
  49.                 suml += belong[lmageWidth*lmageHeight*k+nindex]*center2[clustermap[k]*3+0];  
  50.                 suma += belong[lmageWidth*lmageHeight*k+nindex]*center2[clustermap[k]*3+1];  
  51.                 sumb += belong[lmageWidth*lmageHeight*k+nindex]*center2[clustermap[k]*3+2];  
  52.             }  
  53.             LabToRgb(l,suma,sumb,lpDIBBits3[nindex*3+2],lpDIBBits3[nindex*3+1],lpDIBBits3[nindex*3+0]);  
  54.         }  
  55.     }  
  56.     return TRUE;  
  57. }  

[cpp]  view plain  copy
  1. BOOL FCMCluster(LPBYTE lpDIBBits, LONG lmageWidth, LONG lmageHeight,double* belong,double* center,int classnum,int m)  
  2. {  
  3.     int i,j,l,nindex;//循環控制變量  
  4.     int k=0;  
  5.     int LOOP=500;  
  6.     double* center2=new double[classnum*3];//聚類中心  
  7.     long x,y;//隨機確定聚類中心坐標  
  8.     long* num=new long[classnum];//每個類的像素個數  
  9.     double* lpImageLab = new  double[lmageWidth*lmageHeight*3];  
  10.     double sumu,suml,suma,sumb;   
  11.   
  12.     //初始化聚類中心  
  13.     for(i=0;i<classnum;i++)  
  14.     {  
  15.         x=rand()%lmageWidth;  
  16.         y=rand()%lmageHeight;  
  17.         nindex=((lmageHeight-y-1)*lmageWidth+x);  
  18.         RgbToLab(lpDIBBits[nindex*3+2],lpDIBBits[nindex*3+1],lpDIBBits[nindex*3+0],center[i*3+0],center[i*3+1],center[i*3+2]);  
  19.         for(j=0;j<i;j++)  
  20.         {     
  21.             double dis=DistanceLab(center[i*3+0],center[i*3+1],center[i*3+2],center[j*3+0],center[j*3+1],center[j*3+2]);  
  22.             if(dis<0.2) {i--;break;}//限值公式 暫取限值為1待優化 對初始化聚類中心的選擇非常關鍵  
  23.         }  
  24.     }  
  25.   
  26.     //計算隸屬度矩陣、更新聚類中心、直至前后聚類中心距離小於限值e暫定0.1待優化  
  27.     while(k!=classnum && LOOP--)//限值公式  
  28.     {  
  29.         //計算隸屬度矩陣  
  30.         for(j = 0;j <lmageHeight; j++)  
  31.         {  
  32.             for(i = 0; i <lmageWidth; i++)  
  33.             {     
  34.                 nindex=((lmageHeight-j-1)*lmageWidth+i);  
  35.                 RgbToLab(lpDIBBits[nindex*3+2],lpDIBBits[nindex*3+1],lpDIBBits[nindex*3+0],  
  36.                     lpImageLab[nindex*3+0],lpImageLab[nindex*3+1],lpImageLab[nindex*3+2]);  
  37.                 //means_Assign();             
  38.                 double blg=-1;//隸屬度  
  39.                 for(k=0;k<classnum;k++)  
  40.                 {  
  41.                     sumu=0;  
  42.                     double dis1=DistanceLab(lpImageLab[nindex*3+0],lpImageLab[nindex*3+1],lpImageLab[nindex*3+2],center[k*3+0],center[k*3+1],center[k*3+2]);  
  43.                     if (dis1==0) {belong[lmageWidth*lmageHeight*k+nindex]=1;continue;}    
  44.                     for(l=0;l<classnum;l++)  
  45.                     {  
  46.                         double dis2=DistanceLab(lpImageLab[nindex*3+0],lpImageLab[nindex*3+1],lpImageLab[nindex*3+2],center[l*3+0],center[l*3+1],center[l*3+2]);  
  47.                         if (dis2==0) break;  
  48.                         sumu+=pow((dis1*dis1)/(dis2*dis2),1.0/(m-1));                     
  49.                     }  
  50.                     if (l!=classnum) {belong[lmageWidth*lmageHeight*k+nindex]=0;continue;}  
  51.                     belong[lmageWidth*lmageHeight*k+nindex]=1/sumu;  
  52.                 }  
  53.             }  
  54.         }  
  55.           
  56.         //更新聚類中心  
  57.         for(k=0;k<classnum;k++)  
  58.         {  
  59.             suml=suma=sumb=sumu=0;        
  60.             for(j = 0;j <lmageHeight; j++)  
  61.             {  
  62.                 for(i = 0; i <lmageWidth; i++)  
  63.                 {     
  64.                     nindex=((lmageHeight-j-1)*lmageWidth+i);  
  65.                     suml+=pow(belong[lmageWidth*lmageHeight*k+nindex],m)*lpImageLab[nindex*3+0];  
  66.                     suma+=pow(belong[lmageWidth*lmageHeight*k+nindex],m)*lpImageLab[nindex*3+1];  
  67.                     sumb+=pow(belong[lmageWidth*lmageHeight*k+nindex],m)*lpImageLab[nindex*3+2];  
  68.                     sumu+=pow(belong[lmageWidth*lmageHeight*k+nindex],m);  
  69.                 }  
  70.             }  
  71.             center2[k*3+0]=suml/sumu;             
  72.             center2[k*3+1]=suma/sumu;  
  73.             center2[k*3+2]=sumb/sumu;  
  74.         }  
  75.           
  76.         //判斷循環終止條件  
  77.         for(k=0;k<classnum;k++)  
  78.         {  
  79.             if(DistanceLab(center[k*3+0],center[k*3+1],center[k*3+2],center2[k*3+0],center2[k*3+1],center2[k*3+2])>0.1) break;//限值e暫定0.1待優化  
  80.         }  
  81.         for(i=0;i<classnum*3;i++)  
  82.         {  
  83.             center[i]=center2[i];  
  84.         }  
  85.           
  86.     }  
  87.   
  88.     return TRUE;  
  89. }  

[cpp]  view plain  copy
  1. double DistanceLab(double l1,double a1,double b1,double l2,double a2,double b2)  
  2. {  
  3.     double lx=l1-l2;  
  4.     double ax=a1-a2;  
  5.     double bx=b1-b2;  
  6.     if (lx<0) lx=-lx;  
  7.     if (ax<0) ax=-ax;  
  8.     if (bx<0) bx=-bx;  
  9.     return lx+ax+bx;      
  10. }  

代碼鏈接

版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/lyh03601/article/details/22896197


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM