做一个图片的 SVD

SVD,奇异值分解。和矩阵的特征值差不多。

在这里可以使用 SVD 进行压缩:取得图片的奇异值后,舍去部分数值比较小的值。这样就是一个有损压缩。

不过,原来一个值就好了,现在变成了三个值,再存储…… 真的能压缩么?我真的不知道工业上是如何存储以达到压缩目的的。

下面只是个 Demo…… 只是个 Demo…… 只是个 Demo……

代码

close all
clear all
clc

% 读入图片
image_filename = 'onion.png';
image_raw = rgb2gray(imread(image_filename));
image_double = double(image_raw);

% 做奇异值分解
[U,S,V] = svd(image_double);

% 使用不同数量的奇异值,对图片做压缩和重建
errors = [];
n_used = [];
for i = 1:12
    N = 25 * i - 20;
    C = S;

    % 舍去部分奇异值,只保留左上角的那些
    C(N+1:end,:)=0;
    C(:,N+1:end)=0;

    % 重建图片
    image_reconstruct=U*C*V';


    % 显示图片,计算与原图的差值
    subplot(4,3,i),imshow(uint8(image_reconstruct));
    title(sprintf('使用 %i 个奇异值', N));
    error=sum(sum((image_double-image_reconstruct).^2));

    % store vals for display
    errors = [errors; error];
    n_used = [n_used; N];
end

% 与原图的差
figure;
title('与原图的差');
plot(n_used, errors);
grid on
xlabel('取多少个奇异值');
ylabel('与原图的差值');

结果

图片结果

与原图差值

最后

本来想拿 Python 写的,无奈一 import skimage.io 之后,就无法用 gui 显示图片了,只能用 imsave 来做输出…… 好忧伤。

《做一个图片的 SVD》有4条留言

留下评论