python中opencv K均值聚類的實現(xiàn)示例
K均值聚類
- 預(yù)測的是一個離散值時,做的工作就是“分類”。
- 預(yù)測的是一個連續(xù)值時,做的工作就是“回歸”。
機器學(xué)習(xí)模型還可以將訓(xùn)練集中的數(shù)據(jù)劃分為若干個組,每個組被稱為一個“簇(cluster)”。這種學(xué)習(xí)方式被稱為“聚類(clusting)”,它的重要特點是在學(xué)習(xí)過程中不需要用標(biāo)簽對訓(xùn)練樣本進行標(biāo)注。也就是說,學(xué)習(xí)過程能夠根據(jù)現(xiàn)有訓(xùn)練集自動完成分類(聚類)。
根據(jù)訓(xùn)練數(shù)據(jù)是否有標(biāo)簽,可以將學(xué)習(xí)劃分為監(jiān)督學(xué)習(xí)和無監(jiān)督學(xué)習(xí)。
K近鄰、支持向量機都是監(jiān)督學(xué)習(xí),提供有標(biāo)簽的數(shù)據(jù)給算法學(xué)習(xí),然后對數(shù)據(jù)分類
聚類是無監(jiān)督學(xué)習(xí),事先并不知道分類標(biāo)簽是什么,直接對數(shù)據(jù)分類。
聚類能夠?qū)⒕哂邢嗨茖傩缘膶ο髣澐值酵粋€集合(簇)中。
聚類方法能夠應(yīng)用于所有對象,簇內(nèi)的對象越相似,聚類算法的效果越好。
K均值聚類的基本步驟
K均值聚類是一種將輸入數(shù)據(jù)劃分為k個簇的簡單的聚類算法,該算法不斷提取當(dāng)前分類的中心點(也稱為質(zhì)心或重心),并最終在分類穩(wěn)定時完成聚類。
從本質(zhì)上說,K均值聚類是一種迭代算法。
在實際處理過程中需要進行多輪的迭代,直到分組穩(wěn)定不再發(fā)生變化,即可認(rèn)為分組完成。
K均值聚類算法的基本步驟如下:
- 隨機選取k個點作為分類的中心點。
- 將每個數(shù)據(jù)點放到距離它最近的中心點所在的類中。
- 重新計算各個分類的數(shù)據(jù)點的平均值,將該平均值作為新的分類中心點。
- 重復(fù)步驟2和步驟3,直到分類穩(wěn)定。
可以是隨機選取k個點作為分類的中心點,也可以是隨機生成k個并不存在于原始數(shù)據(jù)中的數(shù)據(jù)點作為分類中心點。
距離最近: 要進行某種形式的距離計算。(在具體實現(xiàn)時,可以根據(jù)需要采用不同形式的距離度量方法。)
K均值聚類模塊
OpenCV提供了函數(shù)cv2.kmeans()來實現(xiàn)K均值聚類。
該函數(shù)的語法格式為:
retval, bestLabels, centers=cv2.kmeans(data, K, bestLabels, criteria, attempts, flags)
- data:輸入的待處理數(shù)據(jù)集合,應(yīng)該是np.float32類型,每個特征放在單獨的一列中。
- K:要分出的簇的個數(shù),即分類的數(shù)目,最常見的是K=2,表示二分類。
- bestLabels:表示計算之后各個數(shù)據(jù)點的最終分類標(biāo)簽(索引)。實際調(diào)用時,參數(shù)bestLabels的值設(shè)置為None。
- criteria:算法迭代的終止條件。當(dāng)達到最大循環(huán)數(shù)目或者指定的精度閾值時,算法停止繼續(xù)分類迭代計算。該參數(shù)由3個子參數(shù)構(gòu)成,分別為type、max_iter和eps。
- type表示終止的類型,可以是三種情況
- cv2.TERM_CRITERIA_EPS:精度滿足eps時,停止迭代。
- cv2.TERM_CRITERIA_MAX_ITER:迭代次數(shù)超過閾值max_iter時,停止迭代。
- cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER:上述兩個條件中的任意一個滿足時,停止迭代。
- type表示終止的類型,可以是三種情況
- max_iter:最大迭代次數(shù)。
- eps:精確度的閾值。
- attempts:在具體實現(xiàn)時,為了獲得最佳分類效果,可能需要使用不同的初始分類值進行多次嘗試。指定attempts的值,可以讓算法使用不同的初始值進行多次(attempts次)嘗試。
- flags:表示選擇初始中心點的方法,主要有以下3種。
- cv2.KMEANS_RANDOM_CENTERS:隨機選取中心點。
- cv2.KMEANS_PP_CENTERS:基于中心化算法選取中心點。
- cv2.KMEANS_USE_INITIAL_LABELS:使用用戶輸入的數(shù)據(jù)作為第一次分類中心點;如果算法需要嘗試多次(attempts 值大于1時),后續(xù)嘗試都是使用隨機值或者半隨機值作為第一次分類中心點。
- retval:距離值(也稱密度值或緊密度),返回 每個點到相應(yīng)中心點距離的平方和(是一個數(shù))。
- bestLabels:各個數(shù)據(jù)點的最終分類標(biāo)簽(索引)。
- centers:每個分類的中心點數(shù)據(jù)。
簡單例子
例1:
隨機生成一組數(shù)據(jù),使用函數(shù)cv2.kmeans()對其分類。
- 一組數(shù)據(jù)在[0,50]區(qū)間
- 另一組數(shù)據(jù)在[200,250]區(qū)間
- 使用函數(shù)cv2.kmeans()對它們分類。
主要步驟如下:
數(shù)據(jù)預(yù)處理
使用隨機函數(shù)隨機生成兩組數(shù)據(jù),并將它們轉(zhuǎn)換為函數(shù)cv2.kmeans()可以處理的格式。
設(shè)置參數(shù)
設(shè)置函數(shù)cv2.kmeans()的參數(shù)形式。將參數(shù)criteria的值設(shè)置為“(cv2.TERM_CRITERIA_EPS+ cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)”,在達到一定次數(shù)或者滿足一定精度時終止迭代。
調(diào)用函數(shù)cv2.kmeans()
調(diào)用函數(shù)cv2.kmeans(),獲取返回值,用于后續(xù)步驟的操作。
確定分類
根據(jù)函數(shù)cv2.kmeans()返回的標(biāo)簽(“0”和“1”),將原始數(shù)據(jù)分為兩組
顯示結(jié)果
繪制經(jīng)過分類的數(shù)據(jù)及中心點,觀察分類結(jié)果。
完整程序:
import numpy as np? import cv2? from matplotlib import pyplot as plt? # 隨機生成兩組數(shù)組? # 生成60個值在[0,50]內(nèi)的數(shù)據(jù)? num1 = np.random.randint(0,50,60)? # 生成60個值在[200,250]內(nèi)的數(shù)據(jù)? num2 = np.random.randint(200,250,60)? # 組合數(shù)據(jù)為num num = np.hstack((num1, num2)) # 使用reshape函數(shù)將其轉(zhuǎn)換為(120,1) ? num = num.reshape((120,1)) ?#每個數(shù)據(jù)為1列 # 轉(zhuǎn)換為float32類型? num = np.float32(num)? # 調(diào)用kmeans模塊? # 設(shè)置參數(shù)criteria的值? criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)? # 設(shè)置參數(shù)flags的值? flags = cv2.KMEANS_RANDOM_CENTERS? # 調(diào)用函數(shù)kmeans? retval, bestLabels, centers = cv2.kmeans(num,2, None, criteria,10, flags)? # 打印返回值? print(retval)? print(bestLabels)? print(centers)? # 獲取分類結(jié)果? n1 = num[bestLabels==0]? n2 = num[bestLabels==1]? ? ?? # 繪制分類結(jié)果? # 繪制原始數(shù)據(jù)? plt.plot(np.ones(len(n1)),n1,'ro')? plt.plot(np.ones(len(n2)),n2,'bo')? # 繪制中心點? #plt.plot([1],centers[0],'rx')? #plt.plot([1],centers[1],'bx')? plt.show()? ?
例2:
有兩種物體:
- 物體1的長和寬都在 [0,20] 內(nèi)
- 物體2的長和寬都在[40,60] 內(nèi)
使用隨機數(shù)模擬兩種物體的長度和寬度,并使用函數(shù)cv2.kmeans()對它們分類。
根據(jù)題目要求,主要步驟如下:
- 隨機生成數(shù)據(jù),并將它們轉(zhuǎn)換為函數(shù)cv2.kmeans()可以處理的形式。
- 設(shè)置函數(shù)cv2.kmeans()的參數(shù)形式。
- 調(diào)用函數(shù)cv2.kmeans()。
- 根據(jù)函數(shù)cv2.kmeans()的返回值,確定分類結(jié)果。
- 繪制經(jīng)過分類的數(shù)據(jù)及中心點,觀察分類結(jié)果。
import numpy as np?
import cv2?
from matplotlib import pyplot as plt?
# 隨機生成兩組數(shù)值?
#長和寬都在[0,20]內(nèi)?
m1 = np.random.randint(0,20, (30,2))?
#長和寬的大小都在[40,60]?
m2 = np.random.randint(40,60, (30,2))?
# 組合數(shù)據(jù)?
m = np.vstack((m1, m2))?
# 轉(zhuǎn)換為float32類型?
m = np.float32(m)?
# 調(diào)用kmeans模塊?
# 設(shè)置參數(shù)criteria值?
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)?
# 調(diào)用kmeans函數(shù)?
ret, label, center=cv2.kmeans(m,2, None, criteria,10, cv2.KMEANS_RANDOM_CENTERS)?
? ??
'''?
#打印返回值?
print(ret)?
print(label)?
print(center)?
'''?
# 根據(jù)kmeans的處理結(jié)果,將數(shù)據(jù)分類,兩大類?
res1 = m[label.ravel()==0]?
res2 = m[label.ravel()==1]?
# 繪制分類結(jié)果數(shù)據(jù)及中心點?
plt.scatter(res1[:,0], res1[:,1], c = 'g', marker = 's')?
plt.scatter(res2[:,0], res2[:,1], c = 'r', marker = 'o')?
plt.scatter(center[0,0], center[0,1], s = 200, c = 'b', marker = 'o')?
plt.scatter(center[1,0], center[1,1], s = 200, c = 'b', marker = 's')?
plt.xlabel('Height'), plt.ylabel('Width')?
plt.show()?例3:
使用函數(shù)cv2.kmeans()將灰度圖像處理為只有兩個灰度級的二值圖像。
需要對灰度圖像內(nèi)的色彩進行分類,將所有的像素點劃分為兩類。然后,用這兩類的中心點像素值替代原有像素值,滿足題目的要求。
主要步驟如下:
圖像預(yù)處理
讀取圖像,并將圖像轉(zhuǎn)換為函數(shù)cv2.kmeans()可以處理的形式。
在讀取圖像時,如果是3個通道的RGB圖像,需要將圖像的RGB值處理為一個單獨的特征值。具體實現(xiàn)時,用函數(shù)cv2.reshape()完成對圖像特征值的調(diào)整。
為了滿足函數(shù)cv2.kmeans()的要求,需要將圖像的數(shù)據(jù)類型轉(zhuǎn)換為numpy.float32類型。
設(shè)置函數(shù)cv2.kmeans()的參數(shù)形式
設(shè)置參數(shù)criteria的值為“(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)”,讓函數(shù)cv2.kmeans()在達到一定精度或者達到一定迭代次數(shù)時,即停止迭代。
設(shè)置參數(shù)K的值為2,將所有像素劃分為兩類。
調(diào)用函數(shù)cv2.kmeans()
調(diào)用函數(shù)cv2.kmeans(),得到距離值、分類中心點和分類標(biāo)簽,用于后續(xù)操作。
值替換
將像素點的值替換為當(dāng)前分類的中心點的像素值。
顯示變換前后的圖像
分別顯示原始圖像和二值化圖像。
import numpy as np
import cv2
import matplotlib.pyplot as plt
# 讀取待處理圖像
img = cv2.imread('./img/hand2.png')
# 使用reshape將一個像素點的RGB值作為一個單元處理
data = img.reshape((-1,3)) # n行 3列
# 轉(zhuǎn)換為kmeans可以處理的類型
data = np.float32(data)
# 調(diào)用kmeans模塊
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K =2
ret, label, center=cv2.kmeans(data, K, None, criteria,10, cv2.KMEANS_RANDOM_CENTERS)
# 轉(zhuǎn)換為uint8數(shù)據(jù)類型,將每個像素點都賦值為當(dāng)前分類的中心點像素值
# 將center的值轉(zhuǎn)換為uint8
center = np.uint8(center)
# 使用center內(nèi)的值替換原像素點的值
res1 = center[label.flatten()] # 根據(jù)索引來取值,最后結(jié)果的大小同索引的大小
# 使用reshape調(diào)整替換后的圖像
res2 = res1.reshape((img.shape))
# 顯示處理結(jié)果
plt.subplot(121)
plt.imshow(img[:,:,::-1])
plt.axis('off')
plt.subplot(122)
plt.imshow(res2[:,:,::-1])
plt.axis('off')
plt.show()
調(diào)整程序中的K值,就能改變圖像的顯示結(jié)果。例如,K=8,則可以讓圖像顯示8個灰度級。
到此這篇關(guān)于python中opencv K均值聚類的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)opencv K均值聚類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于Python連接Cassandra容器進行查詢的問題
這篇文章主要介紹了Python連接Cassandra容器進行查詢的問題,問題的關(guān)鍵在于尋找到Cassandra的9042端口,從而獲取數(shù)據(jù),具有內(nèi)容詳情跟隨小編一起看看吧2021-11-11
python實現(xiàn)刪除列表中空字符串元素的兩種方法
本文主要介紹了python實現(xiàn)刪除列表中空字符串元素的兩種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-03-03
Python網(wǎng)絡(luò)安全格式字符串漏洞任意地址覆蓋大數(shù)字詳解
這篇文章主要介紹了Python網(wǎng)絡(luò)安全格式字符串漏洞任意地址覆蓋大數(shù)字的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2021-10-10

