用 SVD 進行圖像壓縮


\(A\)\(m \times n\) 實矩陣, 記 SVD 的一般形式為

\[A = U\Sigma V', \]

其中 \(U=(u_1,\dots,u_m)\), \(V=(v_1,\dots,v_n)\) 為正交陣,

\[\Sigma = \begin{pmatrix} S & O\\ O & O \end{pmatrix},\quad\text{where $S = {\rm diag}\{\sigma_1,\dots,\sigma_r\}$ }, \]

\(\sigma_1\ge\dots\sigma_r> 0\)\(A\) 的非零奇異值.

\(\sigma_j\) 越大意味着對應的 \(A'A\) 的特征值 \(\sigma_j^2\) 越大, 從而其主成分 (principal component) \(Av_j\) 的樣本方差越大, 我們把方差大視為提供了更多信息.

\(A\) 可寫為

\[A = \sum_{k=1}^r \sigma_r u_kv_k', \]

把帶有較少信息的小的奇異值扔掉便達到了壓縮 (減少需要存儲的東西) 的目的.

import numpy as np
from numpy.linalg import svd
from PIL import Image
import matplotlib.pyplot as plt

path = r'Lenna_(test_image).png'
image = Image.open(path)
image = np.array(image)
print(np.shape(image))
plt.imshow(image)

(512, 512, 3)

3 表示 RGB 各有一個矩陣, 下面分別對 RGB 做 SVD.

# 保留前 k 個奇異值
def compression(image, k):
    image2 = np.zeros_like(image)
    for i in range(image.shape[2]):
        U, S, Vt = svd(image[:,:,i])
        image2[:,:,i] = U[:,:k].dot(np.diag(S[:k])).dot(Vt[:k,:])
    plt.imshow(image2)
    plt.title('k = %s' % k)

plt.figure(figsize=(20,10))

k = image.shape[0]/2
for i in range(8):
    k = int(k/2)
    pos = 241+i
    plt.subplot(pos)
    compression(image, k)

References

[1] 姚慕生, 吳泉水, 謝啟鴻. (2014). 高等代數學 (第三版) (pp. 414-416). 上海: 復旦大學出版社.
[2] Friedman, J., Hastie, T., & Tibshirani, R. (2001). The elements of statistical learning (pp. 62). New York: Springer series in statistics.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM