Real-ESRGAN 本来是为单张图片设计的超分辨率模型,效果非常出色,但直接拿它逐帧处理视频时,很多人会发现结果并不理想:单帧看还算清晰,连起来播放却会出现明显的闪烁、抖动,甚至物体边缘会一帧一帧地"呼吸"。造成这个问题的根源在于逐帧处理完全忽略了视频的时序信息,每一帧都是独立生成的,误差在时间轴上不连续。视频超分要解决的核心问题,就是如何把相邻帧的信息利用起来,这就要提到 Real-ESRGAN 的视频版方案以及帧对齐技术了。

为什么逐帧超分会闪烁:时序一致性问题
要理解视频超分,先要明白逐帧处理的缺陷在哪。Real-ESRGAN 处理单张图时,模型根据学习到的先验"脑补"细节,比如把模糊的文字边缘补成锐利的笔画。这种脑补本身带有随机性,同一块区域在相邻两帧可能被补成不同的样子,人眼对这种时间上的不连续非常敏感,于是就看到了闪烁。
另一个问题是抖动。视频压缩产生的块效应、压缩伪影在不同帧上的分布不同,单图模型逐帧处理时,去伪影的力度和位置也不一致,导致画面整体稳定性下降。多帧超分的基本思路是:如果能把相邻帧的信息对齐并融合,那么每一帧的细节生成就有了多个"参照物",不确定度大幅降低,时序一致性自然就上来了。
但多帧融合有一个绕不开的前置步骤——对齐。相邻帧之间存在物体运动和镜头运动,像素并没有在同一个位置,直接叠加只会得到重影。如何准确地把参考帧和支撑帧对到一起,就是整个技术链路中最关键的一环。
Real-ESRGAN 视频版方案:Real-BasicVSR 架构
Real-ESRGAN 官方项目在 1.1.0 版本之后提供了专门的视频超分模型,基于 BasicVSR 架构改进而来,称为 Real-BasicVSR。它的整体思路不是在图像层面做超分,而是把"去模糊、去压缩伪影、超分"整合成一个端到端的视频处理网络,先在特征空间里把相邻帧对齐,再进行信息融合和重建。
BasicVSR 的核心组件包括三个部分:光流模块用于估计帧间运动;空间特征变换层(Spatial Feature Transform,即 SFT)根据光流信息对特征进行调制;循环传播结构负责在时间轴上传递和积累信息。Real-BasicVSR 在此基础上增加了针对真实退化的预处理能力,通过一个退化预处理模块先缓解输入视频中的模糊和压缩伪影,再把净化后的特征送入传播和对齐流程,因此对网络视频、老片翻新这类真实素材的适应性明显更好。
需要注意一点,Real-BasicVSR 对输入视频的退化程度比较敏感。如果源视频压缩特别严重,预处理模块可能"用力过猛",产生不自然的平滑效果,官方建议可以适当截取一段视频先做测试再决定参数。
帧对齐的实现原理:光流与可变形对齐
帧对齐在视频超分中有两种主流实现方式。第一种是基于光流的显式对齐,网络先通过 SpyNet 这类轻量光流估计器算出帧间的像素级偏移场,然后用 flow_warp 操作根据光流把支撑帧的特征图"扭曲"到参考帧的坐标系下。这种方式计算量可控、可解释性强,BasicVSR 采用的就是这种方案。
第二种是可变形卷积对齐(Deformable Alignment),即 IconVSR 和 EDVR 使用的方案。它不直接依赖光流,而是让网络自己学习每个采样点的偏移量,通过可变形卷积在支撑帧上自适应地采样特征。可变形对齐的精度上限更高,尤其擅长处理遮挡和大运动场景,但训练难度大,偏移量容易不稳定,通常需要光流结果做初始化辅助。
两者可以结合起来理解:光流对齐像是"按图纸搬运",图纸就是估计出的运动向量;可变形对齐像是"自由发挥搬运",网络边看边调整采样位置。工程实践中,光流对齐已经能覆盖大部分场景,也是 Real-BasicVSR 的默认选择。
命令行与 Python 调用实战
Real-ESRGAN 官方仓库提供了现成的推理脚本,视频超分最简单的调用方式是使用 inference_realesrgan_video.py,指定模型为 Real-BasicVSR 即可。典型命令如下:
python inference_realesrgan_video.py -i input.mp4 -o output.mp4 \
-n RealBasicVSR_x4 \
-s 4 \
--suffix out \
--tile 256其中 -n 指定模型名称,-s 是放大倍数,--tile 参数用于分块推理,可以有效控制显存占用。Real-BasicVSR 是循环网络,需要按顺序输入连续帧序列,如果输入的视频被抽帧得非常稀疏,对齐效果会明显下降,这一点与单图模型完全不同。
如果需要在 Python 代码中集成,也可以直接调用底层接口,示例代码如下:
import cv2
from basicsr.archs.rrdbnet_arch import RRDBNet
from realesrgan import RealESRGANer
# 构建视频超分器,Real-BasicVSR 内部使用 RRDBNet 作为重建骨干
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64,
num_block=23, num_grow_ch=32, scale=4)
upsampler = RealESRGANer(
scale=4,
model_path='weights/RealBasicVSR_x4.pth',
model=model,
tile=256, # 分块大小,显存不足时调小
tile_pad=10, # 分块重叠区域,避免接缝
pre_pad=0,
half=False # 视频超分建议关闭半精度,避免时序抖动放大
)
cap = cv2.VideoCapture('input.mp4')
fps = cap.get(cv2.CAP_PROP_FPS)
writer = cv2.VideoWriter('output.mp4',
cv2.VideoWriter_fourcc(*'mp4v'),
fps, (width * 4, height * 4))
while True:
ret, frame = cap.read()
if not ret:
break
result, _ = upsampler.enhance(frame, outscale=4)
writer.write(result)
cap.release()
writer.release()上面这段代码演示的是接口层面的调用方式。实际做视频任务时,更推荐直接用官方脚本,因为脚本内部会对帧序列做批量组织和状态管理,循环网络的隐藏状态传递会更稳定。分块推理时要特别注意 tile_pad 的设置,重叠区太小容易在块边界产生亮缝,建议保持 10 到 20 像素以上。
逐帧处理与多帧对齐的效果对比与选型建议
从效果上看,Real-BasicVSR 在时序稳定性上远胜逐帧 Real-ESRGAN,画面不再闪烁,运动物体边缘干净利落,同时因为融合了多帧信息,细节恢复的置信度也更高。代价是显存和计算开销显著增加,循环传播结构需要维持隐藏状态,长视频可能触发显存累积问题,必须借助分块推理和分段处理来缓解。
选型上可以遵循几个简单原则:如果输出是静态展示图或截帧,逐帧 Real-ESRGAN 足够;如果要制作完整播放的视频、老电影修复、游戏录屏增强,优先选 Real-BasicVSR 这类视频模型;如果源视频运动剧烈且帧间间隔大,光流对齐可能失效,此时要么提高输入帧率,要么考虑加入可变形对齐的方案。
参数调优方面,显存不足时优先调小 tile 而不是降低分辨率;发现画面过度平滑时,可以检查输入是否压缩过度,必要时先用去压缩工具预处理。另外推理时建议关闭半精度(half=False),循环网络对数值精度更敏感,半精度累积误差可能在长序列上放大成可见的色块。理解了帧对齐的原理和这些工程细节,视频超分这条链路就算真正打通了。
Real-ESRGAN视频超分帧对齐修改时间:2026-09-05 09:30:38