本篇是该系列的第六篇,承接上篇IZigZag变换,介绍接下来的一个步骤——逆离散余弦变换,即逆零偏置前的一个步骤。

  该步骤比较偏理论,其业务是对IZigZag变换后的数据,再进一步的处理,使其恢复DCT变换前的数据。

  需要补充一点说明的是,上面的DCT其实是DCT2,因为jpeg编码下都是对8x8的像素块进行处理。

1. 理论

  1.1. 背景

    DCT,即离散余弦变换,常用图像压缩算法,步骤如下

    1)分割,首先将图像分割成8x8或16x16的小块;
    2)DCT变换,对每个小块进行DCT变换;
    3)舍弃高频系数(AC系数),保留低频信息(DC系数)。高频系数一般保存的是图像的边界、纹理信息,低频信息主要是保存的图像中平坦区域信息。
    4)图像的低频和高频,高频区域指的是空域图像中突变程度大的区域(比如目标边界区域),通常的纹理丰富区域。

  1.2.算法

    二维DCT变换就是将二维图像从空间域转换到频率域。形象的说,就是计算出图像由哪些二维余弦波构成。其算法如下:

    

    其中,F就是变换得到的系数,f是图像的像素值,A是转换矩阵,其中i为二维波的水平方向频率,j为二维波的垂直方向频率,取值范围都是0-(N-1),N是图像块的大小,其中:

    

    即进行如下步骤的处理可以得到DCT变换后的系数矩阵:

    1)求出转换矩阵A;
    2)利用转换矩阵A,转换到频域,即由图像 f 得到系数矩阵F。

2. 实践

  2.1. 图像上运用实现

    DCT用图像上的处理,都是对8x8的像素数据块进行处理,因此,DCT2变换的转换矩阵A为:

    

    其中,

     

    那么转换矩阵A为:

    

    计算如这个链接

 1 void InitTransMat()
2 {
3 int i,j;
4 float a;
5
6 for(i=0;i<MAT_SIZE;i++)
7 {
8 for(j=0;j<MAT_SIZE;j++)
9 {
10 a = 0;
11 if(i==0)
12 {
13 a=sqrt((float)1/MAT_SIZE);
14 }
15 else
16 {
17 a=sqrt((float)2/MAT_SIZE);
18 }
19 DCT_Mat[i][j]= a*cos((j+0.5)*PI*i/MAT_SIZE); //变换矩阵
20 }
21 }
22 /* only for 8x8 */
23 //float Tmp[100][100] = {
24 // {0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536,},
25 // {0.4904, 0.4157, 0.2778, 0.0975, -0.0975, -0.2778, -0.4157, -0.4904,},
26 // {0.4619, 0.1913, -0.1913, -0.4619, -0.4619, -0.1913, 0.1913, 0.4619,},
27 // {0.4157, -0.0975, -0.4904, -0.2778, 0.2778, 0.4904, 0.0975, -0.4157,},
28 // {0.3536, -0.3536, -0.3536, 0.3536, 0.3536, -0.3536, -0.3536, 0.3536,},
29 // {0.2778, -0.4904, 0.0975, 0.4157, -0.4157, -0.0975, 0.4904, -0.2778,},
30 // {0.1913, -0.4619, 0.4619, -0.1913, -0.1913, 0.4619, -0.4619, 0.1913,},
31 // {0.0975, -0.2778, 0.4157, -0.4904, 0.4904, -0.4157, 0.2778, -0.0975,},
32 //};
33 //for (int i=0; i<8; i++)
34 // for (int j=0; j<8; j++)
35 // DCT_Mat[i][j] = Tmp[i][j];
36 }

  2.2. IDCT2—— 由F求f的过程

    前篇文章已介绍了由IZigZag变换后得到的系数矩阵F,那么要恢复原数据,就要进行如下变换:

    

    算法的C语言描述如下:

 1 int IDCT2(float (*dst)[8], int (*block)[8], bool dump)
