Hey guys, in this video I'm going to show how to do image compression using singular value decomposition
or SVD in MATLAB. I have a demo written out already
and I am basing my code on this homework problem. Just as a reference:
I'm reconstructing a photo using 5, 10, 25, and 50% of the singular values.
If it seems kind of random that I'm picking those numbers, it's just because it was based on a homework problem
but the results work for any type of image compression that you want to do. Let's go ahead and get started.
This is--I think they're called MATLAB live scripts or something like that--so it lets me print the code and the output in one
window and I'll try to upload this and put a link to it in the description box.
It's a simple code, but in case anyone wants to look at it directly.
So I just
clear the window
and the variables in the first line. And in the second line, I read in my image that I want to compress.
For me, since this was a random homework assignment
I just Google imaged a star, and I found this cheesy image, so this is star.jpg
that's saved locally on my computer, and it's in single quotes.
And you read it in using this function called
'imread', which stands for "image read"
and it saves it as this variable star. I ran this code already and
as you can see when I hover over it, it gives me these values of what star is. Star is a matrix that has
the values of the image. If you go to
your workspace in MATLAB, 'star' has these weird units--or, I guess class--
I don't know what they're called exactly, but you see how the numbers in the matrix are not double. They're these random units called
'uint8'. You do want to convert the values to doubles before you do singular value decomposition.
This line just prints the star.
Before we convert to double and before we do singular value decomposition,
I'm going to convert the image to grayscale. You can do SVD on a colored image,
but gray scaling the image is easier because if you do SVD on a color image, it produces more matrices.
You'll get a matrix for red, green, and blue separately. And so you can do it,
you just basically have to create a loop. But because this was just for a homework assignment,
I just wanted to make it as simple as possible. I in this step just grayscale the image. To do that
there's a function called
'rgb2gray' and I inputted the matrix of the star values
into a new variable called "I". And then I just printed the grayscale image again. Now that we have the image
"I" that's grayscaled now,
we want to convert that "I" matrix
into the values that are double. I did that in this next line. "I2" is equal to 'image to double'. Now the
values in the matrix "I2" are double and they are the correct values that you want to do singular value decomposition on.
I do SVD in the next step, and this is really simple in MATLAB. When you do SVD for your matrix
"I2", you're going to get 'u', 's', and 'v' matrices.
You just save it by doing a bracket [u, s, v]
as your variables
equals, the function that does SVD is just called 'svd', and then you just input your image matrix.
When I did that for my particular image, the matrix size is basically
381. If you look at "s",
it's a diagonal matrix, and it has the singular values on the main diagonal. And when I checked for my particular image, it has
381 total singular values. For my homework problem,
I started with compressing the image to use just 5% of the singular values. In that case
5% of 381 with rounding is equal to using the first
19 singular values. To do that, then what I did was I copied the original full singular value matrix.
I did 's2' is equal to 's'.
So that just copies the matrix of singular values,
and then I added
zeros to everything after the 19th singular value. In that case this line will put in 0 for
the rows 20 to the end of the matrix and this line puts in zeros
from the 20th column to the end of the columns of the matrix. Together that creates zeros along the rest of the main diagonal and
I didn't convert back, so you can actually just print the image from the
double values. To do that, I did matrix multiplication.
You keep the original 'u' and 'v transpose' from your SVD. The only thing you change is the 's'.
I changed it from 's' to 's2', which has the 5% of the singular values and that gives you back an image
matrix that you can print. If you do 'imshow' again, this would be the image if it's
compressed to using only 5% of the singular values. It looks pretty bad. And I basically just repeated the same thing
three more times, so I won't go over the code because it's basically the same thing.
But this is what it would look--so at 10%--
using 10% of the singular values with rounding is about 38, so if you create an 's'
matrix using only the first 38 singular values and then
recreate the image, it will look like this. As you increase the number of singular values that you're using, it will look increasingly better
by
25% it looks pretty good, and then by 50%
I feel like it's almost identical to the original. So yeah, that's it for this video, and thank you for watching!!
*chiptune music plays for outro*