目录

为什么写这篇文章:

一、傅里叶变换简介

二、DCT是什么

三、DCT在图像有损压缩中的应用

1、图像有损压缩的依据点:

2、使用DCT进行图像有损压缩的具体操作:

3、使用IDCT进行图像解压缩的具体操作:

三、DCT算法的Java实现_AndroidDemo的Gitee地址:

四、libjpeg中对应的DCT代码实现:

五、引用资料:


为什么写这篇文章:

因为自从作为安卓客户端开发以来,开始接触到一些音频视频、图像处理方面的知识,逐渐激发了对其浓厚的兴趣,因此希望能从最底层的理论上开始学习并形成对它们的相关理论的个人理解,只有对这些底层数学知识和工程知识有充分的理解,才有可能未来成为该领域的专家,并做出自己的创新,而不是一直被别人的SDK牵着鼻子走。

另外,其实作为一名Android客户端开发,假如有一天Android不行了,那么在安卓SDK的调用上积累的大部分经验就完全清0,我认为这对整个职业生涯是非常有害的,因此我认为我无论是处于兴趣,还是居安思危,我都必须去学知识架构比较稳定的知识。此时我发现如果结合兴趣来看的话,音频、视频、编解码、图形图像和AI是最接近我所想要的知识领域,他们都基于数学和物理的定理,不会像前端框架、客户端各种轮子、后端Spring框架等基于别人轮子上存活的领域那样很容易被推翻后,整个知识领域被推倒重来,所有花进去的时间随着框架的更新而再次变得从0开始,这就是不稳定的知识领域。但稳定的知识领域,无论是嵌入式、硬件开发、游戏开发、图形图像其知识是稳定可叠加的,每累积多一点知识,技能就增强一分,例如从普通的基于法线向量的光照,再到光线追踪,用到的数学知识都是相近的,都是三角函数为主,最多就是多了概率而已,然而这些数学知识不会像客户端API一样说改就改,而是证明过正确,就不会再变动,而是不断会有新知识往上叠加和改良而已,所以这就是稳定的知识的领域了,只要学会了,就是自己的,而不像SDK性质的知识积累那样,总被SDK的开发者和所谓的时代潮流牵着鼻子走。

也正因为这些稳定领域的知识需要一定程度的数学相关的基本功,所以我不打算只满足于FFMPEG、libJPEG等库的使用上进行学习,而是从音频视频、图形图像的基本数学原理结合它们的实现代码进行学习,把这些知识,内化成自己的内功,才有可能开创自己的创新。

一、傅里叶变换简介

每一个复杂的波形,都可以分解为多个简单波形的叠加,这就是傅里叶变换的基本原则。这里并不打算详细地说明傅里叶变换究竟是什么,只需要知道这个原则,基于这个原则,就可以把时域信号变成频域信号,这时记录一个信号并不需要高密度地采样并记录每个采样点的值,而是记录信号各频率的分量的振幅、相位即可,还原时使用三角函数生成波形并重新相加即可。

二、DCT是什么

DCT全称为Discrete Cosine Transform,即离散余弦变换。其原则与傅里叶变换相近,都是把目标信号从复杂的时域信号,分解为不同频率强度的频域信号。就像上面对傅里叶的简介一样,复杂信号是简单信号的叠加,所以DCT的基本原理就是,通过多个不同强度不同频率的DCT基信号,即可叠加“拼装”为原本的信号,因此实际记录的时候就不再需要记录复杂的原始信号,而是记录DCT的基即可。并且信号转为DCT的频域信号后,左上角表达了其低频信号强度,右下角表达了其高频信号强度,使得信号的频率分量和强度一目了然,没有原始信号的纷繁复杂。

对比二维离散傅里叶变换的高低频域以散布于四角,DCT变换其高低频的分布比较一目了然,越接近左上角低频,越接近右下角越高频,因此更适合用于做频域缩减实现图像有损压缩。

三、DCT在图像有损压缩中的应用

1、图像有损压缩的依据点:

很多时候,我们肉眼观看一个图像,主要关注的是其大面积的色块,而精细部分则关注不多(有阿斯伯格现象的人则可能相反,但大部分人确实如此)。因此,图像中的精细部分即使做了一定程度的削弱,也不影响一副图像的观感,这就是JPEG等有损的图像格式最根本的原理。

对于图像处理来说,细节部分一般具有亮度起伏大、较短的尺度下亮度变化次数多的特点,转换为数学方式的描述,就是图像细节部分一般为“高频信号”,因此,如果能使用“分频器”,把图像的“时域信号”转化为“频域信号”,即可实现筛选走一部分高频信号,只保留高频信号,使得表达图像时需要的空间减少。

2、使用DCT进行图像有损压缩的具体操作:

我们先看DCT和逆DCT(IDCT)的公式:

(引用自《数字图像与视频处理》一书)

先看DCT公式1,u,v为我们需要得出DCT变换的频域结果的矩阵下标,f(x,y)为原8x8信号矩阵的值。

