matlab-利用SVD(奇异值分解)来进行图片压缩

参考博客
参考博客1(大致上的理论理解):https://www.cnblogs.com/MrLJC/p/4158818.html?utm_source=tuicool
参考博客2(压缩率):https://blog.csdn.net/fllubo/article/details/8273493
参考博客3(代码):https://www.cnblogs.com/tiandsp/archive/2012/10/24/2737769.html
参考博客4(彩色图片怎么重建):
https://blog.csdn.net/fllubo/article/details/8273493
感谢各位博主!

文章目录

    • 通俗解释
    • 代码
    • 效果

图象压缩挺重要的,而百度百科上说: 奇异值分解(Singular Value Decomposition,SVD)是线性代数中一种重要的矩阵分解,奇异值分解则是特征分解在任意矩阵上的推广。具体的数学原理我不是很清楚,这篇博客主要总结的是在matlab中如何利用SVD来进行图片压缩。

通俗解释

根据参考博客1中,地址为:https://www.cnblogs.com/MrLJC/p/4158818.html?utm_source=tuicool,该博客说——所说很多情况下,数据的一小部分包含了数据的绝大部分信息,线性代数中有很多矩阵的分解技术可以将矩阵表示成新的易于处理的形式,不同的方法使用与不同的情况。最常见的就是SVD,SVD将一个矩阵分解三个矩阵U,S,V,这里得到的S是一个对角阵(就是非对角线元素都是0),其中对角元素为奇异值,并且它告诉了我们重要的特征。而参考博客2中,地址为:https://blog.csdn.net/fllubo/article/details/8273493,其中,奇异值从小到大的顺序排列。如果从中选取前k项,则数据量为(m+n+1)k<
关于这句话如何理解呢,举个例子吧,有一张图片A大小为250*189.那么对该图片矩阵A进行svd分解,可以得到3个矩阵——U、S、V,其中矩阵U大小是250*250,矩阵S大小是250*189,注意S是一个对角阵,矩阵V大小是189*189
他们的关系是
A=(矩阵U) x (矩阵S) x(矩阵V的转置),
奇异值从小到大的顺序排列。如果从中选取前k项,就是在对应的3个矩阵中,我们可以在3个矩阵中取前k个项,(k不能大于矩阵S的秩)
B=(矩阵U1) x (矩阵S1) x(矩阵V1的转置),
我们可以用B来近似表示A,矩阵U1大小是250*k,矩阵S1大小是k*k,矩阵V1大小是189*k,那么,当k取合适的值的时候,B和A的质量很接近,而一开始我们需要记录矩阵A,250*189=47250个像素来存储一张图片,通过SVD分解后,若K=40,则我们需要矩阵U1(250*40=10000),S1(本来是40*40,但是对角阵,只需要记住对角线上的40个元素就好了,所以只要存储40个)。v1(189*40=7560注意到时候重建时,V1需要转置,matlab中的矩阵转置为V1’),加在一起只要记住10000+40+7560=(m+1+n)*k=17600<<250*189=47250,从而达到图象压缩的目的,压缩后重建的矩阵B大小不变还是250*189,和一开始的矩阵A大小一样。

代码

代码主要参考博客3,地址为https://www.cnblogs.com/tiandsp/archive/2012/10/24/2737769.html
我这个代码是灰度图片,如果是彩色图片的话就是把彩色图片分成r、g、b三张灰度图片,分别重建后再组合起来,可以看下参考博客4,地址是https://blog.csdn.net/fllubo/article/details/8273493

% a=imread('C:\Program Files\MATLAB\R2018b\toolbox\images\imdata\lena.tif');
a=imread('bag.png');%这张图非方阵

k=40;%取前k个奇异值
[m,n,dim] = size(a);
%如果a不是灰度图片,要将他转成灰度图片
if dim>1
    a=rgb2gray(a);
end

imshow(a);
title('原图') ;%原图

a=double(a);%将a转成double类型
r=rank(a);
[u s v]=svd(a);%对a进行SVD分解

u1=u(:,1:k);%取出u的前k项
ss=diag(s);%取出s的对角线元素
sss=ss(1:k);%取s前k项
s1=diag(sss);%构造s1,s1此时是k*k的对角阵
v1=v(:,1:k);%取出v的前k项
re=u1*s1*v1';%re是重建的图片

% re=u(:,1:k)*s(1:k,1:k)*v(:,1:k)';%re是重建的图片
re=uint8(re);%为了显示,将re转回uint8
figure;
imshow(re);
title(['图象压缩后,k=',num2str(k)]) ;
imwrite(re,'1.jpg');%保存图片

效果

原图
matlab-利用SVD(奇异值分解)来进行图片压缩_第1张图片
k=1
matlab-利用SVD(奇异值分解)来进行图片压缩_第2张图片
k=5
matlab-利用SVD(奇异值分解)来进行图片压缩_第3张图片
k=10
matlab-利用SVD(奇异值分解)来进行图片压缩_第4张图片

k=20
matlab-利用SVD(奇异值分解)来进行图片压缩_第5张图片

k=40
matlab-利用SVD(奇异值分解)来进行图片压缩_第6张图片

你可能感兴趣的:(烟酒僧,matlab,奇异值分解,图片压缩,SVD)