1. 程式人生 > >k-means演算法及opencv實現

k-means演算法及opencv實現

K-means演算法是最為經典的基於劃分的聚類方法,是十大經典資料探勘演算法之一。K-means演算法的基本思想是:以空間中k個點為中心進行聚類,對最靠近他們的物件歸類。通過迭代的方法,逐次更新各聚類中心的值,直至得到最好的聚類結果。

假設要把樣本集分為c個類別,演算法描述如下:

(1)適當選擇c個類的初始中心;

(2) 在第k次迭代中,對任意一樣本,求其到c箇中心的距離,將其歸類到距離最短的中心所在的類;

(3) 利用均值等方法更新該類的中心值;

(4) 重複步驟(2)(3),直到聚類中心保持不變。

該演算法的最大優勢在於簡潔和快速,演算法的關鍵在於初始中心的選擇和距離公式。[百度百科]

K-means在opencv中的實現:

  1. void kmeans_mat(const Mat& src_img,Mat& dst_img)

  2. {

  3. int width_src=src_img.cols;

  4. int height_src=src_img.rows;

  5. Mat samples=Mat::zeros(width_src*height_src,1,CV_32FC3);//建立樣本矩陣,CV_32FC3代表32位浮點3通道(彩色影象)

  6. Mat clusters;//類別標記矩陣

  7. int k=0;

  8. for (int i=0;i<height_src;i++)

  9. {

  10. for (int j=0;j<width_src;j++,k++)

  11. {

  12. //將畫素點三通道的值按順序排入樣本矩陣

  13. samples.at<Vec3f>(k,0)[0]=(float)src_img.at<Vec3b>(i,j)[0];

  14. samples.at<Vec3f>(k,0)[1]=(float)src_img.at<Vec3b>(i,j)[1];

  15. samples.at<Vec3f>(k,0)[2]=(float)src_img.at<Vec3b>(i,j)[2];

  16. }

  17. }

  18. int nCuster=2;//聚類類別數,自己修改。

  19. //聚類,KMEANS PP CENTERS Use kmeans++ center initialization by Arthur and Vassilvitskii

  20. kmeans(samples,nCuster,clusters,TermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,10,1.0),2,KMEANS_PP_CENTERS);

  21. //顯示聚類結果

  22. if (dst_img.empty())

  23. {

  24. dst_img=Mat::zeros(height_src,width_src,CV_8UC1);

  25. }

  26. k=0;

  27. int val=0;

  28. float step=255/(nCuster-1);

  29. for (int i=0;i<height_src;i++)

  30. {

  31. for (int j=0;j<width_src;j++,k++)

  32. {

  33. val=255-clusters.at<int>(k,0)*step;//int

  34. dst_img.at<uchar>(i,j)=val;

  35. }

  36. }

  37. }

 k-means聚類演算法,初始中心的選擇是關鍵,有時間還需要研究下KMEANS_PP_CENTERS Use kmeans++ center initialization by Arthur and Vassilvitskii方法。