基本的JPEG压缩编码算法笔记

1. 颜色模式转换

JPEG采用的是YCrCb颜色空间,而BMP采用的是RGB颜色空间,要想对BMP图片进行压缩,首先需要进行颜色空间的转换。YCrCb颜色空间中,Y代表亮度,Cr,Cb则代表色度和饱和度。有时候U也表示Cb,V 表示Cr。RGB和YCrCb之间的转换关系如下所示:

Y = 0.299R + 0.587G + 0.114B

Cb = -0.1687R -0.3313G + 0.5B + 128

Cr = 0.5R - 0.418G - 0.0813B + 128

一般来说,C值(包括Cb Cr)应该是一个有符号的数字,但这里加上128,使其变为8位的无符号整数,从而方便数据存储和计算。

R = Y+1.402(Cr-128)

G = Y-0.34414(Cb-128)-0.71414(Cr-128)

B = Y+1.772(Cb-128)

2. 采样

研究发现,人眼对亮度变换的敏感度要比对色彩变换的敏感度高出很多。因此,我们可以认为Y分量要比Cb,Cr分量重要。在BMP图片中,RGB三个分量各采用一个字节进行采样,也就是我们常听到的RGB888的模式;而JPEG图片中,通常采用两种采样方式:YUV411和YUV422,它们所代表的意义是Y,Cb,Cr三个分量的数据取样比例一般是4:1:1或者4:2:2(4:1:1含义就是:在2x2的单元中,本应分别有4个Y,4个U,4个V值,用12个字节进行存储。经过4:1:1采样处理后,每个单元中的值分别有4个Y、1个U、1个V,只要用6个字节就可以存储了)。这样的采样方式,虽然损失了一定的精度但也在人眼不太察觉到的范围内减小了数据的存储量。当然,JPEG格式里面也允许将每个点的U,V值都记录下来;


3. 分块

由于后面的DCT变换是对8x8的子块进行处理的,因此,在进行DCT变换之前必须把源图像进行分块。源图像中每点的3个分量是交替出现的,先把这3个分量分开,存放到3张表中去,然后由左及右,由上到下依次读取8x8的子块,存放在长度为64的表中,即可进行DCT变换。注意编码时,程序从源数据中读取一个8x8的数据块后,进行DCT变换,量化,编码,然后再读取,处理下一个8x8的数据块。JPEG编码是以每8x8个点为一个单位进行处理的,所以如果原始图片的长宽不是8的倍数,都需要先补成8的倍数,使其可以进行一块块的处理。将原始图像数据分为8x8的数据单元矩阵之后,还必须将每个数值减去128,然后一一带入DCT变换公式,即可达到DCT变换的目的。图像的数值减去128,是因为DCT所接受的数字范围是-128~127之间 。

4.离散余弦变换

DCT是码率压缩中常用的一种变换编码方法。任何连续的实对称函数的傅里叶变换中只含有余弦项,因此,余弦变换同傅里叶变换一样具有明确的物理意义。DCT是先将整体图像分成N*N的像素块,然后针对N*N的像素块逐一进行DCT操作。需要提醒的是,JPEG的编码过程需要进行正向离散余弦变换,而解码过程则需要反向离散余弦变换。

N是水平垂直的像素数目,一般取值为8,8*8的二维像素块经过DCT操作之后,就得到了8*8的变换系数矩阵。这些系数,都有具体的物理含义,例如,U=0,V=0时的F(0,0)是原来的64个数据的均值,相当于直流分量,也有人称之为DC系数或者直流系数。随着U,V的增加,另外的63个系数则代表了水平空间频率和垂直空间频率分量的大小,多半是一些接近于0的正负浮点数,我们称之为交流系数AC。DCT变换后的8*8系数矩阵中,低频分量集中在矩阵的左上角,高频成分集中在右下角。

由于大多数图像的高频分量比较小,相应的图像高频分量的DCT系数经常接近于0,再加上高频分量中只包含了图像的细微的细节变化信息,而人眼对这种高频成分的失真不太敏感,所以,可以考虑将这一些高频成分予以抛弃,从而降低需要传输的数据量。这样一来,传送DCT变换系数的所需要的编码长度要远远小于传送图像像素的编码长度。到达接收端之后通过反离散余弦变换就可以得到原来的数据,虽然这么做存在一定的失真,但人眼是可接受的,而且对这种微小的变换是不敏感的。
5.Zigzag扫描

DCT讲一个8*8的数组变换成另一个8*8的数组,但是内存里面所有数据都是线性存放的,保存和读取顺序按照下图

可见是按照Z字形或者之字形来的

6.量化

图像数据转换为DCT频率系数之后,还要进行量化阶段,才能进入编码过程。量化阶段需要两个8*8量化矩阵数据,一个是专门处理亮度的频率系数,另一个则是针对色度的频率系数,将频率系数除以量化矩阵的值之后取整,即完成了量化过程。当频率系数经过量化之后,将频率系数由浮点数转变为整数,这才便于执行最后的编码。不难发现,经过量化阶段之后,所有的数据只保留了整数近似值,也就再度损失了一些数据内容。在JPEG算法中,由于对亮度和色度的精度要求不同,分别对亮度和色度采用不同的量化表。前者细量化,后者粗量化。

7. DC系数的差分脉冲调制编码

8*8的图像块经过变换之后得到的DC系数有两个特点:系数的数值比较大;相邻的8*8图像块的DC系数值变换不大;根据这两个特点,DC系数一般采用差分脉冲调制编码DPCM(Difference Pluse Code Modulation),即:取同一个图像分量中每个DC值与前一个DC值的差值来进行编码。对差值进行编码所需要的位数会比对原值进行编码所需要的位数少了很多。假设某一个8*8图像块的DC系数值为15,而上一个8*8图像块的DC系数为12,则两者之间的差值为3。

8. DC系数的中间格式计算

 JPEG中为了更进一步节约空间,并不直接保存数据的具体数值,而是将数据按照位数分为16组,保存在表里面。这也就是所谓的变长整数编码VLI。即,第0组中保存的编码位数为0,其编码所代表的数字为0;第1组中保存的编码位数为1,编码所代表的数字为-1或者1......,如下面的表格所示,这里,暂且称其为VLI编码表:

前面提到的那个DC差值为3的数据,通过查找VLI可以发现,整数3位于VLI表格的第2组,因此,可以写成(2)(3)的形式,该形式,称之为DC系数的中间格式。

9. AC系数的行程长度编码(RLC)

量化之后的AC系数的特点是,63个系数中含有很多值为0的系数。因此,可以采用行程编码RLC(Run Length Coding)来更进一步降低数据的传输量。

10. AC系数的中间格式

Huffman编码:对出现概率大的字符分配字符长度较短的二进制编码,对出现概率小的字符分配字符长度较长的二进制编码,从而使得字符的平均编码长度最短。Huffman编码的原理请参考数据结构中的Huffman树或者最优二叉树。

11. 简单举例说明

Before computing the DCT of the 8×8 block, its values are shifted from a positive range to one centered on zero. For an 8-bit image, each entry in the original block falls in the range {\displaystyle [0,255]}. The midpoint of the range (in this case, the value 128) is subtracted from each entry to produce a data range that is centered on zero, so that the modified range is {\displaystyle [-128,127]}. This step reduces the dynamic range requirements in the DCT processing stage that follows.

发布了33 篇原创文章 · 获赞 3 · 访问量 1908

猜你喜欢

转载自blog.csdn.net/FeNGQiHuALOVE/article/details/105359170
今日推荐