2 {
3 float trans_matrix[8][8] = {
4 {0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536,},
5 {0.4904, 0.4157, 0.2778, 0.0975, -0.0975, -0.2778, -0.4157, -0.4904,},
6 {0.4619, 0.1913, -0.1913, -0.4619, -0.4619, -0.1913, 0.1913, 0.4619,},
7 {0.4157, -0.0975, -0.4904, -0.2778, 0.2778, 0.4904, 0.0975, -0.4157,},
8 {0.3536, -0.3536, -0.3536, 0.3536, 0.3536, -0.3536, -0.3536, 0.3536,},
9 {0.2778, -0.4904, 0.0975, 0.4157, -0.4157, -0.0975, 0.4904, -0.2778,},
10 {0.1913, -0.4619, 0.4619, -0.1913, -0.1913, 0.4619, -0.4619, 0.1913,},
11 {0.0975, -0.2778, 0.4157, -0.4904, 0.4904, -0.4157, 0.2778, -0.0975,},
12 };
13
14 float tmp[8][8];
15
16 float t=0;
17 int i,j,k;
18 for(i=0;i<8;i++) //same as A'*I
19 {
20 for(j=0;j<8;j++)
21 {
22 t = 0;
23 for(k=0; k<8; k++)
24 {
25 t += trans_matrix[k][i] * block[k][j]; //trans_matrix's ith column * block's jth column
26 }
27 tmp[i][j] = t;
28 }
29 }
30
31 for(i=0; i<8; i++) //same as tmp*A
32 {
33 for(j=0; j<8; j++)
34 {
35 t=0;
36 for(k=0; k<8; k++)
37 {
38 t += tmp[i][k] * trans_matrix[k][j];
39 }
40 dst[i][j] = t;
41 }
42 }
43
44 if (dump) {
45 puts("----after idct2----");
46 for (i=0; i<8; i++) {
47 for (j=0; j<8; j++) {
48 printf("%3.4f ", dst[i][j]);
49 }
50 puts("");
51 }
52 puts("");
53 }
54
55 return 0;
56 }

  2.3. 例子实践

    根据前篇文章的IZigZag结果恢复数据,如下:

    有没有注意到许多值是近似相等的?

3. 篇外补充

  正是图像上这种特性,才有了图像压缩的这种方法——空间去冗余。

  但是,需要说明一点的是,DCT2/IDCT2不是有损失压缩(压缩是数据量降低的概念,有损/无损是转换前后信息是否丢失的概念),因为它可以完全恢复数据,只是这种变换将图像在空间域/频率域之间转换。

  空间域的数据量很多,但是经DCT2转换后,数据量变得非常少(非0数据),这个例子可能看的还不是太直观但有了初步雏形。

  在这里,要特别感谢傅里叶这位法国数学家,正是因为他的出色工作,才使得如今的最常见的图像压缩技术变成了现实。

  正可谓,前人栽树后人乘凉。前人的理论成果,后人在应用上开花结果。

