Teoria delle ondicelle 2/ Compressione di segnali e immagini a.a. 2006/2007 JPEG
function y = im2jpeg(x,quality) % y = im2jpeg(x,quality) comprime una immagine x usando lo schema % di JPEG: dct 8x8, quantizzazione, codifica di Huffman. % quality è uno scalare con il quale si modifica la tabella di % quantizzazione rispetto alla qualità con cui si vuole codificare % y è una variabile di tipo struct con i seguenti campi % y.size = dimensione di x % y.numblocks = numero di blocchi 8*8 % y.quality = fattore di qualità (in percentuale) % y.huffman = output della funzione mat2huff error(nargchk(1,2,nargin)); % controllo delle variabili di input if ndims(x)~= 2 | ~isreal(x) | ~isnumeric(x) | ~isa(x,'uint8') error('la variabile di input deve essere una immagine uint8 ') end if nargin < 2, quality = 1;, end
% tabella di quantizzazione m = [ ; ; ; ; ; ; ; ] * quality; % tabella per l'ordinamento a zig zag order = [ ];
[xm,xn] = size(x); % determina la dimensione della immagine di input x = double(x) - 128; % sottrae 128 ai valori della immagine di input t = dctmtx(8); % determina la matrice 8x8 per il calcolo della DCT y = blkproc(x,[8 8],'P1*x*P2',t,t'); % calcolo della DCT di x su blocchi % Bi di dimensione 8x8 usando la % seguente formula t*Bi*t' y = blkproc(y,[8 8],'round(x./P1)',m); % quantizza i coefficienti della % DCT di ogni blocco secondo % la tabella m y = im2col(y,[8 8],'distinct'); % trasforma ogni blocco 8x8 in un vettore % colonna, y è ora una matrice di % dimensione 64*numero_di_blocchi xb = size(y,2); % calcola il numero dei blocchi y = y(order,:); % ordina gli elementi di ogni blocco secondo % lo schema a zig zag in order
eob = max(x(:)) + 1; % definisce il simbolo di fine blocco r = zeros(numel(y)+size(y,2),1); count = 0; for j = 1:xb % per ogni blocco: i = max(find(y(:,j))); % trova l'ultimo elemento diverso da zero if isempty(i) i = 0; end p = count + 1; % tronca la sequenza eliminando gli zeri e % la aggiunge al vettore di output insieme q = p + i; % al simbolo di fine blocco r(p:q) = [y(1:i,j);eob]; count = count + i + 1; end r(count+1:end) = []; % elimina gli elementi di r non usati
% definisce la variabile di output y.size = uint16([xm xn]); y.numblocks = uint16(xb); y.quality = uint16(quality*100); y.huffman = mat2huff(r);
function x = jpeg2im(y) % x = jpeg2im(y) decodifica un' immagine codificata con la funzione % im2jpeg.m % % y è una variabile di tipo struct generata dalla funzione im2jpeg % x è una matrice corrispondente alla approssimazione della immagine % codificata in y error(nargchk(1,1,nargin)); % controllo della variabile di input
% tabella di quantizzazione m = [ ; ; ; ; ; ; ; ]; % tabella per l'ordinamento a zig zag order = [ ];
rev = order; % calcola l'ordinamento inverso % (da zig zag a lessicografico) for k = 1:length(order) rev(k) = find(order == k); end m = double(y.quality)/ 100 * m; % ricostruisce la tabella di % quantizzazione rispetto alla qualità % con cui si è effettuata la codifica xb = double(y.numblocks); % legge il numero di blocchi sz = double(y.size); % legge la dimensione della immagine da % decodificare xn = sz(2); % numero di colonne xm = sz(1); % numero di righe x = huff2mat1(y.huffman); % decodifica con l'algoritmo di Huffman eob = max(x(:)); % estrae il simbolo di fine blocco
z = zeros(64,xb); % definisce una matrice di zeri in cui ogni colonna % ha la dimensione di un blocco 8x8 stirato k = 1; % legge il vettore x e conserva gli elementi diversi % da zero in ogni colonna di z. for j = 1:xb % Ogni volta che trova un eob cambia blocco, % ovvero colonna di z for i = 1:64 if x(k) == eob k = k + 1; break; else z(i,j) = x(k); k = k + 1; end
z = z(rev,:); % ordina gli elementi di ogni colonna di z % secondo l'ordinamento lessicografico di % una matrice 8x8 x = col2im(z,[8 8],[xm xn],'distinct'); % genera una matrice di % dimensione xm*xn come % composizione di blocchi di % dimensione 8x8 i cui % elementi corrispondono ad % una colonna di z x = blkproc(x,[8 8],'x.*P1',m); % operazione inversa della % quantizzazione t = dctmtx(8); % determina la matrice 8x8 per % il calcolo della DCT x = blkproc(x,[8 8],'P1*x*P2',t',t); % per ogni blocco calcola la dct % inversa con l'operazione t'*Bi*t x = uint8(x + 128); % aggiunge 128 e trasforma in una % variabile uint8
% esempio di codifica e decodifica di una immagine usando le funzione % im2jpeg e jpeg2im I = zeros(16)+2; % immagine da codificare I(5:12,4:13) = 200; I = uint8(I); C1 = im2jpeg_ese(I); % codifica con im2jpeg Id = jpeg2im(C1); % decodifica con jpeg2im CR = imratio(I,C1); % calcola il rapporto di compressione disp('RAPPORTO DI COMPRESSIONE'), disp(CR), pause bpp = 8/CR % calcola il bpp % calcola il PSNR psnr = 10*log10(255^2/(mean2(abs(double(I)-double(Id)).^2))) figure, imshow(I,[]), title('immagine originale') figure, imshow(Id,[]), title('immagine decodificata')
function CR = imratio(I1,I2) % calcolo del rapporto di compressione CR = bytes(I1)/bytes(I2); % function b = bytes(I) % legge il numero di bytes della variabile b. Se b è di tipo struct, legge % i bytes occupati da ogni campo if ischar(I) % caso in cui I è il nome di un file info = dir(I);, b = info.bytes; elseif isstruct(I) % se I è una variabile di tipo struct, richiama ricorsivamente se stessa b = 0;, fields = fieldnames(I); for k = 1:length(fields) b = b + bytes(getfield(I,char(fields(k)))); end else % I non è una variabile di tipo struct info = whos('I');, b = info.bytes; end
% esempio di codifica e decodifica di una immagine usando le funzione % im2jpeg e jpeg2im I = imread('cameraman.tif'); % legge l'immagine da codificare C1 = im2jpeg(I); % codifica con im2jpeg Id = jpeg2im(C1); % decodifica con jpeg2im CR = imratio(I,C1); % calcola il rapporto di compressione disp('RAPPORTO DI COMPRESSIONE') disp(CR), pause bpp = 8/CR % calcola il bpp % calcola il PSNR psnr = 10*log10(255^2/(mean2(abs(double(I)-double(Id)).^2))) figure, imshow(I,[]), title('immagine originale') figure, imshow(Id,[]), title('immagine decodificata')
function [bpp,psnr] = curvaRDjpeg(nameim) % disegna la curva Rate Distortion per l'immagine nameim I = imread(nameim); % legge l'immagine da codificare for q = 1:15 C1 = im2jpeg(I,q); % codifica con im2jpeg Id = jpeg2im(C1); % decodifica con jpeg2im CR(q) = imratio(I,C1); % calcola il rapporto di compressione disp('qualita'), disp(q) disp('RAPPORTO DI COMPRESSIONE'), disp(CR(q)) bpp(q) = 8/CR(q) % calcola il bpp psnr(q) = 10*log10(255^2/(mean2(abs(double(I)-double(Id)).^2))) %PSNR pause figure, imshow(I,[]), title('immagine originale') figure, imshow(Id,[]), title(['immagine decodificata, qualita ',num2str(q)]) pause end figure, plot(bpp,psnr), title('Curva RD')