一个离开.NET的程序员

ryhan

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

编辑器加载中...

JPEG压缩方法由于其较高的压缩比和理想的压缩效果,是目前应用最广泛的图像压缩方法。它采用一种特殊的有损压缩算法,将不易被人眼察觉 的图像颜色删除,从而能够将图像压缩在很小的储存空间。JPEG压缩技术十分先进,它用有损压缩方式去除冗余的图像数据,在获得极高的压缩率的同时能展现 十分丰富生动的图像,换句话说,就是可以用最少的磁盘空间得到较好的图像品质。
本文对JPEG图像压缩方法进行了基本介绍,包括它的发展历史,现 阶段的研究情况,压缩原理等。其中重点介绍了哈夫曼编码和游程编码的基本原理和在JPEG压缩编码算法中的具体应用,以及以变换编码方法为例,介绍了离散 余弦变换(DCT)的基本过程。最后介绍了用VC++编写JPEG压缩程序所涉及到的几个基本模块,从而实现了BMP图像和JPEG图像的相互转换,这也 是最主要的编程思想和依据。
关键词: 图像压缩,JPEG,DCT,哈夫曼编码,行程编码

摘 要 I
ABSTRACT II
第一章 绪论 1
1.1 图像压缩的意义 1
1.2 JPEG图像压缩的国际标准 2
1.3 本论文的研究内容 3
第二章 JPEG图像压缩技术基础研究 4
2.1 JPEG图像压缩技术 4
2.2 JPEG压缩中图像文件的格式 5
2.2.1 BMP图像的格式 5
2.2.2 JPEG图像格式 8
2.3 本章小结 8
第三章 JPEG图像压缩相关算法及实现 9
3.1 JPEG图像压缩编码方法 9
3.1.1 哈夫曼编码的原理 10
3.1.2 哈夫曼编码在图像压缩中的实现 11
3.2 JPEG图像压缩原理 13
3.2.1 前向DCT变换 14
3.2.2 量化 15
3.2.3 使用哈夫曼可变字长编码器对量化系数进行编码 16
3.3 本章小结 19
第四章 JPEG图像压缩的设计与实现 20
4.1 总体设计 20
4.1.1设计思想 20
4.1.2 模块设计 20
4.2 JPEG图像压缩软件的实现 21
4.2.1 BMP图像的读入、显示模块 22
4.2.2 DCT量化编码模块 25
4.2.3 组成位数据流模块 29
4.2.4 JPEG图像存储模块 31
4.2.5 解压缩模块 31
4.3 软件应用 32
4.4 压缩效果的评价 33
4.4.1 压缩效果理论分析 34
4.4.2 压缩效果实际分析 34
4.5 本章小结 35
第五章 总 结 36
5.1 JPEG图像压缩结论 36
5.2 JPEG图像压缩前景分析 36
参考文献 38
致 谢 39
附 录 40
ABSTRACT
JPEG compression is the most widely used image compression method because of its higher compression ratio and ideal compression effect. It uses a special lossy compression algorithm and deletes colors of images that is not detected easily by human eye, thus images can be compressed in a small storage space. JPEG compression technology is very advanced, it is used lossy compression methods to remove redundant image data. Thus, high compression ratios can be got, at the same time, a very rich and vivid images can be displayed, in other words, it is possible to get better image quality with the least disk space.
The paper introduces the JPEG compression algorithm firstly, including its history and the basic situation of this stage, compression principle, and so on. Referring to the JPEG compression method, the paper focuses on the basic tenets of Huffman coding and run-length coding and their specific application in JPEG compression algorithm. To transform coding method as an example, it introduces the discrete cosine transform (DCT) the basic process. Finally, Using the VC + +, it involves several basic modules of JPEG compression process and realizes the BMP images and JPEG image conversion, which is the most important ideological basis for programming.
KEY WORDS:Image compression, JPEG, DCT, Huffman coding, run-length coding

第一章 绪论
1.1 图像压缩的意义

