Skip to content

JPEG图像压缩在STM32平台的实现,包含主要算法,但未创建文件信息部分,不是严格意义上的JPEG。

Notifications You must be signed in to change notification settings

HuffieWang/STM32F4-JPEG

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

简介

硬件

  主控芯片:STM32F407ZET6

  拓展内存:IS62WV51216BLL(1Mbyte)

  液晶显示:ILI9341彩屏(320*240像素)

  原图信息:320*240像素、RGB565模式的lenna局部图

算法

  颜色模式:YUV444

  压缩算法:DCT变换

  编码方法:行程编码、霍夫曼编码

算法原理及实现

数据分块

  将320x240图像数据划分为1200个8x8的数据块。

原因

  JPEG是以每8x8个点为一个单元进行处理的,即将一个单元做完格式转换、DCT变换、量化、编码等全部处理后,再操作下一个单元。所以需要将图像进行分块。

实现

  按从左到右、从上到下的顺序从原数据中取出8x8的数据,依次存放在64长度的数组中。

    for(m = 0; m < 8; m++)
        for(n = 0; n < 8; n++)
            temp[m*8+n] = image[(i*8+m)*240+j*8+n];

  对全图进行8x8的分块处理,暂时左上角部分的8x8块为后面的处理作准备。

Alt Text

颜色模式转换

  将RGB565模式的原图像转换为YUV444模式。RGB565模式由Red(红)、Green(绿)、Blue(蓝)三个分量按5:6:5共16bit组成,YUV444模式由Y(亮度)、U(色度)、V(饱和度)三个分量按8:8:8共24bit组成。 ###原因   研究发现,人眼对亮度变换的敏感度要比对色彩(色度和饱和度)变换的敏感度高出很多。利用这个特性,我们可以对YUV模式的图像进行亮度权重较高、色度权重较低的采样,得到数据量更小的图片,同时损失的精度又不易被人眼察觉。YUV常用的采样比例有4:1:1和4:2:2等,下图为YUV411采样。

Alt Text

  RGB模式显然不具备YUV这种采样优势,所以需要对其进行转换。本设计中因为在4:4:4采样时的压缩率已达成设计要求,所以暂时采用YUV444来保证最好的图像质量。

实现

  因原始图像为RGB565格式,所以需先将其分离为8位的red、green、blue分量,C语言实现方法如下。

     red = (rgb565 & 0xF800) >> 8;   
     green = (rgb565 & 0x07E0) >> 3;
     blue = (rgb565 & 0x001F) << 3;

  又因后续的DCT变换所能处理的数值范围为-127~+127,所以需将RGB转YUV得的到数值均减去128。

     Y = 0.299f*red + 0.587f*green + 0.114f*blue - 128; 
     U = -0.1687f*red - 0.3313f*green + 0.5f*blue;             
     V = 0.5f*red - 0.418f*green - 0.0813f*blue; 

  对图像的第一个8x8数据块进行上述格式转换,得到其亮度、色度、饱和度三层数据,这里只选取其亮度层作为展示,后续的一系列处理均以此8x8亮度层数据为例。

Alt Text

DCT变换

  将8x8的图像数据变换为8x8的频域系数矩阵。

原因

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

实现

  DCT变换公式:

  DCT变换相关代码见本项目的User\JPEG\hnit_jpeg.c"jpeg_dct2"

  图像信号通过DCT被分解为直流成分和一些从低频到高频的各种余弦成分。而DCT系数只表示了该种成分所占原图像信号的份额大小。例如,U=0,V=0时的F(0,0)是原来的64个数据的均值,相当于直流分量,也有人称之为DC系数或者直流系数。随着U,V的增加,相另外的63个系数则代表了水平空间频率和垂直空间频率分量(高频分量)的大小,多半是一些接近于0的正负浮点数,我们称之为交流系数AC。DCT变换后的8x8的系数矩阵中,低频分量集中在矩阵的左上角。高频成分则集中在右下角。

Alt Text

量化

  将8x8的频域系数矩阵按照量化表进行量化。

