Skip to content

Image compression

dmckinnon edited this page Dec 18, 2019 · 4 revisions

Image compression

This assumes you've either read the SVD page in this wiki, or have a good understanding of SVD anyway.

Here I'm going to go over the basics of how SVD can be used for image compression, how my code works, and some analysis of this. Plenty of other people have already written about this, some really well, and there are working demos too, so I feel I don't need incredible detail.

Compress an image with SVD

The basic idea of this is that we treat an image as a matrix (let's assume that all images are grayscale, For colour, just multiply by three for each channel), say a 640x480 matrix A. Then we can compute the SVD of A, and approximate it with the top k singular values. When we compute A (k), which is the k - singular value approximation to A, we then have an approximation to the original image. Pretty simple! But how does this compress the image? It still has the same number of pixels, after all.

Well, let's consider it in number of values to store. A 640x480 image, raw, uses 640 * 480 = 307200 bytes + a small overhead of image header. Let k = 50, which experimentally gives a reasonable image approximation. Then we're storing 50 vectors of length 480 for the left singular vectors, the same for right, and 50 singular values. Adding this up, we get 100*480 + 50 = 4850 values < 307200 values. A much smaller number! There's our compression.

But if this is so wonderful, why is it not used everywhere? Why do we not have .svd image files? Well, for two reasons. One, jpg compression is even better - a quick test found that a raw image size of 122kb got compressed down to 16kb. That's a compression factor of 7.6. That may look less than the above ratio, but this brings us to the second reason - how to store these values. This is something that none of the sources I found addressed - alas - but is rather important. SVD is computed in floating point, and in C++ at least a float uses 4 bytes. So while we store only 4850 numbers, it takes up 19400 bytes, when stored in a raw format, plus some small overhead in the file to denote where the matrices start and end. This could be compressed further with some sacrifice of accuracy - 2 byte floats exist, so we could halve that. But the jpg I computed had far less image error - defined as the pixel-wise difference between two images - than a 50-singular value approximation. So SVD Image Compression, while it legitimately compresses, isn't as good as the leading methods out there. But it's still good! And it's an interesting application of Singular Value Decomposition.

Clone this wiki locally