人类社会已经进入信息时代了,在这个时代,人们每天都可以通过各种手段(如PDA、网络、电视、广播等等)获得大量的信息,而信息的本质,就要求交流和传播,在有必要的时候还要进行储存。在大量信息给人们生活增加了更多色彩的同时,随之而来的问题就是,如何利用有限的传输和储存资源来传输和保存更多的信息,这就要用到压缩数据的方法。具体的说,数据压缩的意义[1]有以下几个方面:首先是为了减少存储容量,以利信息的保存。如果说数据库是一个桶,那么单位数据的体积越小,同一数据库存储的信息也就越多。一般的卫星图像的4个信道的平均压缩比为2,也就是说,同一容量的数据库可以成倍地增加有效库存。其次是有利于数据传输。由于数据压缩是一种”去伪存真,去粗取精”的筛选,又由于可以用”代码”表示一组数据,所以压缩后的数据非常”精干”,这样就可以极大地减少必须传输的数据量,以满足人眼和机器分析的要求。第三是便于特征提取,以利计算机模式识别。如用计算机对卫星图像中不同类型的农作物进行分类时,使用图像压缩方法,只要考虑区分植物与非植物的特征以及区分植物类型特征即可,从而减少了数据量又满足了实际需要。数据压缩技术经过几十年的发展,现在来说还是比较成熟的。
而在介绍图像的压缩编码之前,先考虑一个问题:为什么要压缩?其实这个问题不用我回答,你也能想得到。因为图像信息的数据量实在是太惊人了。举一个例子就明白:一张A4(210mm×297mm) 幅面的照片,若用中等分辨率(300dpi)的扫描仪按真彩色扫描,其数据量为多少?让我们来计算一下:共有(300×210/25.4) ×(300×297/25.4)个象素,每个象素占3个字节,其数据量为26M字节,其数据量之大可见一斑了。
如今在Internet上,传统基于字符界面的应用逐渐被能够浏览图像信息的WWW(World Wide Web)方式所取代。WWW尽管漂亮,但是也带来了一个问题:图像信息的数据量太大了,本来就已经非常紧张的网络带宽变得更加不堪重负,使得World Wide Web变成了World Wide Wait。总之,大数据量的图像信息会给存储器的存储容量,通信干线信道的带宽,以及计算机的处理速度增加极大的压力。单纯靠增加存储器容量,提高信道带宽以及计算机的处理速度等方法来解决这个问题是不现实的,这时就要考虑压缩。
压缩的理论基础是信息论。从信息论的角度来看,压缩就是去掉信息中的冗余,即保留不确定的信息,去掉确定的信息(可推知的),也就是用一种更接近信息本质的描述来代替原有冗余的描述。这个本质的东西就是信息量(即不确定因素)。
图像压缩一般通过改变图像的表示方式来达到,因此压缩和编码是分不开的。图像压缩的主要应用是图像信息的传输和存储,可广泛地应用于广播电视、电视会议、计算机通讯、传真、多媒体系统、医学图像、卫星图像等领域。
1.2 JPEG图像压缩的国际标准

图像数据文件的格式有很多,如GIF、TIFF、PCX、TGA、BMP、JPG等。其中BMP图像对于原始的图像数据(直接来自于CCD数码相机)不压缩或压缩比例很小。JPEG由于有较高的压缩比,被广泛地应用于多媒体和网络程序中,例如HTML语法中选用的图像格式之一就是JPEG(另一种是GIF), 目前网站上百分之八十的图像都是采用JPEG的压缩标准。美国国防部及情报部门亦采用此标准为各部门间交流图像资料的标准格式。JPEG全名为Joint Photographic Experts Group,它是一个在国际标准组织(ISO)下从事静态影像压缩标准制定的委员会,它和国际电信同盟(ITU)下属的国际电话与电报顾问委员会(CCITT)及国际电工委员会(IEC)合作,共同制定出了第一套国标静态影像压缩标准:ISO/IEC 10918-1,也被称作CCITT Rec.T.81,就是俗称的JPEG,它被公布于1992年9月份。
随著多媒体应用领域的激增,传统JPEG压缩技术已无法满足人们对多媒体影像资料的要求。因此,更高压缩率以及更多新功能的新一代静态影像压缩技术JPEG 2000就诞生了。JPEG 2000与传统JPEG最大的不同,在于它放弃了JPEG所采用的以离散余弦转换(Discrete Cosine Transform)为主的区块编码方式,而改用以小波转换(Wavelet transform)为主的多解析编码方式。小波变换的主要目的是要将影像的频率成分抽取出来。JPEG2000中只采用了数学编码。编码的基本单位变为TILE,它可以任意大小甚至是整幅图像,TILE越大,压缩的效果越好,但对系统缓存的要求也就越高。JPEG2000的于JPEG相比增加了不少新的功能,如对图像中细节较多或较为感兴趣的区域(形状与大小可以是任意的)进行高精度的无损编码、很强的容错性、支持水印等。JPEG2000的许多优点和新的功能都是建立在复杂的计算与较大的缓存基础上,因此其速度与JPEG相比要慢许多。
JPEG-LS[2](JPEG-Lossless)标准是JPEG组织在1997年制定的连续色度(Continuous-tone)图像的无损压缩标准,它的无损压缩效果与JPEG2000相当,但算法相对简单。它的压缩原理也是基于预测,误差编码,但它的预测器要比JPEG中的复杂,并根据预测误差符合双边几何分布(Two-sided geometric distribution)的推论对误差进行修正,同时它对即将编码的像素的背景(Context)也进行建模以提高预测精度。
1.3 本论文的研究内容

