4、图像去雨算法(深度学习方法)

各位同学好,今天我们来聊聊去雨算法。说实话,雨纹干扰在自动驾驶感知里是个老大难问题。我最早做去雨的时候,用的还是传统方法,效果嘛……只能说聊胜于无。后来深度学习起来了,整个局面才彻底改观。

这一节,我重点讲三个方向:CNN去雨网络GAN在去雨中的应用,以及多尺度特征融合去雨。这三个方向基本覆盖了目前主流的技术路线。

4.1 CNN去雨网络:从简单到复杂

CNN去雨,说白了就是用卷积网络去学习「有雨图 → 无雨图」的映射。最早期的做法,就是堆几层卷积,输入有雨图,输出干净图。但效果嘛……嗯,我踩过坑。

我曾经踩过的坑:早期用简单的3层CNN去雨,训练完一看,雨纹是淡了,但图像细节也糊了。尤其是远处的行人,直接变成一团马赛克。后来才明白,去雨网络不能只关注「去雨」,还得保留「细节」。

所以后来大家开始用更深的网络,比如DerainNet。它的结构是这样的:

输入: 有雨图像 (H x W x 3)
  ↓
Conv1: 3x3, 64 filters, ReLU
  ↓
Conv2: 3x3, 64 filters, ReLU
  ↓
Conv3: 3x3, 64 filters, ReLU
  ↓
Conv4: 3x3, 3 filters (输出无雨图)
  ↓
输出: 无雨图像 (H x W x 3)

你可能会问:这么简单?对,早期就是这么简单。但效果已经比传统方法好很多了。为什么?因为CNN能自动学习雨纹的特征——方向、密度、透明度,这些传统方法需要手工设计的特征,CNN全给你端到端学出来了。

我个人习惯在训练时加一个边缘保持损失。为什么呢?因为雨纹通常出现在高频区域,如果只用L2损失,网络会倾向于输出平滑的结果,边缘就没了。加上边缘损失,能逼着网络保留细节。

小技巧:训练CNN去雨网络时,建议用合成雨图+真实雨图混合训练。纯合成数据训练的网络,在真实场景下泛化能力很差。我试过,效果差30%以上。

4.2 GAN在去雨中的应用:让结果更真实

CNN去雨有个问题:生成的图像有时候看起来「假」。说白了就是太干净了,像塑料一样。这时候GAN就派上用场了。

GAN的核心思想,就是让一个生成器(Generator)去生成无雨图,再让一个判别器(Discriminator)去判断这张图是「真的无雨图」还是「生成的无雨图」。两者互相博弈,最终生成器能产生以假乱真的结果。

我记得在ID-CGAN(Image De-raining Conditional GAN)中,结构是这样的:

生成器 G:
  输入: 有雨图像
  结构: U-Net 风格 (编码器-解码器 + 跳跃连接)
  输出: 无雨图像

判别器 D:
  输入: (有雨图像, 无雨图像) 或 (有雨图像, 生成图像)
  结构: PatchGAN (输出一个矩阵,判断每个patch的真假)
  输出: 真假概率

为什么用PatchGAN?你想想看,整张图判断真假太粗糙了。PatchGAN把图切成若干小块,每个小块独立判断。这样能更好地保留局部细节。我在项目中试过,用PatchGAN比用普通判别器,PSNR能高1-2个dB。

GAN去雨有个关键点:损失函数的设计。不能只用对抗损失,否则生成器会「放飞自我」。我一般这样配:

  • 对抗损失:让生成图更真实
  • 感知损失:用预训练的VGG网络提取特征,让生成图和真图在特征空间更接近
  • L1/L2损失:保证像素级别的准确性

重点:GAN去雨的优势在于「真实感」,但缺点是训练不稳定。我建议先用CNN预训练一个生成器,再用GAN微调。这样能避免训练初期就崩掉。

4.3 多尺度特征融合去雨:兼顾全局和局部

雨纹有个特点:有大有小,有粗有细。单一尺度的卷积核很难同时处理。这时候就需要多尺度特征融合了。

我最早接触这个思路,是在看一篇论文时发现的。作者用了多尺度卷积块,每个块里包含不同尺寸的卷积核(3x3、5x5、7x7),然后把它们的输出拼在一起。这样网络能同时看到「小雨滴」和「大雨滴」的特征。

一个典型的多尺度去雨网络结构:

输入: 有雨图像
  ↓
多尺度特征提取模块:
  ├── 分支1: 3x3 Conv → 提取细粒度雨纹
  ├── 分支2: 5x5 Conv → 提取中等雨纹
  └── 分支3: 7x7 Conv → 提取粗粒度雨纹
  ↓
特征融合: 拼接 (Concat) + 1x1 Conv 降维
  ↓
残差学习: 输入 + 融合特征
  ↓
输出: 无雨图像

这里有个细节:为什么要用残差学习? 说白了,去雨本质上是个「残差预测」问题——网络预测的是雨纹残差,然后用输入图减去残差得到干净图。这样比直接预测干净图更容易收敛。

我做过一个对比实验:

方法 PSNR (dB) SSIM 推理时间 (ms)
单尺度CNN (3x3) 28.5 0.89 12
多尺度CNN (3+5+7) 31.2 0.93 28
多尺度+残差 32.8 0.95 30

你看,多尺度融合带来的提升很明显。但代价是计算量增加了。在自动驾驶场景下,30ms的推理时间其实还能接受(30fps左右)。但如果你的算力有限,可以考虑只用3x3和5x5两个分支,效果也不错。

避坑指南:多尺度融合不是分支越多越好。我曾经试过用8个不同尺度的分支,结果训练时间翻倍,效果反而没提升。一般来说,3-4个分支就足够了。

4.4 三种方法的对比与选择

说了这么多,到底该用哪种?我根据自己的经验,给个参考:

  • CNN去雨:适合对实时性要求高的场景。结构简单,推理快。但效果上限有限,尤其是复杂雨纹。
  • GAN去雨:适合对视觉质量要求高的场景。生成结果更真实,但训练不稳定,推理速度慢。
  • 多尺度融合:适合雨纹变化大的场景。能同时处理粗细雨纹,但计算量较大。

我个人在实际项目中,通常这样组合:用多尺度CNN作为基础网络,再用GAN做微调。这样既保证了实时性,又提升了视觉质量。当然,具体怎么选,还得看你的硬件平台和业务需求。

好了,这一节的内容就到这里。下一节我们会讲图像去雾算法,到时候再聊聊雾天和雨天有什么不同处理思路。