理解參數(shù)
輸入?yún)?shù)
1.samples:應(yīng)該是np.float32數(shù)據(jù)類型足陨,且每個(gè)特征應(yīng)該放在一個(gè)單獨(dú)的列症脂。
2.nclusters(K): 需要的聚類的數(shù)量
3.criteria: 這是迭代終止準(zhǔn)則忘渔。當(dāng)滿足這個(gè)準(zhǔn)則時(shí)婚陪,算法迭代停止棍丐。實(shí)際上,它應(yīng)該是一個(gè)3個(gè)參數(shù)的元組茉兰。他們是:(type, max_iter, epsilon):
? ? ·3.a - 終止準(zhǔn)則的類型: 有3個(gè)標(biāo)志如下:
? ? ? ? cv2.TERM_CRITERIA_EPS - 如果滿足了指定準(zhǔn)確度尤泽,epsilon就停止算法迭代。
? ? ? ? cv2.TERM_CRITERIA_MAX_ITER - 在指定次數(shù)的迭代后就停止算法规脸。
? ? ? ? cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER - 當(dāng)任何上面的條件滿足就停止迭代
? ? ·3.b - max_iter - 指定最大的迭代次數(shù)坯约,整數(shù)
? ? ·3.c - epsilon - 需要的準(zhǔn)確度
4.attempts: 標(biāo)志,指定算法使用不同初始標(biāo)簽執(zhí)行的次數(shù)莫鸭。算法返回能得到最好密度的標(biāo)簽闹丐。密度作為輸出被返回。
5.flags:這個(gè)標(biāo)志是用來指定如何得到初始中心的被因。一般兩個(gè)標(biāo)志會(huì)用到:cv2.KMEANS_PP_CENTERS和cv2.KMEANS_RANDOM_CENTERS.
輸出參數(shù)
1.compactness: 這是從每個(gè)點(diǎn)到他們對(duì)應(yīng)的中心的距離的平方和卿拴。
2.labels: 這是標(biāo)簽數(shù)組(和'code'一樣),每個(gè)元素被標(biāo)記為'0', '1'...
3.centers: 這是聚類中心的數(shù)組
現(xiàn)在我們用三個(gè)例子看看怎么應(yīng)用K-Means算法
1.只有一個(gè)特征的數(shù)據(jù)
你有一個(gè)只有一個(gè)特征或者一個(gè)維度的數(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'是一個(gè)大小為50的數(shù)組粥鞋,值的范圍從0到255缘挽。我們把'z'變形成列向量。當(dāng)超過一個(gè)特征被顯示時(shí)很有用呻粹。那么我們把數(shù)據(jù)變成np.float32類型壕曼。
現(xiàn)在我們使用KMeans函數(shù)。在此之前我們需要制定criteria等浊。我們的criteria是當(dāng)10次算法迭代或者準(zhǔn)確度epsilon=1.0滿足時(shí)窝稿,停止算法并返回結(jié)果。
# 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)
這給我們密度凿掂,標(biāo)簽和中心,在這個(gè)例子里纹蝴,我們得到中心60和207. 標(biāo)簽會(huì)有和測(cè)試數(shù)據(jù)相同的大小庄萎,每個(gè)數(shù)據(jù)會(huì)根據(jù)他們的質(zhì)心被標(biāo)記為'0', '1', '2'。現(xiàn)在我們根據(jù)標(biāo)簽把數(shù)據(jù)分為不同的聚類塘安。
A = z[labels==0]
B = z[labels==1]
現(xiàn)在我們用紅色畫出A用藍(lán)色畫B糠涛,他們的質(zhì)心用黃色
# 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. 多個(gè)特征的數(shù)據(jù)
在前面的例子里,我們對(duì)于T恤問題只取身高兼犯。這里忍捡,我們?nèi)∩砀吆腕w重兩個(gè)特征集漾。
記住,在前面的例子里砸脊,我們把我們的數(shù)據(jù)弄成單列向量具篇。每個(gè)特征作為一列。每行對(duì)應(yīng)一個(gè)輸入測(cè)試樣本凌埂。
例如驱显,在這個(gè)例子里,我們?cè)O(shè)置一個(gè)大小為50x2的測(cè)試數(shù)據(jù)瞳抓,是50個(gè)人的身高和體重埃疫。第一列對(duì)應(yīng)著所有50個(gè)人的身高,第二列對(duì)應(yīng)他們的體重孩哑。第一行包含兩個(gè)元素栓霜,第一個(gè)元素是第一個(gè)人的身高,第二個(gè)元素是他的體重横蜒,類似的剩下的行對(duì)應(yīng)剩下的人的身高和體重胳蛮。看下圖:
現(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.顏色量化
顏色量化是減少一個(gè)圖像里的顏色數(shù)量的過程愁铺。做這個(gè)的一個(gè)原因是減少內(nèi)存使用鹰霍。有時(shí)候,一些設(shè)備會(huì)受限只能生成有限的顏色數(shù)量茵乱。在那些情況下也會(huì)執(zhí)行顏色量化茂洒。這里我們使用k-means聚類來做顏色量化。
沒有新的內(nèi)容要解釋瓶竭。這里有3個(gè)特征督勺,R,G,B。所以我們需要把圖像改造成Mx3大小的數(shù)組(M是圖像像素的數(shù)量)斤贰。聚類之后智哀,我們應(yīng)用中心值到所有的像素上,這樣結(jié)果圖像會(huì)有指定數(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時(shí)的結(jié)果:
END