1.JPEG图像压缩意义和现状.
2.JPEG压缩方法的原理及实现的具体步骤。
3.通过试验,主要观察JPEG有损压缩方法对图像的压缩效果。
4.哈夫曼编码是种常用的熵编码方法,论文中分析了它的原理和在图像压缩中应用。

第二章 JPEG图像压缩技术基础研究
2.1 JPEG图像压缩技术

图像数据的压缩基于两点:(1)像信息存在着很大的冗余度,数据之间存在着相关性,如相邻像素之间色彩的相关性等。(2)人眼是图像信息的接收端。因此,可利用人的视觉对于边缘急剧变化不敏感(视觉掩盖效应),以及人眼对图像的亮度信息敏感、对颜色分辨率弱的特点实现高压缩比,而解压缩后的图像信号仍有着满意的主观质量。
从信号系统的角度理解,数据的压缩就是对原来信号进行某种变换。借助这种变换,信号的表达更经济,存储传输更为方便。从信息论角度理解,信号本身的具体表达形式不过是其内在携带信息的外在表象,一定的信息可以用各种形式加以体现,每种表达形式的表达效率并不相同,存在着信息冗余。数据压缩的目的就是寻找在一定约束条件下最为高效的信息表达方式。从压缩技术的角度理解,数据压缩一般分为:建模、去相关、量化、编码四道工序。
由此发展出数据压缩的两类基本方法:第一类压缩过程是可逆的,也就是说,从压缩后的图像能够完全恢复出原来的图像,信息没有任何丢失,称为无损压缩;第二类压缩过程是不可逆的,无法完全恢复出原图像,信息有一定的丢失,称为有损压缩。选择哪一类压缩,要折衷考虑,尽管我们希望能够无损压缩,但是通常有损压缩的压缩比(即原图像占的字节数与压缩后图像占的字节数之比,压缩比越大,说明压缩效率越高)比无损压缩的高。
无损压缩是将相同的或相似的数据或数据特征归类,使用较少的数据量描述原始数据,达到减少数据量的目的。无损压缩又称信息保持编码,或叫做熵保持编码[3]。图像的无损压缩通常分为两步,即去相关和编码。去相关就是要去除图像冗余,降低信源熵。
在对数据进行编码时,可对那些经常出现的数据指定较少的位数表示,而那些不常出现的数据指定较多的位数表示。用这种方法得到的代码,其码的位数,也即码长就是不固定的,故称为变长码。Huffman在1952年根据香农(Shannon)在1948年和范若(Fano)在1949年阐述的这种编码思想提出了一种不定长编码的方法,也称哈夫曼(Huffman)编码[4]。哈夫曼编码的基本方法是先对图像数据扫描一遍,计算出各种像素出现的概率,按概率的大小指定不同长度的唯一码字,由此得到一张该图像的哈夫曼码表。哈夫曼编码(Huffman编码)是完全依据字符出现概率来构造字符的平均长度最短的码字,又称为最佳编码。
有损压缩是有利用人眼的视觉特性有针对性地简化不重要的数据,以减少总的数据量。有损算法有很多种,比较常见的主要是预测编码、变换编码等。预测编码法中最重要的是线性预测法,通常也成为”差值脉冲编码调制法”(DPCM)。DPCM编码的基本思想是用反馈方法预测估值。变换域编码[5]就是将通常在时间域或空间域描述的信号通过多维坐标的旋转、变换,将原散布在各坐标轴上的能量集中到少数坐标轴上,减少各信号分量的相关性。因此,可以使用较少的编码位数来表示一组信号样本,实现高效率的压缩编码。变换编码是一种有损编码。变换编码中理论上最佳的是K-L变换,其去相关最彻底,但目前尚无快速算法,且变换矩阵随数据集变化,不能广泛应用。而离散余弦变换(DCT)是一种实变换,去相关能力仅次于K-L变换,压缩效果好,压缩比易于调整,压缩率高,易于硬件实现。DCT有固定基,性能最接近K-L变换,现已出现了DCT的多种快速算法。有损压缩方法利用了人类视觉对图像中的某些频率成分不敏感的特性,允许压缩过程中损失一定的信息;虽然不能完全恢复原始数据,但是所损失的部分对理解原始图像的影响较小,却换来了大得多的压缩比。只要损失的数据不太影响人眼主观接收的效果,就可采用。
通过上面简单分析可知,压缩比与图像内容、压缩方法、允许失真的限制等等因素有关。实际编码图像时,也常常采用混合编码方法,甚至一幅图像采用好几种算法在多层次上反复进行处理,其目的当然是为了达到尽可能高的压缩比而不影响图像质量。除了压缩比,衡量压缩效果的常用指标为[6]PSNR(Peak Signal-to-Noise Ratio),但它要和主观评价相配合来对压缩效果进行评价。

2.2 JPEG压缩中图像文件的格式

