基于SVD的图像压缩
奇异值分解(SVD) 奇异值分解(SingularValueDecomposition,简称SVD)是线性代数中一种非常重要的矩阵分解技术,广泛应用于信号处理、图像处理、统计学、计算机科学等领域。它将一个复杂的矩阵分解为三个简单矩阵的乘积,这三个矩阵分别是: 1、左奇异向量矩阵(U矩阵):一个正交矩阵,其列向量是原矩阵的左奇异向量。 2、奇异值对角矩阵(矩阵):一个对角矩阵,对角线上的元素是原矩阵的奇异值,这些奇异值是非负的,并且按降序排列。 3、右奇异向量矩阵(矩阵):一个正交矩阵,其列向量是原矩阵的右奇异向量。 对于任意一个的矩阵,其奇异值分解可以表示为: 其中,是一个的正交矩阵,是一个对角矩阵,是一个的正交矩阵,是的转置。 奇异值分解的步骤大致为: 1、计算奇异值:首先计算矩阵的奇异值,即求解特征值问题或的非负平方根。 2、构造奇异值矩阵:将奇异值按降序排列,构成对角矩阵。 3.构造奇异向量矩阵:计算与的关系,得到左奇异向量和右奇异向量,分别构成矩阵和。 奇异值分解具有以下性质和应用: 1、降维:通过保留最大的几个奇异值和对应的奇异向量,可以对矩阵进行降维,这在数据压缩和特征提取中非常有用。 2、噪声过滤:在信号处理中,奇异值分解可以用来过滤噪声,因为噪声通常对应较小的奇异值。 3、数据近似:通过保留最大的几个奇异值,可以得到原矩阵的最佳近似,这在数据压缩和图像处理中非常有用。 4、矩阵伪逆:奇异值分解可以用来计算矩阵的伪逆,这对于解决线性方程组的最小二乘问题非常有用。图像压缩步骤 奇异值分解(SVD)在图像压缩中的作用是通过减少矩阵的秩来实现压缩,同时尽量保留图像的关键视觉信息。具体来说,SVD在图像压缩中的应用可以分为以下几个步骤: 1、图像矩阵转换:首先将图像表示为一个矩阵,其中每个像素值对应矩阵的一个元素。对于彩色图像,通常需要将其转换为灰度图像或分别对RGB三个通道进行处理。 2、应用SVD:对图像矩阵进行奇异值分解,得到三个矩阵。 3、选择奇异值:由于奇异值按从大到小的顺序排列在对角矩阵中,较大的奇异值代表了图像的主要特征,而较小的奇异值则代表了细节和噪声。在压缩时,可以选择保留最大的个奇异值。 4、重构图像:使用保留的个奇异值和对应的和矩阵中的列向量,重构图像矩阵。具体来说,计算,其中和分别是和的前列,Σ𝑘Σk是由前个奇异值构成的对角矩阵。 5、压缩效果和质量权衡:通过选择不同的值,可以控制压缩的程度和图像质量之间的平衡。较小的值意味着更高的压缩率,但可能会丢失一些图像细节;较大的值则保留了更多的图像信息,压缩率较低。SVD压缩图像实例 这里以一个图片为例,图片选自电影《荒岛余生》,截取主角快要精神崩溃时刻懵逼的场景,后面还有主角的精神支柱:Vilson,(剧透一下,后来主角决意离开小岛,扎了个皮筏,在海上漂浮的过程中,Vilson被大浪吹走了,主角万念俱灰,躺在皮筏上面等死,最后........。) 原图片为: 帖子给出了详细的代码,下面逐行讲解代码。clc;clearall;%%%读取图像img=imread('island.png');%将图像转换为灰度图像,如果它不是灰度图ifsize(img,3)==3img=rgb2gray(img);end%将图像转换为双精度浮点数格式img_double=im2double(img); 上面的代码将图片读进内存,但是matlab的imread函数读进的图片数据类型为unit8,因此需要将数据处理为浮点型数组,方便后续进行矩阵分解。%对图像进行奇异值分解[U,S,V]=svd(img_double,'econ'); 这里没有自己写算法进行分解,直接调用了matlab的svd函数,返回左右奇异值矩阵和对角矩阵。%选择奇异值的数量来压缩图像k=50;%选择一个较小的k值来压缩图像 k就是我们选择的前阶特征值,这里选择了50,后续我会修改值,观察不同的k值对压缩后的图片质量影响。%选择奇异值的数量来压缩图像U_k=U(:,1:k);S_k=S(1:k,1:k);V_k=V(:,1:k); 选取前阶特征值对左右奇异值矩阵和对角矩阵重构。%重构压缩后的图像img_compressed=U_k*S_k*V_k'; 生成重构后的矩阵,即生成保留前阶特征值的图片。%显示原始图像和压缩后的图像subplot(1,2,1);imshow(img_double);title('OriginalImage');subplot(1,2,2);imshow(img_compressed);title(['CompressedImagewithk=',num2str(k)]); 上面的代码用与显示压缩前后的矩阵。 这张图片经过处理后的浮点矩阵大小为,因此,左奇异矩阵的大小为,右奇异矩阵的大小为,对角矩阵大小为。 这张图片经过奇异值分解,共计849个特征值,我们依次保留不同的特征值,分别保留了25、50、75、100、125、15、175、200,比较压缩后的图片质量。 下面给出了原图与压缩后的图片对比图,每张图片的左边均是原图,右面是压缩后的图片,图片下方标注了相应的压缩程度。 25/849 50/849 75/849 100/849 可以发现,从这里开始,如果没有仔细分辨,已经看不出来原图和压缩后的图片的细微区别,这时截取的特征值占比为11.78%,压缩了将近百分之九十! 125/849 150/849 175/849 200/849 从上面图片的对比中发现,采用SVD对图像进行压缩,仅仅截取十分之一的特征值就达到了接近原图效果的压缩图。可见该方法在图像处理方面有极大的应用前景,并且已经有了极为广泛的应用。详细的matlab代码 下面给出了详细的matlab代码,使用的时候注意修改图片的名字。clc;clearall;%%%读取图像img=imread('island.png');%将图像转换为灰度图像,如果它不是灰度图ifsize(img,3)==3img=rgb2gray(img);end%将图像转换为双精度浮点数格式img_double=im2double(img);imwrite(img_double,'origin.png');%对图像进行奇异值分解[U,S,V]=svd(img_double,'econ');%选择奇异值的数量来压缩图像k=200;%选择一个较小的k值来压缩图像U_k=U(:,1:k);S_k=S(1:k,1:k);V_k=V(:,1:k);%重构压缩后的图像img_compressed=U_k*S_k*V_k';%显示原始图像和压缩后的图像subplot(1,2,1);imshow(img_double);title('OriginalImage');subplot(1,2,2);imshow(img_compressed);title(['CompressedImagewithk=',num2str(k)]);%如果需要,保存压缩后的图像imwrite(img_compressed,string(k)+'.png'); 上面的东西写的花里胡哨的,可是,这是有限元领域的公众号啊!SVD跟有限元又有什么关系呢!? 列位看官,敬请期待!喜欢就点个关注呗来源:有限元先生