公式大致意义(重点):

  DCT变换基表可以理解为一个从(8*8)的二维余弦信号从最低频到最高频的穷举表,频率随着u和v的增大而增大。把8*8大小的二维时域信号矩阵,乘以(u, v)指定频率的基表单元矩阵,并对结果矩阵求和,即可得到输入信号f(x, y)对指定(u, v)频率的权值——这个值的大小表示了和对应(u, v)频率的相关性。把这些权值从(0, 0)到(8, 8),也就是从左到右、从上至下放到一个8*8大小的新表F(u, v)中,就可以把二维时域信号,转化为关于不同频率的相关性权值频域信号,并且从(0, 0)到(8, 8)频率以此递进,从而可以方便地进行频率筛选,这是原始二维信号做不到的。

       而其逆向操作,就是利用频率相关性权值表F(u, v),把不同权值比例的8*8频率表叠加为一个8*8的实际画面。

根据u,v的递增,的频率会越发增大,直到(u,v)为(7,7)时达到每一个像素都和周围的像素有差异为止,(u, v)从(0,0)到(7,7)的频率基图像如下所示:

计算代码:

    public void calcDCTBase(int u, int v) {this.mU = u;this.mV = v;double c_u = 1;double c_v = 1;if (u == 0 && v == 0) {c_u = c_v = 1f / Math.sqrt(2);}for (int y = 0; y < 8; y ++) {for (int x = 0; x < 8; x ++) {double base = c_u * c_v * Math.cos(((2 * x + 1) * u * Math.PI / 16f)) * Math.cos(((2 * y + 1) * v * Math.PI / 16f));mDCTBaseMatrix[x][y] = base;}}invalidate();}

之前说过,任何复杂的周期信号都可以简单的周期函数叠加而得。所以我们的输入图像,也可以通过不同强度的不同频率的基图像叠加而成。然后我们的二维图像信号f(x, y)通过乘以(0,0)~(u,v)不同频率的基函数,产生的结果就是信号f(x,y)和(0,0)~(u,v)的基图像的相关性图像,把从(0,0)~(u,v)这个范围的这个相关性结果求和后放到对应的结果矩阵的(u,v)位置,最后便得到了图像f(x,y)对应基图像从(0,0)~(u,v)不同频率的相关性(权值)图像。

最后,根据人眼的视觉特性,可以使用量化表使得肉眼敏感的低频信号使用较小的量化间隔值来确保进度,对肉眼不敏感的高频信号使用大的量化间隔粗糙量化即可,达到数据压缩的目的——高频信号量化后几乎成了0了。我使用的量化表如图:

如输入图像f(x,y):

DCT变化并使用量化表量化后得到输出:

可以发现这副图像大部分信号和低频的几个基图像相关性最强,此时我们就已经把图像从时域转化为频域,并且压缩了高频信号了。

计算代码:

    /**对输入的8*8矩阵信号,分别乘以从最低频(u,v为(0,0)处的DCT基)到最高频的DCT(u,v为(u,v)处的DCT基)基矩阵并求和,* 求和结果进行亮度量化后,放到输出矩阵对应坐标(u,v)处**/private void signalToDCTSignalTrans(int inputMatrix[], double outputMatrix[][]) {for (int u = 0; u < 8; u ++) {for (int v = 0; v < 8; v ++) {double base = 0;for (int x = 0; x < 8; x ++) {for (int y = 0; y < 8; y ++) {base += inputMatrix[y * 8 + x] * mDCTBaseMatrix[u][v].getSignalDCTBaseVal(x, y);}}outputMatrix[u][v] = 1f / 4f * base / Constant.DCT_BRIGHTNESS_TRANS_TABLE[u * 8 + v];}}}

3、使用IDCT进行图像解压缩的具体操作:

因为任何复杂的周期信号都可以简单的周期函数叠加而得,因此,按照DCT图像(0,0)~(u,v)存储的每个和基图像相关性值(权值),乘以对应的基图像,叠加(求和)后得到的值就是时域信号,也就是源图像。

把刚刚得到的DCT图像通过逆亮度量化和IDCT之后,就得到了图像:

可以看到图像经历过变换之后,因为量化误差的原因,产生了一定程度的误差。这也是为什么JPEG图像经过多次解压再重压缩之后图像质量会越来越差的原因。

