在图像处理领域,颜色量化是一种减少图像颜色数量的技术,目的是为了压缩图像数据。本示例展示了如何将夏宫图像的颜色数量从96,615种减少到64种,同时尽量保持图像的整体外观质量。在这个过程中,使用了K-Means聚类算法来实现颜色的量化。
首先,将图像的像素表示为三维空间中的点,然后使用K-Means算法找到64个颜色聚类。在图像处理文献中,从K-Means算法得到的码本(聚类中心)被称为颜色调色板。使用单个字节,可以表示多达256种颜色,而RGB编码则需要每个像素3个字节。例如,GIF文件格式就使用了这样的调色板。
为了比较,还展示了使用随机码本(随机选择的颜色)量化的图像。在数据的一个小样本上进行模型拟合,预测整个图像的颜色索引(使用K-Means和随机方法),并记录了所需的时间。
以下是使用Python和scikit-learn库实现的代码示例。首先,导入了必要的库,并设置了颜色数量为64。然后,加载了夏宫的图片,并将其转换为浮点数数组,以便在0到1的范围内进行处理。接下来,对图像进行了采样,并使用K-Means算法对样本进行了拟合。最后,使用预测的颜色索引重新创建了图像,并展示了原始图像和量化后的图像。
from sklearn.cluster import KMeans
from sklearn.datasets import load_sample_image
from sklearn.metrics import pairwise_distances_argmin
from sklearn.utils import shuffle
import numpy as np
import matplotlib.pyplot as plt
import time
n_colors = 64
china = load_sample_image("china.jpg")
china = np.array(china, dtype=np.float64) / 255
w, h, d = china.shape
assert d == 3
image_array = np.reshape(china, (w * h, d))
print("在数据的小样本上拟合模型")
t0 = time()
image_array_sample = shuffle(image_array, random_state=0, n_samples=1000)
kmeans = KMeans(n_clusters=n_colors, random_state=0).fit(image_array_sample)
print(f"完成时间:{time() - t0:0.3f}秒。")
print("预测整个图像的颜色索引(K-Means)")
t0 = time()
labels = kmeans.predict(image_array)
print(f"完成时间:{time() - t0:0.3f}秒。")
codebook_random = shuffle(image_array, random_state=0, n_samples=n_colors)
print("预测整个图像的颜色索引(随机)")
t0 = time()
labels_random = pairwise_distances_argmin(codebook_random, image_array, axis=0)
print(f"完成时间:{time() - t0:0.3f}秒。")
def recreate_image(codebook, labels, w, h):
""“从码本和标签重新创建(压缩)图像”""
return codebook[labels].reshape(w, h, -1)
plt.figure(1)
plt.clf()
plt.axis("off")
plt.title("原始图像(96,615种颜色)")
plt.imshow(china)
plt.figure(2)
plt.clf()
plt.axis("off")
plt.title(f"量化图像({n_colors}种颜色,K-Means)")
plt.imshow(recreate_image(kmeans.cluster_centers_, labels, w, h))
plt.figure(3)
plt.clf()
plt.axis("off")
plt.title(f"量化图像({n_colors}种颜色,随机)")
plt.imshow(recreate_image(codebook_random, labels_random, w, h))
plt.show()
通过上述代码,可以看到使用K-Means聚类算法对夏宫图像进行颜色量化的过程。首先,加载了夏宫的图片,并将其转换为浮点数数组。然后,对图像进行了采样,并使用K-Means算法对样本进行了拟合。接下来,使用预测的颜色索引重新创建了图像,并展示了原始图像和量化后的图像。
在这个过程中,使用了单个字节来表示多达256种颜色,而RGB编码则需要每个像素3个字节。通过使用K-Means聚类算法,可以将图像的颜色数量从96,615种减少到64种,同时尽量保持图像的整体外观质量。这种方法在图像压缩和存储方面具有很大的潜力。