量化是实现数据有损压缩的一个非常重要步骤。JPEG2000里面对小波系数的有损量化有个叫"死区标量量化"的东西(deadzone scalar quantization)。听起来很唬人的东西,其实就是说在待量化系数在"死区"的范围内,被量化为0。而这个"死区"就是量化系数的两倍。
好了,在讨论量化系数之前,我们先看看这些量化系数的由来。在有损压缩中,我们的系数一般一开始是8位的0~255的颜色分量。这些系数经过电平偏移(DC level shifting),变成了-128~127的系数。然后是CDF9/7小波变换,因为小波变换后,样本有可能超出范围,因此我们还要扩大这个范围:[-2G+R-1,2G+R-1],R是我们原先图像的比特深度,比如8。在CDF9/7小波变换中,我们取G=1,即范围扩大为[-1,1],就足够了。但在JASPER里面,估计作者为了稳重起见,把G默认为2。
在JPEG2000里面,还有一个很重要的量:标称动态范围Gb,在CDF9/7小波变换中,Gb=0。但在5/3小波中,Gb随子带不同而不同。具体是LL子带为0,LH和HL为1,HH为2。这其实就是在上面的范围[-2G+R-1,2G+R-1]再扩大范围,于是最终的量化前范围是
[-2G+R-1+Gb,2G+R-1+Gb],当然,在9/7中Gb =0,切记。
我们再看看死区量化的公式:
-------------------------------------------(1)
△b就是我们的量化步长。简单嘛,量化其实就是把输入的数值编程以△b为倍数的值。
在JPEG2000标准里面,其实我们记录在码流里面的不是直接的△b。而是把△b分成两个数,指数ξ和尾数μ。他们的关系就是:
---------------------------------------------(2)
我们应该好好研究下这条公式,因为这条公式有非常大的意义。
首先第一项:2R+Gb,在9/7里面,Gb=0呀,所以不就变成了在量化时首先要除以2R了吗?怎么有点熟悉?
对,这就是在有些JPEG2000资料里面提到的把输入系数归一化,但在JPEG2000的官方标准文档书里面只字不提的东西。就是先把输入系数归一到[-1/2,1/2]中。在(2)式的后面亮相就是我们量化步长的真实内容了。的取值是多少呢?不管多少,反正肯定是小于1。为什么?这留给朋友们自己去思考啦。
好了,我们观察下,这里面的ε和μ是我们要记录在JPEG2000码流里面两个关于量化步长的参数。其实这个存储格式跟浮点数的存储格式类似。根据定义,μ为11位,ε是5位。2-ε可以表示成数值上的右移ε位,也就是缩小ε倍。μ最大也就是11个1呀,所以就是个1点多的 不超过2的数。如上文所说,肯定是小于1的,那么ε和μ就好理解了。不明白的朋友可以看看浮点数的定义啦。比如说=0.0011101,那么μ就是11010000000,ξ就是3。
在JPEG2000中,△b的计算主要有两种方法。
方法一:△b=△*sqrt(1/Gb)
其中△称为基本量化步长,Gb为能量增益因子,Gb近似于22*d,其中d表示所在子带的小波变换级数。比如LL3,d=3。有比如LH1,就是1。△=2-R,R为原始图像的比特位深,比如8位。
不过估计这种方法太简单了,误差比较大,用得比较少。
方法二:
△d的一个典型值是21-R,R位原始图像的比特深度。Rb为我们变换系数的最后比特深度,就是R+Gb,在9/7小波中,Gb=0。 γb就麻烦些,按照规定, γb就是所在小波子带的能量权值。在编程中,我们一般通过查表实现,至于怎么计算,我们另外再讨论。
好了,现在的任务是如何从计算得到的△d转化成指数ε和尾数μ,上面已经说过啦。把△d先右移Rb位,然后照上面那个例子,该怎么弄就怎么弄,不难实现的。
至此,△d的计算基本上完成了。还有个小问题,我们量化后的系数,到底取多少位呢(就是多少个位平面给后面的位平面编码)?如上,量化前的范围是[-2G+R-1+Gb,2G+R-1+Gb],而,用2G+R-1+Gb/△d,然后下取整,得到最大值是G+R-1+Gb-R-Gb+ξ=G+ε-1位。因此最终量化后,我们的数据有G+ε-1个位平面待后续的位平面编码。
另外再补充下,要让能同时适用于可逆和不可逆的量化过程。因为可逆的压缩没有量化,并且不用对系数归一化,所以在可逆中,μ=0,ε=R+Gb,从而是可逆压缩中的量化步长为1。