數字圖像處理|Matlab-數字圖像編碼實驗-有損壓縮/壓縮算法實驗-JPEG編碼壓縮

Matlab-數字圖像編碼實驗-有損壓縮/壓縮算法實驗

代碼鏈接:https://download.csdn.net/download/qq_43571150/12033274

查閱JPEG編碼的有關資料,對圖像進行JPEG壓縮
算法步驟必須包括如下幾個部分:

  1. 圖像分塊
  2. 離散餘弦變換
  3. 量化
  4. ac和dc係數的Z字形編排

問題1:質量因子分別選爲20,60,80,對比顯示原圖與不同質量因子下解碼後的圖像;
問題2:記錄圖像大小、壓縮比、均方根誤差;對結果進行分析。

JPEG標準亮度量化表👇
在這裏插入圖片描述
結果👇
在這裏插入圖片描述
在這裏插入圖片描述

Matlab代碼👇

function JPEG;

close all;clear all;clc;
J=imread('05.jpg'); 
imwrite(J,'05 質量因子80.jpg','quality',80);
x=imread('05 質量因子80.jpg');
R=rgb2gray(x);
I=double(R);
imwrite(R,'05 灰度圖.jpg');

圖像分割
以8x8爲最小單元分割,可分割成4096個方塊,從上往下,得到32768x8的矩陣

%% 圖像分割 以8x8爲最小單元分割,可分割成4096個方塊,從上往下,得到32768x8的矩陣
% lena512: 512*512
% Block: 32768*8
Block=[];
for numi=1:64 %逐行取方陣
    m=(numi-1)*8+1; %每塊行的開頭
    for numj=1:64 %逐列取方陣
        n=(numj-1)*8+1; %每塊列的開頭
        Block=[Block; I(m:m+7,n:n+7)];
    end
end

離散餘弦變換(DCT變換)
對4096個方陣分別進行DCT變換,得到4096個變換方陣,從上往下存,32768x8的矩陣

%% 離散餘弦變換 DCT變換 對4096個方陣分別進行DCT變換,得到4096個變換方陣,從上往下存,32768x8的矩陣
% Block: 32768*8
% FBlock: 32768*8
for num=1:4096
    start=(num-1)*8+1;
    FBlock(start:start+7,:)=dct2(Block(start:start+7,:));
end

量化
對4096個方陣分別根據JPEG亮度標準量化表進行量化,從上往下

%% 量化 對4096個方陣分別根據JPEG亮度標準量化表進行量化,從上往下存,32768x8的矩陣,部分高頻分量被捨棄,減小了視覺冗餘
% FBlock: 32768*8
% QBlock: 32768*8
load('JPEG512.mat','lighttable');%JPEG標準亮度量化表
for num=1:4096
    start=(num-1)*8+1;
    QBlock(start:start+7,:)=round(FBlock(start:start+7,:)./lighttable);
end

反向量化

%% 反向量化
% QBlock: 32768*8
% reFBlock: 32768*8
for num=1:4096
    start=(num-1)*8+1;
    reFBlock(start:start+7,:)=QBlock(start:start+7,:).*lighttable;
end

反離散餘弦變換(IDCT)

for num=1:4096
    start=(num-1)*8+1;
    Block(start:start+7,:)=idct2(reFBlock(start:start+7,:));
end

圖像重構

%% 圖像重構
reI=[];
for numi=1:64
    m=(numi-1)*512+1;
    % 分成64512*8陣列,每個陣列有648*8方陣
    A=[];
    for numj=1:64
        n=(numj-1)*8;
        A=[A Block(m+n:m+n+7,:)];
    end
    reI=[reI; A];
end

JPEG Figure

subplot(1,2,1);imshow(I./256);title('input');
subplot(1,2,2);imshow(reI./256);title('JPEG壓縮');
imwrite(reI./256,'05 質量因子80.jpg');

CODE

%% 鋸齒形 ZIG-ZAG 對每一個方陣採用ZIG-ZAG排序,以增加圖像中的連0個數,得到4096x64的矩陣
% QBlock: 32768*8
% QLine: 4096*64
QLine=[];
load('JPEG512.mat','zigzag');%快速Z型排序行向量
zigzag = zigzag + 1;  % 下標加1,從0開始

