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:\matla开发者_如何学编程b\bildanalys\compressedterminator.gif','gif')
S2
the compressed image is 3times bigger...
I do svd on the image, throw away the smaller singular values(although they are quite big) then multiply together the matrices again to get the compressed image. the compressed image is black and white and bigger than the original. where do i fail?
I'm not sure how you end up with 3 times bigger, as conversions between classes scale in powers of 2. The only explanation I can think of is that the original image, im
was probably a uint8
with 3 color channels. This upon conversion to grayscale and double
, becomes 8/3~2.67
times as big. However, it doesn't look like you're going from 3 dims to 1, unless if you didn't post that part of the code here.
As for using SVDs to reduce storage, if you re-multiply your matrices, you're going back to a full matrix with the exact same number of elements as you started with and hence you'll get the same sized image.
The original problem is A = USV* with dimensions of (m x n) = (m x m) (m x n) (n x n).
The central idea is to use the thin SVD and replace the image with the decomposition products U, S, and V* after discarding the null space components corresponding to the new zero values in the SVD. For example, a deep space probe may have lots of computational power and little transmission bandwidth. The satellite records an image, decomposes, compresses and transmits the decomposition products, NOT the image. The image is recomposed later.
Compression reduces the rank from p = min( m, n ) to rho. As r.m. notes the dimensions for the compressed image are the same (m x n) = (m x rho) (m x rho) (rho x n).
The original rank p may be in the thousands, with rho being as low as 10. The input matrix has mn elements; the compressed data requires rho( m + n + rho) elements.
Example: m = n = 2048, rho = 10. The image requires 4,194,304 elements; the sum of elements in the compressed decomposition is 41,060, less than 1% of the original data volume.
The factor of three increase is a MATLAB issue which r.m. has diagnosed accurately.
You're probably saving redundant columns and rows. After you truncate the singular values diagonal---which you're storing as a 1D array, of course---you should also truncate the columns and rows of the matrices U
and V^t
to macth, respectively. Otherwise, you are storing a bunch of values that will be multiplied out to 0 during the reconstruction M = U * S * Vt
.
For example, using the Apache Commons library for Java (as I'm less familiar with MatLab, sorry):
// 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));
精彩评论