Image Compression using DCT implementing Matlab
Name: Kaushik Baruri
ASU ID: 1207833857
Email ID:
[email protected]
Subject Code: CEN 501
Table of Contents:
Introduction 3
Matlab Code and Implementation 8
Simulation Results: 11
Conclusion 15
Introduction:
In today's technological world as our use of and reliance on computers
continues to grow, so too does our need for efficient ways of storing large
amounts of data and due to the bandwidth and storage limitations, images
must be compressed before transmission and storage.
However, the compression will reduce the image fidelity, especially when
the images are compressed at lower bit rates. The reconstructed images
suffer from blocking artifacts and the image quality will be severely
degraded under the circumstance of high compression ratios. In order to
have a good compression ratio without losing too much of information when
the image is decompressed we use DCT (Discrete Cosine Transform).
Discrete Cosine Transform
A discrete cosine transform (DCT) expresses a sequence of finitely many
data points in terms of a sum of cosine functions oscillating at different
frequencies. Image compression using DCT process includes:
1. The image is broken into 8x8 blocks of pixels.
2. Working from left to right, top to bottom, the DCT is applied to each
block.
3. Each block is compressed through quantization.
4. The array of compressed blocks that constitute the image is stored in
a drastically reduced amount of space.
5. The image is reconstructed through decompression, a process that uses
the Inverse Discrete Cosine Transform (IDCT).
The DCT equation is:
The DCT Matrix:
For 8X8 block it results in a matrix:
The columns of the above matrix T form an orthonormal set, so T is an
orthogonal matrix. When doing the inverse DCT the orthogonality of T is
important, as the inverse of T is T' which is easy to calculate.
DCT on an 8X8 block:
Read the original image and get the values of the pixels from the image in
the blocks. Because DCT is designed to work on pixel values ranging from
-128 to 127, the original block is leveled off by subtracting 128 from each
entry.
The discrete cosine transform is accomplished by:
D = TMT' --------------------------------
--------------------------------- Eq (1)
Here T is the DCT matrix and M is the original image matrix which is
leveled off by subtracting 128.
In Eq (1): Matrix M is first multiplied on the left by the DCT matrix T,
this transforms the rows. The columns are then transformed by multiplying
on the right by the transpose of DCT matrix. This will result in DCT
matrix.
The Matrix M after leveling off (8x8 BLOCK):
The matrix D after DCT (8X8) block:
Quantization:
Our 8x8 block of DCT coefficients is now ready for compression by This
enables the user to decide on quality levels ranging from 1 to 100, where 1
gives the poorest image quality and highest compression, while 100 gives
the best quality and lowest compression. As a result, the
quality/compression ratio can be tailored to suit different needs.
Subjective experiments involving the human visual system have resulted in
the JPEG standard quantization matrix. With a quality level of 50, this
matrix renders both high compression and excellent decompressed image
quality.
DCT_quantizer = ... % levels for quantizing the DCT block (8x8 matrix)
[ 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 ];
For a quality level greater than 50 (less compression, higher image
quality), the standard quantization matrix is multiplied by (100-quality
level)/50. For a quality level less than 50 (more compression, lower image
quality), the standard quantization matrix is multiplied by 50/quality
level. The scaled quantization matrix is then rounded and clipped to have
positive integer values ranging from 1 to 255.
Quantization is achieved by dividing each element in the transformed image
matrix D by corresponding element in the quantization matrix, and then
rounding to the nearest integer value. Example of a Quantized matrix is:
The coefficients situated near the upper-left corner correspond to the
lower frequencies to which the human eye is most sensitive of the image
block. In addition, the zeros represent the less important, higher
frequencies that have been discarded, giving rise to the lossy part of
compression. As mentioned earlier, only the remaining nonzero coefficients
will be used to reconstruct the image. It is also interesting to note the
effect of different quantization matrices; use of quality level Q10 would
give significantly more zeros, while Q90 would result in very few zeros.
CODING
Before storage, all coefficients of C are converted by an encoder to a
stream of binary data (01101011...).
Decompression
Reconstruction of our image begins by decoding the bit stream representing
the Quantized matrix. Each element of quantized matrix is then multiplied
by the corresponding element of the quantization matrix originally used.
The IDCT is applied to the resulted matrix which is rounded to the nearest
integer. Final 128 is added to the each element of the matrix to produce
the decompressed original image.
Matlab Code and Implementation
%Read the image from the local disk
fid=fopen('E:\ASU\Courses\1st Sem\Computer Systems - I\lena.raw','r');
data=fread(fid);
%read the data from the image
data=reshape(data,[512 512]);
data=data';
%Read the original data for DCT
orig_img=data;
imshow(orig_img);
% Define block size for segementation
blocksize=8;
% Calculate the DCT transform matrix DCT_Trans
i = 0;
for j = 0: blocksize - 1
DCT_trans(i + 1, j + 1) = sqrt(1 / blocksize) ...
* cos ((2 * j + 1) * i * pi / (2 * blocksize));
end
for i = 1: blocksize - 1
for j = 0: blocksize - 1
DCT_trans(i + 1, j + 1) = sqrt(2 / blocksize) ...
* cos ((2 * j + 1) * i * pi / (2 * blocksize));
end
end
sz = size(orig_img);
rows = sz(1,1); % finds image's rows and columns
cols = sz(1,2);
% Because the DCT is designed to work on pixel values ranging from -128 to
127, the original
%block is "leveled off"
%by subtracting 128 from each entry.
orig_img=orig_img-128;
DCT_quantizer = ... % levels for quantizing the DCT block (8x8 matrix)
[ 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 ];
quant_multiple = 0.05; % set the multiplier to change size of quant.
levels
% (The values of this defines the number of zero
% coefficients)
% Take DCT of blocks of size blocksize
fprintf(1, '\nFinding the DCT and quantizing...\n');
starttime = cputime; % "cputime" is an internal cpu time
counter
jpeg_img = orig_img - orig_img; % zero the matrix for the compressed
image
for row = 1: blocksize: rows
for col = 1: blocksize: cols
% take a block of the image:
DCT_matrix = orig_img(row: row + blocksize-1, col: col + blocksize-1);
% perform the transform operation on the 2-D block
DCT_matrix = DCT_trans * DCT_matrix * DCT_trans';
% quantize it (levels stored in DCT_quantizer matrix):
DCT_matrix = floor (DCT_matrix ...
./ (DCT_quantizer(1:blocksize, 1:blocksize) *
quant_multiple)+0.5);
% place it into the compressed-image matrix:
jpeg_img(row: row + blocksize-1, col: col + blocksize-1) = DCT_matrix;
end
end
% Reverse the process (take the Inverse DCT)
fprintf(1, 'Reconstructing quantized values and taking the inverse
DCT...\n');
starttime = cputime;
recon_img = orig_img - orig_img; % zero the matrix for the reconstructed
image
for row = 1: blocksize: rows
for col = 1: blocksize: cols
% take a block of the image:
IDCT_matrix = jpeg_img(row: row + blocksize-1, col: col + blocksize-1);
% reconstruct the quantized values:
IDCT_matrix = IDCT_matrix ...
.* (DCT_quantizer(1:blocksize, 1:blocksize) *
quant_multiple);
% perform the inverse DCT:
IDCT_matrix = DCT_trans' * IDCT_matrix * DCT_trans;
% place it into the reconstructed image:
recon_img(row: row + blocksize-1, col: col + blocksize-1) =
IDCT_matrix;
end
end
%Adding 128 as we substracted 128 from the original image
orig_img=orig_img+128;
recon_img=recon_img+128;
% Calculate signal-to-noise ratio
fprintf(1, 'Finding the signal-to-noise ratio...\n');
PSNR = 0;
for row = 1:rows
for col = 1:cols
PSNR = PSNR + (orig_img(row, col) - recon_img(row, col)) ^ 2;
end
end
PSNR = 10 * log10 ((255^2) / (1 / (((rows + cols) / 2) ^ 2) * PSNR));
% (averaged rows and cols together)
% Plot the original, compressed and deconstructed image.
figure(1)
subplot(3,2,1), image(data), title('Original Image');
subplot(3,2,2), image(jpeg_img), title('compressed Image with one half the
coefficients in each blocks to be zero');
subplot(3,2,3), image(recon_img), title('reconstructed Image where one half
the coefficient in each block is zero');
fprintf(1, '\nThe signal-to-noise ratio (PSNR) for one half of the
coefficient to be zero is: %1.3f dB\n\n', PSNR);
% Code the image
% No of non zero elements in the matrix
n=0;
n=nnz(jpeg_img);
%Total bits to code the image
tb=0;
tb=n*10;
%Average no of bits per pixel
Avg_bits=0;
Avg_bits=tb/(512*512);
fprintf(1, '\nThe total no of bits used to code the image is:%1.3f\n', tb);
%#ok
fprintf(1, '\nThe average no of bits per pixel is: %1.3f\n', Avg_bits);
%#ok
%Plot 2D DFT magnitude spectrum of original signal
fs = 1000;
t = 0:1/fs:1-(1/fs);
X1 = fftshift(fft(data));
X1 = abs(X1);
subplot(3,2,4)
plot(X1/fs);
title('Magnitude Spectrum of original signal');
X2=fftshift(fft(recon_img));
X2=abs(X2);
subplot(3,2,5)
plot(X1/fs);
title('Magnitude Spectrum of reconstructed image signal');
Simulation Results:
For one half the coefficient in each block is zero
The original Image, the compressed image, the reconstructed image,
magnitude spectrum of original and reconstructed image is:
The total no of bits used to code the image is: 1311790.000(10-bit used
for each non zero coef)
The average no of bits per pixel is: 5.004
The signal-to-noise ratio (PSNR) for one half of the coefficient to be zero
is: 45.289 dB
For one fourth the coefficient in each block is zero:
The signal-to-noise ratio (PSNR) for one half of the coefficient to be zero
is: 52.837 dB
The total no of bits used to code the image is: 1976510.000(10-bit used for
each non zero coef)
The average no of bits per pixel is: 7.540
For three fourth the coefficient in each block is zero:
The signal-to-noise ratio (PSNR) for one half of the coefficient to be zero
is: 40.098 dB
The total no of bits used to code the image is: 679220.000(10-bit used for
each non zero coef)
The average no of bits per pixel is: 2.591
Conclusion
The simulation results show that with increase in the number of zero
coefficients the image is compressed more.
As a result, the number of bits required transmitting decreases with
increase in the number of zero coefficients and the PSNR also decreases.
And moreover if we observe as the resolution of the image is very high,
even after sufficient compression and decompression there is very less
change in the original and decompressed image. Thus, we can also conclude
that at the same compression ratio the difference between original and
decompressed image goes on decreasing as there is increase in image
resolution.