JPEG解码——(6)IDCT逆离散余弦变换的更多相关文章

  1. Python 实现图像快速傅里叶变换和离散余弦变换

    图像的正交变换在数字图像的处理与分析中起着很重要的作用,被广泛应用于图像增强.去噪.压缩编码等众多领域.本文手工实现了二维离散傅里叶变换和二维离散余弦变换算法,并在多个图像样本上进行测试,以探究二者的 ...

  2. 在python3下使用OpenCV做离散余弦变换DCT及其反变换IDCT

    对图像处理经常用到DCT, Python下有很多带有DCT算法包, 这里使用OpenCV的DCT做变换, 并简单置0部分数据, 再查看反变换图像的效果. import numpy as np impo ...

  3. 在python3下对数据分块(8x8大小)使用OpenCV的离散余弦变换DCT

    在MATLAB中有blkproc (blockproc)对数据处理, 在python下没找到对应的Function, 这里利用numpy 的split(hsplit和vsplit) 对数据分块处理成8 ...

  4. Discrete cosine transform(离散余弦转换)

    A discrete cosine transform (DCT) expresses a finite sequence of data points in terms of a sum of co ...

  5. 离散傅立叶变换与快速傅立叶变换(DFT与FFT)

    自从去年下半年接触三维重构以来,听得最多的词就是傅立叶变换,后来了解到这个变换在图像处理里面也是重点中的重点. 本身自己基于高数知识的理解是傅立叶变换是将一个函数变为一堆正余弦函数的和的变换.而图像处 ...

  6. Maths | 离散K-L变换/ 主成分分析法

    目录 1. 概述 2. K-L变换方法和原理推导 2.1. 向量分解 2.2. 向量估计及其误差 2.3. 寻找最小误差对应的正交向量系 3. K-L变换高效率的本质 4. PCA在编.解码应用上的进 ...

  7. JPEG解码--(1)JPEG文件格式概览

    由于懒和人的忘性,以前做的一些笔记再回过头看时又有些生疏了,我决定把一些内容整理出来,以供有需要的来参考. 了解的人知道其价值所在,不知道的人就弃之如废物吧. 本篇是JPEG解码系列的第一篇--JPE ...

  8. JPEG解码——(3)文件头解析

    与具体的编码数据空间相比,jpeg文件头占据非常小乃至可以忽略不计的大小. 仍然拿JPEG解码--(1)JPEG文件格式概览中的<animal park>这张图片来举例,从跳过SOS(FF ...

  9. python 图像的离散傅立叶变换

    图像(MxN)的二维离散傅立叶变换可以将图像由空间域变换到频域中去,空间域中用x,y来表示空间坐标,频域由u,v来表示频率,二维离散傅立叶变换的公式如下: 在python中,numpy库的fft模块有 ...

随机推荐

  1. useful life skills website

    useful life skills website 绳子打结技巧 https://www.animatedknots.com/complete-knot-list tools https://tab ...

  2. base 64 bug & encodeURIComponent

    base64 bug & encodeURIComponent window.btoa("jëh²H¶�%28"); // "autoskiptoclMjiu&q ...

  3. React & Calendar

    React & Calendar 日历 https://github.com/YutHelloWorld/calendar/blob/master/src/Calendar.js // 国际化 ...

  4. React 函数式组件的 Ref 和子组件访问(useImperativeHandle)

    引入:如何调用函数式组件内部的方法 对于 React 中需要强制修改子组件的情况,React 提供了 Refs 这种解决办法,使得我们可以操作底层 DOM 元素或者自定的 class 组件实例.除此之 ...

  5. Linux 内核和 Windows 内核有什么区别?

    Windows 和 Linux 可以说是我们比较常见的两款操作系统的. Windows 基本占领了电脑时代的市场,商业上取得了很大成就,但是它并不开源,所以要想接触源码得加入 Windows 的开发团 ...

  6. 第48天学习打卡(HTML 行内元素和块元素 列表 表格 视频和音频 页面结构分析 iframe内联框架 表单语法 )

    行内元素和块元素 块元素 ​ 无论内容多少,该元素独占一行 ​ (p.h1-h6) 行内元素 ​ 内容撑开宽度,左右都是行内元素的可以排在一行 ​ (a.strong.em...) 列表 什么是列表 ...

  7. 基于QT的全自动超声波焊接机上位机追溯系统(已经在设备上应用)

    应用说明: 本上位机程序是我在做锂电池产线项目的时候开发的,用于采集设备数据以及实现设备自动控制,下位机采用基恩士PLC,超声波机采用上海一家的超声波焊接机,实现电芯极耳的自动焊接,上位在设备焊接过程 ...

  8. Java RPC 框架 Solon 1.3.9 发布,更便利的支持

    Solon 是一个微型的Java RPC开发框架.项目从2018年启动以来,参考过大量前人作品:历时两年,4000多次的commit:内核保持0.1m的身材,超高的跑分,良好的使用体验.支持:RPC. ...

  9. Canvas 如何画一个四分之一圆

    转: Canvas 如何画一个四分之一圆 HTML: Document JS: var c = document.getElementById('ctx') var ctx = c.getContex ...

  10. 基于Hi3559AV100的视频采集(VDEC-VPSS-VO)整体框图设计

    下面给出基于Hi3559AV100的视频采集整体设计,具体设计将在后续给出: 图形采集端整体设计 Hi3559AV100软件程序按结构划分可分为4层,第一层是硬件驱动层,第二层是操作系统层,第三层是媒 ...