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, 则结果如下:

results matching ""

    No results matching ""