第 8 章 图像压缩
学习目标:理解压缩的信息论基础,掌握无损编码(Huffman、算术、RLE、LZW)、JPEG 的完整流水线、现代压缩标准(WebP、AVIF、HEIC)以及视频压缩的核心思想。 本章是”每天在你手机后台运行几百次”的学问——看不见但不可缺。
8.1 压缩的必要性与可行性
8.1.1 为什么要压缩?
原始图像数据量:
- 24-bit 全色 4K (3840×2160):24 MB / 帧
- 60 fps 30 秒 1080p 视频:2.8 GB
- 一部 2 小时 4K HDR 电影(未压缩):20 TB
如果不压缩,网络、存储、带宽都会被瞬间吃光。
8.1.2 压缩的可行性:冗余
定义 8.1(信息量):事件 (x) 出现概率为 (p(x)),其信息量: [ I(x) = -\log_2 p(x) \quad \text{(bits)} ]
Shannon 熵:信源平均信息量 [ H(X) = -\sum_x p(x) \log_2 p(x) ]
压缩的理论下限:无损压缩后的平均码长 (\ge H(X))。
图像的冗余类型:
| 冗余 | 含义 | 压缩手段 |
|---|---|---|
| 编码冗余 | 像素值出现频率不均(常见灰度用短码) | Huffman、算术编码 |
| 空间冗余 | 相邻像素相关(大片天空) | 差分、预测 |
| 时间冗余 | 视频相邻帧相似 | 帧间预测、运动补偿 |
| 心理视觉冗余 | 人眼不敏感的信息(高频、色度) | 量化、下采样 |
| 结构冗余 | 模式重复(字典库) | LZ77、LZW |
前三种是客观冗余(无损压缩利用),后两种是主观冗余(有损压缩利用)。
8.1.3 压缩率与率失真
压缩率 (Compression Ratio): [ C = \frac{\text{原始比特数}}{\text{压缩后比特数}} ] (C = 10) 表示压缩到原来的 1/10。
率失真 (Rate-Distortion):对有损压缩,衡量每 bit 代价换取多少质量。
[ D(R) \equiv \min \text{失真,使码率} \le R ]
率失真曲线:
失真 D ▲ │╲ │ ╲ │ ╲_ │ ╲__ │ ╲___ │ ───── 0 ────────────── 码率 R好的压缩算法 = 这条曲线靠近左下角。
8.1.4 质量评价指标
MSE / PSNR
[ \text{MSE} = \frac{1}{MN} \sum (f - g)^2 ] [ \text{PSNR} = 10 \log_{10} \frac{\text{MAX}^2}{\text{MSE}} \quad (\text{dB}) ] (\text{MAX} = 255) for 8-bit。
经验:
| PSNR (dB) | 质量 |
|---|---|
| > 40 | 几乎无损 |
| 30-40 | 良好 |
| 20-30 | 可见失真 |
| < 20 | 很差 |
SSIM (Structural Similarity)
考虑亮度、对比度、结构三分量: [ \text{SSIM}(x, y) = \frac{(2\mu_x \mu_y + c_1)(2\sigma_{xy} + c_2)}{(\mu_x^2 + \mu_y^2 + c_1)(\sigma_x^2 + \sigma_y^2 + c_2)} ]
范围 [-1, 1],1 表示完全相同。比 PSNR 更接近人眼判断。
感知指标 (LPIPS, DISTS)
深度学习时代:用 VGG/CLIP 特征计算距离,最接近主观感受。
8.2 无损压缩
8.2.1 信源编码基础
Kraft 不等式
任何前缀码的码长 (l_i) 满足: [ \sum_i 2^{-l_i} \le 1 ]
最优平均码长
Shannon 定理:存在前缀码使平均码长 (\bar{L}) 满足: [ H(X) \le \bar{L} < H(X) + 1 ]
8.2.2 Huffman 编码
思想:给常见符号分配短码,罕见符号长码。
算法
1. 统计各符号概率 p(x_i)2. 取最小两个概率,合并成新节点(概率之和)3. 重复直到只剩一个节点 → 形成二叉树4. 从根到叶:左 0,右 1 → 每个符号得到码示例:符号 {a, b, c, d, e},概率 {0.4, 0.2, 0.2, 0.1, 0.1}
1.0 / \ 0.6 0.4 (a) / \ 0.4 0.2 (b or c) / \ 0.2 0.2 (b or c) / \ 0.1 0.1 (d)(e)
码: a=0, b=10, c=11, d=100, e=101 (示意,具体依合并顺序)平均码长: [ \bar{L} = \sum p(x_i) l_i = 0.4 \cdot 1 + 0.2 \cdot 2 + 0.2 \cdot 2 + 0.1 \cdot 3 + 0.1 \cdot 3 = 2.0 ]
比较熵: [ H = -0.4 \log 0.4 - 2 \cdot 0.2 \log 0.2 - 2 \cdot 0.1 \log 0.1 \approx 2.12 ]
Huffman 码长 2.0 < 熵 2.12 × 系数?不对,实际上 Huffman 最优整数码长 = 2.12 bits/symbol 的上取整 + 合并损失。
特点
- 最优:平均码长最小的整数前缀码
- 需传输概率表(或预定义,如 JPEG 标准表)
- 只适合静态概率已知
8.2.3 算术编码
思想:把整条消息映射为 ([0, 1)) 中的一个数。
算法(编码)
初始区间 [low, high) = [0, 1)对每个输入符号 x: 范围 = high - low high = low + 范围 × CDF(x) (上界) low = low + 范围 × CDF(x-1) (下界)最后输出 [low, high) 中任意一个数(通常取能用最少 bit 表示的)特点
- 非整数编码(理论上可达熵的下限)
- 比 Huffman 更紧凑,尤其概率分布极不均匀时
- 实现复杂,早期有专利(已过期)
- JPEG2000, H.264/265 的标准熵编码(改名 CABAC 等)
8.2.4 游程编码(RLE)
场景:连续重复值多(二值图、简笔画)。
编码:5, 5, 5, 5, 3, 3, 7 → (5, 4), (3, 2), (7, 1)(值 + 个数)
应用:
- 传真(ITU G.3 / G.4)
- BMP、PCX、TIFF(可选 RLE 模式)
- JPEG 的 AC 系数 0 游程
8.2.5 LZW 编码(字典压缩)
Lempel-Ziv-Welch 1984。
思想:边编码边建字典,遇到已见过的序列就输出字典索引。
算法
字典 = 所有单字符(256 项)w = ""对每个字符 k: 如果 w + k 在字典: w = w + k 否则: 输出字典[w] 的索引 把 w + k 加入字典 w = k输出 w解码:同步建相同字典。
特点:
- 无需预先统计(流式)
- 适合结构化重复(文本、GIF 索引色)
- GIF / TIFF 使用
与 LZ77 的关系:LZ77 用”前向滑动窗口”,LZW 是其简化变种。Deflate (zip/PNG) 用 LZ77 + Huffman 组合。
8.2.6 预测编码(DPCM)
思想:不存像素值,存残差(实际 - 预测)。
预测器: [ \hat{f}(m, n) = a \cdot f(m-1, n) + b \cdot f(m, n-1) + c \cdot f(m-1, n-1) ] 残差: [ e(m, n) = f(m, n) - \hat{f}(m, n) ]
- 自然图像中残差接近 0(小幅度),熵低
- 用 Huffman 或算术编码压缩残差
LOCO-I / JPEG-LS(Hewlett-Packard):无损压缩的业界标杆,医学 DICOM 广泛使用。
8.3 有损压缩的核心:变换 + 量化
8.3.1 为什么要变换?
自然图像像素高度相关(相邻 RGB 很接近),直接编码效率低。
变换后:
- 系数去相关(KLT 最优,但依赖信号统计;DCT 近似 KLT)
- 能量集中(大多数系数接近 0)
- 可对不同系数差别量化(低频保留,高频丢弃)
8.3.2 KLT(理论最优)
对信号 (x) 的协方差矩阵 (C_x) 做特征分解: [ C_x = V \Lambda V^T ] 变换 (y = V^T x) 使 (y) 协方差对角 → 完全去相关。
缺点:(V) 依赖具体信号 → 传输时需同时传 (V),得不偿失。
8.3.3 DCT(工程最优)
离散余弦变换: [ C(u, v) = \alpha(u) \alpha(v) \sum_{x=0}^{N-1} \sum_{y=0}^{N-1} f(x, y) \cos\frac{(2x+1) u \pi}{2N} \cos\frac{(2y+1) v \pi}{2N} ]
(\alpha(0) = 1/\sqrt{N}, \alpha(u) = \sqrt{2/N}) 其他。
关键性质:
- 实数变换(FT 是复数)
- 对一阶马尔可夫过程(自然图像近似)接近 KLT
- 快速算法(与 FFT 类似,(O(N \log N)))
- 基函数如下(8×8 DCT):
(0,0) DC (0,7) 最高水平频率 ┌──────┐ ┌──────┐ │██████│ │▉▁▉▁▉▁│ │██████│ │▁▉▁▉▁▉│ └──────┘ └──────┘
(7,0) 最高垂直频率 (7,7) 最高对角频率 ┌──────┐ ┌──────┐ │▉▉▉▉▉▉│ │▉▁▉▁▉▁│ │▁▁▁▁▁▁│ │▁▉▁▉▁▉│ └──────┘ └──────┘8.3.4 量化:信息丢失的地方
量化是有损的唯一来源。
均匀量化: [ \hat{C}(u, v) = \text{round}\left( \frac{C(u, v)}{Q(u, v)} \right) \cdot Q(u, v) ]
- (Q(u, v)):量化步长,每个频率不同
- 低频 (Q) 小(精细保留)
- 高频 (Q) 大(粗糙近似甚至归零)
JPEG 亮度量化表(Quality 50):
16 11 10 16 24 40 51 61 12 12 14 19 26 58 60 55 14 13 16 24 40 57 69 56 14 17 22 29 51 87 80 62 18 22 37 56 68 109 103 77 24 35 55 64 81 104 113 92 49 64 78 87 103 121 120 101 72 92 95 98 112 100 103 99- 左上 DC 步长 16
- 右下高频步长 99(几乎归零)
Q(质量因子)控制整体步长:
- Q=100:步长除以 2(近乎无损)
- Q=50:标准
- Q=10:所有系数归零(几乎只剩 DC) → 严重失真
8.4 JPEG 标准(必会)
8.4.1 JPEG 流水线全图
输入 RGB │ ▼(1) 色彩空间转换 RGB → YCbCr │ ▼(2) 色度子采样 4:2:0 │ ▼(3) 分 8×8 块(可能补边) │ ▼(4) DCT 变换 │ ▼(5) 量化(按量化表除+取整) │ ▼(6) 之字形扫描 (Zigzag) │ ▼(7) DC 差分编码 (DPCM)(8) AC 游程编码 (Run-Length) │ ▼(9) Huffman 编码 │ ▼输出比特流8.4.2 每步详解
(1) 色彩转换(已在第 6 章讲)
(2) 色度子采样 4:2:0
省略 3/4 的色度信息,肉眼几乎看不出。
(3) 分块
每通道切成 8×8 块。
- 为什么是 8?历史折衷(太大:相关性差;太小:DCT 效率低)
- 不够 8 倍数:边界复制填充
(4) DCT
对每个 8×8 块做 2D DCT,得到 8×8 系数矩阵。 左上 (0, 0) 是 DC 系数(块平均亮度)。 其他 63 个是 AC 系数。
(5) 量化
系数 / 量化表 + round。精度损失发生在这里。
(6) Zigzag 扫描
把 8×8 重排成 64 元素的 1D 序列,从低频到高频:
Z = 0 1 5 6 14 15 27 28 2 4 7 13 16 26 29 42 3 8 12 17 25 30 41 43 9 11 18 24 31 40 44 53 10 19 23 32 39 45 52 54 20 22 33 38 46 51 55 60 21 34 37 47 50 56 59 61 35 36 48 49 57 58 62 63目的:把通常为 0 的高频系数聚到序列末尾 → 游程编码高效。
(7) DC 差分
只存相邻块的 DC 差: [ \text{DC}_i’ = \text{DC}i - \text{DC}{i-1} ]
利用 DC 相邻相关(同一图大片区域亮度连续)。
(8) AC 游程编码
把 AC 的 63 个系数编成 (run, level) 对:
run:前面有多少个 0level:这个非零值
末尾如果全是 0,用特殊符号 EOB(End Of Block)。
(9) Huffman
对 (run, level) 对查 JPEG 标准 Huffman 表编码。
8.4.3 JPEG 的块效应(Block Artifact)
低质量 JPEG 的明显缺陷:8×8 方块边界可见。
原因:每块独立 DCT + 独立量化,块间不连续。
缓解:
- 解码后做去块滤波 (Deblocking Filter)
- JPEG 本身无此功能
- H.264/265 内置去块滤波 → 视频看不出块效应
8.4.4 渐进 JPEG
普通 JPEG:从上到下逐行显示。 渐进 JPEG:先传所有块的 DC + 低频,再逐步细化。
效果:网络慢时先出模糊整图,再变清晰 → 用户体验好。
cv2.imwrite('out.jpg', img, [cv2.IMWRITE_JPEG_PROGRESSIVE, 1, cv2.IMWRITE_JPEG_QUALITY, 85])8.5 JPEG2000
8.5.1 为什么要替代 JPEG?
- 块效应
- 固定 8×8,无法适应图像内容
- 低码率下失真严重
8.5.2 JPEG2000 的核心技术
- 小波变换替代 DCT
- 无分块 → 无块效应
- 多分辨率 → 天然支持渐进解码
- EBCOT(位平面编码 + 算术编码)
- 比 Huffman 更高压缩率
- 可在任何 bit 截断 → 细粒度率控制
- ROI (Region of Interest)
- 对重要区域高质量编码
- 无损 ↔ 有损统一
- 5/3 整数小波:无损
- 9/7 浮点小波:有损
8.5.3 现状
- 压缩率比 JPEG 高 20-30%
- 计算复杂度高、专利问题、浏览器不支持 → 未普及
- 医学 DICOM、数字电影(DCP)使用
8.6 现代图像格式
8.6.1 PNG(无损)
- LZ77(Deflate)+ 滤波预测
- 支持 Alpha 通道、索引色
- 无损 → 适合截图、图标、线条图
- 不适合照片(压缩率低)
8.6.2 WebP(Google 2010)
- 基于 VP8 视频编码(帧内压缩)
- 比 JPEG 小 25-35%,同等质量
- 同一格式支持无损 + 有损 + 透明
- Chrome/Firefox/Safari 已支持
8.6.3 HEIC / HEIF(Apple iOS 11+)
- 基于 H.265 (HEVC) 帧内压缩
- 比 JPEG 小约 50%,同等质量
- 支持 HDR、实时照片、图像序列
- 专利费高,未广泛采用(但 iPhone 默认)
8.6.4 AVIF(2019)
- 基于 AV1 视频编码
- 开源、免专利
- 比 JPEG 小 50-60%,比 HEIC 略好
- 未来的 JPEG 替代者
- 编码慢(几秒一张 4K),但解码快
8.6.5 JPEG XL(2022)
- JPEG 集团新标准
- 完全无损兼容 JPEG → 老 JPEG 可直接转换不重编
- 压缩率与 AVIF 近
- 支持任意位深、HDR、动画
- 浏览器支持还不普及
8.6.6 对比表
| 格式 | 典型压缩率(对照 JPEG) | 支持 | 缺点 |
|---|---|---|---|
| JPEG (1992) | 基准 | 万物支持 | 老、有块效应 |
| PNG | 无损(大) | 万物 | 不适合照片 |
| JPEG2000 (2000) | +20% | 专业 | 复杂、专利 |
| WebP (2010) | +25-35% | Web | iOS 支持晚 |
| HEIC (2015) | +50% | iOS | 专利、兼容差 |
| AVIF (2019) | +50-60% | 新浏览器 | 编码慢 |
| JPEG XL (2022) | +50% | 实验 | 推进慢 |
8.7 视频压缩的核心
8.7.1 相比图像的最大不同:时间冗余
相邻帧几乎相同 → 存”差”(帧间预测)而非整帧。
8.7.2 I / P / B 帧
| 帧类型 | 参考 | 压缩率 |
|---|---|---|
| I (Intra) | 无(独立编码,类 JPEG) | 低(1) |
| P (Predicted) | 前一帧 | 中(4-5×) |
| B (Bidirectional) | 前后两帧 | 高(8-10×) |
GOP 结构:
I B B P B B P B B P ... I (GOP = 12)- I 帧:随机访问点(可跳转)
- P 帧:单向预测
- B 帧:双向预测
8.7.3 运动估计与补偿(ME/MC)
核心:对当前块,在参考帧中找最相似的块。
块匹配搜索:
- 块大小 16×16(宏块)、H.264 起变 4×4 到 64×64 自适应
- 搜索范围 ±16 到 ±128 像素
- 匹配准则:SAD、SSD
运动向量 (MV):找到的位移 ((dx, dy))。
编码时:当前块 = 参考块(位置+MV) + 残差
只存 MV 和残差,两者都高度冗余 → 大幅压缩。
搜索算法
- 全搜索:精确但慢
- 三步搜索 (TSS):(\log N) 步,快
- 菱形搜索 (DS):现代标准(H.264)
- 分层搜索 (HBMA):多分辨率金字塔
8.7.4 视频压缩标准
| 标准 | 年 | 代表应用 |
|---|---|---|
| MPEG-1 | 1993 | VCD |
| MPEG-2 | 1995 | DVD、数字电视 |
| MPEG-4 Part 2 | 1998 | 互联网视频(早期) |
| H.264 / AVC | 2003 | Blu-ray、YouTube、直播 |
| H.265 / HEVC | 2013 | 4K UHD、HDR |
| VP9 (Google) | 2013 | YouTube |
| AV1 | 2018 | 开源替代 HEVC |
| H.266 / VVC | 2020 | 8K、VR |
压缩进步规律:每代约省 50% 码率,同等质量。
8.7.5 H.264 概览
- I 帧:帧内 4×4 / 16×16 空间预测(9 种方向)
- P/B 帧:运动补偿 + 残差 DCT(整数变换)
- CABAC:上下文自适应二进制算术编码(比 Huffman 省 10-15%)
- 去块滤波:边界平滑
8.8 深度学习图像压缩
8.8.1 传统 vs 学习型
传统: DCT/DWT Huffman/CABAC 图像 ──────────> 系数 ──────> 比特流
学习型: Encoder Entropy Model 图像 ─────────> 潜在 ──────> 比特流 (CNN) (学得)8.8.2 核心论文
- Ballé 2017 “End-to-end Optimized Image Compression”
- 引入 GDN(广义除法归一化)代替 BN
- 可微”近似量化”做端到端训练
- Ballé 2018 “Variational Image Compression with a Scale Hyperprior”
- 引入超先验网络估计熵模型
- Minnen 2018 “Joint Autoregressive and Hierarchical Priors”
- SOTA
- Mentzer 2020 “High-Fidelity Generative Image Compression”
- GAN-based,在极低码率下”创造”合理细节
8.8.3 深度学习压缩的优势
- 比 BPG (HEVC intra) 压缩率高 5-15%
- 主观质量(LPIPS)显著更好
- 自适应不同图像类型(天然纹理、人脸、文本)
8.8.4 商业应用
- Netflix 的 VMAF 度量
- Disney+ 的 AV1 编码
- WeChat、抖音的智能压缩后端
8.9 图像压缩的工程实用技巧
8.9.1 质量参数选择建议
| 场景 | JPEG Q | 备注 |
|---|---|---|
| 照片打印 | 90-95 | 几乎无损 |
| Web 照片 | 75-85 | 肉眼难辨 |
| 缩略图 | 60-70 | 可接受失真 |
| 监控视频帧 | 40-60 | 极小文件 |
8.9.2 优化 JPEG 大小的技巧
- resize:先缩小到目标显示尺寸
- chroma subsampling:4:2:0 默认
- optimize:Huffman 表重新统计
- progressive:渐进编码通常更小
- MozJPEG:Mozilla 优化版,比 libjpeg 小 10%
# PIL 优化img.save('out.jpg', 'JPEG', quality=85, optimize=True, progressive=True)8.9.3 PNG 优化
pngquant --quality=65-80 input.png # 色彩量化到 256 色oxipng -o max input.png # 重压缩 zlib往往能把 PNG 缩小一半。
8.9.4 视频转码
# H.264 一般质量ffmpeg -i in.mp4 -c:v libx264 -crf 23 out.mp4
# H.265 高压缩ffmpeg -i in.mp4 -c:v libx265 -crf 28 out.mp4
# AV1 极压缩ffmpeg -i in.mp4 -c:v libsvtav1 -crf 35 out.mp4CRF (Constant Rate Factor):0-51,23 视觉几乎无损,越小质量越高文件越大。
8.10 本章要点与面试考点
✅ 必须掌握
- 5 种冗余类型与对应压缩手段
- Shannon 熵的公式与含义
- Huffman 编码的构造流程
- JPEG 完整流水线(9 步)
- DCT 的优点:接近 KLT、快速算法、实数
- 量化表的设计原则(低频细、高频粗)
- JPEG vs JPEG2000 的差别
- I/P/B 帧及运动估计
- 现代格式对比(WebP, HEIC, AVIF, JPEG XL)
💡 高频面试题
Q1. JPEG 的 9 个步骤是什么?
答:色彩转换(RGB→YCbCr) → 色度子采样(4:2:0) → 分 8×8 块 → DCT → 量化 → Zigzag → DC 差分 → AC 游程 → Huffman。
Q2. 为什么 JPEG 用 DCT 而不是 FFT?
答:
- DCT 是实数变换,FFT 是复数 → 系数数少一半
- DCT 对一阶马尔可夫(自然图像)近似 KLT → 去相关好
- DCT 无周期延拓问题(FFT 的隐含循环边界造成人为不连续)
Q3. JPEG 的块效应怎么产生的?
答:图像被分成 8×8 块独立 DCT + 独立量化,低质量下量化粗粒度导致相邻块的 DC/低频不一致,在块边界出现”台阶”。解决:JPEG2000(小波无分块)、H.264(去块滤波)。
Q4. 为什么用 Zigzag 扫描?
答:DCT 后低频(左上)非 0、高频(右下)多为 0。Zigzag 按频率从低到高重排成 1D 序列,让末尾连续 0 最多 → 游程编码高效(大量 0 用一个 EOB 表示)。
Q5. Huffman 编码一定最优吗?
答:Huffman 在整数码长约束下最优。但当某符号概率 > 0.5 时,它的理想码长 < 1 bit,Huffman 只能用 1 bit → 不够精细。算术编码可以做非整数,因此总是 ≥ Huffman。
Q6. 压缩率和码率如何换算?
答:
- 压缩率 (C = \text{原始大小} / \text{压缩后大小})
- 码率 (R = \text{压缩后比特} / \text{像素数}) (bpp, bits per pixel)
- 8-bit 原始 bpp=8,压缩到 bpp=1 即 C=8
Q7. B 帧为什么比 P 帧压缩率高?
答:B 帧同时看前后两个参考帧,搜索空间更大 → 找到匹配更精确 → 残差更小 → 编码更短。代价:必须缓存未来帧、延时高(直播不友好)。
Q8. 若图像基本全黑(大片 0),哪种编码最优?
答:RLE 或算术编码。此时熵极低,理论下限 ≈ 0 bit/symbol。Huffman 的”至少 1 bit” 限制此处浪费严重;算术编码无此限制;RLE 直接一条”run of 10000 zeros”。
Q9. DCT 和 KLT 的关系?
答:KLT 依赖具体信号协方差,理论最优但必须传变换矩阵。DCT 是对一阶马尔可夫过程((\rho \to 1))KLT 的渐近形式,且有固定快速算法 → 工程最优解。
8.11 延伸阅读
- Gonzalez, Digital Image Processing (4th), Ch. 8
- Sayood, Introduction to Data Compression(压缩教材经典)
- Shannon, “A Mathematical Theory of Communication”, 1948
- Wallace, “The JPEG Still Picture Compression Standard”, IEEE T. Cons. Elec. 1992
- Christopoulos et al., “The JPEG2000 Still Image Coding System”, IEEE Comm. 2000
- Sullivan et al., “Overview of the HEVC Standard”, IEEE TCSVT 2012
- Ballé et al., “End-to-end Optimized Image Compression”, ICLR 2017
- CompressAI 库:https://github.com/InterDigitalInc/CompressAI
下一章:从”全局变换”回到”局部几何”。形态学处理用简单的集合运算(腐蚀、膨胀)解决许多看似困难的形状分析问题,是二值图像世界里的代数。
如果這篇文章對你有幫助,歡迎分享給更多人!
部分資訊可能已經過時





