计算代码:

    /**IDCT变换,把DCT变换后的频域信号重新转化为时域信号**/private void DCTSignalInverseDCTToSignal() {for (int y = 0; y < 8; y ++) {for (int x = 0; x < 8; x ++) {double base = 0;for (int u = 0; u < 8; u++) {for (int v = 0; v < 8; v++) {//逆亮度量化,逆DCTbase += mDCTTransResult[u][v] * Constant.DCT_BRIGHTNESS_TRANS_TABLE[u * 8 + v] * mDCTBaseMatrix[u][v].getSignalDCTBaseVal(x, y);}}mDCTReverseTransResult[x][y] = 1f / 4f * base;}}}

总体运作图像:

三、DCT算法的Java实现_AndroidDemo的Gitee地址:

lvlv/AndroidDemo大全 - Gitee.com

(为了呈现整个过程,突然花了心思做了写自定义控件)

四、libjpeg中对应的DCT代码实现:

//todo:

五、引用资料:

1、《数字图像与视频处理》 (机械工业出版社 卢官明、唐贵进、崔子冠 编)

2、Discrete Cosine Transform

JPEG图像压缩探索_DCT变换的应用相关推荐

  1. JPEG图像压缩探索_zigzag扫描(原创)

    续:<DCT变换的应用> http://t.csdn.cn/h1KmE 在DCT图像变换完成后,需要把数据从高频到低频频域强度信号进行筛选等操作,为了方便算法进行操作,最好转化为一个一维的 ...

  2. 基于DCT变换的JPEG图像压缩原理

    1.为什么要进行图像压缩 众所周知,当今人类社会具有三大支柱,即物质.能量.信息.当下已由物质过渡到信息,从农业现代化到工业现代化,再到当今的信息化时代.信息具有通用性.抽象性.无限性.其通用性表现在 ...

  3. 基于DCT变换的JPEG图像压缩

    基于DCT变换的JPEG图像压缩 摘 要:图像和视频通常在计算机中表示会占用非常大的空间,而出于节省硬盘空间的考虑,往往要进行压缩.而随着网络的发展,图像压缩技术越来越被人所重视.DCT变换是图像压缩 ...

  4. 基于DCT变换的JPEG图像压缩原理与JPEG2000编解码原理

    目录 参考文章 基于DCT变换的JPEG图像压缩原理 图像数据压缩 图像处理 为什么可以进行图像压缩? 颜色空间转换 RGB CMY HSV/HSI/HSB/HSL YUV/YCbCr YCbCr与R ...

  5. JPEG图像压缩解压算法——C++实现

    兹于2017年11月,应<多媒体技术基础>课程实验的要求,本人就基于JPEG图像压缩解压算法做了较为深入的理解,用C++语言实现JPEG图像压缩解压算法. JPEG图像压缩解压算法 一.实 ...

  6. 令人拍案叫绝的JPEG图像压缩原理

    作者 | Jack Sigmoid  编辑 | 3D视觉开发者社区 前言 从事各行各业的大佬们,我相信,你们对图像格式是不陌生的,有很多种图像格式,比如,png,jpeg等等,但是你发现,同一张图片, ...

  7. Baumer工业相机堡盟相机如何使用JPEG图像压缩功能(LXT.JP系列相机图像压缩功能的使用和优点以及行业应用)(C#)

    项目场景 Baumer工业相机堡盟相机是一种高性能.高质量的工业相机,可用于各种应用场景,如物体检测.计数和识别.运动分析和图像处理. Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分 ...

  8. 压缩减小图像大小技巧:8个最佳 JPEG 图像压缩软件

    如果您必须压缩以减小特定图像的大小,Jpeg 图像压缩软件可能会有很大用处.您无需自己动手,只需将图像上传到各种软件,等待工作完成即可.然而,大多数人通常对他们应该选择哪种软件感到困惑,因为可供选择的 ...

  9. JPEG图像压缩原理与DCT离散余弦变换

    原文网址:http://blog.csdn.net/newchenxf/article/details/51719597 转载请注明出处喔 1 前言 JPEG是joint Photographic E ...

最新文章

  1. 为了上班摸鱼,我用Python开发“BOSS来了”
  2. C++中输入输出的十六进制八进制
  3. Android中从assets资源中读取图片文件并保存到内部存储器并加载显示在ImageView中
  4. flink sql client读取hive时卡住
  5. 计算机科学美国大学专业,2018美国大学计算机科学专业大排名
  6. 【华为云技术分享】打卡APIG服务专享版,打造全栈API治理方案
  7. XStream 反序列化漏洞 (CVE-2020-26258 26259) 的复现与分析
  8. Python 实现 pdf转图片 和 图片转pdf
  9. 取文件操作fopen(file open)
  10. hololens 播放video
  11. 走吧走吧,拿着更多的票子把活干吧!
  12. 微型计算机中backspace键是什么键,backspace是哪个键?最实用按键的大揭秘
  13. 人像图片Relight
  14. 河南大学计算机学院魏倩,何欣-计算机与信息工程学院官网
  15. 惠普服务器开机显示系统恢复选项,惠普一键恢复出厂设置【操作办法】
  16. 计算机管理中不显示独立显卡,win10系统下检测不到独立显卡如何解决
  17. 超市管理系统源码,超市进销存管理系统源码 (CS架构)
  18. Pytorch可视化_cartopy+matplotlib_绘制雷达图像
  19. CSS 中 display 的 block,inline,inline-block 这三个属性的区别
  20. webAudio学习

热门文章

  1. Linux 系统 vim 的常用命令
  2. 关于网络广告及其收费标准
  3. 2007 年世界顶级杀毒软件排名
  4. unc0ver5.3.1发布,直装版
  5. 到底什么时候该跳槽?
  6. C/C++开发工程师 架构师 如何写简历(跳槽必看)
  7. java压缩包加密上传,解密下载
  8. sysstat使用及字段说明
  9. 家里服务器组无盘,家里无盘服务器配置
  10. ZZULIOJ.1156: 单数变复数