数据压缩实验5——JPEG编解码

1 实验目的

掌握JPEG编解码系统的基本原理。初步掌握复杂的数据压缩算法实现,并能根据理论分析需要实现所对应数据的输出。

2 JPEG编解码原理

在这里插入图片描述

  • 两张量化表——亮度,色度
  • 四张Huffman码表——亮度DC,亮度AC,色度DC,色度AC

2.1 Level Offset 零偏置

  • 对于灰度级是 2n 的像素,通过减去 2n-1 ,将无符号的整数值变成有符号数。
    例如:n=8,灰度级0 ~ 255,通过减去128,转化为-128 ~ 127

  • 目的:使像素的绝对值出现3位10进制的概率大大降低。

2.2 DCT变换

离散DCT变换的变换核矩阵为:
在这里插入图片描述

一维DCT变换

在这里插入图片描述
若N=8,则每个变换核矩阵的物理意义如下图所示:

二维DCT变换

变换对象为图像块。
变换核可分离,先进行垂直方向的8 * 1DCT变换,再进行水平方向的8 * 1DCT变换。
在这里插入图片描述
二维DCT变换的性质:

  • 二维DCT变换可以使DCT系数矩阵中数值较大的低频分量数据向左上方集中,使数值较小的高频分量数据向右下方集中。
  • 具有很好的去相关性能量集中
  • 去相关: 变换后的系数为正交频率分量的幅度,幅度之间没有相关性——每个数值可以独立编码(有记忆 ——> 无记忆)
  • 能量集中: 变换系数的能量往往被集中在少数低频样值(幅度大)上,大多数高频样值幅度小——可以非均匀量化(人眼对低频敏感,所以可以对高频粗量化来实现数据压缩)

在JPEG编解码原理中,对每个单独的彩色图像分量,把整个分量图像分成8*8的图像块,如下图所示,并作为二维DCT的输入:
在这里插入图片描述

2.3 量化

  • 采用中平型均匀量化器
  • 因为人眼对亮度信号比对色差信号敏感,因此使用两种量化表:亮度量化值和色差量化值。
  • 根据人眼视觉特性(对低频敏感,对高频不太敏感),对低频分量采取较细的量化,对高频分量采取较粗的量化
  • 人眼对亮度的敏感性如下图所示:
    在这里插入图片描述

2.4 DC系数的差分编码

  • 8 * 8图像块经过DCT变换后得到的DC系数有两个特点:
    系数数值比较大;
    相邻 8 * 8 图像块的DC系数值变化不大——冗余

  • 根据这个特点,JPEG算法使用了DPCM技术,对相邻图像块之间量化DC系数的差值DIFF进行Huffman编码:
    在这里插入图片描述

2.5 AC系数的zizag(z字扫描)

由于经过DCT变换后,系数大多数集中在左上角,即低频分量区,因此采用z字形按频率由低到高的顺序读出,可以出现很多连零的机会。
在这里插入图片描述
可以使用游程编码。尤其在最后,如果都是0,直接给出EOB(end of block)即可。

2.5 AC系数的游程编码

编码要求:
在这里插入图片描述

2.6 AC系数和DC系数的Huffman编码

采用4张Huffman码表:亮度AC、亮度DC、色度AC、色度DC。


3 JPEG码流结构分析

利用JPEGParser分析码流结构。选取的照片为testrgb-2x2.jpg:
在这里插入图片描述
输出文档命名为out.txt。
命令行参数如下图:
在这里插入图片描述
运行程序后,生成了码流结构分析文档:
在这里插入图片描述
分析:
在这里插入图片描述
0xFFD8:表示图像的开始(SOI=Start of Image)
0xFFE0:应用程序保留标记0(APP0)

在这里插入图片描述
0xFFDB:标记着量化表的开始
0xDB后的两个字节,图中为0043,表示量化表的长度
量化表长度的后一个字节,图中为00,表示量化表信息:

bit0-bit3bit4-bit7
量化表号(只能取 0-3,否则错误)量化表精度(0为8bit,否则为16bit)

