1. 程式人生 > >利用K-means進行影象壓縮

利用K-means進行影象壓縮

前面幾篇文章 淺談支援向量機 神經網路——手寫數字識別 中涉及的演算法都屬於監督學習的範疇,今天小編給大家介紹一種屬於無監督學習範疇的演算法——K-means。

K-means是一種應用很廣泛的聚類演算法。聚類,通俗的講就是“人以群分物以類聚”。

K-means是怎麼實現聚類的呢?下面我們以一個簡單的樣例來闡述它的工作原理。

觀察上面的圖,我們一般會認為這些資料點集中分佈在三個區域,即這些資料點可以聚成三個族。K-means的工作過程是:首先隨機挑選三個點作為中心點,然後計算所有的資料點離哪個中心點最近,再根據離中心點近的點更新中心點,迴圈多次直到中心點不怎麼變化即可。

利用K-means聚類上面的資料,中心點更新過程如下。

好了,現在大致瞭解了K-means的作用和工作原理,下面就進入我們這次的主題——影象壓縮。

上圖是128*128的png影象,儲存格式是RGB,所以這副影象佔用的位數是128×128×24=393216。我們怎樣利用K-means演算法實現這副影象的壓縮呢?

我的想法是:這副影象存在許多很大一塊區域的顏色相近,既然相近,我們就用一種顏色替代一大塊區域中的各色。我們可以人為的用8、16、24、32種顏色表示整幅影象的顏色,也即說明聚類的個數為8、16、24、32。

具體的Python程式碼如下。

import matplotlib.pyplot as plt # plt 用於顯示圖片
import matplotlib.image as mpimg # mpimg 用於讀取圖片
from sklearn.cluster import KMeans
import numpy as np

pixel = mpimg.imread('bird_small.png')
pixel = pixel.reshape((128*128 , 3))

kmeans = KMeans(n_clusters=16, random_state=0).fit(pixel)

newPixel = []
for i in kmeans.labels_:
    newPixel.append(list(kmeans.cluster_centers_[i,:]))

newPixel = np.array(newPixel)
newPixel = newPixel.reshape((128,128,3))

plt.imshow(newPixel)
plt.show()

如果用了16個類,則壓縮之後的影象佔用的位數為128×128×4 = 65536,壓縮比為16.7%。但這種壓縮是有失真壓縮,影象質量會下降,使用8、16、24、32壓縮後效果圖如下。

可以看到,影象的質量較原圖是有所下降的,有點類似在原圖上進行平滑處理,並且分類數越多,圖片質量越接近原圖,這個應該不難理解。

好了,以上就是本次的全部內容。