You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于SVD的k秩近似图像压缩:为何矩阵维度不变但文件大小减小?

问题原因及修正方案

核心原因拆解

1. SVD的错误使用导致矩阵维度未变化

你的代码存在两个关键逻辑错误:

  • 误处理灰度图像通道:灰度图的矩阵维度应为(高度, 宽度),但代码里通过image_data.shape[2]拆分通道,说明输入图像实际是RGB格式,或是代码逻辑误将灰度图按多通道处理。
  • 致命操作:将通道矩阵拉成列向量做SVD:你把每个通道的H×W矩阵reshape成(H*W, 1)的列向量,这种矩阵的秩最大只能是1,设置k=10完全无效——截断奇异值后得到的矩阵和原列向量本质一致,reshape回原维度后自然和原图尺寸相同。

正确的SVD图像压缩逻辑是直接对**二维通道矩阵(H×W)**做分解:对H×W矩阵A做SVD得到U(H×H)、S(H×W)、Vt(W×W),取前k个奇异值及对应的U的前k列、Vt的前k行,重构出A_k = U[:, :k] @ np.diag(S[:k]) @ Vt[:k, :],重构后的矩阵维度依然是H×W,但仅保留了前k个最重要的图像特征。

2. 文件体积变小是JPEG格式的功劳,和SVD无关

你看到的文件从5MB降到2MB,是因为保存时用了JPEG格式——JPEG本身就是有损压缩算法,不管有没有做SVD处理,只要把图像保存为JPEG,都会比未压缩格式(比如BMP、无压缩PNG)的体积小。你的SVD处理实际上没起到压缩作用,只是JPEG的压缩效果让你误以为是SVD的功劳。

修正后的灰度图像SVD压缩代码

import os
import numpy as np
from PIL import Image

def calculate_file_size(filepath):
    return os.path.getsize(filepath)

def compress_gray_image(input_filename, output_folder, k):
    input_image_path = os.path.join("images", input_filename)
    
    # 以灰度模式打开图像
    image = Image.open(input_image_path).convert('L')
    image_data = np.array(image)
    H, W = image_data.shape

    # 对二维灰度矩阵直接做SVD
    u, s, vt = np.linalg.svd(image_data, full_matrices=False)
    # 取前k个奇异值重构图像
    compressed_data = u[:, :k] @ np.diag(s[:k]) @ vt[:k, :]
    # 裁剪到0-255范围并转成uint8格式
    compressed_data = np.clip(compressed_data, 0, 255).astype(np.uint8)

    # 保存重构后的图像(用PNG格式避免JPEG额外干扰)
    compressed_image_path = os.path.join(output_folder, f"compressed_rank_{k}.png")
    Image.fromarray(compressed_data).save(compressed_image_path, "PNG")

    # 计算SVD压缩的实际参数存储量:U前k列 + S前k个值 + Vt前k行(按float32计算)
    svd_storage_size = (k * H + k + k * W) * 4
    original_file_size = calculate_file_size(input_image_path)
    compressed_file_size = calculate_file_size(compressed_image_path)

    print(f"原图矩阵维度: {image_data.shape}")
    print(f"重构后矩阵维度: {compressed_data.shape}")
    print(f"原图文件大小: {original_file_size // 1024} KB")
    print(f"重构后PNG文件大小: {compressed_file_size // 1024} KB")
    print(f"SVD压缩后参数存储量: {svd_storage_size // 1024} KB (仅需存储这部分即可恢复图像)")

补充说明

SVD图像压缩的核心优势是通过存储更少的参数来恢复图像,而非让重构后的图像文件体积变小——重构后的图像维度和原图一致,只有当你不保存重构后的图像,而是保存SVD分解得到的前k个参数时,才会真正实现数据压缩。如果要对比SVD的压缩效果,建议将原图和重构后的图像都保存为无压缩格式,再看文件体积差异,或者直接计算SVD参数的存储量。

内容的提问来源于stack exchange,提问作者jimmyshoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 01:35:25