后面的64个数据为量化表实际信息。
在这里插入图片描述
0xFFDB:标记着第二张量化表的开始(共两张量化表,亮度+色度)。其余信息同上。
在这里插入图片描述
0xFFC0:帧图像的开始(SOF0,start of frame marker),其余信息如下表:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

0xFFC4:Huffman码表开始的标志

0xFFC4后面的第三个字节表示Huffman表类型,上面四张图依次表示DC直流0号表、AC交流0号表、DC直流1号表、AC交流1号表。(其实我们可以通过数据的长短来判断DC和AC,短的自然是DC)

其余信息如下面例子所示:
在这里插入图片描述

在这里插入图片描述
0xFFDA:扫描开始(编码开始)(SOS=Start of Scan)、

在这里插入图片描述
最后,0xFFD9:标记图像结束(EOI=End of Image)


4 JPEG解码流程

4.1 读取文件
4.2 解析 Segment Marker
4.2.1 解析 SOI
4.2.2 解析 APP0
  • 检查标识“JFIF”及版本
  • 得到一些参数
4.2.3 解析 DQT
  • 得到量化表长度(可能包含多张量化表)
  • 得到量化表的精度
  • 得到及检查量化表的序号(只能是 0 - 3)
  • 得到量化表内容(64 个数据)
4.2.4 解析 SOF0
  • 得到每个 sample 的比特数、长宽、颜色分量数
  • 得到每个颜色分量的 ID、水平采样因子、垂直采样因子、使用的量化表序号(与 DQT 中序号对应)
4.2.5 解析 DHT
  • 得到 Huffman 表的类型(AC、DC)、序号
  • 依据数据重建 Huffman 表
4.2.6 解析 SOS
  • 得到解析每个颜色分量的 DC、AC 值所使用的 Huffman 表序号(与 DHT
    中序号对应)
4.3 依据每个分量的水平、垂直采样因子计算 MCU 的大小,并得到每个 MCU 中 8*8宏块的个数
4.4 对每个 MCU 解码(依照各分量水平、垂直采样因子对 MCU 中每个分量宏块解码)
4.4.1 对每个宏块进行 Huffman 解码,得到 DCT 系数
4.4.2 对每个宏块的 DCT 系数进行 IDCT,得到 Y、Cb、Cr
4.4.3 遇到 Segment Marker RST 时,清空之前的 DC DCT 系数
4.5 解析到 EOI,解码结束
4.6 将 Y、Cb、Cr 转化为需要的色彩空间并保存。

5 实验代码分析

5.1 将输出文件保存为可供YUVViewer观看的YUV文件

只需在函数 write_yuv 中增加如下代码即可:
在这里插入图片描述
运行程序:
在这里插入图片描述
成功生成了yuv文件:
在这里插入图片描述
在这里插入图片描述

5.2 三个重要结构体
5.2.1 struct huffman_table
struct huffman_table
{
  /* Fast look up table, using HUFFMAN_HASH_NBITS bits we can have directly the symbol,
   *快查找表
   * if the symbol is <0, then we need to look into the tree table 
   *如果符号小于0,则在慢查找表中查找*/
  short int lookup[HUFFMAN_HASH_SIZE];//得到权值对应的码字
  /* code size: give the number of bits of a symbol is encoded */
  unsigned char code_size[HUFFMAN_HASH_SIZE];//得到权值对应的码长
  /* some place to store value that is not encoded in the lookup table 
   * FIXME: Calculate if 256 value is enough to store all values
   *给出在快查找表中没有出现的码字*/
  uint16_t slowtable[16-HUFFMAN_HASH_NBITS][256];
};

用来存储哈夫曼码表,分为快查找表和慢查找表,主要目的是提高解码效率。

