K-rank Approximation for Image Compression Using SVD (How is Storage Size Affected?)

62 views Asked by At

I have a grayscale image that I run SVD on using numpy. I then create a k-rank (let's say rank 10) approximation of it and save it as an image locally. On my finder, the original grayscale image is 5 MB and the new compressed image is 2MB, showing that the compression did indeed work!

However, when I print out the original and compressed image matrix sizes, they're the same! Not sure what's going on here...

import os
import sys
import numpy as np
from PIL import Image
import time

def calculate_file_size(filepath):
    return os.path.getsize(filepath)

def compress_image(input_filename, output_folder, k):
    # Construct the full path
    input_image_path = os.path.join("images", input_filename)

    image = Image.open(input_image_path)
    image_data = np.array(image)

    # Separate color channels
    channels = [image_data[:, :, i] for i in range(image_data.shape[2])]
    compressed_channels = []
    for channel in channels:
        # Reshape data for SVD
        original_shape = channel.shape
        reshaped_data = channel.reshape((-1,1))
        # Apply SVD to reshaped data
        u, s, vt = np.linalg.svd(reshaped_data, full_matrices=False)
        scopy = s.copy()
        scopy[k:] = 0.0
        compressed_data = u.dot(np.diag(scopy)).dot(vt)

        # Reshape data to the original state
        compressed_channel = compressed_data.reshape(original_shape)
        compressed_channels.append(compressed_channel)

    # Combine compressed channels back into a color image
    compressed_image_data = np.stack(compressed_channels, axis=-1)

    # Save compressed image
    compressed_image_path = os.path.join(output_folder, f"compressed_image_rank_{k}.jpg")
    Image.fromarray(compressed_image_data.astype(np.uint8)).save(compressed_image_path, "JPEG")

    original_file_size = calculate_file_size(input_image_path)
    compressed_file_size = calculate_file_size(compressed_image_path)
    print(f"Original File (Matrix) Dimensions: {image_data.shape}")
    print(f"New File (Matrix) Dimensions: {compressed_image_data.shape}")
    print(f"Original File Size: {original_file_size} bytes")
    print(f"Compressed File Size (Rank {k}): {compressed_file_size} bytes")

    percent_compression = (1 - (compressed_file_size / original_file_size)) * 100
    print(f"Percent Compression (Rank {k}): {percent_compression}%")
0

There are 0 answers