閱讀910 返回首頁    go 阿裏雲 go 技術社區[雲棲]


DIY圖像壓縮——機器學習實戰之K-means 聚類圖像壓縮:色彩量化

更多深度文章,請關注:https://yq.aliyun.com/cloud
作者:ML bot2

這篇文章是K-means聚類(K-means clustering)的一個簡單應用:壓縮圖像。

在彩色圖像中,每個像素的大小為3字節(RGB),可以表示的顏色總數為256 * 256 * 256。下圖為1280 x 720像素的圖像,采用PNG格式(一種無損壓縮技術),大小為1.71 MB。 我們的目標是使用顏色量化進一步壓縮圖像,盡管壓縮過程會有損失。


tiger.png?w=1024


K均值聚類


這是一種在給定的數據點集合中找到“K”個簇的優化算法。最初,它隨機分配K個簇中心,然後基於一些距離度量(例如,歐幾裏得距離),使來自簇中心的數據點的距離之和最小化。K均值聚類算法有兩個步驟:


a)分配 - 將每個數據點分配給離中心距離最近的簇。
b)更新 - 從指定給新簇的數據點計算新的均值(質心)。

為了描述K均值聚類前後的區別,請看下麵這個例子。
image.png
                                       K均值聚類,K=3

在圖像壓縮問題中,K-means聚類會把類似的顏色分別放在K個簇中——也就是說,每個簇的顏色都變成了一種。因此,我們隻需要保留每個像素的標簽(表明該像素在哪個簇中),以及每個簇的顏色編碼即可完成圖像的壓縮。


壓縮


我們將編寫一個簡單的python代碼來壓縮圖像,並將壓縮圖像與代碼本(Codebook)一起存儲。這裏保存的壓縮圖像隻是原始圖像的每個像素的簇標簽。代碼本是在運行K-means算法後實現的簇中心存儲列表的別名。簇標簽和代碼本都保存在數據類型“無符號整數”中。以下為圖像壓縮代碼:


from skimage import io
from sklearn.cluster import KMeans
import numpy as np

image = io.imread('tiger.png')
io.imshow(image)
io.show()

rows = image.shape[0]
cols = image.shape[1]
 
image = image.reshape(image.shape[0]*image.shape[1],3)
kmeans = KMeans(n_clusters = 128, n_init=10, max_iter=200)
kmeans.fit(image)

clusters = np.asarray(kmeans.cluster_centers_,dtype=np.uint8) 
labels = np.asarray(kmeans.labels_,dtype=np.uint8 )  
labels = labels.reshape(rows,cols); 

np.save('codebook_tiger.npy',clusters.imsave('compressed_tiger.png',labels

我們可以選擇足夠大的K來表示圖像的顏色。示例中K為128,表明原始圖像中的所有顏色組合被量化為128種不同的顏色。這些顏色將會在新圖片中呈現(解壓縮後),並且應在視覺上類似於原始圖像。


解壓縮


我們還需要解壓縮圖像,以便可視化重建的圖像。以下為圖像解壓縮代碼:


from skimage import io
import numpy as np

centers = np.load('codebook_tiger.npy_image = io.imread('compressed_tiger.png')

image = np.zeros((c_image.shape[0],c_image.shape[1],3),dtype=np.uint8 )
for i in range(c_image.shape[0]):
    for j in range(c_image.shape[1]):
            image[i,j,:] = centers[c_image[i,j],:]
io.imsave('reconstructed_tiger.png',imageo.imshow(image)
io.show()


下圖為解壓縮後的圖像。雖然新圖像失去了大量的像素顏色信息,但沒有出現任何主要的差異。


reconstructed_tiger.png?w=1024


此外,您可以通過單獨查看碼本中的顏色來找到新圖像的128種顏色。


注意

  1. 如果您嚐試按照博客文章中的方式來壓縮“jpeg”圖像,那麼您將會發生錯誤,因為jpeg會進行有損壓縮。 jpeg的壓縮算法改變了像素的值,因此包含標簽的壓縮圖像中的像素可能會超過K,從而導致錯誤。
  2. K-means算法是在給定數據集中查找指定數量簇的優化問題。圖像尺寸增加或K值增加都會增加執行時間。所以,你可以從較低的K值開始,以便快速獲得結果。
  3. 在壓縮時間和壓縮比率之間存在折衷。較高的K值將產生更好的壓縮圖像質量,但壓縮時間也會更長。


結論


您可以在這裏查看博客文章中的圖像所占用的磁盤空間,如下圖所示。原始的png圖像是1757 KB(tiger.png),而壓縮的虎圖像和碼本總共隻有433 KB。新圖像也占用更少的空間:由於隻有128種獨特的顏色,新的壓縮比超過2。


spaces.jpg


該壓縮方法僅僅減少了圖像中的顏色數量,又被稱為顏色量化(Colour Quantization)。壓縮過程中沒有減少圖像的大小或像素的取值範圍。


希望你很容易在再現本文的例子。完整的Python代碼可以在Github中找到。如果您喜歡這篇文章,請follow博客以獲取文章更新,並請分享這篇文章。請盡管討論有關該帖子的任何內容,我很樂意收到您的反饋。祝你機器學習愉快!



本文由北郵@老師推薦,組織翻譯。
文章原標題《Image Compression using K-means Clustering : Colour Quantization – Machine Learning in Action》,作者:ML bot2,譯者:楊輝,審閱:,附件為原文的pdf。

原文



最後更新:2017-04-20 20:01:26

  上一篇:go Python實現簡單文本分割工具
  下一篇:go 當 Kubernetes 遇到阿裏雲 之 快速部署1.6.1版本