【Machine Learning】OpenCV中的K-means聚類

在上一篇(【Machine Learning】K-means算法及優化)中,我們介紹了K-means算法的基本原理及其優化的方向。opencv中也提供了K-means算法的接口,這裏主要介紹一下如何在python+opencv的環境下,使用k-means接口(C++的接口形式相似)。

python版本的k-means算法接口,即cv2.kmeans()


輸入參數

-samples: 類型必須是np.float32型,每個特徵應該放置在單獨的一個列中;

-nclusters(K):最終要確定的類別數;

-criteria:迭代終止的條件,3通道參數,分別是(type, max_iter, epsilon):

  • 3.a -type: 終止條件的類型,有如下3個flag: cv2.TERM_CRITERIA_EPS(精度滿足epsilon時,終止迭代);cv2.TERM_CRITERIA_MAX_ITER(最大迭代次數達到後終止);cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER(二者滿足其一即可終止迭代);
  • 3.b -  max_iter:最大迭代次數;
  • 3.c - epsilon:精度;

-attempts: 算法使用不同初始化標識執行的次數,改算法返回最佳集聚性的標籤,該值作爲輸出值返回;

-flags:用於指定如何初始化聚類中心,通常有兩種方式:cv2.KMEANS_PP_CENTERS(初始的K個點)和cv2.KMEANS_RANDOM_CENTERS(隨機產生的K個點)。


輸出參數

-compactness: 集聚性,指每個點到相應聚類中心點的距離平方的和;

-labels:聚類的標識序列(‘0’, ‘1’......);

-centers:聚類中心的序列。


1、一維特徵的聚類

首先,使用如下代碼,創建一個隨機數組序列,並繪製其分佈直方圖:

import numpy as np
import cv2
from matplotlib import pyplot as plt

x = np.random.randint(25,100,25)
y = np.random.randint(175,255,25)
z = np.hstack((x,y))
z = z.reshape((50,1))
z = np.float32(z)
plt.hist(z,256,[0,256]),plt.show()

由此,我們可以得到一個大小爲50的數組‘Z’,值的範圍爲0-255。這裏,將z轉換成列向量,這樣對不止一個特徵的聚類會非常有幫助,值的數據類型爲np.float32。直方分佈圖如下:

這裏,調用K-means方程,首先我們要設定好criteria,這裏最大迭代次數設定爲10,誤差設定爲1.0,且終止條件指定爲不管達到誤差還是達到最大迭代次數,都將終止迭代。同時,指定將以上數據聚類爲2類。具體代碼如下:

# Define criteria = ( type, max_iter = 10 , epsilon = 1.0 )
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)

# Set flags (Just to avoid line break in the code)
flags = cv2.KMEANS_RANDOM_CENTERS

# Apply KMeans
compactness,labels,centers = cv2.kmeans(z,2,None,criteria,10,flags)

這裏返回了compactness, labels and centers.這裏,我們得到64和210兩個中心點(每次運行可能不太一樣,因爲數據是隨機出來的)。labels的大小和輸入數據的大小相同,每個數據都將根據他們所屬類的中心被標記爲‘0’,‘1’,‘2’ 等等。下面將根據他們的標識,將數據按類分離開:

A = z[labels==0]
B = z[labels==1]

下面將A類用紅色繪製,B類用藍色繪製,他們的中心均用黃色繪製:

# Now plot 'A' in red, 'B' in blue, 'centers' in yellow
plt.hist(A,256,[0,256],color = 'r')
plt.hist(B,256,[0,256],color = 'b')
plt.hist(centers,32,[0,256],color = 'y')
plt.show()

可得到如下結果:


2、多維特徵的聚類


下面考慮二維特徵的聚類,按照上面類似的思路,生成數據,進行聚類,並繪製聚類結果。代碼如下:

import numpy as np
import cv2
from matplotlib import pyplot as plt

X = np.random.randint(25,50,(25,2))
Y = np.random.randint(60,85,(25,2))
Z = np.vstack((X,Y))

# convert to np.float32
Z = np.float32(Z)

# define criteria and apply kmeans()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
ret,label,center=cv2.kmeans(Z,2,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)

# Now separate the data, Note the flatten()
A = Z[label.ravel()==0]
B = Z[label.ravel()==1]

# Plot the data
plt.scatter(A[:,0],A[:,1])
plt.scatter(B[:,0],B[:,1],c = 'r')
plt.scatter(center[:,0],center[:,1],s = 80,c = 'y', marker = 's')
plt.xlabel('Height'),plt.ylabel('Weight')
plt.show()

聚類結果如下:





2017.11.17

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章