理解參數(shù)
輸入參數(shù)
1.samples:應該是np.float32數(shù)據(jù)類型,且每個特征應該放在一個單獨的列。
2.nclusters(K): 需要的聚類的數(shù)量
3.criteria: 這是迭代終止準則。當滿足這個準則時,算法迭代停止。實際上,它應該是一個3個參數(shù)的元組。他們是:(type, max_iter, epsilon):
? ? ·3.a - 終止準則的類型: 有3個標志如下:
? ? ? ? cv2.TERM_CRITERIA_EPS - 如果滿足了指定準確度,epsilon就停止算法迭代。
? ? ? ? cv2.TERM_CRITERIA_MAX_ITER - 在指定次數(shù)的迭代后就停止算法。
? ? ? ? cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER - 當任何上面的條件滿足就停止迭代
? ? ·3.b - max_iter - 指定最大的迭代次數(shù),整數(shù)
? ? ·3.c - epsilon - 需要的準確度
4.attempts: 標志,指定算法使用不同初始標簽執(zhí)行的次數(shù)。算法返回能得到最好密度的標簽。密度作為輸出被返回。
5.flags:這個標志是用來指定如何得到初始中心的。一般兩個標志會用到:cv2.KMEANS_PP_CENTERS和cv2.KMEANS_RANDOM_CENTERS.
輸出參數(shù)
1.compactness: 這是從每個點到他們對應的中心的距離的平方和。
2.labels: 這是標簽數(shù)組(和'code'一樣),每個元素被標記為'0', '1'...
3.centers: 這是聚類中心的數(shù)組
現(xiàn)在我們用三個例子看看怎么應用K-Means算法
1.只有一個特征的數(shù)據(jù)
你有一個只有一個特征或者一個維度的數(shù)據(jù)集,比如,我們你只能用人的身高來決定T恤的尺寸。
所以我們創(chuàng)建數(shù)據(jù)并用Matplotlib繪制:
import numpy as np
import cv2
from matplotlib import pyplot as pltx = 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()
所以我們的'z'是一個大小為50的數(shù)組,值的范圍從0到255。我們把'z'變形成列向量。當超過一個特征被顯示時很有用。那么我們把數(shù)據(jù)變成np.float32類型。
現(xiàn)在我們使用KMeans函數(shù)。在此之前我們需要制定criteria。我們的criteria是當10次算法迭代或者準確度epsilon=1.0滿足時,停止算法并返回結果。
# 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)
這給我們密度,標簽和中心,在這個例子里,我們得到中心60和207. 標簽會有和測試數(shù)據(jù)相同的大小,每個數(shù)據(jù)會根據(jù)他們的質心被標記為'0', '1', '2'。現(xiàn)在我們根據(jù)標簽把數(shù)據(jù)分為不同的聚類。
A = z[labels==0]
B = z[labels==1]
現(xiàn)在我們用紅色畫出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. 多個特征的數(shù)據(jù)
在前面的例子里,我們對于T恤問題只取身高。這里,我們取身高和體重兩個特征。
記住,在前面的例子里,我們把我們的數(shù)據(jù)弄成單列向量。每個特征作為一列。每行對應一個輸入測試樣本。
例如,在這個例子里,我們設置一個大小為50x2的測試數(shù)據(jù),是50個人的身高和體重。第一列對應著所有50個人的身高,第二列對應他們的體重。第一行包含兩個元素,第一個元素是第一個人的身高,第二個元素是他的體重,類似的剩下的行對應剩下的人的身高和體重。看下圖:
現(xiàn)在我們直接看代碼:
import numpy as np
import cv2
from matplotlib import pyplot as pltX = 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()
下面是輸出:
3.顏色量化
顏色量化是減少一個圖像里的顏色數(shù)量的過程。做這個的一個原因是減少內存使用。有時候,一些設備會受限只能生成有限的顏色數(shù)量。在那些情況下也會執(zhí)行顏色量化。這里我們使用k-means聚類來做顏色量化。
沒有新的內容要解釋。這里有3個特征,R,G,B。所以我們需要把圖像改造成Mx3大小的數(shù)組(M是圖像像素的數(shù)量)。聚類之后,我們應用中心值到所有的像素上,這樣結果圖像會有指定數(shù)量的顏色。再次我們需要把它變形回去變成原始圖片的形狀。下面是代碼:
import numpy as np
import cv2img = cv2.imread('home.jpg')
Z = img.reshape((-1,3))# convert to np.float32
Z = np.float32(Z)# define criteria, number of clusters(K) and apply kmeans()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 8
ret,label,center=cv2.kmeans(Z,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)# Now convert back into uint8, and make original image
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img.shape))cv2.imshow('res2',res2)
cv2.waitKey(0)
cv2.destroyAllWindows()
看下面K=8時的結果:
END