使用K—Means進(jìn)行圖像分割
一、需要用到的庫:
sklearn.cluster中的kmeans、PIL中的image、skimage中的color、PIL中的image
PIL是圖像處理標(biāo)準(zhǔn)庫,用image得到圖像的像素值和尺寸大小,依據(jù)尺寸,可以得到各個(gè)點(diǎn)的RGB值(三通道值),還可以利用image內(nèi)的函數(shù)保存圖片。利用PIL庫可以對(duì)圖像進(jìn)行讀寫
<pre>import PIL.Image as image
# 得到圖像的像素值
img = image.open(f)
# 得到圖像尺寸
width, height = img.size</pre>
二、準(zhǔn)備階段
加載數(shù)據(jù)—獲取圖像信息【包括圖像像素?cái)?shù)據(jù)、圖像的尺寸和通道數(shù)】—對(duì)圖像每個(gè)通道的數(shù)據(jù)進(jìn)行數(shù)據(jù)規(guī)范化
jpg格式的圖像具有三個(gè)通道(R,G,B),也就是一個(gè)像素點(diǎn)具有3個(gè)特征值,特征值的范圍在0-255之間。
為了加速聚類的收斂,可以對(duì)通道值進(jìn)行規(guī)范化。
三、進(jìn)行聚類
Fit_predict進(jìn)行kmeans
四、將聚類結(jié)果可視化
將聚類表示轉(zhuǎn)換為不同顏色的矩陣,可以手動(dòng)對(duì)各個(gè)聚類標(biāo)識(shí)規(guī)定顏色,比如得到各個(gè)聚類中心的RGB通道來代表這一類的RGB通道值,下圖舉了三個(gè)例子,表示第0、1、2類的通道值
五、總的代碼
<pre>
import numpy as np
import PIL.Image as image
from sklearn.cluster import KMeans
from sklearn import preprocessing
# 加載圖像,并對(duì)數(shù)據(jù)進(jìn)行規(guī)范化
def load_data(filePath):
? ? # 讀文件
? ? f = open(filePath,'rb')
? ? data = []
? ? # 得到圖像的像素值
? ? img = image.open(f)
? ? # 得到圖像尺寸
? ? width, height = img.size
? ? for x in range(width):
? ? ? ? for y in range(height):
? ? ? ? ? ? # 得到點(diǎn) (x,y) 的三個(gè)通道值
? ? ? ? ? ? c1, c2, c3 = img.getpixel((x, y))
? ? ? ? ? ? data.append([(c1+1)/256.0, (c2+1)/256.0, (c3+1)/256.0])
? ? f.close()
? ? return np.mat(data), width, height
# 加載圖像,得到規(guī)范化的結(jié)果 imgData,以及圖像尺寸
img, width, height = load_data(r'C:\users\dell\Desktop\weixin.jpg')
# 用 K-Means 對(duì)圖像進(jìn)行 16 聚類
kmeans =KMeans(n_clusters=16)
label = kmeans.fit_predict(img)#因?yàn)閒it和predict傳入的數(shù)據(jù)是一樣的,所以可以直接寫在一起,直接得到聚類結(jié)果
# 將圖像聚類結(jié)果,轉(zhuǎn)化成圖像尺寸的矩陣
label = label.reshape([width, height])
# 創(chuàng)建個(gè)新圖像 img,用來保存圖像聚類壓縮后的結(jié)果
img=image.new('RGB', (width, height))
for x in range(width):
? ? for y in range(height):
? ? ? ? c1 = kmeans.cluster_centers_[label[x, y], 0]
? ? ? ? c2 = kmeans.cluster_centers_[label[x, y], 1]
? ? ? ? c3 = kmeans.cluster_centers_[label[x, y], 2]
? ? ? ? #c1,c2,c3代表了每個(gè)類RGB通道的數(shù)值
? ? ? ? img.putpixel((x, y), (int(c1*256)-1, int(c2*256)-1, int(c3*256)-1))
? ? ? ? # #用 putpixel 函數(shù)對(duì)新圖像的點(diǎn)進(jìn)行RGB的設(shè)置,因?yàn)榍懊鎸?duì)通道值進(jìn)行了規(guī)范化,控制在了0-1,但是通道值要在0-255的時(shí)候才會(huì)顯示出顏色,所以這邊*256恢復(fù)到0-255的范圍
img.save(r'C:\users\dell\Desktop\weixin_new.jpg')
<\pre>
得到的圖片如下所示: