1、任务说明

  将LENA图像用JPEG方式压缩。

2、算法原理

  JPEG(Joint Photographic Experts Group)是一个由ISO和IEC两个组织机构联合组成的一个专家组,负责制定静态

的数字图像数据压缩编码标准,这个专家组开发的算法称为JPEG算法,并且成为国际上通用的标准,因此又称为JPEG标准。

JPEG是一个适用范围很广的静态图像数据压缩标准,既可用于灰度图像又可用于彩色图像。

  JPEG专家组开发了两种基本的压缩算法,一种是采用以离散余弦变换(Discrete Cosine Transform,DCT)为基础的

有损压缩算法,另一种是采用以预测技术为基础的无损压缩算法。JPEG压缩是有损压缩,它利用了人的视角系统的特性,使用

量化和无损压缩编码相结合来去掉视角的冗余信息和数据本身的冗余信息。JPEG算法框图如图:

其中,压缩算法的主要步骤如下:

1)        正向离散余弦变换(FDCT)

  通过离散余弦变换,空间域表示的图可以变换成频率域表示的图。离散余弦变换的公式如图所示:

  然而,这种变换方式时间复杂度很高,会占用程序的运行时间。因此,在这里我们使用DCT的矩阵变换公式替代之。

余弦变换矩阵C满足:

            

  此时,设C的转置矩阵为 ,则离散余弦变换公式可以表示为:

                  

  其中,P为像素矩阵。使用余弦变换矩阵可以大大的减少离散余弦变换的运算时间。值得注意的是,在离散余弦变换矩阵

变换公式中,我们添加了sqrt(1/N)这个成分。该成分的作用是,将是变换矩阵C成为一个正交矩阵。因此,我们有:

  那么,在解压缩过程中,我们同样可以使用离散余弦变换矩阵实现逆向的离散余弦变换。

             

2)        量化

  量化是对经过FDCT变换后的频率系数进行量化。量化的目的是减小非“0”系数的幅度以及增加“0”值系数的数目。量化是

图像质量下降的最主要原因。量化过程的公式可以表示为:

    量化后的值(i,j) = ROUND(DCT(i,j)/量子(i,j));

逆量子化公式则为:

DCT(i,j) = 量化后的值(i,j)*量子(i,j);

  其中,量子由对应的量子表得到。一种常用的亮度和色度量子表是:

    

  这种表对于CCIR 601标准的电视图像是最佳的。我们还可以定义自己的量子表,或者借鉴量子表公式:

        

  对应不同的quality值,图像也会产生不同的压缩效果,具体将在实验中进行展示。

3)        Z字形编排

  经过后FDCT和量子化变化之后的系数矩阵,会呈现左上角系数较大,而右下方0居多的趋势。为了达到压缩的效果,我们对系数

矩阵进行Z字形编排。编排后的系数数组,连续的0系数增多,成为一个1*64位的矢量,频率低的系数位于矢量的顶部。

            

  则系数矩阵对应矢量数组的顺序为:

0

1

5

6

14

15

27

25

2

4

7

13

16

26

29

42

3

8

12

17

25

30

41

43

9

11

18

24

31

40

44

53

10

19

23

32

39

45

52

54

20

22

33

38

46

51

55

60

21

34

37

47

50

56

59

61

35

36

48

49

57

58

62

63

4)        直流与交流系数的编码

  8×8图像块经过DCT变换之后得到的DC直流系数有两个特点,一是系数的数值比较大,二是相邻8×8图像块的DC系数值变化不大。根据这个特点,JPEG算法使用了差分脉冲调制编码(DPCM)技术,对相邻图像块之间量化DC系数的差值(Delta)进行编码。

  量化AC系数的特点是1×64矢量中包含有许多“0”系数,并且许多“0”是连续的,因此使用非常简单和直观的游程长度编码(RLE)对它们进行编码。
  JPEG使用了1个字节的高4位来表示连续“0”的个数,而使用它的低4位来表示编码下一个非“0”系数所需要的位数,跟在它后面的是量化AC系数的数值。

5)       
熵编码

  为了进一步的压缩图像,我们还可以使用熵编码,一般使用霍夫曼编码劳减少熵。

  以上为图像压缩过程的主要步骤。相对应的,解压缩过程为解码,Z字形编排回复,逆量子化,逆向离散余弦变换。

3、主要算法实现

1)        离散余弦变换

