利用SVD分解,保留前20个、30个等奇异值,完成彩色图像(见下图)的压缩。 (1)计算压缩比例。 (2)利用pickle等工具将SVD分解的三个矩阵保存到本地,并二次读取出来,完成图片的复原。最后要显示彩色图片不要灰色的
时间: 2024-10-19 10:07:27 浏览: 46
基于奇异值分解(SVD)的图片压缩实践
5星 · 资源好评率100%
对于彩色图像的SVD压缩,我们需要对每个颜色通道(如红、绿、蓝)分别进行处理。以下是详细的步骤:
(1)**计算压缩比例**:
- 首先,将彩色图片(RGB模式)分解成三个灰度图像(R, G, B)。
- 对每个灰度图像执行SVD,得到U, s, Vt(注意Vt应改为VT)。
- 保留前k个奇异值(如20或30个)。
- 计算每个灰度图像的压缩比例,即(Uk.size + sk.size + Vk.size)/(原图像尺寸),然后将这三个值相加,得到总的压缩比。
(2)**保存和恢复SVD矩阵**:
- 对于每个灰度图像,分别执行SVD并保存:
```python
for channel in ['r', 'g', 'b']:
channel_img = img[:, :, channel].astype(float) # 提取特定通道
Uk_channel, sk_channel, Vk_channel = np.linalg.svd(channel_img, full_matrices=False)
with open(f'{channel}_svd_components.pkl', 'wb') as f:
pickle.dump((Uk_channel, sk_channel, Vk_channel), f)
```
- 再次读取并组合这些矩阵以复原彩色图像:
```python
restored_Uk = []
restored_sk = []
restored_Vk = []
for channel in ['r', 'g', 'b']:
with open(f'{channel}_svd_components.pkl', 'rb') as f:
Uk_channel_restored, sk_channel_restored, Vk_channel_restored = pickle.load(f)
restored_Uk.append(Uk_channel_restored)
restored_sk.append(sk_channel_restored)
restored_Vk.append(Vk_channel_restored)
Uk_all = np.concatenate(restored_Uk, axis=1)
sk_all = np.concatenate([np.diag(channel_s) for channel_s in restored_sk], axis=1)
Vk_all = np.concatenate(restored_Vk, axis=0)
reconstructed_channels = [Uk_all @ sk_all @ Vk_all[:, :img.shape[1]] for channel in ['r', 'g', 'b']]
```
- 最后,将重构的三个通道合并成彩色图片:
```python
reconstruct_img = np.dstack((reconstructed_channels[0], reconstructed_channels[1], reconstructed_channels[2]))
```
- 显示彩色图片:
```python
plt.imshow(reconstruct_img, cmap='rgb')
```
现在,`reconstruct_img` 就是一个经过压缩后复原的彩色图像,而不是灰度的。
阅读全文