数字图像处理 实验七:JPEG压缩编码

DIP实验7:JPEG压缩编码

实验目的

1)掌握n×n块的DCT图像变换及频谱特点。
2)熟悉JPEG基本系统的图像编解码方法。

实验原理

基于DCT有损压缩编码的基本系统的主要计算步骤
1)通过前向离散余弦变换(FDCT)减少图像数据相关性;
2)利用人眼的视觉特性对DCT系数进行量化;

附:可供参考的Matlab函数有dctmtx/dct2、blkproc、hist、bar、num2str和strcat

实验内容

1)编程实现n×n块DCT变换的图像频谱显示,块DCT系数按照Zig-Zag扫描并取部分进行图像重建,计算图像的均方根误差RMSE,显示误差图像和误差直方图。
2)对8×8块的DCT系数,采用JPEG默认的量化矩阵进行量化和反量化,计算原图像与重建图像之间的均方根误差RMSE、并显示误差图像。

输出图像排列格式如下:

原图像8×8 DCT频谱显示取?个DCT系数时的重建图像
差值直方图, RMSE=Scale为?时的重建图像量化误差图像, RMSE=

需要编写的函数:
1)分块DCT函数:
根据给定的n值,计算原图像的n×n块的DCT系数,并转换为可视频谱图以便观察

function dctfre = DctBlock(oldbuf,n,t);
% 输入
%     oldbuf         		 原始图像数据
%     n              		 分块的大小
%     t             	     DCT变换矩阵
% 输出
%     dctfre                 DCT系数矩阵
%     log(abs(dctfre)*5+1)   修正DCT系数以便频谱观察

2)ZigZag及IDCT函数:
按Zig-Zag扫描顺序,只保留64个DCT系数中的前x个系数,并对修改后的DCT系数用逆DCT变换重建图像。将x值从1开始增大,观察图像由模糊到清晰的变化情况。计算重建图像的均方根误差RMSE,显示误差图像和误差直方图。

function e = ZigIDCT(oldbuf,dctfre,x,n,t);
% 输入
%     oldbuf          原始图像数据
%     dctfre          DCT系数矩阵
%     x                每个分块中需要保留的DCT系数个数
%     n                分块的大小
%     t                DCT变换矩阵
% 输出
%     e                原图像与保留部分DCT系数后的重建图像之间的误差矩阵

3)量化和反量化函数:
根据给定的默认JPEG量化表,对每个n×n块的DCT系数进行量化和反量化,显示量化误差图像及其直方图。

function QuanIQuan(oldbuf,dctfre,Scale,n,t);
% 输入
%     oldbuf          原始图像数据
%     dctfre          DCT系数矩阵
%     Scale           乘积因子
%     n               分块的大小
%     t               DCT变换矩阵

zigzag = [1 2 6 7 15 16 28 29          
          3 5 8 14 17 27 30 43
          4 9 13 18 26 31 42 44
          10 12 19 25 32 41 45 54
          11 20 24 33 40 46 53 55
          21 23 34 39 47 52 56 61
          22 35 38 48 51 57 60 62
          36 37 49 50 58 59 63 64];
          
% Luminance quantization table
QuanTable =      
	[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]; 

参考代码

OI = imread('lena.bmp');
n = 8;    % DCT分块大小
x = 2;    % 每个分块中需要保留的DCT系数个数

dctfre = DctBlock(OI, n);    % 分块DCT函数
[Lerror, Lrestored] = ZigIDCT(OI, dctfre, x, n);    % ZigZag及IDCT函数
 
Scale = 2;    % 乘积因子
[Qerror, Qrestored] = QuanIQuan(OI, dctfre, Scale, n);    % 量化和反量化函数

subplot(2, 3, 1);     
imshow(OI);     
title('原图像');

dct_amend = log(abs(dctfre) * 5 + 1);    % 修正DCT系数以便频谱观察
dct_amend = Calibration(dct_amend);

subplot(2, 3, 2);       
imshow(dct_amend);      
title([num2str(n), '×', num2str(n), ' DCT频谱显示']);

subplot(2, 3, 3);
imshow(Lrestored);       
title(['取', num2str(x), '个DCT系数时的重建图像']);

error_lessen_rms = sqrt( sum(sum(Lerror.^2)) / numel(Lerror) );
% numel: 返回数组或者向量中所含元素的总数

