”“”K-Means to realize Image segmentation “”“ import numpy as np import PIL.Image as image from sklearn.cluster import KMeans #Define loadDato to solve my image def loadData(filePath): f = open(filePath,'rb')#deal with binary data = [] img = image.open(f)#return to pixel(像素值) m,n = img.size#the size of image for i in range(m): for j in range(n): x,y,z = img.getpixel((i,j)) #deal with pixel to the range 0-1 and save to data data.append([x/256.0,y/256.0,z/256.0]) f.close() return np.mat(data),m,n imgData,row,col = loadData("./picture/apple.png") #setting clusers(聚類中心) is 3 label = KMeans(n_clusters=3).fit_predict(imgData) #get the label of each pixel label = label.reshape([row,col]) #create a new image to save the result of K-Means pic_new = image.new("L",(row,col)) #according to the label to add the pixel for i in range(row): for j in range(col): pic_new.putpixel((i,j),int(256/(label[i][j]+1))) pic_new.save("./picture/km.jpg","JPEG")
K-Means算法:
我們常說的K-Means算法屬於無監督分類(訓練樣本的標記信息是未知的,目標是通過對無標記訓練樣本的學習來揭示數據的內在性質和規律,為進一步的數據分析提供基礎),它通過按照一定的方式度量樣本之間的相似度,通過迭代更新聚類中心,當聚類中心不再移動或移動差值小於閾值時,則就樣本分為不同的類別。聚類試圖將數據集中的樣本划分為若干個通常是不相交的子集,每個子集稱為一個”簇“,通過這樣的划分,每個簇可能對應於一些潛在的類別。
算法實現步驟:
- 隨機選取聚類中心
- 根據當前聚類中心,利用選定的度量方式,分類所有樣本點
- 計算當前每一類的樣本點的均值,作為下一次迭代的聚類中心
- 計算下一次迭代的聚類中心與當前聚類中心的差距,若差距小於迭代閾值時,迭代結束。
算法偽代碼:
其中,D為樣本集,聚類所得簇划分為C
圖像分割實驗:利用圖像的灰度、顏色、紋理、形狀等特征,把圖像分成若 干個互不重疊的區域,並使這些特征在同一區域內呈現相似性,在不同的區 域之間存在明顯的差異性。然后就可以將分割的圖像中具有獨特性質的區域 提取出來用於不同的研究。本次實驗我們將apple聚類中心設置n_clusters=3,cat聚類中心設置為2
1、實驗步驟
- 建立kms.py工程並導入所需python包
- 加載本地圖片進行預處理
- K-Means聚類算法實現
- 聚類像素點並保存輸出
2、實驗數據
測試image:
3、實驗結果
3、實驗總結
在本次實驗中,我們通過設置不同的聚類中心,從而得到不同的聚類結果。如果想要得到預想的效果,必須多次嘗試,這使得K值具有不確定性,不利於我們操作。
在進行本次實驗時,遇到如下問題:
(1)IndentationError: unindent does not match any outer indentation level
(2)ValueError: cannot reshape array of size 500 into shape (500,500)
問題解決:
這兩個問題出現的原因均是對其python格式對齊出現問題,f的打開和f的關閉應該對齊,而報錯的原因也恰在這里。一般(2)的報錯原因最多可能是數據格式有問題,但在考慮數據格式有問題的時候,首先查看代碼格式是否正確。