[Week2.4]图像DCT变换

均方差(Mean Square Error, MSE)

02_04 - Video -[00_03_19][20140411-000348-0]
  评价一幅图像压缩前和压缩还原后的差异,有两种常用方法:
  ①大家来找茬——进化程度高的人类可轻易识别;
  ②数学方法——压缩前和还原后的图像作均方差;
均方差计算方法:


显然,MSE越小,图像的质量越好。

K-L 转换:

  要想获得最小均方差的转换,可以使用K-L转换。K-L转换(Karhunen-Loève Transform)是建立在统计特性基础上的一种转换,它是均方差(MSE, Mean Square Error)意义下的最佳转换,因此在资料压缩技术中占有重要的地位。K-L转换是对输入的向量x,做一个正交变换,使得输出的向量得以去除数据的相关性。
  简单地说,只要能不辞劳苦地算出图像的K-L转换,就能找到MSE最小的转换。
  我的天啊,这听起来真棒!等等,K-L转换的计算复杂度奇高,半天压缩才压缩一副图片,恐怕自拍狂们会hold不住。
  那有没有简单的变换方法,计算简单,又能保证图像质量?

图像变换 - 从空间到频域

02_04 - Video -[00_09_00][20140411-001050-1]
  在进一步忽悠之前,先讲讲“变换”到底是个啥。
  “变换”就是,换个角度看问题。讲得装逼点,就是将函数从“时域”投影到“频域”,于是我们就能从频率的角度分析问题。
transform

DCT - 离散余弦变换

02_04 - Video -[00_11_18][20140411-001308-2]
  DCT( Discrete Cosine Transform),与傅里叶变换相关的一种变换,类似于离散傅里叶变换,但是只使用实数。离散余弦变换相当于一个长度大概是它两倍的离散傅里叶变换。
  对二维灰度图像进行DCT变换,就能得到图像的频谱图:低阶(变化幅度小)的部分反映在DCT的左上方,高阶(变化幅度大)的部分反映在DCT的右下方。由于人眼对高阶部分不敏感,依靠低阶部分就能基本识别出图像内容,所以JPEG进行压缩的时候,基本上只存储DCT变换后的左上部分,而右下部分则直接丢弃。
02_04 - Video -[00_16_07][20140414-224707-0]

为什么JPEG采用DCT而非DFT?

02_04 - Video -[00_19_18][20140414-224734-1]
  DCT跟DFT都是将二维空间图像转换到频域,为什么JPEG会采用DCT而非DFT呢?一个重要的原因,是子图之间的连续性。DFT变换没有考虑到子图之间的边界,整幅大图变换出来会得到如图上方的波形,波形不连续容易导致Gibbs phenomenon;而DCT得到子图间的波形则是连续的。

MATLAB实验代码

>> %量化矩阵
>> quantization_mat = [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;];

>> %读取原始图像
>> lena_ori = imread('F:/dip/lena.bmp');
>> lena_int = int16(lena_ori);
>> lena_offset = lena_int - 128;
>> % 作8*8 DCT
>> lean_dct = blkproc(lena_offset,[8 8],'dct2(x)');
>> % 量化
>> lena_quantization = blkproc(lean_dct,[8 8],'x./P1',quantization_mat);
>> lena_jpeg = int16(lena_quantization);  %取整
>> 
>> %还原图像
>> restore_dct = blkproc(lena_jpeg,[8 8],'x.*P1',quantization_mat);
>> restore_offset = blkproc(restore_dct,[8 8],'idct2(x)');
>> restore_img = restore_offset + 128;
>> 
>> restore_img = mat2gray(restore_img); %图像经过反量化反DCT之后,灰度值的范围超出0-255之内,通过这个函数将像素范围缩小。
>> 
>> % 原图与压缩后图像作差
>> lena_ori = mat2gray(lena_ori);
>> img_error = abs(restore_img - lena_ori);
>> figure; subplot(1,3,1); imshow(lena_ori);subplot(1,3,2); imshow(restore_img);subplot(1,3,3);imshow(img_error);
>> 

实验结果图 左为原图,中为压缩后图像,右为前两者的差值 (没看出差别吧~)
DCT的高阶部分因量化损失掉了,所以前两者是有细节差别的,但人眼几乎无法识别。
dct