JPEG图像压缩算法流程详解

JPEG代表Joint Photographic Experts Group(联合图像专家小组)。此团队创立于1986年,1992年发布了JPEG的标准而在1994年获得了ISO10918-1的认定。

JPEG是一种有损压缩。

色彩空间转换

图片由RGB色彩空间转换到YUV色彩空间,转换关系如下

一般来说U,V是有符号的数字,但这里通过加上128,使其变为无符号数,方便存储和计算

采样

研究发现,人眼对亮度变换的敏感度比色彩变换的敏感度高。因此,可以认为Y分量比U,V分量更为重要。故采样时通常会降低U,V分量的采样率,这里采用411采样方式,即Y,U,V三个分量的取样比例为4:1:1,其含义为在2*2的单元中,Y分量采样4次,U,V分量各采样一次。这样采样的优点是虽然损失了一定精度,但也在人眼几乎不可见的前提下减小了数据存储量。

分块

DCT变换是对8 * 8的子块进行处理的,且U,V分量在2 * 2的单元中采样一次,故在DCT变换之前将原图像长宽分别用0补齐到16的倍数。之后再对Y,U,V三个分量分别分为8*8的块便进行后续操作。

离散余弦变换

离散余弦变化的公式为

其中

由于已经明确每次进行离散余弦变化的矩阵大小为8*8,故这里不再采用上述方法进行离散余弦变换,而是利用DCT变换矩阵实现DCT变换以降低运算量。

DCT变换矩阵计算公式为

故8*8的DCT变换矩阵

其转置矩阵

DCT可简化为T * B * T',其中B为8*8的原矩阵。

实施二维DCT可将图像的能量集中在极少的几个系数之上,其他系数相比于这些系数,绝对值要小很多。这些系数大都集中在左上角,即低频分量区。

数据量子化

量子化是JPEG算法中损失图像精度的根源, 也是产生压缩效果的源泉。

人类眼睛在一个相对大范围区域,辨别亮度上细微差异是相当的好,但是在一个高频率亮度变动之确切强度的分辨上,却不是如此地好。这个事实让我们能在高频率成分上极佳地降低信息的数量。简单地把频率领域上每个成分,除以一个对于该成分的常量就可完成,且接着舍位取最接近的整数。这是整个过程中的主要有损运算。以这个结果而言,经常会把很多更高频率的成分舍位成为接近0,且剩下很多会变成小的正或负数。

JPEG提供的量子化算法如下

其中G是我们需要处理的图像矩阵,Q称作量化系数矩阵 ,round函数是取整函数。JPEG算法提供了两张标准的量化系数矩阵,分别用于处理亮度数据Y和色差数据U以及V。

标准亮度量化表

标准色差量化表

DCT系数矩阵中的不同位置的值代表了图像数据中不同频率的分量,这两张表中的数据时人们根据人眼对不不同频率的敏感程度的差别所积累下的经验制定的,一般来说人眼对于低频的分量比高频分量更加敏感,所以两张量化系数矩阵左上角的数值明显小于右下角区域。 这样就使得量化后的矩阵更多地保留高频信息。

量化后的一个8*8矩阵:

通常一张图片中的一个8*8矩阵经过上述变化之后,矩阵都如上矩阵一样,其中的一大部分数据都会变成0,这非常有利于后面数据的压缩。

编码

差值编码和Zig-zag扫描

量化后矩阵左上角的值被称为直流分量DC,其他63个值被称为交流分量AC。其中DC不参与Z字形扫描,而是与前一矩阵的DC系数进行差分编码(DPCM);AC分量则采用Z字形扫描排列并进行游程长度编码(RLE)。

游程长度编码(Run-Length Encoding, RLE)

量化AC系数的特点是包含很多连续的0,故使用RLE对其进行编码。JPEG使用了1个字节的高4位来表示连续的0的个数,而使用其低四位来表示下一个非0系数需要的位数,紧随其后的是量化AC系数的值。

假设Zig-zag​扫描后的一组向量的AC​分量为

经RLE压缩后如下

其中EOB表示后面都是0。实际上,用(0,0)表示EOB。若这组数字不以0结束,则不需要EOB

