📑 本页目录
DVC视频压缩学习笔记
沿着预测、运动和残差的关系,理解一个视频压缩网络如何学习在画质与码率之间取舍。
版本与使用范围
本文将论文设计、作者原始 TensorFlow 仓库、作者链接的后续 PyTorch 重实现,以及本地教学代码分别说明。PyTorch 参考源码固定于提交 e9dafc2bccfa5d49f464e7b031f587a2225d3927;对应文件和来源见 source_manifest.json。
视频压缩的基本框架
视频压缩利用可以预测的信息,量化则通过近似表示降低数据量。
一帧图像可以看作像素数组。常见的 8 位灰度像素取值为 0—255,视频是按时间排列的图像序列。空间冗余指同一帧中相邻像素的相关性;时间冗余指相邻帧之间的相关性。
对原始块 ,先生成预测块 ,计算残差:
如果精确传输残差,接收端可以通过 恢复原图。常见有损编码进一步变换、量化残差,再进行熵编码。
| 操作 | 作用 | 需要区分的概念 |
|---|---|---|
| 帧内预测 | 用同一帧中已重建的邻域预测当前块 | 帧内编码也有预测和残差 |
| 运动估计 | 找到参考图像中合适的取样位置 | 编码器需要搜索或估计运动 |
| 运动补偿 | 按运动信息生成预测图像 | 解码端根据收到的运动重建预测 |
| 变换 | 把残差换成更适合压缩的表示 | 变换本身不直接减少数值数量 |
| 量化 | 用较粗的数值近似原值 | 常见有损编码中引入失真的主要环节 |
| 熵编码 | 利用符号概率编码为比特 | 能精确恢复输入符号,但不能找回量化损失 |
教学例子:,,所以 。使用一个两点求和、求差变换:
若量化步长为 5,则 ,反量化为 ,逆变换得到 ,最终重建为 。这是说明原理的两点变换;H.264 常用的变换包括 整数近似 DCT。
H.264 的编码器通常还需要选择预测模式、分块和量化参数。常用率失真代价为 。运动搜索可以用绝对差之和作为基础匹配指标:
SAD 最小的候选预测不一定使总编码成本最小,因为运动和模式信息也要占用比特。
I、P、B 可分别理解为允许帧内预测、允许参考图像预测、允许两组参考列表组合预测的编码类型。严格说它们是切片类型。B 类型可以造成解码顺序与播放顺序不同;并非每个 B 块都必须同时使用前后两帧。
DVC 的两条编码分支
DVC 用运动分支生成预测,用残差分支补偿预测误差。
主论文第 3 节及图 2 是整个方法的阅读中心。P1
| 符号 | 含义 |
|---|---|
| 当前原始帧 | |
| 上一帧重建结果,作为参考 | |
| 估计光流、压缩后解码光流 | |
| 运动潜变量、量化运动潜变量 | |
| 预测帧 | |
| 像素域残差、解码残差 | |
| 残差潜变量、量化残差潜变量 | |
| 当前帧最终重建结果 | |
| 实现中显式使用的超潜变量及其量化结果 |
下面的函数名是为讲解定义的记号。运动分支为:
论文的运动补偿先变形,再利用参考图、变形图和解码光流进行修正:
残差分支为:
最终:
运动补偿使用解码光流 ,参考帧使用重建结果 。 编码端与解码端必须从相同的已知信息生成预测。解码端不需要当前原始帧,也不重新估计光流。
论文图 3 的运动编码器经过四次空间下采样,将 光流变成 潜变量。潜变量通道不是图像颜色通道,量化后也不意味着每个数值只占一位。实际码率由符号及其概率共同决定。
率失真目标与训练
共同的率失真损失,让运动和残差围绕最终效果协作。
论文公式(1)为:
使用 MSE;两个编码成本项分别对应运动和残差信息。传统编码已经使用率失真优化,DVC 的贡献在于联合学习多个模块的参数。
光流改变后,运动码率、残差码率和最终失真都会变化。教学例子:若运动多花 0.01 bpp,却让残差少花 0.03 bpp,并保持最终失真不变,总码率就减少 0.02 bpp。
DVC 的 乘在失真项上,越大通常越重视画质。与 比较时,在度量和归一化一致的前提下,等价的权重关系是 。论文分别训练了 的四个模型。
取整几乎处处梯度为零。训练时使用均匀噪声近似量化,推理时取整:
给定采样噪声,,梯度可以传回编码器。概率模型提供可微的编码成本估计,实际熵编码不参与这种逐操作反向传播。
论文训练还缓存已经重建的帧,供之后的训练迭代读取和更新,避免每次重新编码整段历史。该描述支持当前帧链路的联合训练,不能据此推断所有历史帧都展开并跨时间反向传播。
GDN 的变换与梯度
GDN 根据通道能量调节幅度,IGDN 学习近似逆变换。
对同一空间位置的多个通道,GDN 定义为:G1
分母中的加权平方和描述特征能量, 保证数值稳定。参数通过压缩目标学习,不使用当前批次的均值或方差。
若多个通道共享幅度因素 ,其中 ,忽略较小的 时:
共同幅度因素被削弱,有助于减少某些统计依赖;这不是特征完全独立的保证。
令 ,利用链式法则得到:
第一项来自分子,第二项来自分母。 在 时为 1,否则为 0;因此一个通道也能通过归一化影响其他通道。
教学代码使用正值重参数化和 卷积:
beta = F.softplus(self.beta_raw) + 1e-6
gamma = F.softplus(self.gamma_raw)[:, :, None, None]
norm = F.conv2d(x.square(), gamma, bias=beta).sqrt()
output = x / normIGDN 则为:
编码、解码两侧使用各自的可学习参数。IGDN 不是将同一组 GDN 参数直接代入就能获得的精确代数逆。
原 PyTorch GDN 使用平方重参数化和自定义 LowerBound。参数低于下界时,如果梯度会使参数回到可行区域,反向传播仍然放行。教学版改用 softplus,保留正值约束,但不保证与原权重兼容。
金字塔光流与可微采样
金字塔光流先处理粗尺度运动,再逐层学习修正量。
亮度恒定假设给出:
对右侧作一阶展开,可得 。一个像素只有一个约束却有两个位移未知量,所以需要邻域、纹理与先验信息。大运动还会削弱小位移近似的适用性。
SPyNet 在图像金字塔上由粗到细估计光流。原图中移动 32 个像素,在缩小到 的图像中只移动约 4 个像素。F1
第 层先放大已有光流,再变形参考图,最后估计修正量:
上采样后乘 2 是为了转换位移单位:粗图上 2 个像素的位移,对应尺寸加倍的细图上 4 个像素。
每层网络输入为 3 通道当前图、3 通道变形参考图和 2 通道光流,共 8 通道。卷积通道为 ,卷积核为 ,末层不加 ReLU。原 SPyNet 论文使用五级金字塔,对照的 DVC PyTorch 实现使用四级。
本地代码采用反向取样约定:输出位置 到参考图像 取值。因此,正水平位移表示向参考图右侧取样,不能直接解释成物体向右运动。
双线性插值让取样坐标可以接受梯度。令采样位置的水平、竖直小数部分为 ,四个邻居为 :
在同一个插值单元内部:
因而图像误差能通过采样位置传给光流。均匀区域的梯度可能很小,也说明其运动难以仅靠局部外观唯一确定。教学版显式设置 grid_sample 的 align_corners=True,并使用与之匹配的坐标归一化。
原 SPyNet 的监督训练使用光流端点误差;进入 DVC 后,光流还需要服务于最终的画质和编码成本。论文损失中没有额外的真实光流监督项。
概率模型与尺度超先验
概率模型通过量化区间的概率计算编码成本,超先验提供分布的条件信息。
设真实符号分布为 ,编码采用模型分布 。理想平均码长是交叉熵:
模型不匹配会带来额外编码成本;压缩训练既学习特征,也学习其概率模型。E1
连续特征 量化成整数 ,意味着它落在 。若连续密度为 、CDF 为 ,则:
连续密度值可以大于 1,不能直接当作整数符号的概率。代码需要计算区间概率,再计算 。
BitEstimator 为每个通道学习一条 CDF,参数在空间位置之间共享。其非末层可以写成:
因为 ,这些层保持单调。末层 sigmoid 将输出限制为 0—1,多层复合形成可学习 CDF。
残差特征在不同位置具有不同幅度,因此使用超编码器提取旁信息:
先被编码和传输。接收端先恢复 ,再预测分布尺度 ,最后用相同的条件概率解码 。一旦 已经恢复,像素重建网络就不再需要 ;这不代表熵解码时可以省略它。
Ballé 2018 的尺度超先验使用零均值 Gaussian 描述条件分布;对照的 PyTorch 重实现实际使用 Laplace:
是尺度参数,标准差为 。源码虽然使用 gaussian、sigma 等变量名,仍应以创建的 Laplace 对象为准。
实现将总成本分成三项:
旁信息也要付出成本。对 [B, 3, H, W] 图像,总 bpp 为:
分母是原图像素数,不是潜变量数,也不再乘 RGB 通道数 3。训练时若 ,则:
该梯度把“特征如何变化能降低编码成本”的信号传给编码器;概率参数同时学习如何拟合特征分布。
代码入口:可学习 CDF、Laplace 区间概率、原概率估计器、原残差概率计算。
实验结果与消融证据
实验支持联合学习的价值,性能结论受指标、序列和编码配置影响。
论文使用 Vimeo-90k 训练,在 UVG 和 HEVC Class B/C/D/E 上评估。训练裁剪为 ,批次大小为 4,Adam 初始学习率为 。传统基线使用 FFmpeg 的 veryfast 配置。P1P2
率失真曲线应在相同 bpp 下比较质量,或在相同质量下比较 bpp。补充表 1 所列 16 个 HEVC 序列的平均 BD-BR 如下,负数表示相对 H.264 节省码率:
| 质量指标 | DVC 相对 H.264 | H.265 相对 H.264 |
|---|---|---|
| PSNR | −19.22% | −25.06% |
| MS-SSIM | −29.32% | −21.73% |
DVC 平均优于论文配置下的 H.264;与 H.265 相比,平均 PSNR 结果仍有差距,MS-SSIM 结果更有竞争力。29.32% 的比较基线是 H.264。序列差异也明显,例如 BQMall 在 PSNR 下的 DVC BD-BR 为 +26.13%,并非所有序列都胜出。
主文表 1 对比了冻结与联合训练光流网络:
| 光流训练方式 | 运动编码成本 | 变形图像 PSNR |
|---|---|---|
| 冻结预训练光流网络 | 0.044 bpp | 27.33 dB |
| 联合训练 | 0.029 bpp | 28.17 dB |
联合训练后,运动成本约降低 34%,变形图像 PSNR 提升 0.84 dB。这里测量的是变形图像,不是加上解码残差后的最终重建。
图 6 的消融进一步显示:去掉运动补偿修正网络,相同 bpp 下 PSNR 约下降 1 dB;去掉运动压缩网络或不使用运动,下降超过 2 dB;训练时用原始参考帧代替缓存重建帧,约损失 0.2 dB。
图 7 中联合训练后的重建光流有更多零运动区域。均匀区域即使使用不完全符合真实运动的光流,也可能生成接近的像素,因此压缩目标能够选择更容易编码的运动表示。最终码率仍取决于潜变量和概率模型。
图 8 中,随 增大,总码率上升,运动码率占比由 38.8% 降至 26.9%。占比下降不能直接推出运动的绝对码率下降。
方法的研究边界包括:主网络只使用一个过去的参考帧;不同工作点使用分别训练的模型;论文在 上报告约 24.5 fps 编码和 41 fps 解码,该速度不能直接用于推断高分辨率实时表现。
从论文到代码
阅读实现时,先确定版本,再追踪张量和编码成本。
| 项目 | 论文或引用方法 | 后续 PyTorch 重实现 | 本地教学代码 |
|---|---|---|---|
| 运动压缩 | 图 3 使用四次下采样及 GDN/IGDN | 八层卷积和 LeakyReLU | 跟随重实现的数据流,缩小通道数 |
| 运动补偿 | 参考图、变形图和解码光流共同输入 | 拼接参考图和变形图,预测修正量后加回变形图 | 跟随六通道输入与修正结构 |
| 残差变换 | 引用深度图像压缩网络 | GDN/IGDN,默认 N=64、M=96 | 默认 N=16、M=24 |
| 条件分布 | Ballé 2018 以 Gaussian 建模尺度超先验 | 实际使用 Laplace | 使用 Laplace 区间概率 |
| 训练参考 | 描述在线缓存重建帧 | 数据加载器直接读取参考图 | 合成图像对 |
| 训练目标 | 主文公式为率失真目标 | 前 50 万步加入辅助预测损失 | 纯率失真目标 |
| 首帧 | 主网络图未展开 | README 要求先用 H.265 产生 I 帧 | 直接提供参考图像,不编码 I 帧 |
| 熵编码 | 论文报告算术编码码率检查 | 有 torchac 分支,默认 calrealbits=False | 估计码率,不生成熵编码码流 |
作者原始 TensorFlow 仓库的 README 则采用学习式图像压缩处理帧内图像,并明确说明公开代码没有提供熵编码模块,特征保存为 .pkl,报告估计 bpp。C1 上表的 PyTorch 版本与该原始仓库不可直接混为一谈。
本地教学模型没有预训练权重,与原仓库检查点不兼容。其 GDN 改用 softplus 参数化,超解码器也通过 softplus 保证尺度为正,并显式设置现代采样坐标约定。
按以下顺序读代码:
| 顺序 | 函数或类 | 需要追踪的问题 |
|---|---|---|
| 1 | GDN |
跨通道平方和如何用 1×1 卷积实现 |
| 2 | warp |
像素坐标如何转换为 grid_sample 坐标 |
| 3 | PyramidFlow |
上采样与位移单位如何同步变化 |
| 4 | FactorizedCDF |
单调性与区间概率如何保证 |
| 5 | laplace_mass |
如何稳定计算量化区间概率 |
| 6 | MiniDVC.forward |
两条压缩分支和旁信息如何连接 |
| 7 | self_check |
数学约束和梯度是否得到验证 |
教学代码的核心前向过程为:
flow = model.flow(current, reference)
m_hat = quantize(model.motion_encoder(flow), model.training)
prediction, warped = model.predict(reference, m_hat)
y = model.residual_encoder(current - prediction)
z_hat = quantize(model.hyper_encoder(y.abs()), model.training)
scale = F.softplus(model.hyper_decoder(z_hat)) + 1e-4
y_hat = quantize(y, model.training)
reconstruction = prediction + model.residual_decoder(y_hat)
R_m = estimated_bits(model.motion_cdf.likelihood(m_hat))
R_z = estimated_bits(model.hyper_cdf.likelihood(z_hat))
R_y = estimated_bits(laplace_mass(y_hat, scale)) 其中 model、current、reference 及函数定义来自教学文件;上面是主体流程摘录。训练步骤为:
B, _, H, W = current.shape
bpp = (R_m + R_z + R_y) / (B * H * W)
loss = 256 * F.mse_loss(reconstruction, current) + bpp
optimizer.zero_grad()
loss.backward()
optimizer.step()原重实现的早期目标使用 ,50 万步后去掉辅助项;原脚本还逐元素裁剪梯度。教学版使用梯度范数裁剪,不复现整套训练日程。
当前机器可用以下 PowerShell 命令检查数学与数据流,并运行三步合成训练:
& "D:\soft\py12\python.exe" "E:\Projects\research\paper-reading\dvc-internals\dvc_internals.py" --check --steps 3已保存的 verification.json 记录了 CPU 上的验证:GDN 解析梯度、半像素插值及梯度、CDF 单调性与归一化、Laplace 区间概率、所有模块接受率失真梯度,以及从相同解码潜变量重建出相同图像。该记录使用 PyTorch 2.13.0+cu126,验证不代表真实数据集上的压缩性能。
实际熵编解码还需要双方一致的离散概率表、符号范围、终止及尾部处理,并需要统计旁信息和必要头信息。-log2(probability)、.pkl 文件大小和真实压缩码流大小是三个不同概念。
理解自查
复习时用下面这些问题检查理解。
| 问题 | 答案要点 |
|---|---|
| 编码端为什么也要重建当前帧 | 后续参考必须与解码端一致 |
| 为什么用解码光流生成预测 | 解码端只能获得压缩后恢复的光流 |
| 预测准确是否保证总码率更低 | 还要计算运动、模式和残差的成本 |
| 光流越接近真实运动越好吗 | 压缩评价需要考虑最终失真和总码率 |
| GDN 是否保证完全独立 | 不能保证,只学习有利于压缩的非线性表示 |
| IGDN 是否是精确逆 | 是学习的近似逆形式,参数独立 |
| 连续密度能否直接当整数概率 | 应计算量化区间的概率质量 |
| BitEstimator 是否直接输出比特 | 输出 CDF,先作区间差,再取负对数 |
| 超先验 z 为什么需要传输 | 解码端需要它恢复相同的条件概率模型 |
| 为什么码率是三项 | 运动 m、旁信息 z、条件残差特征 y 都要编码 |
| 光流放大为什么乘 2 | 图像像素单位随分辨率变化 |
| 推理时还能依赖当前原始帧吗 | 编码端可以,解码端只能使用码流、参考与共享模型 |
| 估计 bpp 是否等于真实码流大小 | 只是理想编码成本估计,实际编码还存在实现开销 |
| 29.32% 是相对 H.265 的节省吗 | 是补充表 1 中相对 H.264 的平均结果 |
能够从图 2 独立写出“运动潜变量→解码光流→预测→残差潜变量→解码残差→最终重建”,并补上 的条件解码关系、总 bpp 和损失函数,就建立了从论文到代码的对应关系。
论文与代码来源
- P1 DVC 主论文:方法、损失、训练策略、主实验与消融。
- P2 DVC 补充材料:BD-BR、传统编码器设置和运动补偿网络结构。
- H1 H.264 AVC 总览论文:预测、变换编码、参考关系与环内滤波。
- G1 End-to-end Optimized Image Compression:GDN、IGDN 与量化训练近似。
- F1 Optical Flow Estimation using a Spatial Pyramid Network:金字塔、残差光流及网络结构。
- E1 Variational image compression with a scale hyperprior:交叉熵、条件尺度模型、可学习 CDF 与旁信息。
- C1 作者原始 DVC 仓库:原始测试代码与熵编码公开范围。
- C2 固定提交的 PyTorch 重实现:本地
reference文件的来源,许可证保存于 LICENSE。 - C3 本地教学代码及来源清单:小通道、无预训练权重的数学与数据流演示。
KaTeX license The MIT License (MIT) Copyright (c) 2013-2020 Khan Academy and other contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Fonts: IBM Plex Sans, SIL Open Font License 1.1. Source: @fontsource/ibm-plex-sans 5.2.5. Source-code excerpts retain their upstream MIT license in the embedded LICENSE entry.