在MATLAB中使用SVD压缩图像
image-processing
matlab
8
0

我是MATLAB的新手,但正在尝试为灰度图像做一些图像压缩代码。

问题

如何使用SVD修剪低值特征值以重建压缩图像?

到目前为止的工作/尝试

到目前为止,我的代码是:

B=imread('images1.jpeg');   
B=rgb2gray(B);  
doubleB=double(B);  
%read the image and store it as matrix B, convert the image to a grayscale
photo and convert the matrix to a class 'double' for values 0-255  
[U,S,V]=svd(doubleB);

这使我能够使用存储在变量S中的特征值成功分解图像矩阵。

如何截断S(167x301,双精度类)?假设有167个特征值我只想取前100个(或者实际上是n个),我该怎么做并重建压缩图像?

更新的代码/思想

而不是在注释部分添加一堆代码,这是我目前的草案。我已经能够通过手动更改N成功创建压缩图像,但是我想做2件事:

1-显示各种压缩图像的面板(即,对N = 5,10,25等运行循环)

2-以某种方式计算每个图像与原始图像之间的差异(误差)并绘制图形。

我对理解循环和输出感到恐惧,但这是我尝试过的:

B=imread('images1.jpeg');  
B=rgb2gray(B);  
doubleB=im2double(B);%  
%read the image and store it as matrix B, convert the image to a grayscale  
%photo and convert the image to a class 'double'  
[U,S,V]=svd(doubleB);   
C=S;  
for N=[5,10,25,50,100]  
C(N+1:end,:)=0;  
C(:,N+1:end)=0;  
D=U*C*V';  
%Use singular value decomposition on the image doubleB, create a new matrix  
%C (for Compression diagonal) and zero out all entries above N, (which in  
%this case is 100). Then construct a new image, D, by using the new  
%diagonal matrix C.  
imshow(D);  
error=C-D;  
end

显然有一些错误,因为我没有多张图片或不知道如何“绘制”错误矩阵

参考资料:
Stack Overflow
收藏
评论
共 3 个回答
高赞 时间 活跃

例如,这是Lena的512 x 512黑白图像:

莉娜

我们计算Lena的SVD。选择大于最大奇异值1%的奇异值,我们只剩下53个奇异值 。用这些奇异值和相应的(左和右)奇异向量重构Lena,我们得到Lena的低秩近似

在此处输入图片说明

无需存储512 * 512 = 262144个值(每个取8位),我们可以存储2 x(512 x 53)+ 53 = 54325个值,大约是原始大小的20% 。这是如何使用SVD进行有损图像压缩的一个示例。


这是MATLAB代码:

% open Lena image and convert from uint8 to double
Lena = double(imread('LenaBW.bmp'));

% perform SVD on Lena
[U,S,V] = svd(Lena);

% extract singular values
singvals = diag(S);

% find out where to truncate the U, S, V matrices
indices = find(singvals >= 0.01 * singvals(1));

% reduce SVD matrices
U_red = U(:,indices);
S_red = S(indices,indices);
V_red = V(:,indices);

% construct low-rank approximation of Lena
Lena_red = U_red * S_red * V_red';

% print results to command window
r = num2str(length(indices));
m = num2str(length(singvals));
disp(['Low-rank approximation used ',r,' of ',m,' singular values']);

% save reduced Lena
imwrite(uint8(Lena_red),'Reduced Lena.bmp');
收藏
评论

尽管这个问题很旧,但它对我理解SVD有所帮助。我已经修改了您在问题中编写的代码,以使其正常工作。

我相信您可能已经解决了该问题,但是,仅供以后访问此页面的任何人参考,我将在此处包括完整的代码以及输出图像和图形。

下面是代码:

close all
clear all
clc

%reading and converting the image
inImage=imread('fruits.jpg');
inImage=rgb2gray(inImage);
inImageD=double(inImage);

% decomposing the image using singular value decomposition
[U,S,V]=svd(inImageD);

% Using different number of singular values (diagonal of S) to compress and
% reconstruct the image
dispEr = [];
numSVals = [];
for N=5:25:300
    % store the singular values in a temporary var
    C = S;

    % discard the diagonal values not required for compression
    C(N+1:end,:)=0;
    C(:,N+1:end)=0;

    % Construct an Image using the selected singular values
    D=U*C*V';


    % display and compute error
    figure;
    buffer = sprintf('Image output using %d singular values', N)
    imshow(uint8(D));
    title(buffer);
    error=sum(sum((inImageD-D).^2));

    % store vals for display
    dispEr = [dispEr; error];
    numSVals = [numSVals; N];
end

% dislay the error graph
figure; 
title('Error in compression');
plot(numSVals, dispEr);
grid on
xlabel('Number of Singular Values used');
ylabel('Error between compress and original image');

将此应用到下图: 原始图片

仅使用前5个奇异值给出以下结果,

前5个奇异值

具有前30个奇异值,

前30个奇异值

以及前55个奇异值,

前55个奇异值

下图显示了随着奇异值数量的增加,误差的变化。

误差图

在这里您可以注意到该图显示使用大约200个第一奇异值将产生大约为零的误差。

收藏
评论

刚开始时,我假设您已经知道SVD并不是将单个图像中的像素去相关的最佳工具。但这是一个好习惯。

好的,所以我们知道B = U*S*V' 。而且我们知道S是对角线的,并按大小排序。因此,仅使用S的前几个值,您将获得图像的近似值。假设C=U*S2*V' ,其中S2是您修改后的S。U和V的大小尚未更改,因此目前最简单的方法是将不需要的S元素归零使用,并进行重建。 (最简单的方法是: S2=S; S2(N+1:end, :) = 0; S2(:, N+1:end) = 0; )。

现在是压缩部分。 U已满, V也已满,因此无论S2发生什么,您的数据量都不会改变。但是,看看U*S2发生了什么。 (绘制图像)。如果您在保持ň奇异值S2 ,则只有第N行S2是非零。压缩!除非您仍然需要处理V完成(U*S2) ,您将无法使用相同的技巧,因为U*S2的非零数比S2本身多。我们如何在两侧都使用S2?好吧,它是对角线,所以使用D=sqrt(S2) ,现在使用C=U*D*D*V' 。因此,现在U*D仅具有N个非零行,而D*V'仅具有N个非零列。仅传输那些数量,您就可以重建C,这近似于B。

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号