奇异值分解和图像压缩
来源:互联网 发布:联想淘宝商城旗舰店 编辑:程序博客网 时间:2024/05/17 08:03
奇异值分解和图像压缩
=====================代表正义的分割线=====================
今天我们来讲讲奇异值分解和它的一些有意思的应用。奇异值分解是一个非常,非常,非常大的话题,它的英文是 Singular Value Decomposition,一般简称为 SVD。下面先给出它大概的意思:
对于任意一个
其中
U U 是一个m×n m×n 的矩阵,满足UTU=In UTU=In,In In 是n×n n×n 的单位阵V V 是一个n×n n×n 的矩阵,满足VTV=In VTV=InD D 是一个n×n n×n 的对角矩阵,所有的元素都非负
先别急,我看到这个定义的时候和你一样晕,感觉信息量有点大。事实上,上面这短短的三条可以引发出 SVD 许多重要的性质,而我们今天要介绍的也只是其中的一部分而已。
前面的表达式
其中每一个
它们被称为右奇异向量。再然后,假设矩阵
其中
这个式子有什么用呢?注意到,我们假定
那么我们是否可以用
答案是肯定的,不过等一下,这个想法好像似曾相识?对了,多元统计分析中经典的主成分分析就是这样做的。在主成分分析中,我们把数据整体的变异分解成若干个主成分之和,然后保留方差最大的若干个主成分,而舍弃那些方差较小的。事实上,主成分分析就是对数据的协方差矩阵进行了类似的分解(特征值分解),但这种分解只适用于对称的矩阵,而 SVD 则是对任意大小和形状的矩阵都成立。(SVD 和特征值分解有着非常紧密的联系,此为后话)
我们再回顾一下,主成分分析有什么作用?答曰,降维。换言之,就是用几组低维的主成分来记录原始数据的大部分信息,这也可以认为是一种信息的(有损)压缩。在 SVD 中,我们也可以做类似的事情,也就是用更少项的求和
我们知道,电脑上的图像(特指位图)都是由像素点组成的,所以存储一张 1000×622 大小的图片,实际上就是存储一个 1000×622 的矩阵,共 622000 个元素。这个矩阵用 SVD 可以分解为 622 个矩阵之和,如果我们选取其中的前 100 个之和作为对图像数据的近似,那么只需要存储 100 个奇异值
【注:本文只是为了用图像压缩来介绍 SVD 的性质,实际使用中常见的图片格式(png,jpeg等)其压缩原理更复杂,且效果往往更好】
为了直观地来看看 SVD 压缩图像的效果,我们拿一幅 1000×622 的图片来做实验(图片来源:http://www.bjcaca.com/bisai/show.php?pid=33844&bid=40)
SVD演示图片,原图SVD演示图片,k=1SVD演示图片,k=5SVD演示图片,k=20SVD演示图片,k=50SVD演示图片,k=100可以看出,当取一个成分时,景物完全不可分辨,但还是可以看出原始图片的整体色调。取 5 个成分时,已经依稀可以看出景物的轮廓。而继续增加
接下来我们要考虑的问题是,
此外,我们还需要限定
在所有秩为
k k 的矩阵中,Mk Mk 能够最小化与M M 之间的 Frobenius 范数距离。
这意味着,如果我们以 Frobenius 范数作为衡量的准则,那么在给定矩阵秩的情况下,SVD 能够给出最佳的近似效果。万万没想到啊。
在R中,可以使用 svd()
函数来对矩阵进行 SVD 分解,但考虑到 SVD 是一项计算量较大的工作,我们使用了 rARPACK 包中的 svds()
函数,它可以只计算前
library(rARPACK);library(jpeg);factorize = function(m, k){ r = svds(m[, , 1], k); g = svds(m[, , 2], k); b = svds(m[, , 3], k); return(list(r = r, g = g, b = b));}recoverimg = function(lst, k){ recover0 = function(fac, k) { dmat = diag(k); diag(dmat) = fac$d[1:k]; m = fac$u[, 1:k] %*% dmat %*% t(fac$v[, 1:k]); m[m < 0] = 0; m[m > 1] = 1; return(m); } r = recover0(lst$r, k); g = recover0(lst$g, k); b = recover0(lst$b, k); m = array(0, c(nrow(r), ncol(r), 3)); m[, , 1] = r; m[, , 2] = g; m[, , 3] = b; return(m);}rawimg = readJPEG("pic2.jpg");lst = factorize(rawimg, 100);neig = c(1, 5, 20, 50, 100);for(i in neig){ m = recoverimg(lst, i); writeJPEG(m, sprintf("svd_%d.jpg", i), 0.95);}
参考文献
- Image Compression with the SVD in R
- Foundations of Data Science
- SVD维基页面
- 奇异值分解和图像压缩
- 奇异值分解和图像压缩
- 奇异值分解与图像压缩
- 奇异值分解压缩图像SVD
- 矩阵奇异值分解SVD用于图像压缩的要点
- 利用矩阵奇异值分解对图像进行压缩
- 奇异值分解 SVD 图像压缩 Matlab 压缩率
- 基于奇异值分解(SVD)的图像压缩
- 基于奇异值分解的图像压缩与除噪
- matlab练习程序(奇异值分解压缩图像)
- 奇异值分解(SVD)和图像矩阵的分解测试
- 【PCA与LDA】特征值分解与奇异值分解以及图像压缩处理原理
- 奇异值分解和特征值分解
- 奇异值分解和特征值分解
- 主成分分析和奇异值分解
- 矩阵奇异值分解与照片压缩、去噪
- 磁共振指纹的时间域奇异值分解压缩
- [图像] 奇异值分解与隐性语义分析
- 解决android6.0系统无法读写SD的问题
- hdu5886Tower Defence(树形dp)
- OC中一般正则表达式的使用
- Python爬虫__爬取贴吧图片和文本
- 用QMatrix实现帧的旋转、翻转、放大、缩小等简单操作示例
- 奇异值分解和图像压缩
- 防坠落智能小车
- A Review of Lectures, labs, papers and Conferences about Reinforcement Learning
- C++函数重定义、重载、重写
- VS2012连接到osc@git
- POJ 3697USTC campus network
- Tomcat升级JDK
- 重大发现:强大的setOnClickListener!
- error: ext4_allocate_best_fit_partial: failed to allocate 742 blocks, out of space?