一.K-Means聚類原理
第一部分知識主要參考自己的新書《Python網絡數據爬取及分析從入門到精通(分析篇)》和之前的博客 [Python數據挖掘課程] 二.Kmeans聚類數據分析。
K-Means聚類是最常用的聚類算法,最初起源于信號處理,其目標是將數據點劃分為K個類簇,找到每個簇的中心并使其度量最小化。該算法的最大優點是簡單、便于理解,運算速度較快,缺點是只能應用于連續型數據,并且要在聚類前指定聚集的類簇數。
下面是K-Means聚類算法的分析流程,步驟如下:
- 第一步,確定K值,即將數據集聚集成K個類簇或小組。
- 第二步,從數據集中隨機選擇K個數據點作為質心(Centroid)或數據中心。
- 第三步,分別計算每個點到每個質心之間的距離,并將每個點劃分到離最近質心的小組,跟定了那個質心。
- 第四步,當每個質心都聚集了一些點后,重新定義算法選出新的質心。
- 第五步,比較新的質心和老的質心,如果新質心和老質心之間的距離小于某一個閾值,則表示重新計算的質心位置變化不大,收斂穩定,則認為聚類已經達到了期望的結果,算法終止。
- 第六步,如果新的質心和老的質心變化很大,即距離大于閾值,則繼續迭代執行第三步到第五步,直到算法終止。
下圖是對身高和體重進行聚類的算法,將數據集的人群聚集成三類。

二.K-Means聚類分割灰度圖像
在圖像處理中,通過K-Means聚類算法可以實現圖像分割、圖像聚類、圖像識別等操作,本小節主要用來進行圖像顏色分割。假設存在一張100×100像素的灰度圖像,它由10000個RGB灰度級組成,我們通過K-Means可以將這些像素點聚類成K個簇,然后使用每個簇內的質心點來替換簇內所有的像素點,這樣就能實現在不改變分辨率的情況下量化壓縮圖像顏色,實現圖像顏色層級分割。
在OpenCV中,Kmeans()函數原型如下所示:
retval, bestLabels, centers = kmeans(data, K, bestLabels, criteria, attempts, flags[, centers])
- data表示聚類數據,最好是np.flloat32類型的N維點集
- K表示聚類類簇數
- bestLabels表示輸出的整數數組,用于存儲每個樣本的聚類標簽索引
- criteria表示算法終止條件,即最大迭代次數或所需精度。在某些迭代中,一旦每個簇中心的移動小于criteria.epsilon,算法就會停止
- attempts表示重復試驗kmeans算法的次數,算法返回產生最佳緊湊性的標簽
- flags表示初始中心的選擇,兩種方法是cv2.KMEANS_PP_CENTERS ;和cv2.KMEANS_RANDOM_CENTERS
- centers表示集群中心的輸出矩陣,每個集群中心為一行數據
下面使用該方法對灰度圖像顏色進行分割處理,需要注意,在進行K-Means聚類操作之前,需要將RGB像素點轉換為一維的數組,再將各形式的顏色聚集在一起,形成最終的顏色分割。
# coding: utf-8import cv2import numpy as npimport matplotlib.pyplot as plt
#讀取原始圖像灰度顏色img = cv2.imread('scenery.png', 0) print img.shape
#獲取圖像高度、寬度rows, cols = img.shape[:]
#圖像二維像素轉換為一維data = img.reshape((rows * cols, 1))data = np.float32(data)
#定義中心 (type,max_iter,epsilon)criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
#設置標簽flags = cv2.KMEANS_RANDOM_CENTERS
#K-Means聚類 聚集成4類compactness, labels, centers = cv2.kmeans(data, 4, None, criteria, 10, flags)
#生成最終圖像dst = labels.reshape((img.shape[0], img.shape[1]))
#用來正常顯示中文標簽plt.rcParams['font.sans-serif']=['SimHei']
#顯示圖像titles = [u'原始圖像', u'聚類圖像'] images = [img, dst] for i in xrange(2): plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray'), plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
輸出結果如圖所示,左邊為灰度圖像,右邊為K-Means聚類后的圖像,它將灰度級聚集成四個層級,相似的顏色或區域聚集在一起。

三.K-Means聚類對比分割彩色圖像
下面代碼是對彩色圖像進行顏色分割處理,它將彩色圖像聚集成2類、4類和64類。
# coding: utf-8import cv2import numpy as npimport matplotlib.pyplot as plt
#讀取原始圖像img = cv2.imread('scenery.png') print img.shape
#圖像二維像素轉換為一維data = img.reshape((-1,3))data = np.float32(data)
#定義中心 (type,max_iter,epsilon)criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
#設置標簽flags = cv2.KMEANS_RANDOM_CENTERS
#K-Means聚類 聚集成2類compactness, labels2, centers2 = cv2.kmeans(data, 2, None, criteria, 10, flags)
#K-Means聚類 聚集成4類compactness, labels4, centers4 = cv2.kmeans(data, 4, None, criteria, 10, flags)
#K-Means聚類 聚集成8類compactness, labels8, centers8 = cv2.kmeans(data, 8, None, criteria, 10, flags)
#K-Means聚類 聚集成16類compactness, labels16, centers16 = cv2.kmeans(data, 16, None, criteria, 10, flags)
#K-Means聚類 聚集成64類compactness, labels64, centers64 = cv2.kmeans(data, 64, None, criteria, 10, flags)
#圖像轉換回uint8二維類型centers2 = np.uint8(centers2)res = centers2[labels2.flatten()]dst2 = res.reshape((img.shape))
centers4 = np.uint8(centers4)res = centers4[labels4.flatten()]dst4 = res.reshape((img.shape))
centers8 = np.uint8(centers8)res = centers8[labels8.flatten()]dst8 = res.reshape((img.shape))
centers16 = np.uint8(centers16)res = centers16[labels16.flatten()]dst16 = res.reshape((img.shape))
centers64 = np.uint8(centers64)res = centers64[labels64.flatten()]dst64 = res.reshape((img.shape))
#圖像轉換為RGB顯示img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)dst2 = cv2.cvtColor(dst2, cv2.COLOR_BGR2RGB)dst4 = cv2.cvtColor(dst4, cv2.COLOR_BGR2RGB)dst8 = cv2.cvtColor(dst8, cv2.COLOR_BGR2RGB)dst16 = cv2.cvtColor(dst16, cv2.COLOR_BGR2RGB)dst64 = cv2.cvtColor(dst64, cv2.COLOR_BGR2RGB)
#用來正常顯示中文標簽plt.rcParams['font.sans-serif']=['SimHei']
#顯示圖像titles = [u'原始圖像', u'聚類圖像 K=2', u'聚類圖像 K=4', u'聚類圖像 K=8', u'聚類圖像 K=16', u'聚類圖像 K=64'] images = [img, dst2, dst4, dst8, dst16, dst64] for i in xrange(6): plt.subplot(2,3,i+1), plt.imshow(images[i], 'gray'), plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
輸出結果如下圖所示,當K=2顏色聚集成兩種,當K=64顏色聚集成64種。

希望這篇基礎性文章對您有所幫助,如果有錯誤 或不足之處,請海涵!一起加油,2019年四月考博加油,寫于貴陽鐘書閣。

金融電子化
商密君
E安全
一顆小胡椒
D1Net
黑白之道
奇安信集團
中國網絡空間安全協會
奇安信集團
奇安信集團
Coremail郵件安全
FuzzWiki