python實現使用聚類算法進行圖片壓縮
現在我們獲得了一張圖片flower.jpg,我們希望使用聚類算法對圖像進行壓縮,其思想是:其核心思想是通過聚類將顏色表示數量減少。例如,傳統RGB,每個通道0~255(8 bits),則可以表示16777216 (24 bits)種顏色,通過聚類可以減少到16種顏色。
代碼:
import numpy as np
from scipy import misc
from sklearn import cluster
import matplotlib.pyplot as plt
###STEP1###
#compress_image函數實現圖片壓縮功能,compress_image函數將每個像素作爲一個元素進行聚類,以此減少其顏色個數。
#參數img是圖片傳入的接口,因此我們需要知道變量img的數據結構,請自行查看。
def compress_image(img, num_clusters):
#思考,聚類算法對輸入的數據結構要求如何?
#問題一:補全代碼,將img結構進行轉換即每個像素作爲一個元素,使之能符合聚類算法數據輸入的要求。
X = img.reshape((-1, 1)) #將原來的img文件的數據結構轉化爲單列格式。不知道img原來的數據結構可能是一個矩陣,我們將每一個像素點都轉化爲單列的格式。
#print(X.shape)
# 創建KMeans聚類模型,並訓練。
kmeans = cluster.KMeans(n_clusters=num_clusters, n_init=4, random_state=5)
kmeans.fit(X)
#問題二:補全代碼,分別獲取每個數據聚類後的label,以及每個label的質心。
centroids = kmeans.cluster_centers_.squeeze() #把img文件新生成的數組將其數組形狀中的維度刪除 也就是將shape中爲1的刪除。
labels = kmeans.labels_ #那到新數據的質心,目的要替換原來像素點的質心
#問題三:使用質心的數值代替原數據的label值,那麼我們將獲得一個新的圖像。
# 提示,使用numpy的choose函數進行進行質心值的代替,reshape函數回覆原圖片的數據結構,並返回結果。
input_image_compressed = np.choose(labels, centroids).reshape(img.shape)
#使用choose函數將質心替換原來的數據。
return input_image_compressed
###STEP2###
#plot_image函數打印圖片
def plot_image(img, title):
vmin = img.min()
vmax = img.max()
plt.figure()
plt.title(title)
plt.imshow(img, cmap=plt.cm.gray, vmin=vmin, vmax=vmax)
###STEP3###
#讀入圖片,設置壓縮率,實現壓縮
if __name__=='__main__':
#設置圖片的路徑和壓縮比例
input_file = "E:/flower/flower.jpg"
num_bits = 2
if not 1 <= num_bits <= 8:
raise TypeError('Number of bits should be between 1 and 8')
num_clusters = np.power(2, num_bits)
# 輸出壓縮的比例
compression_rate = round(100 * (8.0 - num_bits) / 8.0, 2)
print ("\nThe size of the image will be reduced by a factor of", 8.0/num_bits)
print ("\nCompression rate = " + str(compression_rate) + "%")
# 加載需要壓縮的圖片
input_image = misc.imread(input_file, True).astype(np.uint8)
# 原始圖像的輸出
plot_image(input_image, 'Original image')
# 壓縮後的圖像輸出
input_image_compressed = compress_image(input_image, num_clusters)
plot_image(input_image_compressed, 'Compressed image; compression rate = '
+ str(compression_rate) + '%')
plt.show()
結果:
感謝閱讀!希望能對你有幫助,有問題可以私信我。