subplot(2, 3, 4);
histogram(Lerror);
title(['差值直方图, RMSE=', num2str(error_lessen_rms)]);

subplot(2, 3, 5);
imshow(Qrestored);        
title(['Scale为', num2str(Scale), '时的重建图像']);
 
Qerror_rms = sqrt( sum(sum(Qerror.^2)) / numel(Qerror) );
subplot(2,3,6);
imshow(uint8(Calibration(Qerror)));     
title(['量化误差图像,RMSE=', num2str(Qerror_rms)]);


%% 分块DCT函数
function dctfre = DctBlock(oldbuf, n)
	% 输入
	%     oldbuf         原始图像数据
	%     n              分块的大小
	% 输出
	%     dctfre         DCT系数矩阵
	oldbuf = double(oldbuf);
	oldbuf = oldbuf - 128;    % DCT变换范围:-128~127
	D = dctmtx(n);    % 返回 n×n 的DCT变换矩阵
	% 矩阵ADCT变换可用 D×A×D' 来计算
	% blkporc: 功能为对图像分块进行DCT变换
	% B = blkproc(A, [M N], Fun)A为输入图像,M*N为块大小,Fun为处理函数 
	dctfre=blkproc(oldbuf, [n, n], 'P1*x*P2', D, D'); 
	% D为变换矩阵( D, D'为要传递给函数的参数)P1P2为参数,代表D*x*D’ 
end


%% ZigZag及IDCT函数
function [e, Restored] = ZigIDCT(oldbuf, dctfre, x, n)
	% 输入
	%     oldbuf        原始图像数据
	%     dctfre         DCT系数矩阵
	%     x                 每个分块中需要保留的DCT系数个数
	%     n                 分块的大小
	% 输出
	%     e                 原图像与保留部分DCT系数后的重建图像之间的误差矩阵
	%     Restored    重建图像
	 
	zigzag = [1  2   6   7   15  16  28  29          
	          3  5   8   14  17  27  30  43
	          4  9   13  18  26  31  42  44
	          10 12  19  25  32  41  45  54
	          11 20  24  33  40  46  53  55
	          21 23  34  39  47  52  56  61
	          22 35  38  48  51  57  60  62
	          36 37  49  50  58  59  63  64];
	 
	% 根据当前x值(保留细数个数)得到“Z”字扫描的逻辑值, mask为logic类型
	mask=zigzag<=x;   
	% 返回 n×n 的DCT变换矩阵
	D=dctmtx (n);      
	% Restored为重建的压缩图像矩阵
	Restored = blkproc(dctfre, [n, n], 'P1*(x.*P2)*P3', D' ,mask,D);     
	Restored = Restored+128;
	Restored = uint8(Restored); 
	% 原图像与保留部分DCT系数后的重建图像之间的误差矩阵
	e = double(oldbuf)-double(Restored);     
end

%% 量化和反量化函数
function [e, Restored] = QuanIQuan(oldbuf, dctfre, Scale, n)
	% 输入
	%     oldbuf           原始图像数据
	%     dctfre           DCT系数矩阵
	%     Scale            乘积因子
	%     n                分块的大小
	% 输出
	%     e                量化误差
	%     Restored         重建图像
	
	% Luminance quantization table
	QuanTable = [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];     
	 
	Qvalue = blkproc(dctfre, [n n],'round(x./P1)', Scale*QuanTable);     
	% 量化
	IQvalue = blkproc(Qvalue, [n n], 'x.*P1', Scale*QuanTable);     % 反量化
	% 对经过量化和反量化后的矩阵进行逆DCT变换得到重建图像矩阵
	D = dctmtx(n);
	Restored = blkproc(IQvalue, [n n], 'P1*x*P2', D', D);
	Restored = Restored + 128;
	Restored = uint8(Restored); 
	% e为量化误差矩阵
	e = double(Restored) - double(oldbuf);
end

%% 标定
function cal = Calibration(img)
    img = double(img);
    [M, N] = size(img);
    fmin = min(min(img));
    fm = img - fmin * ones(M, N);
    fmmax = max(max(fm));
    fs = 255 * fm ./ fmmax;
    cal = uint8(fs);
end


实验结果

在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值