2
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 を実行し、小さい特異値を破棄して (かなり大きいですが)、行列を再度掛け合わせて圧縮画像を取得します。圧縮された画像は白黒で、元の画像よりも大きくなります。どこで失敗しますか?

4

3 に答える 3

2

クラス間の変換は 2 のべき乗でスケーリングされるため、どのようにして 3 倍の大きさになるかはわかりません。私が考えることができる唯一の説明は、元の画像imがおそらくuint83 つのカラー チャネルであったということです。これをグレースケールに変換するとdouble、 は28/3~2.67倍になります。ただし、コードのその部分をここに投稿しない限り、3 ディムから 1 になるようには見えません。

ストレージを削減するために SVD を使用する場合、行列を再度乗算すると、元の要素とまったく同じ数の完全な行列に戻るため、同じサイズの画像が得られます。

于 2011-04-12T15:38:49.250 に答える
0

冗長な列と行を保存している可能性があります。特異値の対角線を切り捨てた後 (もちろん、1D 配列として保存しています)、行列の列と行をそれぞれ macth に切り捨てる必要がありUますV^t。それ以外の場合は、再構築中に 0 に乗算される一連の値を格納していますM = U * S * Vt

たとえば、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));
于 2016-06-25T07:54:33.067 に答える