由于图像数据文件的格式有很多,如GIF、TIFF、PCX、TGA、BMP、JPEG等。而现在实现的是BMP和JPEG的相互转换,所以要具体介绍BMP和JPEG文件的格式。
2.2.1 BMP图像的格式
BMP图像采用RGB(Red Green Blue)色彩模型,将各种颜色视为为红,绿,蓝(R,G,B)三个部分的组合。由于一幅图像中许多像素对应的颜色是相同的,BMP图像中采用了一个表:表中的每一行记录一种颜色的R,G,B值。这样,当表示一个象素的颜色时,只需要指出该颜色是在第几行,即该颜色在表中的索引值,这个表在BMP图像中称为调色板。有一种图,它的颜色数高达256×256×256种,也就是说包含上述提到的R,G,B颜色表示方法中所有的颜色,这种图叫做真彩色图(True Color)。真彩色图并不是说一幅图包含了所有的颜色,而是说它具有显示所有颜色的能力,即最多可以包含所有的颜色。表示真彩色图时,每个象素直接用R,G,B三个分量字节表示,而不采用调色板技术。
下面来看一看Windows的位图文件(.bmp文件)的格式是什么样子的。BMP文件大体上分成四个部分,如图2-1。
为了使文件格式更形象,在下文中给出图解。首先做出一些约定,在图2-2中:1B存储在一个字节中;2B存储在2个字节中;4B存储在4个字节中;b1、b2存储在4Bit中,也即半个字节中。本小节中的给出的图解都采用图2-2中的约定。
图2-1 BMP文件的结构

图2-2在BMP图像格式说明中的约定
图2-1第一部分为位图文件头(Bit map file header)这个结构的长度是固定的,为14个字节,结构如图2-3所示。
图2-3 BMP文件头的结构
开头两个字节指定文件类型,必须是0×424D,即字符串”BM”,也就是说所有.bmp文件的头两个字节都是”BM”。bfSize指定文件大小,其中包括这14个字节。bfReserved1,bfReserved2为保留字,不用考虑。bfOffBits为从文件头到实际的位图数据的偏移字节数,即图2-4中前三个部分的长度之和。
第二部分为位图信息头(Bit map info header), 这个结构的长度是固定的,为40个字节各部分,如图2-4。 biSize指定这个位图信息头的长度,等于40。biWidth指定图像的宽度,单位是象素。biHeight指定图像的高度,单位同样是象素。biPlanes必须是1,不用考虑。biBitCount指定表示颜色时要用到的位数,常用的值为1(黑白二色图),4(16色图),8(256色),24(真彩色图)。biCompression指定位图是否压缩,今后所讨论的只有不压缩的情况,即biCompression为0的情况。biSizeImage指定实际的位图数据占用的字节数,其实也可以从式(2-1)中计算出来。

a) 信息头的前24个字节

b) 信息头的后16个字节
图2-4 BMP图像的信息头
(2-1)
公式2-1中的biWidth’必须是4的整倍数(所以不是biWidth,而是biWidth’,表示大于或等于biWidth的,离4最近的整倍数。举个例子,如果biWidth=240,则biWidth’=240;如果biWidth=241,biWidth’=244。biXPelsPerMeter指定目标设备的水平分辨率,单位是每米的象素个数,打印时用到这个参数。biYPelsPerMeter指定目标设备的垂直分辨率,单位同上。biClrUsed指定本图像实际用到的颜色数,如果该值为零,则用到的颜色数为2的biBitCount次方。biClrImportant指定本图像中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。
第三部分为调色板(Palette),当然,这里是对那些需要调色板的位图文件而言的。有些位图,如真彩色图,前面已经讲过,是不需要调色板的,位图信息头后直接是位图数据。 如果视调色板实际上为一个数组,共有biClrUsed个元素(如果该值为零,则有2的biBitCount次方个元素)。数组中每个元素占用四个字节,四个字节分别为 rgbBlue(该颜色的蓝色分量) rgbGreen(该颜色的绿色分量),rgbRed(该颜色的红色分量),rgbReserved(保留值)。
第四部分就是实际的图像数据了。对于用到调色板的位图,图像数据就是该像素颜色在调色板中的索引值,对于真彩色图,图像数据就是实际的R,G,B值。对于256色位图,一个字节刚好可以表示1个像素。对于真彩色图,三个字节才能表示1个像素。要注意两点:
1)每一行的字节数必须是4的整倍数,如果不是,则需要补齐。这在前面介绍biSizeImage时已经提到了。
2)一般来说,BMP文件的数据从下到上,从左到右的。也就是说,从文件中最先读到的是图像最下面一行的左边第一个像素,然后是左边第二个像素…接下来是倒数第二行左边第一个像素,左边第二个像素…依次类推,最后得到的是最上面一行的最后一个像素。
介绍完BMP图像的格式,就好对它进行处理了。
2.2.2 JPEG图像格式
JPEG文件大体上可以分成以下两个部分[7]:标记码(Tag)加压缩数据。先介绍标记码部分。标记码部分给出了JPEG图像的所有信息(有点类似于BMP中的头信息,但要复杂的多),如图像的宽、高、Huffman表、量化表等等。标记码有很多,但绝大多数的JPEG文件只包含几种。标记码的结构为:
SOI
DQT
DRI
SOF0
DHT
SOS

