矢量量化(Vector Quantization)

矢量量化(VQ)是信号处理和数据压缩中的有损压缩方法,常用于JPEG和MPEG-4等格式。其基本思想是将连续信息转化为数字信号,通过将多维空间中的点用有限子集编码来压缩数据。K-means聚类常用于选择代表性点作为量化矢量,从而减少颜色数量并实现压缩。随着聚类数量增加,压缩后的图像质量接近原始图像。
摘要由CSDN通过智能技术生成

一个比较老的技术,但还是学习了解一下。

矢量量化(Vector Quantization, VQ)

矢量量化是一种信号压缩方法,也是一种基于块编码规则的有损压缩方法。这项技术广泛地用在信号处理以及数据压缩等领域。事实上,在 JPEG 和 MPEG-4 等多媒体压缩格式里都有 VQ 这一步。

引言

Vector Quantization 这个名字听起来有些玄乎,其实它本身并没有这么高深。大家都知道,模拟信号是连续的值,而计算机只能处理离散的数字信号,在将模拟信号转换为数字信号的时候,我们可以用区间内的某一个值去代替着一个区间,比如,[0, 1) 上的所有值变为 0 ,[1, 2) 上的所有值变成 1 ,如此类推。其这就是一个 VQ 的过程。一个比较正式一点的定义是:VQ 是将一个向量空间中的点用其中的一个有限子集来进行编码的过程。

原理

即连续信息到数字信号的转化。

基本思想:
将若干个标量数据组构成一个矢量,然后在矢量空间给以整体量化,从而压缩了数据而不损失多少信息。
在这里插入图片描述
VQ实际上就是一种逼近:使用一个数字近似地表示它周围的数字;例如数学中取整⌊ x ⌋

举例

一维例子:
VQ实际上就是一种逼近。它的思想和“四舍五入”有异曲同工之妙,都是用一个和一个数最接近的整数来近似表示这个数。
在这里插入图片描述
这里,小于-2的数都近似为-3,在-2和0之间的数都近似为-1,在0和2之间的数都近似为1,大于2的数都近似为3。这样任意的一个数都会被近似为-3、-1、1或者3这四个数中的其中一个。而我们编码这四个数只需要两个二进制位就行了。所以这是1-dimensional,2-bit VQ,它的rate(量化速率?)为2bits/dimension。

二维例子:

在这里插入图片描述
上图,蓝色实线将这张图划分为16个区域,每个区域有个红星点;任意的坐标都会落到上面这张图中的某一特定区域。然后它就会被该区域的红星的点近似表示。

这些红星点就是量化矢量,表示图中的任意一个点都可以量化为这16个矢量中的其中一个。也就是这16个红星点可以描述这一整张图。
在这里插入图片描述

然后这16个值就可以用4位的二进制码来编码表示(2^4=16)。因此,这是个2-dimensional, 4-bit VQ,它的速率同样是2bits/dimension。

图像编码例子:
最简单的情况,考虑一个灰度图片,0 为黑色,1 为白色,每个像素的值为 [0, 1] 上的一个实数。现在要把它编码为 256 阶的灰阶图片,一个最简单的做法就是将每一个像素值 x 映射为一个整数 floor(x255) 。当然,原始的数据空间也并不以一定要是连续的。比如,你现在想要把压缩这个图片,每个像素只使用 4 bit (而不是原来的 8 bit)来存储,因此,要将原来的 [0, 255] 区间上的整数值用 [0, 15] 上的整数值来进行编码,一个简单的映射方案是 x15/255 。

不过这样的映射方案颇有些 Naive ,虽然能减少颜色数量起到压缩的效果,但是如果原来的颜色并不是均匀分布的,那么的出来的图片质量可能并不是很好。例如,如果一个 256 阶灰阶图片完全由 0 和 13 两种颜色组成,那么通过上面的映射就会得到一个全黑的图片,因为两个颜色全都被映射到 0 了。一个更好的做法是结合聚类来选取代表性的点。

实际做法就是:将每个像素点当作一个数据,跑一下 K-means ,得到 k 个 centroids ,然后用这些 centroids 的像素值来代替对应的 cluster 里的所有点的像素值。对于彩色图片来说,也可以用同样的方法来做,例如 RGB 三色的图片,每一个像素被当作是一个 3 维向量空间中的点。

VQ 2、VQ 10 和 VQ 100 三张图片分别显示聚类数目为 2 、10 和 100 时得到的结果,可以看到 VQ 100 已经和原图非常接近了。把原来的许多颜色值用 centroids 代替之后,总的颜色数量减少了,重复的颜色增加了,这种冗余正是压缩算法最喜欢的。考虑一种最简单的压缩办法:单独存储(比如 100 个)centroids 的颜色信息,然后每个像素点存储 centroid 的索引而不是颜色信息值,如果一个 RGB 颜色值需要 24 bits 来存放的话,每个(128 以内的)索引值只需要 7 bits 来存放,这样就起到了压缩的效果。

原始图像:
在这里插入图片描述

VQ 2:
在这里插入图片描述

VQ 10:
在这里插入图片描述

VQ 100:
在这里插入图片描述
代码:
直接使用了 SciPy 提供的 kmeans 和 vq 函数,图像读写用了 Python Image Library 。

#!/usr/bin/python
 
from scipy.cluster.vq import kmeans, vq
from numpy import array, reshape, zeros
from mltk import image
 
vqclst = [2, 10, 100, 256]
 
data = image.read('example.jpg')
(height, width, channel) = data.shape
 
data = 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, :]
    image.write('result-%d.jpg' % k, reshape(im_vq,
        (height, width, channel)))

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

数学公式描述

  • 假定一个有M个矢量源(训练样本)的训练序列(训练集):T={x1, x2,…, xM};

  • 假设每个源矢量是k维的:
    xm=(xm1,xm2, …, xmk), m=1,2,…,M

  • 假设码矢的数目是N(也就是我们要把这个矢量空间划分为N个部分,或者说量化为N种值),码书(所有码矢的集合)表示为:C={c1, c2,…, cN};

  • 每一个码矢是个k维向量:cn=(cn1, cn2, …, cnk),n=1,2,…,N;

  • 与码矢cn对应的编码区域表示为Sn,然后将空间的划分表示为:
    P={S1, S2,…,SN};

如果源矢量xm在Sn内,那么它的近似(用Q(xm)表示)就是cn,
Q(xm)=cn 。

假设我们采用均分误差失真度量,那么平均失真度表示如下(用欧式距离):
在这里插入图片描述

那么设计问题就可以简单的描述为:
给定T(训练集)和N(码矢数目),找到能使Dave(平均失真度)最小的C(码书)和P(空间划分)。

优化准则:
如果C和P是上面这个最小化问题的一个解,那么这个解需要满足以下两个条件:

(1)Nearest NeighborCondition 最近邻条件:

在这里插入图片描述这个条件的意思是编码区域Sn应该包含所有与cn最接近的矢量(相比于与其他码矢的距离)。对于在边界(蓝色线)上面的矢量,需要采用一些决策方法(any tie-breaking procedure)。

(2)Centroid Condition质心条件:

在这里插入图片描述
这个条件要求码矢cn是编码区域Sn内所有的训练样本向量的平均向量。在实现中,需要保证每个编码区域至少要有一个训练样本向量,这样上式的分母才不为0。

LBG算法

LBG

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值