public class FDCT {
int max = 512;
double[][] C = new double[max][max];
double[][] Ct = new double[max][max];
double[][] temp1 = new double[max][max];
double[][] temp2 = new double[max][max];
SquareMul sm = new SquareMul(); //正向离散余弦变换
double[][] calculateF(double[][] pixel,int size)
{
int i,j; //计算余弦变换矩阵
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
double valueC;
if(i==0)
valueC = (double)1.0/(Math.sqrt(size));
else
{
valueC = Math.sqrt(2.0/size)*Math.cos((2*j+1)*i*Math.PI/(2*size));
}
C[i][j]=Ct[j][i]=valueC;
}
} sm.mul(C, pixel,temp1, size);
sm.mul(temp1, Ct,temp2, size); return temp2;
} //使用已有的离散余弦变换矩阵,完成逆向离散余弦变换
double[][] calculateB(double[][] pixel,int size)
{
sm.mul(Ct, pixel,temp1, size);
sm.mul(temp1, C,temp2, size); return temp2;
}
}

  

2)        量子化

public class Quantum {
//默认的量化矩阵
int[][] stdQuan={
{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}
}; //根据quality值生成量化矩阵
int quancal(int quality,int i,int j)
{
if(quality==0)
return stdQuan[i][j];
else
return (1+((1+i+j)*quality));
} //对像素矩阵进行量化
double[][] calculateF(double pixel[][],int size,int quality)
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
pixel[i][j]/=quancal(quality,i,j);
pixel[i][j]=Math.round(pixel[i][j]);
}
}
return pixel;
} //对矩阵进行逆向量子化
double[][] calculateB(double pixel[][],int size,int quality)
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
pixel[i][j]*=quancal(quality,i,j);
}
}
return pixel;
}
}

  

3)        Z字形编排

public class zCode {
int size = 8;
int zlength = 64;
//将矩阵Z字形编排
void zEncode(double[][] curM,double[] zpix)
{
int zct,i,j,fck;
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
zct=i+j;
if(zct>7)
{
zct=14-zct;
fck=7-j;
}
else
fck=j; if((i+j)%2==0)
{
zct = (1+zct)*zct/2+fck;
}
else
{
zct++;
zct = (1+zct)*zct/2-fck-1;
}
if((i+j)>7)
zpix[63-zct] = curM[i][j];
else
zpix[zct] = curM[i][j];
}
}
} //将系数数组回复为矩阵形式
void zDecode(double[][] curM,double[] zpix)
{
int zct,i,j,fck;
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
zct=i+j;
if(zct>7)
{
zct=14-zct;
fck=7-j;
}
else
fck=j; if((i+j)%2==0)
{
zct = (1+zct)*zct/2+fck;
}
else
{
zct++;
zct = (1+zct)*zct/2-fck-1;
}
if((i+j)>7)
curM[i][j] = zpix[63-zct];
else
curM[i][j] = zpix[zct];
}
} }
}

  

4)        分割图像

bi = ImageIO.read(f);
int size = bi.getWidth();
//将图像分割成若干个8*8矩阵
int iternum = size/8;
FandB fb = new FandB();
for(int i=0;i<iternum;i++)
{
for(int j=0;j<iternum;j++)
{
int code = i*64+j;
fb.comF(code, pixels,zpixels[code]);
}
}

  

4、实验

       源图像                                 默认量子表

           quality=5                              quality=10

quality=30

  随着quality值增大,量子化矩阵中的值也相应增大,那么在量子化后的矩阵中将会有更多的0系数。经过熵编码我们得到的压缩格式也越小。与此同时,quality增大也使图像的质量明显下降。

