理论:
矩阵的奇异值分解变换是一种正交变换,它可以将矩阵对角化
定理:
设A是一个秩为
r
r
r的
m
∗
n
m*n
m∗n矩阵,则存在正交矩阵
U
U
U和
V
V
V,使得
U
T
A
V
=
[
Σ
0
0
0
]
U^TAV= \begin{bmatrix} \Sigma & 0 \\ 0 & 0 \\ \end{bmatrix}
UTAV=[Σ000]
其中
Σ
=
d
i
a
g
{
σ
1
,
σ
2
,
σ
3
,
.
.
.
.
,
σ
r
}
\Sigma=diag\{\sigma_1,\sigma_2,\sigma_3,....,\sigma_r\}
Σ=diag{σ1,σ2,σ3,....,σr},这里
σ
1
>
=
σ
2
>
=
σ
3
.
.
.
.
>
=
σ
r
\sigma_1>=\sigma_2>=\sigma_3....>=\sigma_r
σ1>=σ2>=σ3....>=σr,
σ
1
2
.
.
.
.
σ
r
2
\sigma_1^2....\sigma_r^2
σ12....σr2是矩阵
A
T
A
A^TA
ATA对应的特征值。
称
A
=
U
[
Σ
0
0
0
]
V
T
A=U \begin{bmatrix} \Sigma & 0 \\ 0 & 0 \\ \end{bmatrix}V^T
A=U[Σ000]VTA的奇异值分解,
σ
i
(
i
=
1
,
.
.
.
r
)
\sigma_i(i=1,...r)
σi(i=1,...r)称为A的奇异值
根据自己的理解,压缩的思路就是先进行奇异值分解,将前k大个特征值保留下来,其余的变为0,然后进行逆变换,起到基本替代原来奇异值矩阵的作用,从而实现图像的压缩,压缩率也会随k的变化而变化,诚然,k越大,压缩率越小。
实现步骤:
- 读取RGB图像
- 将RGB图像变为灰度图像
- 奇异值分解
- 保留前k大个特征值
- 逆变换
- 计算压缩率
- 打印图像(保存)
- 修改k的值,重复以上步骤
实现:
% 通过奇异值分解 进行图像压缩
clc;clear;
I = imread('figure1.jpg'); % rgb图像为274KB
[m,n,h] = size(I);
% Igray = rgb2gray(I);
% imwrite(Igray,'figure1grayByrgb2gray.png','png') % 灰度图像为993KB,文件变大了好几倍
% 参考别人的博客,手写将rgb图像变成灰度图像
for i=1:m
for j=1:n
Igray(i,j)=0.299*I(i,j,1)+0.587*I(i,j,2)+0.114*I(i,j,3);
end
end
imwrite(Igray,'figure1grayBymyself.png','png')
k = 20;
Igray = double(Igray);
[U,S,V] = svd(Igray);
S = diag(S); % 变成列向量
Smax = max(S);
Smin = min(S);
S1 = S;
S1(k:end)=0; %保留前k个
% S1 = diag(S1); % 考虑不周到
if m>=n % 对于非方图形
S1 = [diag(S1);zeros(m-n,n)];
else S1 = [diag(S1),zeros(m,n-m)];
end
g = U*S1*V'; % S1的奇异值分解
g = uint8(g);
compressration = n^2/(k*(2*n+1));
subplot(1,2,1),imshow(mat2gray(Igray)),title('soure');
subplot(1,2,2),imshow(g),title(['k =',num2str(k),' compress ratio =',num2str(compressration)]);
imwrite(g,'figure1Compress20.png','png')
figure,plot(S,'.','Color','k'); % 画出奇异值对应的点
- 原RGB图像:
- 灰度图像
- 特征值分布
- K=20时的压缩率
可以调节k的值得到不同的压缩率