原因

  原因有三点。其一,去掉部分高频分量,因为我们要保留低频分量,适当去掉高频分量来压缩数据;其二,减小数据的数值大小,在压缩方面,小数值的数据一般比大数值的更有优势;其三,化浮点型为整型,方便后面的编码处理。

实现

  首先我们需要一张8x8的量化矩阵,以下是常用的一张根据心理阀制作的量化表,当然也可以按照需要自行编写。

Alt Text

  将频域系数矩阵点除量化矩阵,即可完成量化,结果如下,可见出现了大量的0,尤其是右下方的高频部分。

Alt Text

排序

说明

  将量化后的数据按照Z形重新排序,一般称其为Zigzag排序。

原因

  在上一步得到的频域数组中的数据是按从左到右、从上到下的顺序存放的。但频域中从低频到高频的顺序应为下表所示,最低频位于左上角,最高频位于右上角。所以需对其进行重排序,使其内存存储顺序和频率增长顺序一致。这样做会使有效的数据更为紧凑,尾部出现更多的连零。

Alt Text

实现

  因为排序的数据量较小,只有64个,所以出于实现难度和运行速度的考虑,设计中使用查表法完成Zigzag排序。

    for(i = 0; i < 64; i++)
        temp[zigzag_code[i]] = data[i]; 

  代码中的zigzag_code为上图排序表,排序后的结果如下,频率增长方向已用不同深度的灰色标出。可见,原数据从第一个数据'-8'开始到最后一个不为0的数据'1'需要9个长度,已用下划线标出,而排序后则只需要6个长度。

Alt Text

行程编码

  将排序后的数据进行针对连零的行程编码。

原因

  利用该编码方式,可以将包含大量连零的数据块用几个行程数据包来替代。因为Zigzag排序后的数据出现了很多连零,所以用此方法可以很好的压缩数据长度。

实现

  每个行程数据包有三个字节,第一个字节为出现“非零数据”前的连零数量,若出现超过15个连零,则用一个额外的包(15,0,0)表示;第二个字节为该“非零数据”的绝对值的二进制位数,例如'-8'的绝对值'8'的二进制"1000"为4位,则该字节的值为4;第三个字节为该“非零数据”的值'-8'。(3,4,-8)代表本次查询到的非零数据为'-8',是4位的,前面有3个连零,还原后为'0','0','0','-8'。

  行程编码的相关代码见本项目的User\JPEG\hnit_jpeg.c"jpeg_rle"。

  编码后的结果如下所示,共得到4组有效数据包和1组编码结束数据包,已用不同深度的灰色标出。

Alt Text

霍夫曼编码

  将行程编码进行已知霍夫曼表的霍夫曼编码。

原因

  利用该编码方式,可以为出现概率较大的行程码分配较短的霍夫曼码字,给概率较小的分配较长的码字,借此达到最小平均码长。又因为霍夫曼码基于二叉树而得,所以将二进制的数据流逐位解码总能得到唯一的子码,这样使得解码很方便。

实现

  为编解码方便和获得较快的编解码速度,本设计使用一张根据经验得出的霍夫曼表来进行编码和解码。行程码的前两字节(m,n)值域范围为(0,0)~(15,0)共151种组合,分别对应表中的151个霍夫曼码,对应关系为i=mx10+n。以下是从霍夫曼表截取的一部分。

  编码分两步进行,以(0,4,-8)举例。第一步,查找到(0,4)对应的霍夫曼码(4)为"1011",将其编入数据流;第二步,将'-8'编入数据流,'8'的二进制"1000",因为它是负数,所以需将"1000"的最高位置'0'得"0000",最终编码后的结果为"1011 0000"。

  行程编码的相关代码见本项目的User\JPEG\hnit_jpeg.c"jpeg_huffman"。

  编码后的结果如下所示,霍夫曼码为白色背景,4个实际值为不同深度的灰色背景。

Alt Text

解码还原

  逆向进行以上步骤即可完成解码和还原,相关代码见本项目的User\JPEG\hnit_jpeg.c。

  原频域数据和还原后的频域数据对比。

Alt Text

  原图像数据和还原后的图像数据对比。

Alt Text

About

JPEG图像压缩在STM32平台的实现,包含主要算法,但未创建文件信息部分,不是严格意义上的JPEG。

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published