5.2.2 struct component
struct component 
{
  unsigned int Hfactor;//水平采样情况
  unsigned int Vfactor;//垂直采样情况
  float *Q_table;		/* Pointer to the quantisation table to use 指向量化表的指针*/
  struct huffman_table *AC_table;//指向AC Huffman表
  struct huffman_table *DC_table;//指向DC Huffman表
  short int previous_DC;	/* Previous DC coefficient 前一个DC系数*/
  short int DCT[64];		/* DCT coef DCT系数*/
#if SANITY_CHECK
  unsigned int cid;
#endif
};

用来保存一个MCU(最小结构单元)的信息,每处理完一个MCU,值都会更新。

5.2.3 struct jdec_private
struct jdec_private
{
  /* Public variables */
  uint8_t *components[COMPONENTS];
  unsigned int width, height;	/* Size of the image */
  unsigned int flags;

  /* Private variables */
  const unsigned char *stream_begin, *stream_end;
  unsigned int stream_length;

  const unsigned char *stream;	/* Pointer to the current stream */
  unsigned int reservoir, nbits_in_reservoir;

  struct component component_infos[COMPONENTS];//每个通道的信息
  float Q_tables[COMPONENTS][64];		/* quantization tables 3张量化表,实际只使用2张(亮度+色度) */
  struct huffman_table HTDC[HUFFMAN_TABLES];	/* DC huffman tables 4张DC Huffman码表,实际只用2张(亮度+色度) */
  struct huffman_table HTAC[HUFFMAN_TABLES];	/* AC huffman tables 4张AC Huffman码表,实际只用2张(亮度+色度) */
  int default_huffman_table_initialized;
  int restart_interval;
  int restarts_to_go;				/* MCUs left in this restart interval */
  int last_rst_marker_seen;			/* Rst marker is incremented each time */

  /* Temp space used after the IDCT to store each components */
  uint8_t Y[64*4], Cr[64], Cb[64];//解码后的信息

  jmp_buf jump_state;
  /* Internal Pointer use for colorspace conversion, do not modify it !!! */
  uint8_t *plane[COMPONENTS];

};

定义了指向三个components的指针和三个components结构体;定义了图像的宽高、码流长度、始末指针,还有三张量化表(实际只用到两张,亮度+色度)、DC Huffman表和AC Huffman表各四张(实际各用两张:亮度DC、亮度AC、色度DC、色度AC)。

5.3 Trace的目的

Trace主要用于输出各种中间变量,将Trace设置为1时打开,设置为0时关闭。

#define TRACE 1
5.4 以txt文件输出所有的量化矩阵和所有的HUFFMAN码表

将Trace打开,运行程序后,我们发现已经可以输出所有Huffman码表。
部分Huffman码表截图:
在这里插入图片描述
所以,我们需要增加代码,让它可以输出所有量化表:

  1. tinyjpeg.h 中增加量化表的文件指针
    在这里插入图片描述
  2. loadjpeg.c的主函数中增加如下代码,将量化表信息写入txt文件:
    在这里插入图片描述
  3. tinyjpeg.c中添加如下代码
    函数 build_quantization_table() 中:
    在这里插入图片描述
    函数 parse_DQT
    在这里插入图片描述
    运行loadjpeg.c,发现 quantization_table.txt 已经生成:
    在这里插入图片描述
    在这里插入图片描述
5.5 输出DC图像和AC图像

增加如下代码来实现:
tinyjpeg.h中定义文件指针:
在这里插入图片描述
宏定义文档名:
在这里插入图片描述
在tinyjpeg.c中,开缓冲区:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
loadjpeg.c的main函数中:
在这里插入图片描述
在这里插入图片描述
运行结果:
在这里插入图片描述

5.6 统计DC图像和AC图像的概率分布

调用数据压缩作业1-2中的代码,将文件目录和文件大小修改一下,统计概率分布。

  1. DC图像
    在这里插入图片描述

在这里插入图片描述
利用Excel画图:
在这里插入图片描述

  1. AC图像
    在这里插入图片描述

在这里插入图片描述
利用Excel画图:
在这里插入图片描述
从对比可以看出,DC图像的方差更大,信息熵更大,包含着更多的图像信息。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值