SVD for image compression
In-class work
Math 221 Linear Algebra
December 3, 2024

T. Ratliff, Wheaton College
ratliff_thomas@wheatoncollege.edu

Loading an image and converting to grayscale

These are the Mathematica commands to import an image, 
convert it to grayscale, and 
place the numeric code for each pixel in a matrix aGray.

image1 =Import["https://tratliff.webspace.wheatoncollege.edu/2024_Fall/math221/local/Paper_Deer_Trophy.jpg"]
image1Gray = ColorConvert[image1,"Grayscale"]
aGray= N[ImageData[image1Gray,"Byte"]];

Let’s compare the dimensions

ImageDimensions[image1Gray]
Dimensions[aGray]

It’s kind of annoying that these are in different orders, but the image dimensions are width x height, whereas the matrix is rows x columns.

Looking at the singular values

Load the singular values of aGray into a list, see how long the list is, and then look at the first 50 singular values.

sVals=SingularValueList[aGray];
Length[sVals]
sVals[[1;;50]]

They sure start big, (Subscript[σ, 1]) = 137 179 but then start to get smaller quickly. 
Let’s plot the first 200 singular values.

ListPlot[sVals[[1;;200]]]

These seem to drop pretty quickly from over 130,000 to under 1000 by the time we hit the 100th singular value.

A singular value decomposition using the largest 100 singular values

Rather than taking the entire singular value decomposition, let’s look at the singular value decomposition with the 100 largest singular values, and see what the resulting image looks like. 

The Image[aGraySVG/256] will convert the array back to the image format that is pleasing to Mathematica.

{aGu, aGs, aGv} = SingularValueDecomposition[aGray,100];
aGraySVG = aGu.aGs.Transpose[aGv];
Image[aGraySVG/256]

And what’s the point?

How many values do we need to store for our original image?

Dimensions[aGray]

So we have 1200 x 900 = 1,080,000 values in the original image. 

To create the matrix aGraySVG, we used the svd with 100 singular values:  aGu, aGs, aGv

Dimensions[aGu]
Dimensions[aGs]
Dimensions[aGv]

This required us storing  (1200 x 100) + (1 x 100) + (900 x 100) =  210,100 values.

Notice that since we know that we only need to store the diagonal entries of aGs to recreate it.

Therefore, we are storing a lower-resolution version of the image using

N[210100/1080000]

about 19.5% of the space of the original!

Some exercises for you

1. What does the image look like if you compress it by 50% instead?

Some Mathematica work here!

2. What does image look like if you compress it by 90%?

Some more Mathematic work here!

Another image to play around with

Repeat the two exercises above for this image

image2 = Import["https://tratliff.webspace.wheatoncollege.edu/2024_Fall/math221/local/Link.jpg"]