Huffman编码

JEPG压缩编码时,通过查表实现霍夫曼编码器,本次实验中我使用了ISO/IEC International Standard 10918-1中JPEG推荐的典型霍夫曼表(Typical Huffman tables),我已经将4张表格发表在个人博客,篇幅所限这里就不再给出了。

之所以需要四张Huffman 编码表是因为,编码时每个矩阵数据的1个DC值与63个AC值分别使用不同的Huffman 编码表,而且亮度Y与色度U,V也要使用不同的Huffman 编码表。

为提高储存效率,JEPEG里并不直接保存数值,而是将数值按实际值所需要的位数分成16组,如下表所示

Value Size Bits
0 0 -
-1, 1 1 0, 1
-3, -2, 2, 3 2 00, 01, 10, 11
-7, -6, -5, -4, 4, 5, 6, 7 3 000, 001, 010, 011, 100, 101, 110, 111
-15, …, -8, 8, …, 15 4 0000, …, 0111, 1000, …, 1111
-31, …, -16, 16, …, 31 5 0 0000, …, 0 1111, 1 0000, …, 1 1111
-63, …, -32, 32, …, 63 6 00 0000, …, …, 11 1111
-127, …, -64, 64, …, 127 7 000 0000, …, …, 111 1111
-255, …, -128, 128, …, 255 8 0000 0000, …, …, 1111 1111
-511, …, -256, 256, …, 511 9 0 0000 0000, …, …, 1 1111 1111
-1023, …, -512, 512, …, 1023 10 00 0000 0000, …, …, 11 1111 1111
-2047, …, -1024, 1024, …, 2047 11 000 0000 0000, …, …, 111 1111 1111
-4095, …, -2048, 2048, …, 4095 12 0000 0000 0000, …, …, 1111 1111 1111
-8191, …, -4096, 4096, …, 8191 13 0 0000 0000 0000, …, …, 1 1111 1111 1111
-16383, …, -8192, 8192, …, 16383 14 00 0000 0000 0000, …, …, 11 1111 1111 1111
-32767, …, -16348, 16348, …, 32767 15 000 0000 0000 0000, …, …, 111 1111 1111 1111

设一个一维化后的亮度的数据块为

其中第一个数字代表本数据块DC值与前一数据块DC值之差为5。

那么RLE压缩后的data变为

其中EOB = (0,0)。

对data'中每个数对的第二个数v求对应的s值,并将s置于数对中v之前,得到data''

其中第一个数对为DC分量运算得到的结果。

由于假设该以为数据由亮度数据块变换得来,因此对于DC和AC分量,分别对data''数对中的第一个数字查Huffman DC亮度表和Huffman AC亮度表,再对数对中的第二个数字查上表,即可得到一维数据块data编码后的序列。data''查表得结果为

其中的标点是为了方便对照,实际编码中没有标点。

压缩比

最终共用70973bit保存压缩后的数据,压缩前的数据大小为256 * 256 * 8+256 * 256/4 * 2 * 8 = 786432bit,故压缩比为70973/786432 * 100% =9.02% 。

解码

解码过程为编码过程的逆过程,这里不再赘述。

解码后的图片与原图片比较

原图片

经过编码、解码的图片

可以看出,处理后的图片与原图片有一定差异,推测差异是在量化和反量化过程中产生的。

代码链接

