实验目的:
- 熟悉Matlab/C/Python图像处理编程环境
- 图像JPEG压缩实验
实验内容
- 模拟数字图像JPEG压缩,绘制PSNR-Q曲线
- 显示压缩前后图像的灰度直方图,观察并分析所存在的差异
- 读取JPEG图像文件,自己编程解码提取某个宏块的量化后DCT系数、模拟反量化和逆DCT变换,恢复并显示对应空域图像块,观察并分析JPEG压缩引起的块效应
实验过程
-
实验环境:MATLAB2018
-
实验使用图片:lena256.png
-
代码
-
模拟数字图像JPEG压缩,绘制PSNR-Q曲线
Q=0:100;//质量因子 PSNR=zeros(1,101); %psnr值 for i=1:101 %进行每个质量因子对应的JPEG压缩,并记录PSNR值 img= imread('lena256.png'); imwrite(img,"lena256.jpg","quality",Q(i));%imwrite函数直接JPEG压缩,Q(i)为质量因子 jpeg= imread('lena256.jpg'); PSNR(i)=psnr(img,jpeg); end %绘制曲线图 plot(Q,PSNR); grid on set(gca,'ytick',20:0.5:38)//设置y坐标轴显示精度 xlabel('质量因子Q') ylabel('PSNR') title('PSNR~Q曲线');
说明:PSNR的计算这里直接使用的MATLAB自带函数,去网上搜索学习了一下此函数的具体实现过程,代码如下
function [PSNR, MSE] = psnr(X, Y) %%%%%%%%%%%%%%%%%%%%%%%%%%% % % 计算峰值信噪比PSNR % 将RGB转成YCbCr格式进行计算 % %%%%%%%%%%%%%%%%%%%%%%%%%%% if size(X,3)~=1 %判断图像是不是彩色图,如果是,结果为3,否则为1 org=rgb2ycbcr(X);%将R,G,B格式转换为YCbCr test=rgb2ycbcr(Y); Y1=org(:,:,1);%这里只示例计算y分量(亮度分量),总的PSNR计算分别计算R,G,B三个通道总和,最后MSE直接在原公式上多除以3 Y2=test(:,:,1); Y1=double(Y1); %计算平方时候需要转成double类型,否则uchar类型会丢失数据 Y2=double(Y2); else %灰度图像,不用转换 Y1=double(X); Y2=double(Y); end if nargin<2 D = Y1; else if any(size(Y1)~=size(Y2)) error('The input size is not equal to each other!'); end D = Y1 - Y2; end MSE = sum(D(:).*D(:)) / numel(Y1); PSNR = 10*log10(255^2 / MSE);
-
绘制图像灰度直方图
jpg=imread('lena256.jpg'); JPG=rgb2gray(jpg);%彩色图像转为灰度图像 imhist(JPG);
-
解码提取一个宏块的量化后DCT系数、模拟反量化和逆DCT变换,恢复并显示对应空余图像块
img=jpeg_read('lena256.jpg');%读取jpeg图像,jpeg_read()是jpeg_tool_box内的函数,下载后放到代码根目录下就可以使用啦 Y=img.coef_arrays{1,1};%提取Y分量 cb=img.coef_arrays{1,2};%提取cb分量 cr=img.coef_arrays{1,3};%提取cr分量 Y=Y(1:8,129:136);%这里作业要求的是要提取学号数对应的宏块,整幅图的话就不需要截取矩阵了 Y=Y.*img.quant_tables{1,1};%反量化 cb=cb(1:8,73:80);%同上 cb=cb.*img.quant_tables{1, 2}; cr=cr(1:8,73:80); cr=cr.*img.quant_tables{1, 2}; Y=idct(Y);%逆DCT变换,idct()函数下面给出,可直接使用matlab内置idct2()函数 cb=idct(cb); cr=idct(cr); R=Y+1.14*cr;%转换为RGB分量 G=Y-0.39*cb-0.58*cr; B=Y+2.03*cb; rgb=cat(3,R,G,B); rgb=uint8(rgb+128);//这里要加128是因为原始图像在进行DCT变换时,其接受的数据范围为正负128,所以当时减去了128 imshow(rgb);%显示图像块
逆dct变换函数idct()
function Y = idct(X) [M,~] = size(X); w=zeros(M,M); for i = 0:M-1 for j = 0:M-1 if i == 0 w(i+1,j+1) = sqrt(1/M)*cos(((2*j+1)*i*pi)/(2*M)); else w(i+1,j+1) = sqrt(2/M)*cos(((2*j+1)*i*pi)/(2*M)); end end end w = double(w); %变换后的矩阵数据类型为double Y = w'*X*w; end
实验结果展示
-
PSNR-Q曲线图
可以看到图像的PSNR值随Q的增大而增大。 -
压缩前后图像灰度直方图
左侧为压缩前,右侧为压缩后
分析:由两张图对比可知,图像进行JPEG压缩前后灰度值总体几乎没有变化,灰度范围及分布大致相同,仅有少数一些灰度值有微小的变化,从实际图像看来并不影响图像内容,由此可见JPEG不会对图像灰度产生明显改变。
-
解码复原图像
原图像vsJPEG图像(压缩时质量因子分别为10和90)
分析整张图片的JPEG压缩效果,可得压缩时质量因子越大,图像的内容越精细,和原图更相似,而质量因子越小jpeg图像内容越粗糙,块与块之间的连续性越差,即块效应越明显。