ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ Ανώτατο Εκπαιδευτικό Ίδρυμα Πειραιά Τεχνολογικού Τομέα ΕΠΕΞΕΡΓΑΣΙΑ ΕΙΚΟΝΑΣ Ενότητα 7: Πρότυπο Συμπίεσης Εικόνας JPEG Ιωάννης Έλληνας Τμήμα Υπολογιστικών Συστημάτων
Άδειες Χρήσης Το παρόν εκπαιδευτικό υλικό υπόκειται σε άδειες χρήσης Creative Commons. Για εκπαιδευτικό υλικό, όπως εικόνες, που υπόκειται σε άλλου τύπου άδειας χρήσης, η άδεια χρήσης αναφέρεται ρητώς. Χρηματοδότηση Το παρόν εκπαιδευτικό υλικό έχει αναπτυχθεί στα πλαίσια του εκπαιδευτικού έργου του διδάσκοντα. Το έργο «Ανοικτά Ακαδημαϊκά Μαθήματα στο Ανώτατο Εκπαιδευτικό Ίδρυμα Πειραιά Τεχνολογικού Τομέα» έχει χρηματοδοτήσει μόνο τη αναδιαμόρφωση του εκπαιδευτικού υλικού. Το έργο υλοποιείται στο πλαίσιο του Επιχειρησιακού Προγράμματος «Εκπαίδευση και Δια Βίου Μάθηση» και συγχρηματοδοτείται από την Ευρωπαϊκή Ένωση (Ευρωπαϊκό Κοινωνικό Ταμείο) και από εθνικούς πόρους. 2
1. Σκοποί ενότητας... 4 2. Περιεχόμενα ενότητας... 4 3. Συνοπτική θεωρία... 5 3.1 Κωδικοποιητής JPEG... 5 3.2 Ανάλυση προγράμματος... 8 3.2.1 Έλεγχος εισόδου... 8 3.2.2 Πίνακες... 8 3.2.2.1 Πίνακας 7.1: Πίνακας κβάντισης για το JPEG... 8 3.2.2.2 Πίνακας 7.2: ZigZag ordering... 9 3.2.3 Αφαίρεση DC συνιστώσας... 9 3.2.3.1 Πίνακας 7.3: Ένα τυχαίο μπλοκ εικόνας... 9 3.2.3.2 Πίνακας 7.4: Το μπλοκ της εικόνας μετά την μετατόπιση... 9 3.2.4 Υπολογισμός του πίνακα μετασχηματισμού DCT... 10 3.2.4.1 Πίνακας 7.5: Πίνακας μετασχηματισμού DCT... 10 3.2.5 Μετασχηματισμός DCT... 10 3.2.5.1 Πίνακας 7.6: Το μπλοκ της εικόνας μετά τον μετασχηματισμό DCT 11 3.2.6 Κβάντιση... 11 3.2.6.1 Πίνακας 7.7: Το μπλοκ της εικόνας μετά την κβάντιση... 11 3.2.7 Αναδιοργάνωση συντελεστών... 12 3.2.8 Εύρεση μηδενικών... 12 3.2.9 Διαμόρφωση δεδομένων εξόδου... 13 3.3 Αποκωδικοποιητής JPEG (Αντίστροφη διαδικασία)... 13 4. Ασκήσεις... 16 4.1 1 η Άσκηση... 16 4.2 2 η Άσκηση... 16 4.3 3 η Άσκηση... 16 4.4 4 η Άσκηση... 16 4.4.1 Εικόνα 1: Αρχική εικόνα... 17 4.4.2 Εικόνα 2: Συμπιεσμένη εικόνα... 18 4.5 5 η Άσκηση... 18 4.5.1 Πίνακας 1: Πίνακας κβάντισης... 18 4.5.2 Εικόνα 3: Συμπιεσμένη εικόνα με διαφορετικό πίνακα κβάντισης... 19 4.6 6 η Άσκηση... 20 4.6.1 Εικόνα 4: Αρχική εικόνα... 20 4.6.2 Εικόνα 5: Συμπιεσμένη εικόνα... 21 3
1. Σκοποί ενότητας Σκοπός της ενότητας είναι να περιγραφεί το πρότυπο συμπίεσης εικόνων JPEG και να κληθεί ο εκπαιδευόμενος να λύσει πρακτικές ασκήσεις. 2. Περιεχόμενα ενότητας H ενότητα αυτή καλύπτει τις ακόλουθες βασικές έννοιες: Το πρότυπο συμπίεσης εικόνας JPEG Συμπίεση χωρίς απώλειες Συμπίεση με απώλειες Εκτεταμένος τρόπος συμπίεσης Ιεραρχικός τρόπος συμπίεσης Με τις αντίστοιχες ασκήσεις για λύση που καλύπτουν τις παραπάνω θεματικές. 4
3. Συνοπτική θεωρία Το πρότυπο JPEG λειτουργεί σε τρία στάδια. Αρχικά χωρίζει την εικόνα σε blocks των 8 x 8 pixels από τα αριστερά προς τα δεξιά και από την κορυφή ως το τέλος. Κάθε block κωδικοποιείται με τον DCT και καθένας από τους 64 μετασχηματισμένους συντελεστές που προκύπτουν κβαντίζεται αναλόγως με την ποιότητα που θέλουμε. Στη συνέχεια οι κβαντισμένοι συντελεστές σαρώνονται με προκαθορισμένο τρόπο, κωδικοποιούνται με VLC και Huffman. Το Σχήμα 7.1 δείχνει το μπλοκ διάγραμμα του κωδικοποιητή JPEG. Σχήμα 7.1: Διάγραμμα κωδικοποιητή JPEG 3.1 Κωδικοποιητής JPEG function y = im2jpeg(x, quality) % IM2JPEG Compresses an image using a JPEG approximation. % Y = IM2JPEG(X, QUALITY) compresses image X based on 8 x 8 DCT % transforms, coefficient quantization, and Huffman symbol % coding. Input QUALITY determines the amount of information that % is lost and compression achieved. Y is an encoding structure % containing fields: % % Y.size Size of X % Y.numblocks Number of 8-by-8 encoded blocks % Y.quality Quality factor (as percent) % Y.huffman Huffman encoding structure, as returned by 5
% MAT2HUFF % % See also JPEG2IM. % Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins % Digital Image Processing Using MATLAB, Prentice-Hall, 2004 % $Revision: 1.4 $ $Date: 2003/10/26 18:37:41 $ error(nargchk(1, 2, nargin)); % Check input arguments if ndims(x) ~= 2 ~isreal(x) ~isnumeric(x) ~isa(x, 'uint8') end error('the input must be a UINT8 image.'); if nargin < 2 end quality = 1; % Default value for quality. m = [16 11 10 16 24 40 51 61 % JPEG normalizing array 12 12 14 19 26 58 60 55 % and zig-zag reordering 14 13 16 24 40 57 69 56 % pattern. 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] * quality; order = [1 9 2 3 10 17 25 18 11 4 5 12 19 26 33... 6
41 34 27 20 13 6 7 14 21 28 35 42 49 57 50... 43 36 29 22 15 8 16 23 30 37 44 51 58 59 52... 45 38 31 24 32 39 46 53 60 61 54 47 40 48 55... 62 63 56 64]; [xm, xn] = size(x); % Get input size. x = double(x) - 128; t = dctmtx(8); % Level shift input % Compute 8 x 8 DCT matrix % Compute DCTs of 8x8 blocks and quantize the coefficients. y = blkproc(x, [8 8], 'P1 * x * P2', t, t'); y = blkproc(y, [8 8], 'round(x./ P1)', m); y = im2col(y, [8 8], 'distinct'); % Break 8x8 blocks into columns xb = size(y, 2); y = y(order, :); % Get number of blocks % Reorder column elements eob = max(x(:)) + 1; % Create end-of-block symbol r = zeros(numel(y) + size(y, 2), 1); count = 0; for j = 1:xb i = max(find(y(:, j))); if isempty(i) % Process 1 block (col) at a time % Find last non-zero element % No nonzero block values i = 0; 7
end p = count + 1; q = p + i; r(p:q) = [y(1:i, j); eob]; count = count + i + 1; % Truncate trailing 0's, add EOB, % and add to output vector end r((count + 1):end) = []; % Delete unusued portion of r y.size = uint16([xm xn]); y.numblocks = uint16(xb); y.quality = uint16(quality * 100); y.huffman = mat2huff(r); 3.2 Ανάλυση προγράμματος 3.2.1 Έλεγχος εισόδου error(nargchk(1, 2, nargin)); % Check input arguments Στην αρχή του προγράμματος ελέγχουμε αν οι παράμετροι και ο τύπος της εικόνας που μας έδωσε ο χρήστης είναι σωστοί. 3.2.2 Πίνακες Παραθέτουμε τον Πίνακα κβάντισης και του zig-zag order που θα χρησιμοποιηθούν στην συνέχεια του προγράμματος. 3.2.2.1 Πίνακας 7.1: Πίνακας κβάντισης για το JPEG 16 11 10 16 24 40 51 61 12 12 14 19 26 58 60 55 8
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 3.2.2.2 Πίνακας 7.2: ZigZag ordering 1 9 2 3 10 17 25 18 11 4 5 12 19 26 33 41 34 27 20 13 6 7 14 21 28 35 42 49 57 50 43 36 29 22 15 8 16 23 30 37 44 51 58 59 52 45 38 31 24 32 39 46 53 60 61 54 47 40 48 55 62 63 56 64 3.2.3 Αφαίρεση DC συνιστώσας x = double(x) - 128; % Level shift input Ένα μπλοκ 8 x 8 της εικόνας φαίνεται στον Πίνακα 7.3: 3.2.3.1 Πίνακας 7.3: Ένα τυχαίο μπλοκ εικόνας 162 158 154 154 159 162 159 159 162 171 122 154 208 154 162 159 159 158 162 154 154 162 154 154 154 154 154 154 171 159 153 153 11 159 153 171 154 154 153 154 159 153 171 153 153 154 159 153 171 171 153 153 154 153 153 153 153 153 153 153 253 171 153 153 Ο Πίνακας 7.4 είναι αυτός που προκύπτει μετά την μετατόπιση: 3.2.3.2 Πίνακας 7.4: Το μπλοκ της εικόνας μετά την μετατόπιση 34 30 26 26 31 34 31 31 34 43-6 26 82 26 34 31 31 30 34 26 26 34 26 26 26 26 26 26 43 31 25 25-117 31 25 43 26 26 25 26 31 25 43 25 25 26 31 25 9
43 43 25 25 26 25 25 25 25 25 25 25 125 43 25 25 3.2.4 Υπολογισμός του πίνακα μετασχηματισμού DCT t = dctmtx(8); % Compute 8 x 8 DCT matrix Ο Πίνακας 7.5 που προκύπτει είναι: 3.2.4.1 Πίνακας 7.5: Πίνακας μετασχηματισμού DCT 0,3536 0,3536 3536 0,3536 0,3536 0,3536 0,3536 0,3536 0,4904 0,1913 0,2778 0,0975-0,0975-0,2778-0,4157-0,4904 0,4619 0,4157-0,1913-0,4619-0,4619-0,1913 0,1913 0,4619 0,4157-0,0975-0,4904-0,2778 0,2778 0,4904 0,0975-0,4157 0,3536-0,3536-0,3536 0,3536 0,3536-0,3536-0,3536 0,3536 0,1913-0,4904 0,0975 0,4157-0,4157-0,0975 0,4904-0,2778 0,2778-0,4619 0,4619-0,1913-0,1913 0,4619-0,4619 0,1913 0,0975-0,2778 0,4157-0,4904 0,4904-0,4157 0,2778-0,0975 3.2.5 Μετασχηματισμός DCT y = blkproc(x, [8 8], 'P1 * x * P2', t, t'); Η συνάρτηση blkproc μετασχηματίζει τους συντελεστές της εικόνας μας με DCT. Είναι ουσιαστικά η βασικότερη συνάρτηση του προγράμματος. Η σύνταξή της φαίνεται παρακάτω: B = blkproc(a, [M N], FUN, P1, P2, ) Α είναι η εικόνα που έχουμε δώσει σαν είσοδο, [M N] είναι η διάσταση του μπλοκ που θα χωρίσουμε την εικόνα (στην συγκεκριμένη περίπτωση 8 x 8). Η παράμετρος FUN είναι η συνάρτηση με την οποία επεξεργαζόμαστε το κάθε μπλοκ της εικόνας μας και P1, P2, διάφοροι παράμετροι που θα θέλαμε να χρησιμοποιήσουμε στη συνάρτηση μας. Για το μετασχηματισμό DCT χρησιμοποιούμε την παρακάτω σχέση: B=C*A*C T 10
όπου A είναι ένα block 8x8 μίας εικόνας, C είναι ένας πίνακας 8x8 για μετασχηματισμό DCT που έχουμε παράγει με την dctmtx(8) και CT είναι ο ανάστροφος πίνακας C. Αν κοιτάξουμε προσεκτικά το πρόγραμμά μας θα δούμε ότι η συγκεκριμένη συνάρτηση χρησιμοποιείται στην παράμετρο FUN της blkproc. B=FUN 'P1 * x * P2' C*A*CT είναι η συνάρτηση μετασχηματισμού. C t P1, είναι ο πίνακας μετασχηματισμού DCT, ενώ A x είναι το αρχικό μπλοκ της εικόνας. Η blckproc αναλαμβάνει να κάνει το μετασχηματισμό για όλα τα μπλοκ της εικόνας και αποθηκεύει το αποτέλεσμα στη μεταβλητή y. Ένα μπλοκ μετασχηματισμένο με DCT έχει την παρακάτω μορφή: 3.2.5.1 Πίνακας 7.6: Το μπλοκ της εικόνας μετά τον μετασχηματισμό DCT -0.0214-0.0214 0.0027 0.0202 0.0364 0.0675 0.0672 0.0285-0.0004-0.0451-0.0131 0.0240 0.0887 0.0269 0.0375 0.0651 0.1665-0.0204-0.0426-0.0063-0.0085-0.0302-0.0127 0.0103 0.0508-0.0143-0.0115-0.0252-0.0222-0.0004-0.0020-0.0149-0.0502 0.0071 0.0163 0.0072 0.0045 0.0124 0.0103-0.0054 0.0674 0.0302 0.0154 0.0526 0.0359-0.0061 0.0102 0.0281 0.0088 0.0384 0.0508 0.0080 0.0003 0.0312 0.0187-0.0061-0.0256-0.0074 0.0022-0.0117-0.0138 0.0088 0.0051-0.0046 3.2.6 Κβάντιση y = blkproc(y, [8 8], 'round(x./ P1)', m); Χρησιμοποιούμε πάλι την blkproc αυτή την φορά για την κβάντιση των συντελεστών του κάθε μπλοκ. FUN round(x./ P1) είναι η συνάρτηση που στρογγυλοποιεί (κβαντίζει) του συντελεστές σύμφωνα με τον πίνακα κβάντισης P1 m που έχουμε δηλώσει στην αρχή του προγράμματος. Στον Πίνακα 7.7 βλέπουμε το μπλοκ που προκύπτει: 3.2.6.1 Πίνακας 7.7: Το μπλοκ της εικόνας μετά την κβάντιση 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 1 10-2 -4 0 0-1 0 0 4-1 -1-1 -1 0 0 0-4 1 1 0 0 0 0 0 5 2 1 2 1 0 0 0 0 2 1 0 0 0 0 0-1 0 0 0 0 0 0 0 11
3.2.7 Αναδιοργάνωση συντελεστών y = im2col(y, [8 8], 'distinct'); % Break 8x8 blocks into columns Με την im2col μετατρέπουμε τα μπλοκ σε στήλες. Αυτό θα μας βοηθήσει αργότερα στην εύρεση των μηδενικών και στην κωδικοποίηση. Η έξοδός της είναι ένας πίνακας όπου κάθε στήλη του περιέχει τα στοιχεία ενός μπλοκ της εικόνας. Η σύνταξή της είναι: B = im2col(a, [M N], distinct ) Οι παράμετροι Α, Β και Μ, Ν έχουν τις ίδιες ιδιότητες με τις αντίστοιχες στην blkproc. Η παράμετρος distinct λέει στην im2col ότι τα δεδομένα της εικόνας δεν είναι αλληλοκαλυπτόμενα. Εναλλακτικά μπορούμε να θέσουμε sliding που φτιάχνει μία στήλη στην Β για κάθε pixel της εικόνας Α. 3.2.8 Εύρεση μηδενικών eob = max(x(:)) + 1; % Create end-of-block symbol r = zeros(numel(y) + size(y, 2), 1); count = 0; Φτιάχνουμε αρχικά ένα χαρακτήρα που συμβολίζει το τέλος του μπλοκ. Μετά από αυτόν τον χαρακτήρα ακολουθούν μόνο μηδενικά. for j = 1:xb i = max(find(y(:, j))); if isempty(i) % Process 1 block (col) at a time % Find last non-zero element % No nonzero block values i = 0; end p = count + 1; q = p + i; r(p:q) = [y(1:i, j); eob]; % Truncate trailing 0's, add EOB, 12
count = count + i + 1; % and add to output vector end Με τον παραπάνω κωδικό βρίσκουμε που τελειώνουν οι μη μηδενικοί συντελεστές σε κάθε μπλοκ και τοποθετούμε ένα σύμβολο ΕΟΒ. 3.2.9 Διαμόρφωση δεδομένων εξόδου Τέλος το πρόγραμμα φτιάχνει μια struct μεταβλητή η οποία περιέχει διάφορες πληροφορίες και την κωδικοποιημένη εικόνα μας. y.size = uint16([xm xn]); Περιέχει τις διαστάσεις της εικόνας. y.numblocks = uint16(xb); Ο αριθμός τον μπλοκ που έχει χωριστεί η εικόνα. y.quality = uint16(quality * 100); Η ποιότητα που έχουμε θέσει. y.huffman = mat2huff(r); Τα δεδομένα μας αφού γίνει η κωδικοποίηση Huffman. 3.3 Αποκωδικοποιητής JPEG (Αντίστροφη διαδικασία) function x = jpeg2im(y) %JPEG2IM Decodes an IM2JPEG compressed image. % X = JPEG2IM(Y) decodes compressed image Y, generating 13
% reconstructed approximation X. Y is a structure generated by % IM2JPEG. % See also IM2JPEG. % Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins % Digital Image Processing Using MATLAB, Prentice-Hall, 2004 % $Revision: 1.4 $ $Date: 2003/10/26 18:39:08 $ error(nargchk(1, 1, nargin)); % Check input arguments m = [16 11 10 16 24 40 51 61 % JPEG normalizing array 12 12 14 19 26 58 60 55 % and zig-zag reordering 14 13 16 24 40 57 69 56 % pattern. 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]; order = [1 9 2 3 10 17 25 18 11 4 5 12 19 26 33... 41 34 27 20 13 6 7 14 21 28 35 42 49 57 50... 43 36 29 22 15 8 16 23 30 37 44 51 58 59 52... 45 38 31 24 32 39 46 53 60 61 54 47 40 48 55... 62 63 56 64]; rev = order; % Compute inverse ordering for k = 1:length(order) end rev(k) = find(order == k); m = double(y.quality) / 100 * m; xb = double(y.numblocks); % Get encoding quality. % Get x blocks. sz = double(y.size); 14
xn = sz(2); xm = sz(1); x = huff2mat(y.huffman); eob = max(x(:)); % Get x columns. % Get x rows. % Huffman decode. % Get end-of-block symbol z = zeros(64, xb); k = 1; for j = 1:xb for i = 1:64 if x(k) == eob k = k + 1; break; % Form block columns by copying % successive values from x into % columns of z, while changing % to the next column whenever % an EOB symbol is found. else z(i, j) = x(k); k = k + 1; end end end z = z(rev, :); % Restore order x = col2im(z, [8 8], [xm xn], 'distinct'); x = blkproc(x, [8 8], 'x.* P1', m); % Form matrix blocks % Denormalize DCT t = dctmtx(8); % Get 8 x 8 DCT matrix x = blkproc(x, [8 8], 'P1 * x * P2', t', t); % Compute block DCT-1 x = uint8(x + 128); % Level shift 15
4. Ασκήσεις 4.1 1 η Άσκηση Φορτώστε την εικόνα street.tif. 4.2 2 η Άσκηση Κωδικοποιήστε την εικόνα που φορτώσατε με το im2jpeg.m χρησιμοποιώντας τέσσερις φορές μεγαλύτερο βήμα κβάντισης από το δεδομένο κβαντιστή. Στη συνέχεια αποκωδικοποιήστε την με το jpeg2im.m. 4.3 3 η Άσκηση Εμφανίστε τη συμπιεσμένη εικόνα στην εικόνα 2 και αποθηκεύστε την χρησιμοποιώντας τη συνάρτηση imwrite. Τι διαφορές παρατηρείτε; Ελέγξτε επίσης το χώρο που καταλαμβάνει η συμπιεσμένη εικόνα σε σχέση με την αρχική. 4.4 4 η Άσκηση Χρησιμοποιείστε το imratio.m και τοποθετήστε παρακάτω την αναλογία συμπίεσης: 16
4.4.1 Εικόνα 1: Αρχική εικόνα 17
4.4.2 Εικόνα 2: Συμπιεσμένη εικόνα Σχόλια: 4.5 5 η Άσκηση Κωδικοποιήστε την εικόνα χρησιμοποιώντας τον παρακάτω πίνακα κβάντισης. Τι παρατηρείτε; Σημείωση: θα πρέπει να αλλάξετε τον πίνακα κβάντισης του προγράμματος μ αυτόν που σας δίνετε. 4.5.1 Πίνακας 1: Πίνακας κβάντισης 17 18 24 47 99 99 99 99 18 21 26 66 99 99 99 99 24 26 56 99 99 99 99 99 47 66 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 18
4.5.2 Εικόνα 3: Συμπιεσμένη εικόνα με διαφορετικό πίνακα κβάντισης Σχόλια: 19
4.6 6 η Άσκηση Πως θα μπορούσαμε να αλλάξουμε το βήμα κβάντισης (μεγαλώνοντας ή μικραίνοντας έτσι τη συμπίεση) δίχως να χρησιμοποιήσουμε τη μεταβλητή quality του προγράμματος; Υλοποιείστε ένα παράδειγμα με μια δικιά σας εικόνα (τύπου tiff), γράφοντας στα σχόλια την αναλογία συμπίεσης και τα συμπεράσματα που βγάλατε. 4.6.1 Εικόνα 4: Αρχική εικόνα 20
4.6.2 Εικόνα 5: Συμπιεσμένη εικόνα Σχόλια: 21