matlab中实现图像的JPEG压缩及利用jpeg_tool_box复原图像

实验目的:

  • 熟悉Matlab/C/Python图像处理编程环境
  • 图像JPEG压缩实验

实验内容

  • 模拟数字图像JPEG压缩,绘制PSNR-Q曲线
  • 显示压缩前后图像的灰度直方图,观察并分析所存在的差异
  • 读取JPEG图像文件,自己编程解码提取某个宏块的量化后DCT系数、模拟反量化和逆DCT变换,恢复并显示对应空域图像块,观察并分析JPEG压缩引起的块效应

实验过程

  • 实验环境:MATLAB2018

  • 实验使用图片:lena256.png

  • 代码

  1. 模拟数字图像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);
    
  2. 绘制图像灰度直方图

    jpg=imread('lena256.jpg');
    JPG=rgb2gray(jpg);%彩色图像转为灰度图像
    imhist(JPG);
    
  3. 解码提取一个宏块的量化后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图像内容越粗糙,块与块之间的连续性越差,即块效应越明显。

资料

  • 7
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
JPEG(Joint Photographic Experts Group)是一种针对彩色图像的有损压缩格式。它可以将图像压缩到原始大小的1/10或更小,但在这个过程会丢失一些信息。在本文,我们将使用MATLAB实现JPEG图像压缩和解压缩。 ## JPEG图像压缩 ### 分块和DCT变换 首先,我们需要将图像分成8x8的块。对于每个块,在进行压缩之前,我们需要进行DCT(Discrete Cosine Transform,离散余弦变换)变换。MATLAB提供了一个名为`dct2`的函数来执行DCT变换。 ``` % 读取图像 img = imread('lena.png'); % 将图像转换为灰度图像 img_gray = rgb2gray(img); % 将图像分块为8x8的块 blocks = mat2cell(img_gray, 8*ones(1,size(img_gray,1)/8), 8*ones(1,size(img_gray,2)/8)); % 对每个块执行DCT变换 dct_blocks = cellfun(@dct2, blocks, 'UniformOutput', false); ``` ### 量化和熵编码 接下来,我们需要将DCT系数量化并对其进行熵编码。量化是一个有损过程,它将DCT系数舍入到最接近的量化级别。这可以减少数据量,但会导致信息丢失。 我们可以使用JPEG标准定义的量化矩阵来量化DCT系数。该矩阵包含了高频和低频系数的权重,其高频系数的权重较小,因此它们通常会被量化为0或接近0的值。低频系数的权重较大,因此它们通常会被保留下来。 ``` % 定义JPEG标准的量化矩阵 Q = [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]; % 对DCT系数进行量化 quant_blocks = cellfun(@(block) round(block ./ (Q*0.1)), dct_blocks, 'UniformOutput', false); ``` 接下来,我们需要对量化系数进行熵编码。在这里,我们将使用MATLAB的`jpeg_write`函数来完成此操作。该函数将量化系数写入JPEG文件,并使用Huffman编码对它们进行压缩。 ``` % 将量化系数写入JPEG文件 jpeg_write(quant_blocks, 'compressed.jpg'); ``` ## JPEG图像压缩 ### 解码和逆量化 现在,我们将解压缩JPEG文件并还原原始图像。首先,我们需要将JPEG文件的量化系数解码。我们可以使用MATLAB的`jpeg_read`函数来完成此操作。 ``` % 从JPEG文件读取量化系数 quant_blocks = jpeg_read('compressed.jpg'); quant_blocks = quant_blocks.coef_arrays{1}; ``` 然后,我们需要将量化系数进行逆量化,以还原DCT系数。这可以通过将量化系数乘以JPEG标准的量化矩阵来实现。 ``` % 对量化系数进行逆量化 dct_blocks = cellfun(@(block) block .* (Q*0.1), quant_blocks, 'UniformOutput', false); ``` ### 逆DCT变换和重构图像 最后,我们需要将DCT系数进行逆DCT变换,并将它们组合成原始图像MATLAB提供了一个名为`idct2`的函数来执行逆DCT变换。 ``` % 对每个块执行逆DCT变换 idct_blocks = cellfun(@idct2, dct_blocks, 'UniformOutput', false); % 将块组合成原始图像 img_gray_reconstructed = cell2mat(idct_blocks); ``` 现在我们已经得到了还原的灰度图像。如果需要,我们可以将其转换回彩色图像,以便进行可视化。 ``` % 将图像转换为彩色图像 img_reconstructed = cat(3, img_gray_reconstructed, img_gray_reconstructed, img_gray_reconstructed); % 显示重构的图像 imshow(img_reconstructed); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值