news 2026/4/30 14:56:27

离散余弦变换(DCT)详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
离散余弦变换(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=0N1x[n]cos[Nπ(n+21)k]

其中:

  • k=0,1,...,N−1k = 0, 1, ..., N-1k=0,1,...,N1
  • α(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=0N1y=0N1f(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.cppsource/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(Nlog⁡N)O(N \log N)O(NlogN)

例如,8×88\times88×8DCT 可以分解为多个4×44\times44×42×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 变换后,系数分布呈现明显的非均匀性

  1. DC 系数:通常最大,包含块的主要能量。
  2. 低频 AC 系数:数值较小,但通常非零。
  3. 高频 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×816×1616\times1616×16)。如果量化太粗,块与块之间的边界会出现不连续,形成“格子状”伪影。这就是为什么需要去块滤波(Deblocking Filter)


七、总结

DCT 在视频编码中的地位:

桥梁:连接空间域(像素)和频率域(系数)。
去相关:消除像素间的空间冗余。
能量集中:为量化提供便利,让编码器知道哪些信息重要,哪些可以丢弃。

在 X265 中,DCT 的实现经过了极致的优化(整数化、快速算法、SIMD 加速),以确保在保持高压缩效率的同时,尽可能降低编码器的计算耗时。它是现代视频压缩技术的基石之一。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 14:53:29

从零手写 FlashAttention(PyTorch实现 + 原理推导)

本文基于一个最小 PyTorch 示例&#xff0c;手写实现 FlashAttention 的核心计算流程&#xff0c;并详细解释其数值稳定性和分块计算原理。1. 标准 Attention 回顾 标准 Attention 的计算公式&#xff1a; Attention(Q,K,V)softmax(QKT)V Attention(Q,K,V) softmax(QK^T)V Att…

作者头像 李华
网站建设 2026/4/30 14:49:59

Linux进程资源泄漏自动清理:agent-reaper守护进程的设计与实践

1. 项目概述&#xff1a;一个守护进程的“清道夫”在开发和运维的日常里&#xff0c;我们经常会遇到一种让人头疼的情况&#xff1a;某个后台进程&#xff08;Agent&#xff09;因为各种原因卡死、僵死或者异常退出&#xff0c;但它留下的“烂摊子”却还在系统里。这些“烂摊子…

作者头像 李华
网站建设 2026/4/30 14:49:55

如何快速配置键盘映射:终极游戏操作优化指南

如何快速配置键盘映射&#xff1a;终极游戏操作优化指南 【免费下载链接】socd Key remapper for epic gamers 项目地址: https://gitcode.com/gh_mirrors/so/socd Hitboxer是一款专为游戏玩家设计的键盘重映射工具&#xff0c;它能够智能解决游戏中同时按下相反方向键时…

作者头像 李华
网站建设 2026/4/30 14:48:26

SQL必会的常用函数(三)文本函数

SQL文本函数详解一、基础查询函数1. LENGTH / LEN - 获取字符串长度-- MySQL SELECT LENGTH(Hello World); -- 返回 11-- SQL Server SELECT LEN(Hello World); -- 返回 112. CONCAT - 字符串拼接-- 标准语法&#xff08;所有数据库通用&#xff09; SELECT CONCAT(Hello, …

作者头像 李华
网站建设 2026/4/30 14:47:50

用particles.js创造动态粒子效果的3种实用场景指南

用particles.js创造动态粒子效果的3种实用场景指南 【免费下载链接】particles.js A lightweight JavaScript library for creating particles 项目地址: https://gitcode.com/gh_mirrors/pa/particles.js 你是否曾惊叹于那些科技感十足的网站背景&#xff0c;无数光点如…

作者头像 李华