JPEG图像压缩算法流程详解的更多相关文章

  1. JPEG文件编/解码详解

    JPEG文件编/解码详解(1) JPEG(Joint Photographic Experts Group)是联合图像专家小组的英文缩写.它由国际电话与电报咨询委员会CCITT(The Interna ...

  2. FFmpeg开发笔记(五):ffmpeg解码的基本流程详解(ffmpeg3新解码api)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  3. C++的性能C#的产能?! - .Net Native 系列《二》:.NET Native开发流程详解

    之前一文<c++的性能, c#的产能?!鱼和熊掌可以兼得,.NET NATIVE初窥> 获得很多朋友支持和鼓励,也更让我坚定做这项技术的推广者,希望能让更多的朋友了解这项技术,于是先从官方 ...

  4. [nRF51822] 5、 霸屏了——详解nRF51 SDK中的GPIOTE(从GPIO电平变化到产生中断事件的流程详解)

    :由于在大多数情况下GPIO的状态变化都会触发应用程序执行一些动作.为了方便nRF51官方把该流程封装成了GPIOTE,全称:The GPIO Tasks and Events (GPIOTE) . ...

  5. 迅为4412开发板Linux驱动教程——总线_设备_驱动注册流程详解

    本文转自:http://www.topeetboard.com 视频下载地址: 驱动注册:http://pan.baidu.com/s/1i34HcDB 设备注册:http://pan.baidu.c ...

  6. Linux启动流程详解【转载】

    在BIOS阶段,计算机的行为基本上被写死了,可以做的事情并不多:一般就是通电.BIOS.主引导记录.操作系统这四步.所以我们一般认为加载内核是linux启动流程的第一步. 第一步.加载内核 操作系统接 ...

  7. iOS 组件化流程详解(git创建流程)

    [链接]组件化流程详解(一)https://www.jianshu.com/p/2deca619ff7e

  8. git概念及工作流程详解

    git概念及工作流程详解 既然我们已经把gitlab安装完毕[当然这是非必要条件],我们就可以使用git来管理自己的项目了,前文也多多少少提及到git的基本命令,本文就先简单对比下SVN与git的区别 ...

  9. Lucene系列六:Lucene搜索详解(Lucene搜索流程详解、搜索核心API详解、基本查询详解、QueryParser详解)

    一.搜索流程详解 1. 先看一下Lucene的架构图 由图可知搜索的过程如下: 用户输入搜索的关键字.对关键字进行分词.根据分词结果去索引库里面找到对应的文章id.根据文章id找到对应的文章 2. L ...

随机推荐

  1. 2017-2018-2 20155315《网络对抗技术》Exp1:PC平台逆向破解

    实验目的 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序同时包含另一个代码片段,getShe ...

  2. Laravel 跨框架队列交互

    公司大部分项目是laravel框架,但有些是yii框架,这两个框架之间有消息需要通信,比如在yii框架发布消息,laravel框架中的队列去处理,用redis作为消息连接纽带 laravel 队列原理 ...

  3. 我用 Python 爬取微信好友,最后发现一个大秘密

    前言 你身处的环境是什么样,你就会成为什么样的人.现在人们日常生活基本上离不开微信,但微信不单单是一个即时通讯软件,微信更像是虚拟的现实世界.你所处的朋友圈是怎么样,慢慢你的思想也会变的怎么样.最近在 ...

  4. rabbitMQ的三种路由模式

    rabbitMQ工作流程: 1.声明交换机 2.声明消息队列 3.绑定交换机和队列 4.生产者往交换机里发送新消息 5.交换机根据所选的模式和routingKey决定消息发往哪条消息队列 6.一个消费 ...

  5. Frida----frida tools的使用

    翻译自官方网站:https://www.frida.re/docs/home/ 如果有理解不对的地方,请大家指出 frida Cll frida -U 包名 调试连接到电脑上设备中的应用 frida ...

  6. 获取本地ip和获取公网ip

    import socket def get_local_ip(): ''' 获取本地ip地址 :return: ''' s = socket.socket(socket.AF_INET, socket ...

  7. DQL、DML、DDL、DCL全名是啥?

    SQL(Structure Query Language)结构化查询语言 DQL(data query language)数据查询语言 select操作 DML(data manipulation l ...

  8. python清空列表的方法

    1.大数据量的list,要进行局部元素删除,尽量避免用del随机删除,非常影响性能,如果删除量很大,不如直接新建list,然后用下面的方法释放清空旧list. 2.对于一般性数据量超大的list,快速 ...

  9. 安装配置php

    安装PHP       1.安装PHP       yum install php   #根据提示输入Y直到安装完成        2.安装PHP组件,使PHP支持 MySQL.PHP支持FastCG ...

  10. VS AI 手写数字识别应用

    看过我上一篇文章的朋友应该知道,我用VS训练出了minst模型.output目录中有.pb文件. 关于.pb文件的介绍见[参考链接] (https://stackoverflow.com/questi ...