利用Matlab进行图像的编码与压缩(仿照jpeg)
生活随笔
收集整理的這篇文章主要介紹了
利用Matlab进行图像的编码与压缩(仿照jpeg)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文章包含以下內容:
1.選擇matlab自帶圖像cameraman.tif和westconcordorthophoto.png為編碼壓縮的測試圖像。
2.根據設計要求選擇圖像編碼和壓縮方法;
3、設計編碼與壓縮的算法;
4、顯示原始圖像和壓縮重構圖像;
5、計算壓縮的性能指標:壓縮率和保真度;
6、畫出壓縮率和保真度的關系曲線。
本文章中有:
? ? ? ? 圖像讀取,余弦變換,亮度量化,Z字形重排,游程編碼,參數文件保存,
????????參數文件讀取,逆游程編碼,逆Z字形重排,逆量化壓縮,生成壓縮比,保真度。
仿照JPEG壓縮代碼如下:
(可以放到同一個文件里,R2009b以上可以用,不然的話要改函數)
如果覺著數據不好,可以更改Q_New函數中的值。
因為用到了blockproc函數,在R2009b版本以上可以直接用,否則需要改函數。
因為為了畫曲線,進行了100+次圖像壓縮,運行時間較長,想要時間短點,可以更改36行的for循環。
用到了行程編碼,所以如果圖像復雜,可能會越壓越大。
PadPartialBlocks作用是裁剪時,如果不足8*8,則填充成8*8的矩陣
function U()clear;clc;img = imread('cameraman.tif'); % 讀取文件 % img = imread('westconcordorthophoto.png'); % 讀取文件Q = 30; % 品質(1~100),100最好Q_ = Q_New(Q);% blkproc對圖像進行分塊處理,分成8*8的子塊,并用dct2()處理DCT_c = blkproc(img,[8,8],'dct2');figure(); % 開一個窗口subplot(2,3,1);imshow(img);title('原圖'); %顯示原圖% 顯示余弦變換結果subplot(2,3,2);imshow(log(abs(DCT_c)+1),[0,10]);title('余弦變換結果');T = Y_Table(); % 用亮度量化表,用于量化壓縮DCT_c = blkproc(DCT_c,[8,8],'round(x./(P1*P2))',T,Q_); % 量化壓縮% 顯示量化壓縮結果subplot(2,3,3);imshow(log(abs(DCT_c)+1),[0,10]);title('量化壓縮結果');Z = blockproc(DCT_c,[8,8],@Z_open,'PadPartialBlocks',true); % Z字形重排(展開)Z_openS = size(Z); % 記錄展開后大小,方便以后復原Z = Z(:); % 展開成一維Z = forecast(Z); % 預測編碼Z = RLC(Z); % 游程編碼 % save('圖像.mat','Q','S','Z'); % 將大小,游程編碼后結果,保存到文件中 % load('圖像.mat'); % 讀取保存的變量Z = iRLC(Z); % 游程解碼Z = iforecast(Z); % 預測編碼Z = reshape(Z,S(1),S(2)); % 重組Z = blockproc(Z,[64,1],@Z_merge); % 逆Z字重排(合并)DCT_c = blkproc(Z,[8,8],'x.*P1*P2',T,Q_); % 逆量化壓縮% 顯示逆量化壓縮結果subplot(2,3,6);imshow(log(abs(DCT_c)+1),[0,10]);title('逆量化壓縮結果');% 顯示逆變換圖像subplot(2,3,4);imshow(uint8(blkproc(DCT_c,[8,8],'idct2')));title('逆變換圖像');s = size(img); % 得到原圖像的大小,用于計算壓縮率s_ = s(1)*s(2);x_=[];y_=[];for i = 1:1:100[S,Z] = IC(img,i); % 壓縮s_Z = size(Z); % 壓縮后大小x_(length(x_(:))+1) = s_/(s_Z(1)*s_Z(2) + 3); % 壓縮比,+3是要儲存游程編碼大小和Qimg_=iIC(i,S,Z);img_=img_(1:s(1),1:s(2));y_(length(y_(:))+1) = psnr(uint8(img_),img); % 信噪比,客觀保真度% figure,imshow(uint8(img_));end% 繪制壓縮比-保真度subplot(2,3,5);plot(x_,y_);xlabel('壓縮比');ylabel('客觀保真度');title('壓縮比-保真度'); end% 由1~100,映射到實際用的Q上 function Q_ = Q_New(Q) % 品質(1~100),100最好if(Q>100) % 大于一百的和小于1的都拉回來Q = 100;endif(Q<1)Q = 1;endQ_ = 3.03-0.03*Q; % 真正用的Q是這個,你可以改 end% 圖像壓縮編碼函數,輸入圖像,品質(1~100),100最好得到壓縮后的數據 function [S,Z] = IC(img,Q)Q_ = Q_New(Q);% blkproc對圖像進行分塊處理,分成8*8的子塊,并用dct2()處理DCT_c = blkproc(img,[8,8],'dct2');T = Y_Table(); % 用亮度量化表壓縮DCT_c = blkproc(DCT_c,[8,8],'round(x./(P1*P2))',T,Q_);Z = blockproc(DCT_c,[8,8],@Z_open,'PadPartialBlocks',true); % Z字形重排(展開)Z_openS = size(Z); % 記錄展開后大小,方便以后復原Z = Z(:); % 展開成一維 % Z = forecast(Z); % 預測編碼Z = RLC(Z); % 游程編碼 end% 圖像解壓函數,輸入游程編碼結果,Z字重排前大小,輸出解碼后圖像 function img = iIC(Q,S,Z)Q_ = Q_New(Q);T = Y_Table(); % 亮度量化表Z = iRLC(Z); % 游程解碼 % Z = iforecast(Z); % 預測解碼Z = reshape(Z,S(1),S(2)); % 重組Z = blockproc(Z,[64,1],@Z_merge); % 逆Z字重排(合并)Z = blkproc(Z,[8,8],'x.*P1*P2',T,Q_);img = blkproc(Z,[8,8],'idct2'); end% 掏出一個亮度量化表 function T = Y_Table() T =[16 11 10 16 24 40 51 6112 12 14 19 26 58 60 5514 13 16 24 40 57 69 5614 17 22 29 51 87 80 6218 22 37 56 68 109 103 7724 35 55 64 81 104 113 9249 64 78 87 103 121 120 10172 92 95 98 112 100 103 99]; end% 掏出Z字形重排的地址(8*8) function T = Z_address() T =[ 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 ]; end% Z字展開(矩陣變一維) function Z_out = Z_open(Z_input)Z_out = zeros(64,1);Z_out(Z_address()) = Z_input.data; end% Z字合并(一維變矩陣) function Z_out = Z_merge(Z_input)Z_out = Z_input.data(Z_address()); end% 游程編碼 function Y = RLC(X)% 手動處理第一個Y(1) = X(1);Y(2) = 1;c = 1; % 計數器,記錄當前信號在Y的位置C = 2; % 當前信號的游程,關于我為什么不用c+1,這樣好看。s = max(size(X)); % 看看長度,一會有用 for i = (2:s) % 對于每個數據if(X(i)~=Y(c)) % 如果和當前的不一樣c = C + 1; % 信號位置改變C = c + 1; % 游程位置改變Y(c) = X(i); % 記錄信號Y(C) = 1; % 計數1elseY(C) = Y(C) + 1; % 游程加一endend end% 游程解碼 function Y = iRLC(X)c = 1; % 計數器,記錄Y該到哪里了s = max(size(X)); % 看看長度,一會有用 for i = (1:2:s) % 記錄格式為 信息 游程for j = (1:X(i+1)) % 每個信息加游程個數個Y(c) = X(i); % 信息錄入c = c + 1; % 計數+1endend end% 預測函數 function Y = forecast(X)if(length(X)<3)Y = X;return ends1 = X(1);s2 = X(2);Y(1)=X(1);Y(2)=X(2);for i = (3:length(X)) % 線性預測Y(i) = X(i)-(s1+s2)/2;s1 = s2;s2 = X(i);end % Y(50:90) end% 預測解碼 function X = iforecast(Y)if(length(Y)<3)X = Y;return ends1 = Y(1);s2 = Y(2);X(1)=Y(1);X(2)=Y(2);for i = (3:length(Y)) % 線性預測X(i) = Y(i)+(s1+s2)/2;s1 = s2;s2 = X(i);end end結果示例:
?
總結
以上是生活随笔為你收集整理的利用Matlab进行图像的编码与压缩(仿照jpeg)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序员不适合做威客
- 下一篇: NAS信令学习笔记 ——TAU(1)