【图像处理】第三次实验:JPEG图像压缩的更多相关文章

  1. 20145224&20145238 《信息安全系统设计基础》 第三次实验

    20145224&20145238 <信息安全系统设计基础>第三次实验 课程:信息安全系统设计基础 班级:1452 姓名:陈颢文 荆玉茗 学号:20145224 20145238 ...

  2. 20145330Java程序设计第三次实验

    20145330<Java程序设计>第三次实验报告 实验三 敏捷开发与XP实践 实验内容 1.使用git上传代码 2.使用git实现代码开发实践 3.实现代码的重载 实验步骤 使用git上 ...

  3. 20145320《Java程序设计》第三次实验报告

    20145320<Java程序设计>第三次实验报告 北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1453 指导教师:娄嘉鹏 实验日期:2016.04.22 15: ...

  4. Linux第三次实验报告

    北京电子科技学院(BESTI) 实     验    报     告 课程:信息安全系统设计基础             班级:201352 姓名:池彬宁 贺邦 学号:20135212 2013520 ...

  5. 南京邮电大学java第三次实验报告

    实 验 报 告 ( 2017 / 2018学年 第2学期) 课程名称 JAVA语言程序设计 实验名称 Java集成开发环境的安装与使用. Java变量.表达式与控制结构 实验时间 2018 年 4 月 ...

  6. Java第三次实验敏捷开发与XP实验

    实验三-1 1.实验要求: 实验三 敏捷开发与XP实践 http://www.cnblogs.com/rocedu/p/4795776.html, Eclipse的内容替换成IDEA 参考 http: ...

  7. java第三次实验报告

    北京电子科技学院(BESTI) 实验报告 课程: Java程序设计 班级: 1352 姓名: 池彬宁 学号: 20135212 成绩: 指导教师: 娄嘉鹏 实验日期: 2015.6.3 实验密级: 无 ...

  8. 20162327WJH第三次实验——查找与排序2

    20162327WJH第三次实验--查找与排序2 实 验 报 告 课程:程序设计与数据结构 班级: 1623 姓名: 王旌含 学号:20162327 成绩: 指导教师:娄嘉鹏 王志强 实验日期:11月 ...

  9. 20155210 潘滢昊 Java第三次实验

    Java第三次实验 实验内容 在IDEA中使用工具(Code->Reformate Code)把代码重新格式化 在码云上把自己的学习搭档加入自己的项目中,确认搭档的项目加入自己后,下载搭档实验二 ...

  10. 20155217 《Java程序设计》第三次实验报告

    20155217 <Java程序设计>第三次实验报告 实验内容 XP基础 XP核心实践 相关工具 实验要求 没有Linux基础的同学建议先学习<Linux基础入门(新版)>&l ...

随机推荐

  1. ruby Matrix 输出 格式化

    require 'matrix' class Matrix def to_pretty_s s = "" i = 0 while i < self.column_size s ...

  2. ElasticSearch 嵌套映射和过滤器及查询

    ElasticSearch - 嵌套映射和过滤器 Because nested objects are indexed as separate hidden documents, we can’t q ...

  3. .net使用mvc模式开发web应用 模型与视图间的数据处理

    http://www.cnblogs.com/JeffreyZhao/archive/2009/02/27/mvc-use-strong-type-everywhere.html#3427764 本文 ...

  4. 百度自动发贴,登录很顺利的模拟实现,但发贴攻关失败,能力有限,追JS过程中颇为痛苦

    攻关失败,且短期内看不到希望,看不到方向,且越来越焦急,目前已知的是,用根据用户的鼠标事件以一定的规则结合其他数据,服务器以这些数据验证是否为真正的手动发贴. 不过闲暇时实现了百度贴吧的自动签到. 较 ...

  5. C#中的问号

    本人转载自: ①http://msdn.microsoft.com/zh-cn/practices/dd391752.aspx ②http://jhxk.iteye.com/blog/439888 在 ...

  6. 自定义指令directive

    1.自定义指令 在angular中,module下面的directive方法用于创建自定义指令,用法: m1.directive('myTab',function(){ return { restri ...

  7. EF6配合MySQL或MSSQL(CodeFirst模式)配置指引

    一.新建一个解决方案,包含两个项目:EF6CodeFirstMySQL.Model(动态库项目),EF6CodeFirstMySQL.Tests(控制台应用) 二.通过NuGet将EntityFram ...

  8. 一些PHP性能的优化

      PHP优化对于PHP的优化主要是对php.ini中的相关主要参数进行合理调整和设置,以下我们就来看看php.ini中的一些对性能影响较大的参数应该如何设置. # vi /etc/php.ini ( ...

  9. KindleEditor上传文件报404

    初步怀疑是iis配置的允许上传大小太小了,然后就修改了配置文件但是不起作用. 后来百度了下iis版本是7.5,然后就按照iis8 的配置: IIS8请求筛选模块被配置为拒绝超过请求内容长度,在&quo ...

  10. (转)linux下cp目录时排除一个或者多个目录的实现方法

    原文链接:http://www.jb51.net/LINUXjishu/88971.html 说明:/home目录里面有data目录,data目录里面有a.b.c.d.e五个目录,现在要把data目录 ...