k均值聚类的主要应用之一是向量量化. 简单来说, 矢量量化是"舍入"的N维版本. 当我们处理一维数据(如数字)时, 我们使用舍入技术来减少存储该值所需的内存. 例如, 不是存储23.73473572, 如果我们要准确到第二个小数位, 我们只存储23.73. 或者, 如果我们不关心小数位, 我们可以存储24. 这取决于我们的需要和我们愿意做出的权衡.
类似地, 当我们将这个概念扩展到N维数据时, 它变成矢量量化. 当然有更多细微之处! 您可以在http://www.data-compression.com/vq.shtml上了解更多信息. 矢量量化在图像压缩中被广泛使用, 其中使用比原始图像少的位来存储每个像素以实现压缩.
怎么做...?
- 此配方的完整代码已在已vector_quantization.py文件中给出. 我们来看看它是如何构建的. 我们将从导入所需的包开始. 创建一个新的Python文件, 并添加以下行:
import argparse
import numpy as np
from scipy import misc
from sklearn import cluster
import matplotlib.pyplot as plt
- 我们创建一个函数来解析输入参数. 我们将能够将图像和每像素的位数传递为输入参数:
def build_arg_parser():
parser = argparse.ArgumentParser(description='Compress the input image \
using clustering')
parser.add_argument("--input-file", dest="input_file", required=True,
help="Input image")
parser.add_argument(
"--num-bits",
dest="num_bits",
required=False,
type=int,
help="Number of bits used to represent each pixel"
)
return parser
- 让我们创建一个压缩输入图像的函数:
def compress_image(img, num_clusters):
# Convert input image into (num_samples, num_features)
# array to run kmeans clustering algorithm
X = img.reshape((-1, 1))
# Run kmeans on input data
kmeans = cluster.KMeans(n_clusters=num_clusters, n_init=4, random_state=5)
kmeans.fit(X)
centroids = kmeans.cluster_centers_.squeeze()
labels = kmeans.labels_
# Assign each value to the nearest centroid and
# reshape it to the original image shape
input_image_compressed = np.choose(labels, centroids).reshape(img.shape)
return input_image_compressed
- 一旦压缩了图像, 我们就需要看看它是如何影响质量的. 我们定义一个函数来绘制输出图像:
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)
- 我们现在可以使用所有这些功能了. 我们来定义主要的函数, 它使用输入参数, 处理它们, 并提取输出图像:
if __name__ == '__main__':
args = build_arg_parser().parse_args()
input_file = args.input_file
num_bits = args.num_bits
if not 1 <= num_bits <= 8:
raise TypeError('Number of bits should be between 1 and 8')
num_clusters = np.power(2, num_bits)
# Print compression rate
compression_rate = round(100 * (8.0 - args.num_bits) / 8.0, 2)
print (
"The size of the image will be reduced by a factor of",
8.0 / args.num_bits
)
print ("Compression rate = " + str(compression_rate) + "%")
# Load input image
input_image = misc.imread(input_file, True).astype(np.uint8)
# original image
plot_image(input_image, 'Original image')
# compressed image
input_image_compressed = compress_image(input_image, num_clusters)
plot_image(
input_image_compressed,
'Compressed image; compression rate = ' + str(compression_rate) + '%'
)
plt.show()
- 运行以上代码会得到如下图形:
- 压缩后的图形如下:
- 如果运行如下命令: pythonw vector_quantization.py --input-file flower_image.jpg --num-bits 2, 结果如下:
- 如果运行如下命令: pythonw vector_quantization.py --input-file flower_image.jpg --num-bits 1, 则结果如下: