理论部分参考这篇文章,写的非常好。
本文主要是直观感受一下SVD对图像进行压缩的作用。案例图片如下(PS:图片为华山,拍摄于2023/4/29)
1、首先需要将上述图片转换为矩阵,利用imread命令;
img = imread('1.jpg')
2、我们需要对其进行分解为R,G,B三个矩阵,上述三个矩阵的大小都是 6000 × 8000 6000\times8000 6000×8000的,还是比较大的。
%分解RGB三原色
R = im2double(img(:,:,1));
G = im2double(img(:,:,2));
B = im2double(img(:,:,3));
3、然后对每个矩阵进行SVD分解
%对每个矩阵进行SVD分解
[UR,SR,VR ] = svd(R);
[UG,SG,VG ] = svd(G);
[UB,SB,VB ] = svd(B);
4、提取前K个奇异值,重新组装彩图矩阵
K=1;%前5个奇异值
URK=UR(:,1:K);SRK=SR(1:K,1:K);VRK=VR(:,1:K);
RK=URK*SRK*VRK';
%%
UGK=UG(:,1:K);SGK=SG(1:K,1:K);VGK=VG(:,1:K);
GK=UGK*SGK*VGK';
%%
UBK=UB(:,1:K);SBK=SB(1:K,1:K);VBK=VB(:,1:K);
BK=UBK*SBK*VBK';
%%组装压缩后的RBG矩阵
img_svd = zeros(6000,8000,3);
img_svd(:,:,1) = RK;img_svd(:,:,2) = GK;img_svd(:,:,3) = BK;
虽然上述彩图矩阵的大小依然是
6000
×
8000
×
3
6000\times 8000\times3
6000×8000×3,但是其是由6个比较小的矩阵合成的,以R矩阵为例,其原始大小为
6000
×
8000
6000\times8000
6000×8000,经过svd分解后,取前1个奇异值时,组成RK的三个矩阵为
6000
×
1
,
1
×
1
,
8000
×
1
6000\times1,1\times1,8000\times1
6000×1,1×1,8000×1;直接变成了原来的
6000
×
8000
/
(
6000
+
8000
+
1
)
=
3428
6000\times8000/(6000+8000+1) = 3428
6000×8000/(6000+8000+1)=3428分之1。
5、最后让我们来看一下压缩后的图片与原始图片的对比
% 显示图像
figure;
subplot(1,2,1),imshow(img),title('原始图像')
subplot(1,2,2),imshow(img_svd),title('压缩图像')
sgtitle(strcat(['取前',num2str(K),'个奇异值']))
1)K= 1时
2)K= 10时
3)K= 100时
可以看出,随着所取的奇异值的个数增加,图片越来越接近原始图片,K=100时,已经非常接近,但是数据量却十分的小,仅是原始图片的1/7。由此可以看出SVD压缩图片的威力。
附上完整代码如下:
% 读入PNG图像
img = imread('1.jpg');
%分解RGB三原色
R = im2double(img(:,:,1));
G = im2double(img(:,:,2));
B = im2double(img(:,:,3));
%对每个矩阵进行SVD分解
[UR,SR,VR ] = svd(R);
[UG,SG,VG ] = svd(G);
[UB,SB,VB ] = svd(B);
%%
K=100;%前5个奇异值
URK=UR(:,1:K);SRK=SR(1:K,1:K);VRK=VR(:,1:K);
RK=URK*SRK*VRK';
%%
UGK=UG(:,1:K);SGK=SG(1:K,1:K);VGK=VG(:,1:K);
GK=UGK*SGK*VGK';
%%
UBK=UB(:,1:K);SBK=SB(1:K,1:K);VBK=VB(:,1:K);
BK=UBK*SBK*VBK';
%%组装压缩后的RBG矩阵
img_svd = zeros(6000,8000,3);
img_svd(:,:,1) = RK;img_svd(:,:,2) = GK;img_svd(:,:,3) = BK;
% 显示图像
figure;
subplot(1,2,1),imshow(img),title('原始图像','fontsize',40)
subplot(1,2,2),imshow(img_svd),title('压缩图像','fontsize',40)
sgtitle(strcat(['取前',num2str(K),'个奇异值']),'fontsize',40)