在研究奇异值分解的工程应用之前,我们得明白什么是奇异值?什么是奇异向量?
概念:奇异值描述了矩阵在一组特定向量上的行为,奇异向量描述了其最大的作用方向。
矩阵A的分解涉及一个 m × n m \times n m×n的矩阵 Σ \Sigma Σ,其中 Σ \Sigma Σ= [ D 0 0 0 ] \begin{bmatrix} D &0\\0&0\end{bmatrix} [D0?00?],D是一个 r × r r\times r r×r的方阵 ( r ≤ m , r ≤ n ) ( r \leq m , r\leq n) (r≤m,r≤n)
定理:设A是秩为 r r r的 m × n m\times n m×n的矩阵,那么存在一个类似于 Σ \Sigma Σ的矩阵,其中 D D D的对角线元素是 A A A的前 r r r个奇异值, σ 1 ≥ σ 2 ≥ σ 3 ≥ . . . ≥ σ r > 0 \sigma_1 \geq\sigma_2 \geq\sigma_3 \geq... \geq\sigma_r>0 σ1?≥σ2?≥σ3?≥...≥σr?>0并且存在一个 m × m m\times m m×m的正交矩阵 U U U 和一个 n × n n\times n n×n的正交矩阵 V T V^T VT使得 A = U Σ V T A=U\Sigma V^T A=UΣVT
我们先假设一个矩阵
A
=
[
2
3
?
0
2
]
A = \begin{bmatrix} 2 & 3 \\ \ 0 & 2\end{bmatrix}
A=[2?0?32?]
设
U
=
[
u
1
u
2
u
3
.
.
.
]
U=[u_1 u_2 u_3 ...]
U=[u1?u2?u3?...] ,
∑
=
d
i
a
g
[
σ
1
σ
2
σ
3
.
.
.
]
\sum = diag[\sigma_1 \sigma_2 \sigma_3 ...]
∑=diag[σ1?σ2?σ3?...] ,
V
=
[
v
1
v
2
v
3
.
.
.
]
T
V=\begin{bmatrix} v_1 \\ v_2\\ v_3 \\ ...\end{bmatrix}^T
V=
?v1?v2?v3?...?
?T
其中
U
U
U代表A的正交矩阵;
∑
\sum
∑代表A的由奇异值组成的左奇异向量矩阵;
V
V
V代表A的右奇异向量矩阵。
求A的 U , ∑ , V U , \sum , V U,∑,V.
首先我们先找一张图片来进行实验。
对于JPG格式的彩色图片,拥有3个颜色通道,R(红)、G(绿)、B(蓝),那么可以尝试将每个颜色通道进行分离,产生3个形状均为图像高 x 宽 的单通道剧展,即imageR,imageG,imageB。
进行通道分离,将imageArray数组中的每个通道分别单独取出来,得到3个高 × \times × 宽的二维数组。这3个二维数组中每个位置上的取值就是对应像素的某个颜色通道的取值,代码如下:
import numpy as np
from PIL import Image
originalImage = Image.open(r'teriri.jpg', 'r')
imageArray = np.array(originalImage)
R = imageArray[:, :, 0]
G = imageArray[:, :, 1]
B = imageArray[:, :, 2]
print(R)
print(G)
print(B)
运行结果如下:
[[207 207 207 … 141 141 141]
[207 207 207 … 141 141 141]
[207 207 207 … 141 141 141]
…
[246 247 248 … 239 239 239]
[246 247 248 … 239 239 239]
[246 247 248 … 239 239 239]]
[[198 198 198 … 126 126 126]
[198 198 198 … 126 126 126]
[198 198 198 … 126 126 126]
…
[233 234 235 … 235 235 235]
[233 234 235 … 235 235 235]
[233 234 235 … 235 235 235]]
[[215 215 215 … 149 147 147]
[215 215 215 … 149 147 147]
[215 215 215 … 149 147 147]
…
[230 231 233 … 203 203 203]
[230 231 233 … 203 203 203]
[230 231 233 … 203 203 203]]
至此,我们成功得到了3个二维ndarray数组,将R、G、B三个通道成功进行了分离。
对每个单通道矩阵进行奇异值分解,按照压缩的实际需要取前k个奇异值,进行3个单通道的矩阵的压缩,最后分别形成3个压缩后的矩阵:imageRC,imageGC,imageBC,代码如下:
def imgCompress(channel,percent):
U,sigma,V_T = np.linalg.svd(channel)
m = U.shape[0]
n = V_T.shape[0]
reChannel = np.zeros((m,n))
for k in range (len(sigma)):
reChannel = reChannel + sigma[k] * np.dot(U[:,k].reshape(m,1),V_T[k,:].reshape(1,n))
if float(k) / len(sigma) > percent:
reChannel[reChannel < 0] = 0
reChannel[reChannel > 255] = 255
break
return np.rint(reChannel).astype("unit8")
将经过奇异值分解处理的3个单通道矩阵合并,从而重构出压缩后的彩色图像。
for p in [0.001, 0.005, 0.01, 0.02, 0.03, 0.04, 0.05,
0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]:
#p表示取所有奇异值的前多少比例
reR = imgCompress(R,p)
reG = imgCompress(G,p)
reB = imgCompress(B,p)
reI = np.stack((reR,reG,reB),2)
Image.fromarray(reI).save("{}".format(p)+"img.png")
整体运行结果如下:
比例为0.001至0.04
>0.05至0.5
0.6至原图
总结: