离散余弦变换(DCT)详解
离散余弦变换(DCT)详解
离散余弦变换(Discrete Cosine Transform, DCT)是视频和图像编码中最重要的数学工具之一。它是 JPEG、H.264、H.265 (HEVC) 等标准的核心组件。
简单来说,DCT 的作用是:将图像从“空间域”转换到“频率域”,从而把能量集中起来,方便压缩。
一、为什么要用 DCT?
1. 空间域 vs 频率域
- 空间域(Spatial Domain):我们看到的像素矩阵。每个值代表某个位置的亮度或颜色。
- 特点:数据之间相关性高,难以直接压缩。
- 频率域(Frequency Domain):描述图像变化快慢的系数矩阵。
- 低频系数:代表图像的平坦区域、大致轮廓(能量集中处)。
- 高频系数:代表图像的边缘、细节、噪声(能量分散且人眼不敏感)。
2. DCT 的核心价值:能量集中(Energy Compaction)
自然图像通常具有空间相关性:相邻像素的值往往很接近。
DCT 可以将这种相关性转化为:大部分能量集中在左上角的少数几个低频系数上,而右下角的高频系数接近于 0。
原始残差块 (空间域) DCT 变换后 (频率域) [ 10] [ 12] [ 11] [ 10] [ 45] [ -2] [ 1] [ 0] [ 11] [ 13] [ 12] [ 11] [ -3] [ 1] [ 0] [ 0] [ 10] [ 11] [ 10] [ 9] [ 2] [ 0] [ 0] [ 0] [ 9] [ 10] [ 9] [ 8] [ 0] [ 0] [ 0] [ 0] 注意: 1. 左上角 (DC系数) 很大,代表平均值。 2. 右下角大量变为 0 或极小值。 3. 量化时,右下角的 0 可以被高效压缩(行程编码/熵编码)。二、DCT 的数学原理
1. 一维 DCT 公式
对于长度为NNN的序列x[n]x[n]x[n],其 DCT 变换X[k]X[k]X[k]为:
X[k]=α(k)∑n=0N−1x[n]cos[πN(n+12)k] X[k] = \alpha(k) \sum_{n=0}^{N-1} x[n] \cos\left[ \frac{\pi}{N} \left(n + \frac{1}{2}\right) k \right]X[k]=α(k)n=0∑N−1x[n]cos[Nπ(n+21)k]
其中:
- k=0,1,...,N−1k = 0, 1, ..., N-1k=0,1,...,N−1
- α(0)=1/N\alpha(0) = \sqrt{1/N}α(0)=1/N,α(k)=2/N\alpha(k) = \sqrt{2/N}α(k)=2/N(k>0k > 0k>0)
2. 二维 DCT 公式(图像常用)
对于N×NN \times NN×N的图像块f(x,y)f(x,y)f(x,y):
F(u,v)=α(u)α(v)∑x=0N−1∑y=0N−1f(x,y)cos[πN(x+12)u]cos[πN(y+12)v] F(u,v) = \alpha(u)\alpha(v) \sum_{x=0}^{N-1} \sum_{y=0}^{N-1} f(x,y) \cos\left[ \frac{\pi}{N} \left(x + \frac{1}{2}\right) u \right] \cos\left[ \frac{\pi}{N} \left(y + \frac{1}{2}\right) v \right]F(u,v)=α(u)α(v)x=0∑N−1y=0∑N−1f(x,y)cos[Nπ(x+21)u]cos[Nπ(y+21)v]
- F(0,0)F(0,0)F(0,0)称为DC 系数(直流分量),代表块的平均亮度。
- 其他F(u,v)F(u,v)F(u,v)称为AC 系数(交流分量),代表不同频率的细节。
3. 逆变换(IDCT)
解码器使用 IDCT 将频率系数还原为像素值。由于 DCT 是正交变换,IDCT 公式与 DCT 非常相似,只是余弦项的位置互换。
三、在 H.265/HEVC 中的应用
1. 变换单元(TU)
在 HEVC 中,DCT 作用于变换单元(Transform Unit, TU)。
- TU 的大小可以是4×4,8×8,16×16,32×324\times4, 8\times8, 16\times16, 32\times324×4,8×8,16×16,32×32。
- 对于4×44\times44×4的帧内预测残差,HEVC 还引入了DST(离散正弦变换),因为它对边缘信号的压缩效率略高于 DCT。
2. 编码流程中的位置
原始像素 - 预测像素 = 残差 (空间域) ↓ DCT 变换 ↓ 变换系数 (频率域) ↓ 量化 (Quantization) <-- 有损压缩发生在这里 ↓ 熵编码 (CABAC)3. 整数 DCT(Integer DCT)
问题:标准的 DCT 涉及浮点运算(cosine),在不同硬件上会有精度误差,导致编码器和解码器重建出的图像不一致。
解决:H.265 标准定义了整数近似 DCT。
- 使用整数乘法和移位代替浮点运算。
- 保证编解码端的完全匹配(Match)。
- 虽然引入了微小的舍入误差,但压缩效率几乎不受影响。
四、X265 中的 DCT 实现
在 X265 源码中,DCT 的实现位于source/common/dct.cpp和source/common/x86/dct.asm。
1. 核心函数结构
// source/common/dct.hstructTComTrCore{// 正向变换voidtransformNxN(coeff_t*coeff,constpixel_t*residual,intwidth,intheight);// 反向变换voidinvTransformNxN(pixel_t*reconstruction,constcoeff_t*coeff,intwidth,intheight);// 具体的尺寸实现voiddct2_4x4(constpixel_t*src,coeff_t*dst,intptr_t srcStride);voiddct2_8x8(constpixel_t*src,coeff_t*dst,intptr_t srcStride);voiddct2_16x16(constpixel_t*src,coeff_t*dst,intptr_t srcStride);voiddct2_32x32(constpixel_t*src,coeff_t*dst,intptr_t srcStride);};2. 快速算法(Fast DCT)
直接计算 DCT 需要O(N2)O(N^2)O(N2)次运算。X265 使用类似 FFT 的快速分解算法,将大矩阵分解为小矩阵,复杂度降至O(NlogN)O(N \log N)O(NlogN)。
例如,8×88\times88×8DCT 可以分解为多个4×44\times44×4和2×22\times22×2的步骤,利用对称性减少乘法次数。
3. SIMD 优化
DCT 是计算密集型任务,X265 heavily 依赖 SIMD 指令集加速:
- SSE2/AVX2:并行处理多个像素点的乘加运算。
- 汇编实现:在
dct.asm中手写汇编,精确控制寄存器分配,达到极致性能。
; source/common/x86/dct.asm (简化示例) cglobal dct2_8x8, 3,4 ; 加载 8x8 像素块到 SIMD 寄存器 movu xmm0, [src] movu xmm1, [src+stride] ... ; 执行蝶形运算 (Butterfly Operations) paddw xmm0, xmm1 psubw xmm2, xmm3 ... ; 乘以变换矩阵常数 pmulhw xmm0, [coeff_table] ... ; 存储结果 movu [dst], xmm0 ret五、DCT 系数的分布特征
经过 DCT 变换后,系数分布呈现明显的非均匀性:
- DC 系数:通常最大,包含块的主要能量。
- 低频 AC 系数:数值较小,但通常非零。
- 高频 AC 系数:绝大多数接近 0。
这种分布对后续步骤至关重要:
- 量化:可以对高频系数使用更大的量化步长,将它们直接变成 0。
- 扫描(Scanning):使用 Zig-Zag 扫描或水平/垂直扫描,将非零系数聚在一起,便于行程编码(Run-Length Coding)。
六、常见问题与误区
1. DCT 是有损的吗?
不是。DCT 本身是一个可逆的数学变换(只要精度足够)。
有损发生在量化阶段。量化器根据 DCT 系数的视觉重要性,丢弃或粗略表示高频系数。
2. 为什么不用 FFT(傅里叶变换)?
- 实数运算:DCT 只产生实数系数,而 FFT 产生复数。处理实数更简单、存储更省。
- 边界效应:DCT 隐含了信号偶对称扩展,比 FFT 的周期延拓在块边界处产生的伪影更少。
- 能量集中能力:对于高度相关的图像信号,DCT 的能量集中性能优于 FFT。
3. 块效应(Blocking Artifacts)的来源
DCT 是基于块进行的(如8×88\times88×8或16×1616\times1616×16)。如果量化太粗,块与块之间的边界会出现不连续,形成“格子状”伪影。这就是为什么需要去块滤波(Deblocking Filter)。
七、总结
DCT 在视频编码中的地位:
✅桥梁:连接空间域(像素)和频率域(系数)。
✅去相关:消除像素间的空间冗余。
✅能量集中:为量化提供便利,让编码器知道哪些信息重要,哪些可以丢弃。
在 X265 中,DCT 的实现经过了极致的优化(整数化、快速算法、SIMD 加速),以确保在保持高压缩效率的同时,尽可能降低编码器的计算耗时。它是现代视频压缩技术的基石之一。
