• 聚类技术之向量量化 VQ : vector quantization的实现


    参考

    https://www.cnblogs.com/anyview/p/5055379.html
    https://blog.csdn.net/leemboy/article/details/83792729
    https://blog.csdn.net/weixin_42455135/article/details/115386241

    VQ概念

    这项技术广泛地用在信号处理以及数据压缩等领域。事实上,在 JPEG 和 MPEG-4 等多媒体压缩格式里都有 VQ 这一步。
    大家都知道,模拟信号是连续的值,而计算机只能处理离散的数字信号,在将模拟信号转换为数字信号的时候,我们可以用区间内的某一个值去代替着一个区间,比如,[0, 1) 上的所有值变为 0 ,[1, 2) 上的所有值变成 1 ,如此类推。其这就是一个 VQ 的过程。一个比较正式一点的定义是:VQ 是将一个向量空间中的点用其中的一个有限子集来进行编码的过程。
    一个典型的例子就是图像的编码。最简单的情况,考虑一个灰度图片,0 为黑色,1 为白色,每个像素的值为 [0, 1] 上的一个实数。现在要把它编码为 256 阶的灰阶图片,一个最简单的做法就是将每一个像素值 x 映射为一个整数 floor(x255) 。当然,原始的数据空间也并不以一定要是连续的。比如,你现在想要把压缩这个图片,每个像素只使用 4 bit (而不是原来的 8 bit)来存储,因此,要将原来的 [0, 255] 区间上的整数值用 [0, 15] 上的整数值来进行编码,一个简单的映射方案是 x15/255 。
    虽然能减少颜色数量起到压缩的效果,但是如果原来的颜色并不是均匀分布的,那么的出来的图片质量可能并不是很好。例如,如果一个 256 阶灰阶图片完全由 0 和 13 两种颜色组成,那么通过上面的映射就会得到一个全黑的图片,因为两个颜色全都被映射到 0 了。一个更好的做法是结合聚类来选取代表性的点。
    实际做法就是:将每个像素点当作一个数据,跑一下 K-means ,得到 k 个 centroids ,然后用这些 centroids 的像素值来代替对应的 cluster 里的所有点的像素值。对于彩色图片来说,也可以用同样的方法来做,例如 RGB 三色的图片,每一个像素被当作是一个 3 维向量空间中的点。
    拿一张 Rechard Stallman 大神的照片来做一下实验,VQ 2、VQ 10 和 VQ 100 三张图片分别显示聚类数目为 2 、10 和 100 时得到的结果,可以看到 VQ 100 已经和原图非常接近了。把原来的许多颜色值用 centroids 代替之后,总的颜色数量减少了,重复的颜色增加了,这种冗余正是压缩算法最喜欢的。考虑一种最简单的压缩办法:单独存储(比如 100 个)centroids 的颜色信息,然后每个像素点存储 centroid 的索引而不是颜色信息值,如果一个 RGB 颜色值需要 24 bits 来存放的话,每个(128 以内的)索引值只需要 7 bits 来存放,这样就起到了压缩的效果。

    实验代码

    from scipy.cluster.vq import kmeans, vq
    import numpy as np
    from PIL import Image
    
    vqclst = [2, 10, 100, 256]
    pic = Image.open('ds.jpg')
    data = np.array(pic)
    (height, width, channel) = data.shape
    
    data = np.float32(np.reshape(data, (height*width, channel)))
    for k in vqclst:
        print('Generating vq-%d...' % k)
        (centroids, distor) = kmeans(data, k)
        (code, distor) = vq(data, centroids)
        print('distor: %.6f' % distor.sum())
        im_vq = centroids[code, :]
        new_data = np.uint8(np.reshape(im_vq, (height, width, channel)))
        new_pic = Image.fromarray(new_data)
        new_pic.save('result-%d.jpg' % k)
    

    当然,Vector Quantization 并不一定要用 K-means 来做,各种能用的聚类方法都可以用,只是 K-means 通常是最简单的,而且通常都够用了。

    实验结果

    VQ-2

    VQ-10

    VQ-100

    VQ-256

    踩坑点

    scipy.cluster.vq.kmeans方法接受的数据类型必须是浮点数,Image.fromarray()对输入的numpy array也是有要求的:1. dtypeuint8类型;2. shape(H, W, C)类型。

  • 相关阅读:
    合并报表优化记录
    如何在后台代码中执行原生sql?
    eclipse从数据库逆向生成Hibernate实体类
    用Eclipse进行远程Debug代码
    hibernate自动生成数据库表
    hibernate自动生成数据库表
    php通过UNIX源码编译安装
    php设置方法
    php其他配制选项
    终于做出了目录认证!
  • 原文地址:https://www.cnblogs.com/Higgerw/p/15238513.html
Copyright © 2020-2023  润新知