EOI
标记码由两个字节组成,高字节为0XFF,每个标记码之前可以填上个数不限的填充字节0XFF。

2.3 本章小结

本章主要介绍了JPEG图像压缩技术基础,以及程序中要用到的BMP图像的格式。

第三章 JPEG图像压缩相关算法及实现
3.1 JPEG图像压缩编码方法

压缩编码的方法有很多,主要分成以下四大类:(1)象素编码;(2)预测编码;(3)变换编码;(4)其它方法。所谓象素编码是指,编码时对每个象素单独处理,不考虑象素之间的相关性。在象素编码中常用的几种方法有:(1)脉冲编码调制(Pulse Code Modulation,简称PCM);(2)熵编码(Entropy Coding);(3)行程编码(Run Length Coding);(4)位平面编码(Bit Plane Coding)。所谓预测编码是指,去除相邻象素之间的相关性和冗余性,只对新的信息进行编码。举个简单的例子,因为象素的灰度是连续的,所以在一片区域中,相邻象素之间灰度值的差别可能很小。如果我们只记录第一个象素的灰度,其它象素的灰度都用它与前一个象素灰度之差来表示,就能起到压缩的目的。如248,2,1,0,1,3,实际上这6个象素的灰度是248,250,251,251,252,255。表示250需要8个比特,而表示2只需要两个比特,这样就实现了压缩。常用的预测编码有Δ调制(Delta Modulation,简称DM);微分预测编码(Differential Pulse Code Modulation,DPCM),具体的细节在此就不详述了。所谓变换编码是指,将给定的图像变换到另一个数据域(如频域)上,使得大量的信息能用较少的数据来表示,从而达到压缩的目的。变换编码有很多,如(1)离散傅立叶变换(Discrete Fourier Transform,简称DFT);(2)离散余弦变换(Discrete Cosine Transform,简称DCT);(3)离散哈达玛变换(Discrete Hadamard Transform,简称DHT)。其它的编码方法也有很多,如混合编码(Hybird Coding)、矢量量化(Vector Quantize,VQ) 、LZW算法。
行程编码[8](Run Length coding)的原理也很简单:将一行中颜色值相同的相邻象素用一个计数值和该颜色值来代替。例如aaabccccccddeee可以表示为3a1b6c2d3e。如果一幅图像是由很多块颜色相同的大面积区域组成,那么采用行程编码的压缩效率是惊人的。然而,该算法也导致了一个致命弱点,如果图像中每两个相邻点的颜色都不同,用这种算法不但不能压缩,反而数据量增加一倍。所以现在单纯采用行程编码的压缩算法用得并不多,PCX文件算是其中的一种。
算术编码也是一种常见的无损压缩算法,由于它可以对编码对象的概率分布进行自适应,其效率要高于哈夫曼编码,现在正得到越来越广泛的应用。LZW编码是一种字典压缩算法,其压缩效率比较高,压缩速度较快。如果原始图像数据值中带有随机变化的”噪音图像”,则很难利用LZW算法进行压缩。当前流行的GIF、TIFF等图像文件格式都采用这种压缩算法。这类方法广泛用于文本数据、程序和特殊应用场合的图像数据(如指纹图像、医学图像等)的压缩。由于压缩比的限制,仅使用无损压缩方法不可能解决图像和数字视频的存储和传输问题。
哈夫曼编码是压缩编码中常用的一种编码方法,广泛的应用于图像的压缩,JPEG标准中基准模式采用的就是哈夫曼编码。本章对其原理和在图像压缩中的应用进行论述。

