d=50;
im = imread('H:\matlab\bildanalys\terminator.gif');
M2 = double(im);
[U S V] = svd(M2);
U2 = U(:,1:d);
S2 = S(1:d,1:d);
V2 = V(:,1:d);
compressed=U2*S2*V2';
imwrite(compressed,'H:\matlab\bildanalys\compressedterminator.gif','gif')
S2
压缩图像大3倍......
我在图像上执行svd,丢弃较小的奇异值(尽管它们非常大)然后再次将矩阵相乘以获得压缩图像。压缩图像为黑白,比原始图像大。我在哪里失败了?
答案 0 :(得分:2)
我不确定你最终的结果是3倍,因为类之间的转换比例为2.我能想到的唯一解释是原始图像im
可能是{{{} 1}}有3个颜色通道。转换为灰度和uint8
后,这将变为double
倍。但是,除非你没有在这里发布这部分代码,否则看起来你不会从3个dims变为1。
至于使用SVD来减少存储,如果你重新加倍矩阵,你将回到一个完整的矩阵,其元素的数量与开始时完全相同,因此你将得到相同大小的图像。
答案 1 :(得分:0)
原始问题是 A = U S V * ,尺寸为(mxn) = (mxm) (mxn) (nxn)。
中心思想是使用薄SVD并在丢弃后用分解产物 U , S 和 V * 替换图像与SVD中的新零值对应的零空间分量。例如,深空探测器可能具有大量计算能力和很小的传输带宽。卫星记录图像,分解,压缩和传输分解产物,而不是图像。图像将在以后重新组合。
压缩将等级从p = min(m,n)降低到rho。作为上午注意到压缩图像的尺寸是相同的(mxn) = (mx rho) (mx rho) (rho xn) 的。
原始等级 p 可以是数千,rho低至10.输入矩阵具有 mn 个元素;压缩数据需要 rho(m + n + rho)元素。
示例:m = n = 2048,rho = 10.图像需要4,194,304个元素;压缩分解中的元素总和为41,060,小于原始数据量的1%。
增加三倍的因素是MATLAB问题,其中r.m。已准确诊断出来。
答案 2 :(得分:0)
您可能正在保存冗余的列和行。截断奇异值对角线---当然,你将它作为一维数组存储 - 你还应该截断矩阵U
和V^t
的列和行macth,分别。否则,您将存储一组在重建M = U * S * Vt
期间将乘以0的值。
例如,使用Java的Apache Commons库(因为我对MatLab不太熟悉,抱歉):
// compute your SVD from some input matrix
final SingularValueDecomposition svd = new SingularValueDecomposition(matrix);
// only store necessary matrix portions in memory required to compute compressed matrix
final RealMatrix u = svd.getU().getSubMatrix(0, svd.getU().getRowDimension()-1, 0, (svd.getU().getColumnDimension()-1)-compression);
// grab singular values
final RealMatrix s = svd.getS().getSubMatrix(0, (size-compression)-1, 0, (size-compression)-1);
// grab V transpose
final RealMatrix vt = svd.getVT().getSubMatrix(0, (svd.getVT().getRowDimension()-1)-compression, 0, svd.getVT().getColumnDimension()-1);
// compute compressed matrix
return new Array2DRowRealMatrix(u)
.multiply(new Array2DRowRealMatrix(s))
.multiply(new Array2DRowRealMatrix(vt));