

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 支持中文显示
original_image = Image.open("灰度图片3.jpg").convert('RGB')
img_array = np.array(original_image) # 形状为 (高度, 宽度, 3)
channels = []
for i in range(3):
channel = img_array[:, :, i].astype(np.float64) # 转为浮点型方便计算
channels.append(channel)
reconstructed_channels = []
for channel in channels:
U, S, Vt = np.linalg.svd(channel, full_matrices=False) # 分解
k = 10 # 保留前k个奇异值
S_k = np.diag(S[:k])
U_k = U[:, :k]
Vt_k = Vt[:k, :]
reconstructed = U_k @ S_k @ Vt_k # 矩阵相乘重建
reconstructed = np.clip(reconstructed, 0, 255) # 像素值限制在[0, 255]
reconstructed_channels.append(reconstructed.astype(np.uint8))
merged = np.stack(reconstructed_channels, axis=2)
reconstructed_image = Image.fromarray(merged)
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1), plt.imshow(original_image), plt.title("原始图像")
plt.subplot(1, 2, 2), plt.imshow(reconstructed_image), plt.title(f"重建图像(k={k})")
plt.show()
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
def svd_image_processing(image_path, k):
"""
使用奇异值分解(SVD)进行图像处理
参数:
image_path: 输入图片路径
k: 保留的奇异值数量(k越大保留信息越多)
"""
# 读取图像并转换为RGB矩阵
original_image = Image.open(image_path).convert('RGB')
# 三维数组(高度,宽度,通道)
img_array = np.array(original_image)
print("读取图像的RGB矩阵:")
print(img_array)
# 分离RGB三个通道
channels = []
for i in range(3):
# 转换为浮点数便于计算
channel = img_array[:, :, i].astype(np.float64)
channels.append(channel)
# 对每个通道进行SVD分解和重建
reconstructed_channels = []
U_list, S_list, Vt_list = [], [], []
for channel in channels:
# 执行奇异值分解
U, S, Vt = np.linalg.svd(channel, full_matrices=False)
# 存储分解结果
U_list.append(U)
S_list.append(S)
Vt_list.append(Vt)
# 保留前k个奇异值
# 转换为对角矩阵
S_k = np.diag(S[:k])
# 取前k列
U_k = U[:, :k]
# 取前k行
Vt_k = Vt[:k, :]
# 重建当前通道
reconstructed = U_k @ S_k @ Vt_k
# 确保像素值在合理范围
reconstructed = np.clip(reconstructed, 0, 255)
reconstructed_channels.append(reconstructed)
# 合并通道并转换为图像
merged = np.stack(reconstructed_channels, axis=2).astype(np.uint8)
reconstructed_image = Image.fromarray(merged)
# 打印矩阵信息
print("=== 分解矩阵信息 ===")
print(f"原始图像形状:{img_array.shape}")
print(f"左奇异矩阵U形状(R通道):{U_list[0].shape}")
print(f"奇异值矩阵S长度(R通道):{len(S_list[0])}")
print(f"右奇异矩阵Vt形状(R通道):{Vt_list[0].shape}")
# 显示部分矩阵数据(R通道)
print("\n=== 矩阵示例(R通道前5x5) ===")
print("左奇异矩阵U前5行5列:\n", U_list[0][:5, :5].round(2))
print("\n奇异值前5个:\n", S_list[0][:5].round(2))
print("\n右奇异矩阵Vt前5行5列:\n", Vt_list[0][:5, :5].round(2))
# 显示对比图像
plt.figure(figsize=(10, 10))
plt.subplot(1, 2, 1)
plt.imshow(original_image)
plt.title(f'原始图像\n尺寸:{img_array.shape}')
plt.subplot(1, 2, 2)
plt.imshow(reconstructed_image)
plt.title(f'重建图像(k={k})\n保留比例:{k / len(S_list[0]):.2%}')
plt.tight_layout()
plt.show()
return reconstructed_image
# 使用示例
if __name__ == "__main__":
# 图片路径
input_image = "灰度图片3.jpg"
# 保留的奇异值数量(可自行调整)
k_value = 10
# 执行处理并显示结果
result = svd_image_processing(input_image, k_value)import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
def convert_with_matplotlib(input_path, output_path):
img = mpimg.imread(input_path)
grayscale = np.dot(img[..., :3], [0.299, 0.587, 0.114])
plt.imsave(output_path, grayscale, cmap='gray')
convert_with_matplotlib("演示图片5.jpg","灰度图片3.jpg")


保留奇异值 k | 保留比例 | 重建图像效果 |
|---|---|---|
(k=50) | 2.50% | 接近原始图像,细节清晰 |
(k=30) | 1.50% | 轻微模糊,主要轮廓保留 |
(k=10) | 0.50% | 明显模糊,细节丢失 |



结论:



=== 分解矩阵信息 ===
原始图像形状: (1080, 1920, 3)
左奇异矩阵U形状: (1080, 1080)
奇异值矩阵S长度: 1080
右奇异矩阵Vt形状: (1080, 1920)
=== 矩阵示例(R通道前5×5) ===
左奇异矩阵U前5行5列:
[[0.01 -0.01 0.02 -0.04 0.03]
[0.02 -0.01 0.02 -0.04 0.03]
[0.02 -0.01 0.02 -0.04 0.03]
[0.02 -0.01 0.02 -0.04 0.03]
[0.03 -0.01 0.02 -0.04 0.03]]
奇异值前5个:
[331942.60, 16229.33, 14850.96, 14428.65, 12192.33] 

本次实验通过 Python 实现了基于 SVD 的图像处理,直观展示了数学理论在计算机视觉中的应用。通过调整保留的奇异值数量,我们深入理解了 SVD 在特征提取和数据压缩中的核心作用,为后续学习 PCA、图像降噪等算法奠定了基础。