3.1.1 哈夫曼编码的原理
哈夫曼编码基于不同符号的概率分布,对出现次数较多的符号赋予较短的代码,出现次数较少的符号赋予较长的代码。这里,以一个例子说明如何赋予各个符号哈夫曼码值,即如何生成哈夫曼表。
假设将对由1,2,3,4,5,6,7,共7个数字组成的原信息进行哈夫曼编码,首先应对信息中各个数字出现的次数进行统计,得出各个数字的出现的相对概率。假设各个数据出现的次数如表3-1所示。
表3-1 7个数字的概率分布
数字 1 2 3 4 5 6 7
出现的次数 10 10 10 20 20 25 5
相对概率 0.1 0.1 0.1 0.2 0.2 0.25 0.05
根据表3-1生成哈夫曼树如图3-1所示。
具体的过程是这样的。先将所有的数字随意排列成一行构成7个最底层节点,首先将这一行中最小的两个概率值相加,0.1+0.05=0.15得到新的节点。这时拥有的概率值为0.2,0.2,0.2,0.1,0.1,0.15,0.25,再将这时最小的两个概率值相加,0.1+0.1=0.2得到新的节点。这时拥有的概率值为0.2,0.2,0.2,0.2,0.15,0.25,再将这时最小的两个概率值相加……,直到得到根节点,概率值为1.0为止。相加时,对于概率值相等的多个节点,可以任意选取。 除根节点外,设节点左面的分支为0,右边的分支为1(当然,也可以反过来),对于各个数值的代码就是从根节点出发到最底层的节点所经过的分支的序列。如4的代码为00,7的码值为1011,通常将4和7称为码值(Code value),00和1011被称为相应的码字(Code word),所有码字和码值的对应关系如表3-2所示。进行压缩编码时,只要将原数字(码值)用码字代替即可。如果概率统计十分不准确,则压缩效率会很低,甚至起不到压缩效果。
图3-1 由表3-1生成的哈夫曼树
将所有的码字和码值生成一个表,表达码字和码值的对应关系,称为哈夫曼表,为了整字节的输出码字,表中还要有各个码字的长度,例如JPEG标准中推荐的亮度信息直流系数的哈夫曼表如表3-3所示。
表3-2由图3-1得到的码字和码值的对应关系
码值 1 2 3 4 5 6 7
码字 1000 1001 1010 00 01 11 1011
哈夫曼表一般是事先确定的,(也可以在线实时调整)。本文以JPEG中的一个哈夫曼表(表3-3)为例,来说明如何实现哈夫曼编码,解码。

