视频去雨是计算机视觉中一个经典又实用的研究课题。下雨天拍摄的视频画面中往往叠加了大量半透明的雨条纹,它们会降低画面清晰度,干扰后续的目标检测、跟踪和识别任务。与单帧图像去雨不同,视频去雨拥有一个天然优势:雨条纹是随机快速下落的,而背景物体在相邻帧之间的变化相对平缓,这意味着某一帧被雨遮挡的背景区域,很可能在前后几帧中是清晰可见的。如何利用这种时序相关性,就是视频去雨技术的核心所在。

一、为什么时序相关性是视频去雨的关键
理解视频去雨,首先要理解雨条纹在时序上的分布特性。雨滴的下落速度通常在每秒数米到十几米之间,配合相机的曝光时间,单帧画面中的雨滴会呈现出近似竖直方向的条纹状拖影。更重要的是,雨滴在空间中的分布是稀疏且随机的,同一个背景位置在连续帧中被雨滴反复遮挡的概率很低。
这就产生了一个非常有用的先验:如果把相邻几帧对齐到同一坐标系下,某个位置的像素值序列中,绝大多数采样来自干净的背景,只有少数被雨条纹污染。基于这一观察,传统的多帧融合方法会利用中值滤波或者鲁棒主成分分析(RPCA)来分离背景层和雨层。RPCA把观测矩阵分解为低秩的背景分量和稀疏的雨分量,正好对应了背景的时序一致性和雨条纹的稀疏随机性。
然而这类方法有一个明显短板:相机运动和物体运动会破坏对齐,导致低秩假设失效。一旦背景中出现快速移动的物体,纯依赖矩阵分解的方法很容易产生鬼影或者把运动物体误判为雨条纹。因此现代视频去雨方法更多转向深度学习,让网络自己学习如何在运动补偿的前提下提取时序相关性。
二、基于深度学习的视频去雨框架
深度学习方案通常把视频去雨建模为一个序列到序列的映射问题:输入连续的若干帧含雨图像,输出当前帧的去雨结果。网络结构上主要分为两类思路,一类是以卷积循环神经网络(ConvLSTM)为代表的递归传播结构,另一类是基于注意力机制的帧间信息聚合结构。
递归传播结构的思想是把前一帧提取的特征图通过一个隐状态传递到当前帧,配合光流做变形对齐后进行融合。这种结构的优势在于可以用较少的计算资源处理任意长度的视频序列,隐状态相当于一个不断更新的背景记忆。下面是一个简化的特征传播流程示例,用PyTorch风格伪代码展示:
import torch
import torch.nn as nn
import torch.nn.functional as F
class RainRemovalPropagator(nn.Module):
def __init__(self, num_features=64):
super().__init__()
# 光流估计网络,负责帧间对齐
self.flow_net = FlowEstimator()
# 特征提取与融合
self.feat_conv = nn.Conv2d(3, num_features, 3, padding=1)
self.fuse_conv = nn.Conv2d(num_features * 2, num_features, 3, padding=1)
# 重建干净帧
self.reconstruct = nn.Conv2d(num_features, 3, 3, padding=1)
def forward(self, current_frame, prev_frame, prev_hidden):
# 估计上一帧到当前帧的光流
flow = self.flow_net(prev_frame, current_frame)
# 对齐上一帧的隐状态特征
aligned_hidden = self.flow_warp(prev_hidden, flow)
# 提取当前帧特征并与对齐后的历史特征融合
feat = self.feat_conv(current_frame)
fused = self.fuse_conv(torch.cat([feat, aligned_hidden], dim=1))
hidden = F.relu(fused)
# 重建输出去雨后的当前帧
clean_frame = self.reconstruct(hidden)
return clean_frame, hidden
def flow_warp(self, feat, flow):
# 根据光流对特征图做双线性变形采样
B, C, H, W = feat.size()
grid_y, grid_x = torch.meshgrid(torch.arange(H), torch.arange(W))
grid = torch.stack([grid_x, grid_y], dim=-1).float().to(feat.device)
sample_grid = (grid + flow.permute(0, 2, 3, 1))
sample_grid_x = 2.0 * sample_grid[..., 0] / (W - 1) - 1.0
sample_grid_y = 2.0 * sample_grid[..., 1] / (H - 1) - 1.0
return F.grid_sample(feat, torch.stack([sample_grid_x, sample_grid_y], dim=-1))
注意力机制的方案则更灵活一些,典型做法是让当前帧作为查询,前后多帧作为键和值,通过可变形注意力直接在特征层面搜索相关的干净区域。相比固定窗口的光流对齐,可变形注意力可以处理更大幅度的运动,也避免了光流估计不准确带来的误差累积问题。像基于Transformer的视频去雨模型,通常在每个尺度上堆叠多个时空注意力模块,逐步把相邻帧中的干净背景信息聚合到当前帧。
两种结构各有取舍。递归结构推理速度快、显存占用低,适合处理长视频,但误差会沿时间传播;注意力结构效果好、对运动更鲁棒,但计算量随参与融合的帧数平方增长,实际部署时需要在质量和速度之间做权衡。
三、实践中的关键细节与常见问题
实际搭建视频去雨系统时,光流对齐的质量往往决定了整体效果的下限。如果光流本身在雨区估计不准,对齐后的特征可能出现错位,融合时就会产生重影。常见的改进手段包括:在训练时对光流网络加入雨滴增广,让模型学会在雨天条件下估计运动;或者干脆放弃显式光流,使用可变形卷积隐式地学习采样偏移量。
损失函数的设计同样重要。除了基本的重建误差(L1或L2损失),加入感知损失可以让去雨结果在纹理细节上更自然,加入多尺度损失则有助于兼顾粗大的雨丝和细密的雨雾。部分工作还会显式地监督雨层,即让网络同时预测雨条纹残差图,再从含雨帧中减去它,这种显式分解的方式在重雨场景下通常更稳定。
数据方面,真实的成对 rainy/clean 视频极难获取,绝大多数方法依赖合成数据训练:在干净视频上叠加随机方向、长度、亮度的雨条纹,并模拟雨滴积累带来的整体雾化效果。合成与真实域之间的差距是落地的最大障碍,缓解办法包括域随机化、使用物理更精确的雨渲染模型,以及在少量真实数据上做自监督微调。评估指标一般采用PSNR和SSIM,同时建议辅以目标检测等下游任务的表现来衡量去雨的实用价值,因为有些方法虽然PSNR略低,却能明显提升下游任务的鲁棒性。
四、总结
视频去雨的本质是利用时序冗余补全被遮挡的信息。从早期基于低秩分解的传统方法,到如今融合光流对齐、递归传播和注意力机制的深度模型,技术演进的脉络始终围绕一个核心问题:如何更准确地在帧间建立对应关系,并把干净背景信息可靠地搬运到当前帧。对于希望上手实践的开发者,建议从一个轻量的递归传播模型起步,先在合成数据上跑通训练流程,再逐步引入可变形对齐和多尺度监督来提升真实场景的泛化能力。