小波变换与 JPEG 2000 - 图像压缩的多分辨率分析
小波变换基础 - 时频同步分析
小波变换是一种将信号分解为不同频率和位置成分的数学工具。与傅里叶变换不同,小波变换同时提供时间(空间)和频率信息,特别适合分析图像中的局部特征。
为什么选择小波变换:
傅里叶变换将信号分解为全局正弦波,丢失了空间位置信息。对于图像压缩,我们需要知道"哪个位置有什么频率的细节",小波变换恰好提供这种时频局部化能力。
小波基函数:
小波是一个有限长度的振荡函数(母小波)。通过缩放和平移母小波,可以在不同尺度和位置分析信号。常用小波包括 Haar、Daubechies(db4)、CDF 9/7(JPEG 2000 使用)。
多分辨率分析(MRA):
小波变换将图像分解为多个分辨率层次:低频近似(整体结构)和高频细节(边缘、纹理)。每一层的分辨率是上一层的一半,形成金字塔结构。这种层次结构天然适合渐进式传输和感兴趣区域编码。
与 DCT 的对比:
- DCT(JPEG 使用):将图像分为 8x8 块独立处理,块边界可能产生伪影
- DWT(JPEG 2000 使用):对整幅图像进行变换,无块效应
- DWT 在低比特率下质量明显优于 DCT
离散小波变换(DWT)与滤波器组
离散小波变换通过一对互补滤波器(低通和高通)将信号分解为近似系数和细节系数。对图像进行二维 DWT 产生四个子带,构成多分辨率表示的基础。
一维 DWT:
信号通过低通滤波器(得到近似)和高通滤波器(得到细节),然后下采样 2 倍。低通输出保留信号的整体趋势,高通输出捕获局部变化。
二维 DWT:
对图像先按行进行一维 DWT,再按列进行一维 DWT。产生四个子带:
- LL(低低):近似子带,包含图像的缩小版本
- LH(低高):水平细节(水平边缘)
- HL(高低):垂直细节(垂直边缘)
- HH(高高):对角细节(对角边缘)
多级分解:
对 LL 子带递归应用 DWT,得到更粗糙的近似和更多细节层。JPEG 2000 通常使用 5 级分解。每级分解将 LL 子带的分辨率减半。
JPEG 2000 使用的滤波器:
- CDF 9/7(不可逆):用于有损压缩,浮点运算,压缩效率最高
- CDF 5/3(可逆):用于无损压缩,整数运算,可精确重建
JPEG 2000 压缩流程
JPEG 2000 的编码流程包括预处理、小波变换、量化和熵编码四个主要阶段。每个阶段都经过精心设计以最大化压缩效率。
预处理:
- 色彩空间转换:RGB 转 YCbCr(有损)或 RCT(无损)
- 分块(Tiling):将大图像分为独立编码的块,减少内存需求
- DC 电平偏移:减去 128 使数据零均值化
小波变换:
对每个分块应用 5 级 DWT。有损模式使用 CDF 9/7 滤波器,无损模式使用 CDF 5/3 滤波器。变换后得到多个子带的小波系数。
量化:
有损模式下,将小波系数除以量化步长并取整。不同子带使用不同的量化步长(高频子带步长更大,丢弃更多细节)。无损模式跳过量化步骤。
EBCOT 编码:
嵌入式块编码与优化截断(Embedded Block Coding with Optimized Truncation)。将量化后的系数按位平面从高位到低位编码。这种嵌入式结构支持渐进式传输和精确的码率控制。
码流组织:
最终码流支持多种渐进模式:按质量(SNR)、按分辨率、按位置、按分量。解码器可以在任意点截断码流获得对应质量的图像。
EBCOT - 位平面编码机制
EBCOT 是 JPEG 2000 的核心编码引擎,通过位平面编码和上下文建模实现高效压缩。其嵌入式特性使得单一码流可服务于多种质量需求。
代码块(Code-Block):
每个子带被划分为固定大小的代码块(通常 64x64 或 32x32)。每个代码块独立编码,支持并行处理和灵活的码率分配。
位平面编码:
将代码块中的系数按位平面(从最高有效位到最低有效位)逐层编码。每个位平面分三个编码通道:
- 重要性传播通道:编码首次变为非零的系数
- 幅度精炼通道:精炼已知非零系数的精度
- 清理通道:编码剩余未处理的系数
上下文建模:
使用相邻系数的状态(已知/未知、正/负)预测当前比特的概率。MQ 算术编码器根据上下文概率进行高效编码。共定义 18 个上下文,覆盖各种邻域模式。
优化截断(PCRD):
后压缩率失真优化(Post-Compression Rate-Distortion)在所有代码块的所有截断点中选择最优组合,在给定码率下最小化总失真。这是 JPEG 2000 实现精确码率控制的关键机制。
JPEG 2000 的应用与现状
JPEG 2000 虽然在 Web 领域未能取代 JPEG,但在专业领域有着不可替代的地位。其独特的技术特性使其在特定场景中仍是最佳选择。
数字电影(DCI):
数字电影行业标准(DCI)强制使用 JPEG 2000 作为帧内编码格式。4K 电影每帧使用 JPEG 2000 压缩,码率约 250Mbps。选择原因:帧内编码便于剪辑,质量可精确控制。
医学影像(DICOM):
医学影像存储标准 DICOM 支持 JPEG 2000 无损压缩。CT、MRI 等影像需要无损存储以确保诊断准确性。JPEG 2000 的无损模式压缩率(2:1-3:1)优于 PNG。
卫星遥感:
大幅面卫星图像使用 JPEG 2000 的分块和感兴趣区域(ROI)功能。可以对重要区域分配更多比特,实现选择性高质量编码。
数字档案:
图书馆和档案馆使用 JPEG 2000 无损压缩保存珍贵文档的数字化副本。支持渐进式解码,便于在线浏览大幅面图像。
为什么未在 Web 普及:
- 编解码复杂度高,软件实现速度慢
- 浏览器支持有限(仅 Safari 原生支持)
- 专利问题曾阻碍早期推广
- JPEG 已足够好,迁移动力不足
- WebP 和 AVIF 填补了 Web 领域的需求
实现与使用 - OpenJPEG 和 Python 处理
OpenJPEG 是 JPEG 2000 的开源参考实现,提供命令行工具和 C 库。Python 通过 Pillow 和 Glymur 库可方便地处理 JPEG 2000 文件。
OpenJPEG 命令行:
编码:opj_compress -i input.ppm -o output.j2k -r 20(-r 20 表示压缩比 20:1)
解码:opj_decompress -i input.j2k -o output.ppm
支持的参数:分块大小、分解级数、码率控制、渐进模式等。
Python Pillow:
from PIL import Image
img = Image.open('input.j2k')
img.save('output.j2k', quality_mode='rates', quality_layers=[20])
Pillow 的 JPEG 2000 支持依赖 OpenJPEG 库。
Glymur(Python 专用库):
提供更完整的 JPEG 2000 功能访问,包括元数据读取、分块处理、渐进式解码等。适合需要精细控制的场景。
性能考虑:
- 编码速度:JPEG 2000 编码比 JPEG 慢 5-10 倍
- 解码速度:比 JPEG 慢 2-5 倍
- 内存使用:大图像的 DWT 需要大量内存,分块可缓解
- GPU 加速:部分实现支持 CUDA 加速 DWT 计算