3.1.2 哈夫曼编码在图像压缩中的实现
在JPEG文件格式中,哈夫曼表以哈夫曼码字中位数相同的个数和所有的哈夫曼码值的形式存储,实际上是存储了一个哈夫曼树。根据JPEG文件开始部分对于亮度信息所用的哈夫曼表(对应表3-3)说明字段的可以得到下面两个数组:
bits[17] = { 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
huffval[] ={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
表3-3 JPEG标准中推荐的亮度信息哈夫曼表
码值 码字的长度 码字
0 2 00
1 3 010
2 3 011
3 3 100
4 3 101
5 3 110
6 4 1110
7 5 11110
8 6 111110
9 7 1111110
10 8 11111110
11
9
111111110

这两个数组和上面那个表是对应的。bits[]数组中的元素除bits[0]外,bits[1],bits[2],bits[3],…bits[16]代表哈夫曼代码中长度为1,2,3…16的个数。huffval[]中的各个元素是按照哈夫曼代码长度递增的顺序相对应的哈夫曼值(Huffman value),也即被代表的信息,如果几个元素对应的哈夫曼代码长度相同,顺序可以交换。从这两个数组出发,看看是如何实现编码的。
首先,应该生成哈夫曼表。建立huffcode[],huffcode[],ehufco[],ehufsi[]四个整数型数组,此处它们的元素个数只要大于12即可。
第一步:得到huffsize[]。
int p,l,i,lastp;
p = 0;
for (l = 1; l <= 16; l++) {
i = bits[l];
while (i–)
huffsize[p++] = l;
}
huffsize[p] = 0; /*使huffsize[]最后一个元素为零,是为了后面生成huffcode[]时,能够跳出循环*/
lastp=p; /* lastp-1即是所有码值的个数,后面的程序要用到它*/
这样, huffsize[]对12个哈夫曼码字的有效位的位数(单位是Bit)都有了记录,这主要使为了编码后输出码字时一定要知道码字的长度。
第二步得到huffcode[],它的各个元素是与huffsize[]各元素相对应的哈夫曼码字。
{ int code,si;
code = 0;
si = huffsize[0];
p = 0;
while (huffsize[p]) {
while ( huffsize[p] == si) {
huffcode[p++] = code;
code++;
}
code <<= 1;
si++;
}
}
从程序中可以看出,相邻的相同长度的哈夫曼码字彼此间差1。长度为si+1的代码中数值最小的代码,是长度为si的代码中数值最大的代码加1后并左移一位,这就能保证没有任何一个代码是另外一个代码的前缀,也就是说11,110这样的两个代码是不允许的。否则,解码时就会出现问题。
第三步得到ehufco[],ehufsi[]。
for (p = 0; p < lastp; p++) {
i = huffval[p];
ehufco[i] = huffcode[p];
ehufsi[i] = huffsize[p];
}
很简单,这里只是将huffcode[],huffsize[]中的元素调整了顺序,赋予了ehufco[],ehufsi[],以val[]的元素为索引值。显然,这样调整后,哈夫曼编码的过程就是一个查表过程。

3.2 JPEG图像压缩原理
JPEG的压缩原理其实是前面介绍的那些原理的综合,博采众家之长,这也正是JPEG有高压缩比的原因。其编码器的流程如图3-2:

图3-2 JPEG编码器流程
解码器基本上为上述过程的逆过程如图3-3:

图3-3 解码器流程
3.2.1 前项DCT变换
JPEG 里, 要对数据压缩, 先要做一次前向DCT(Forward cosine transform FDCT)变换,一次只对一个块(Block)进行变换。将原始图像数据视为空间的函数f(x,y),x为像素所处的行,y为像素所处的列,u和v对应频域空间的行和列,前向DCT变换的公式如式(3-1),DCT反变换的公式如式(3-2)。
(3-1)
(3-2)
在(3-1)和(3-2)中当u,v=0时, ;其它情况下, 。 DCT 变换的原理,和离散傅立叶变换差不多,它是将空间域的信号变换到频域,FDCT相当于谐波分析,此处频域共有64个不同的空间频率(对应不同的和),事实上,这种频率体现出光强变化的快慢[9],FDCT得到的数据就是对应频域中各个频率的幅值F(u,v)。值得注意的是在频域中,能量(或者说幅值)主要集中在低频(对应较小的u和v),对应高频的幅值大部分为零或接近零,这显然非常有利于数据的压缩。F(0,0)称为直流系数(DC Coefficient),从公式可以看出它相当于原始图像数据某种意义上的平均值,一般数值较大;其余的F(u,v)称为交流系数(AC Coefficient)。FDCT原理上是可逆的,原始图像数据的损失是由于公式中有余弦函数,计算时的精度引起的,但这往往可以忽略。这里还要注意两个问题:
1)FDCT是对每 8×8个点为一个单位处理的。所以如果原始图片的宽度(Width)或高度(Height)不是 8 的整倍数, 都需要先补成 8的倍数, 好一块一块的处理。例如某幅图像为698×695(高度×宽度),高度,宽度均不是8的整数倍,这在对图像压缩时,图像的右边应再加一列,图像的底部应再加6行,这样图像变为704×696,对于多加的行和列的像素值取为0即可。
2)FDCT变换前,先要将原始图像数据零均值化,如果原始图像的精度为P,则应将数值从[0,2p-1]变换到[-2p-1,2p-1-1],显然将原始数据减去2p-1即可。对于关心的8位的灰度图像,减去128,数据范围为[-27,27-1]。
3.2.2 量化
对于前面得到的64个空间频率振幅值按比例缩小,并取其最接近的整数值的处理过程称为量化。JPEG标准中推荐的量化表如表3-4。一共有64个元素,按照从上到下,从左到右的顺序与FDCT变换后的幅值对应,每一元素记为Q,u和v对应行和列,量化公式为式(3-3),解码时反量化公式为式(3-4)。
(3-3)
(3-4)
代表量化后的幅值, 代表还原(反量化)后的幅值。
RoundInteger 顾名思义是对数值取整,四舍五入就行了。
JPEG标准中推荐的量化表如表3-4。依据心理视觉阀制作,对 8bit 的亮度和色度的图像的处理效果不错,当然可以使用任意的量化表。
表3-4 JPEG标准推荐的量化表
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
由于量化的缘故,产生了信息损失。量化表中对应于和较小的元素数值较小,意味着对低频幅值的量化信息损失较小,相对的,u和v较大时,数值也就较大了,意味着对高频幅值的量化信息损失较大。但事实上人眼对高空间频率远没有低频敏感,所以处理后的视觉损失很小。量化表是控制 JPEG 压缩比的关键[10,11,12],当量化表中某个元素取值较大时,压缩比就高,但图像失真就大。对于像素数值精度为N的数据经过FDCT和量化环节后,数据的整数部分的有效位数(以二进制计算)最多增加3位。对于8位
的灰度图像,此时数据的范围为[-210,210-1]。

3.2.3 使用哈夫曼可变字长编码器对量化系数进行编码
哈夫曼编码要分成3步来完成,1)按Z字型[13]的顺序(Zig-zag sequence)调整量化后的系数;2)将按之字型顺序排列的系数转化为中间符号(Intermediate symbol)序列;3)将中间符号中的一部分进行变长码字编码(Variable-lengths code coding)也就是哈夫曼编码,另一部分进行变长整数编码(Variable-lengths integer code),最终输出数据流[14]。
先看第一步,由前面的叙述可以看出,经过FDCT和量化两个环节后,较高空间频率(对应较大的u和v)的系数很小,大部分为零,因此,按Z字型的顺序调整系数的用意就是使为零的高空间频率系数能够连在一起,以利于游程编码(Run-length coding)。根据这一点,应使u和v较小的系数排列在前面,Z字形顺序如图3-4,图中 表示坐标为(i,j)