for num=1:4096
    start=(num-1)*8+1;
    A=reshape(QBlock(start:start+7,:),1,64);% 變成行向量
    QLine=[QLine;A(zigzag)];
end

%% 對第一列的DC分量進行DPCM編碼 第一個記爲0,後面的都只記錄與前者的差值
% QLine: 4096*64
% VLIDC: 4096*1
% 對第一列進行DPCM編碼,第一個值記爲DC,並賦0
DC=QLine(1,1);%保留備用
sumcode=0;%計算編碼長度

QLine(1,1)=0;
for num=4096:-1:2
    QLine(num,1)=QLine(num,1)-QLine(num-1,1);
end

VLIDC=ones(4096,1);% VLI分組
for num=1:4096
    temp=abs(QLine(num,1));%用絕對值判斷組別
    if temp==0
        VLIDC(num)=0;
    else
        for k=1:7%經測試,第一列最大值爲80,前7組夠用
            if (temp>=2^(k-1)) && (temp<2^k)
                VLIDC(num)=k;
                break;
            end
        end
    end
end

for num=1:4096
    %先根據DC亮度huffman表計算sumcode
    if (VLIDC(num)<=5) && (VLIDC(num)>=0)
        sumcode=sumcode+3;
    elseif VLIDC(num)==6
        sumcode=sumcode+4;
    else
        sumcode=sumcode+5;
    end
    
    %再根據VLI表計算sumcode
    sumcode=sumcode+VLIDC(num);
end

%% 對其餘63列AC分量進行RLC編碼
% QLine: 4096*64
% 經測試,後63列最大值爲58,VLI前6組夠用。
eob=max(QLine(:))+1; %設一個超大值作爲每一行結束符

for numn=1:4096 %放eob
    for numm=64:-1:2
        if QLine(numn,numm)~=0
            QLine(numn,numm+1)=eob;
            break;
        end
        if (numm==2)%沒找到
            QLine(numn,2)=eob;
        end
    end
end
test=QLine';
[col,~]=find(test==eob);%我們只要eob列位置
validAC=col-1; %每一行保留的AC數據量,含EOB
maxcz=0;

for numn=1:4096 %逐行計算並加至sumcode
    cz=[];%記錄前0數
    VLIAC=[];%記錄組號
    count=0;%記錄連0for numm=2:1+validAC(numn)
        if QLine(numn,numm)==eob
            cz=[cz 0];
            VLIAC=[VLIAC 0];
        elseif QLine(numn,numm)==0
            count=count+1;
        else %遇到非0if count>15 %遇到連0大於15的
                cz=[cz 15];
                count=0;
                VLIAC=[VLIAC 0];
                continue;
            end
            cz=[cz count];
            count=0;
            
            temp=abs(QLine(numn,numm));%用絕對值判斷組別
            for k=1:6%經測試,後63列最大值爲58,前6組夠用
                if (temp>=2^(k-1)) && (temp<2^k)
                    VLIAC=[VLIAC k];
                    break;
                end
            end
        end
    end%該行cz和VLIAC已定,開始計算
    
    sumcode=sumcode+4;%EOB對應1010,就是4bit
    czlen=length(cz)-1; %czlen不包括EOB
    load('JPEG512.mat','codelength');%霍夫曼編碼碼長矩陣(AC、DC亮度編碼表)
    for k=1:czlen
        if VLIAC(k)==0
            sumcode=sumcode+11;
        else
            sumcode=sumcode+codelength(cz(k)+1,VLIAC(k));
        end
    end 
end

壓縮率

%% 壓縮率
OB=512*512*8;
CR=OB/sumcode;
D=I-reI;
MSE = sum(D(:).*D(:))/prod(size(I));

disp(['原圖 Bit:                  ',num2str(OB),' bit']);
disp(['壓縮圖像 Bit:               ',num2str(sumcode),' bit']);
disp(['壓縮比:                     ',num2str(CR)]);
disp(['均方根誤差:                  ',num2str(MSE)]);

end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章