图3-4 z字形顺序
再看第二步。在这一步里,DC系数和AC系数是分开来处理的。由于DC系数是一块(Block)图像中像素值的平均值,相邻块之间的DC系数又很大的相关性,或者说往往相差不大,所以对相邻块的DC系数差值(DC Difference)进行编码,如图3-5所示。 紧接着将DIFF转变成中间符号:
Symbol-1 Symbol-2
(SIZE) (AMPLITUDE)
DIFF=DCi-DCi-1
图3-5 DC系数的编码
symbol-1是DIFF的有效位数(以二进制来计算),记为SIZE。如果DIFF为3,则symbol-1应为2。由于计算机中将负数存为反码或补码的形式,当DIFF为负数时,DIFF的有效位数为(-DIFF)的有效位数。前面提到,经过FDCT和量化两个环节后,对于8位
的灰度图,此时的数值范围为[-210,210-1],故DIFF的范围为[-211+1,211-1]故对DIFF来说,SIZE取值范围为0-11。
symbol-2是DIFF的幅值,记为AMPLITUDE,如果DIFF=3,则symbol-2为3。
对于AC系数,同样变成多个中间符号:
symbol-1 symbol-2
(RUNLENGTH,SIZE) (AMPLITUDE)
symbol-1包含RUNLENGTH,SIZE两部分。RUNLENGTH代表某一非零AC系数前面连续的AC系数为零的个数,这是对为零的AC系数进行游程编码。SIZE代表非零AC系数的有效位数。这里要注意,symbol-1的长度是固定的,占8位,RUNLENGTH,SIZE各占4位,故RUNLENGTH最大值为15,它最多可以记录15个连续的为零的系数。在symbol-1后面,往往有symbol-2,但在两种情况下没有:1)连续为零的系数大于15。此时,要用多个symbol-1来完成游程编码,symbol-1为(15,0)时,表示有16个连续的零系数,因为AC系数有63个,故在symbol-1完成游程编码时最多有3个连续的(15,0);2)当一窜连续为零的系数包含最后的AC系数 。这时以标记(0,0)表示后面的系数全为零,此块(Block)的数据结束,(0,0)一般称为EOB(End of block)。symbol-2表示非零系数的数值。
下面看一看哈夫曼编码的最后一步,对上一步产生的中间符号序列中symbol-1进行变长码字编码(Variable-lengths code coding VLC)也就是哈夫曼编码,对symbol-2进行变长整数编码(Variable-lengths integer code VLI),最终输出数据流。DC系数和AC系数的哈夫曼编码是分开的,在8位的灰度图像中,对于DC系数,symbol-1可以有12种取值,对于AC系数,symbol-1可以有162种取值,故它们采用的哈夫曼表不同。对于出现次数较多的symbol-1赋予较短的码字,出现次数较少的symbol-1赋予较长的码字,说它是变长码字编码是恰如其分的。对symbol-2进行变长整数编码实际就是省去非零数值的高位为零的那几位,表达一个非零的数,用它的有效位数个位就足够了,它的位数记录在symbol-1中的SIZE中。例如3,写成二进制数11就行了,没必要写成00000011。这里注意一点,在JPEG中,进行VLI编码时,数值为正,用原码表示,数值为负,用反码表示,例如-3,VLI编码后,变为00。
下面看一个对数据哈夫曼编码的实例。假设某原始图像的一块数据经FDCT和量化环节
后,数据变为:
15 0 -1 0 0 0 0 0
-2 0 0 0 0 0 0 0
-1 -1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
上面的数据是按照从上到下,从左到右的顺序排列的。首先,按z字型的顺序(Zig-zag sequence)调整后的系数序列为:
15 0 -2 -1 -1 -1 0 0 -1 0 •••• 0
假设前一Block的DC系数为12,将系数转为中间符号的序列为:
(2)(3), (1,2)(-2), (0,1)(-1), (0,1)(-1), (0,1)(-1), (2,1)(-1), (0,0)
对于DC系数的symbol-1(2),查哈夫曼表为011,对于AC系数的各symbol-1查哈夫曼表为:
(0,0) 1010
(0,1) 00
(1,2) 11011
(2,1) 11100
对DC和AC系数的Symbol-2进行VLI编码为:
(3) 11
(-2) 01 (为-2的反码)
(-1) 0
则最终,整个输出的压缩数据为:
0111111011010000000001110001010
以上我们介绍了JPEG压缩的原理,其中DC系数使用了预测编码DPCM,AC系数使用了变换编码DCT,二者都使用了熵编码Huffman,可见几乎所有传统的压缩方法在这里都用到了。这几种方法的结合正是产生JPEG高压缩比的原因。
3.3 本章小结

本章介绍了JPEG图像压缩中的各种编码方法和JPEG压缩的原理,其中重点分析了哈夫曼编码的原理及在图像压缩中如何生成哈夫曼表以进行编码、解码。

http://apps.hi.baidu.com/share/detail/19229830

posted on 2011-07-19 15:44  ryhan  阅读(2699)  评论(0编辑  收藏  举报