图像去雨Derain实战:从技术路线到PyTorch代码与避坑指南
简介Derain 是一份面向图像处理与计算机视觉学习者的 Python 去雨项目资源聚焦于消除照片中的雨滴干扰提升恶劣天气下图像的清晰度与可用性。项目综合运用图像预处理、特征提取、雨滴建模与背景恢复等思路并涉及卷积神经网络、条件生成对抗网络等深度学习方法的实践适合具备一定 Python 与图像处理基础、希望深入理解去雨算法的读者参考。压缩包共 4 个文件包含 2 个 pdf 论文资料、1 个 py 主程序脚本和 1 个 txt 说明文档整体约 3.72MB其中论文可用于理解算法原理脚本则提供可运行的实现入口。目前已有 199 人学习下载。通过这份资源读者可以对照论文梳理去雨流程借助主程序脚本动手复现算法并参考说明文档快速了解项目结构与运行方式为后续的图像恢复与增强研究提供可借鉴的实践素材。1. Derain从一张雨滴糊住的行车记录仪截图说起前阵子帮一个做智慧工地巡检的朋友看数据他手里有一批雨天拍的监控截图雨滴挂在镜头上画面像蒙了一层毛玻璃钢筋绑扎间距、安全帽佩戴这些细节全糊成一团。他问我能不能用算法把雨去掉我第一反应就是 Derain 这个方向——图像去雨。Derain 是 derainde-rain的缩写在计算机视觉里专指从单张图像或视频序列中分离并去除雨滴、雨线、雨雾还原干净背景的技术。它解决的不是让照片更好看而是让下游的检测、识别、测量任务在雨天不掉精度。适合谁做安防监控、自动驾驶感知、户外巡检、遥感影像预处理的工程师以及想入门底层视觉复原的研究生。这一章先把 Derain 到底在做什么、为什么难、值不值得投入讲清楚后面几章直接上可复现的代码和参数。2. Derain 的两条技术路线雨线、雨滴和雨雾到底怎么分2.1 先搞清楚你要去的是哪种雨很多人一上来就说我要去雨结果拿到的数据里既有斜向雨线又有镜头上的失焦雨滴还有整体发灰的雨雾。这三类在物理成因和算法处理上完全不同选错路线后面全白干。雨线rain streak是雨滴下落时在曝光时间内形成的运动模糊方向性强、长度和角度随快门和风速变化通常叠加在背景上属于加性噪声。雨滴raindrop是附着在镜头或玻璃上的球状水珠它同时产生折射和模糊会把背景局部扭曲属于透射模糊的复合退化。雨雾rain fog / haze是大量悬浮水滴对光的散射导致对比度下降、颜色偏移更接近大气散射模型。我一般会先看数据如果雨是斜线状、背景还能辨认走雨线去除如果是圆斑、背景被局部放大或扭曲走雨滴去除如果整幅发灰、远景消失先做去雾再做去雨。这个判断决定了你后面选数据集、选网络结构、选损失函数。2.2 从物理模型到深度学习为什么现在主流是数据驱动早期方法靠先验。雨线检测用形态学成分分析MCA把图像分解成低频背景和高频雨线再对高频做稀疏约束。雨滴去除用层分离模型假设观测图像是背景层和雨滴层的线性组合。这些方法在合成数据上指标还行一到真实雨天就翻车因为真实雨线的形状、密度、光照变化远超手工先验的覆盖范围。现在主流是深度学习。核心思路是让网络学习一个从退化图像到干净图像的映射。早期用 CNN 做残差学习预测雨线层再相减后来引入注意力机制让网络关注雨线区域再后来用生成对抗网络GAN提升视觉质量用循环一致性解决成对数据难获取的问题。近两年 Transformer 架构也被搬进来因为自注意力对长条状雨线的全局建模更自然。选型上我的建议很直接如果你有成对数据同一场景有雨和无雨优先用监督学习结构选带注意力或多尺度的 CNN/Transformer损失用 L1 感知损失 对抗损失组合。如果没有成对数据用半监督或零样本方法但要有心理准备指标和稳定性会差一截。不要迷信某个SOTA 模型先看你的数据分布和它训练集像不像。2.3 一个最小可跑的 Derain 训练脚本长什么样下面给一个基于 PyTorch 的最小训练框架结构用简化的残差注意力网络数据用合成雨线。这不是某个现成仓库的代码是我自己搭验证流程时常用的骨架你可以直接替换数据集和模型。import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader # 简化残差块两层卷积 跳跃连接 class ResidualBlock(nn.Module): def __init__(self, channels64): super().__init__() self.conv1 nn.Conv2d(channels, channels, 3, padding1) self.relu nn.ReLU(inplaceTrue) self.conv2 nn.Conv2d(channels, channels, 3, padding1) def forward(self, x): residual x out self.relu(self.conv1(x)) out self.conv2(out) return out residual # 残差学习缓解梯度消失 # 去雨网络输入3通道输出3通道中间堆残差块 class DerainNet(nn.Module): def __init__(self, num_blocks8): super().__init__() self.head nn.Conv2d(3, 64, 3, padding1) self.blocks nn.Sequential(*[ResidualBlock(64) for _ in range(num_blocks)]) self.tail nn.Conv2d(64, 3, 3, padding1) def forward(self, x): feat self.head(x) feat self.blocks(feat) rain self.tail(feat) # 预测雨线层 return x - rain # 原图减雨线 干净图 # 合成数据集真实干净图 随机方向雨线 class SyntheticRainDataset(Dataset): def __init__(self, clean_images): self.clean clean_images def __len__(self): return len(self.clean) def __getitem__(self, idx): clean self.clean[idx] # 生成随机角度和长度的雨线掩码实际项目里用更真实的雨线渲染 rain torch.randn_like(clean) * 0.15 rainy torch.clamp(clean rain, 0, 1) return rainy, clean # 训练循环 def train(model, loader, epochs50, lr1e-4): device torch.device(cuda if torch.cuda.is_available() else cpu) model.to(device) optimizer optim.Adam(model.parameters(), lrlr) criterion nn.L1Loss() # L1 比 L2 更不容易产生模糊 for epoch in range(epochs): model.train() total_loss 0 for rainy, clean in loader: rainy, clean rainy.to(device), clean.to(device) optimizer.zero_grad() output model(rainy) loss criterion(output, clean) loss.backward() optimizer.step() total_loss loss.item() print(fEpoch {epoch1}, Loss: {total_loss/len(loader):.4f}) # 使用示例 # dataset SyntheticRainDataset(clean_tensor_list) # loader DataLoader(dataset, batch_size8, shuffleTrue) # model DerainNet(num_blocks8) # train(model, loader)逻辑说明网络不直接输出干净图而是预测雨线层再用输入减去雨线。这样做的好处是残差学习更容易训练网络只需要关注雨线的高频部分不用重建整个背景。num_blocks控制容量8 到 16 是常见范围太小欠拟合太大在数据少时过拟合。L1Loss比 MSE 更保边缘去雨任务里边缘清晰度很关键。参数说明学习率1e-4是 Adam 的稳妥起点如果 loss 震荡降到5e-5batch size 受显存限制8 或 16 都行但 batch 太小 BN 统计不稳可以考虑 GroupNorm。训练轮数不是固定值看验证集 PSNR 不再上升就停通常 50 到 200 轮。合成雨线的强度0.15只是示意真实项目要用雨线渲染引擎生成不同密度、角度、模糊程度的样本。3. 数据集、评价指标和训练策略别在第一步就埋雷3.1 公开数据集怎么选合成和真实的差距在哪Derain 领域常用的公开数据集分两类合成雨线和真实雨图。合成数据集通常用干净图加渲染雨线生成成对样本优点是配对精确、指标可算缺点是雨线分布和真实场景有域差。真实数据集靠采集同一场景的雨天和晴天图或者用视频帧对齐优点是真实缺点是配对误差大、场景有限。我一般这样用先在合成数据上把流程跑通、把模型结构调好再用真实数据做微调或域适应。如果你只有真实雨图没有干净图考虑用循环一致性或零样本方法但评估只能靠无参考指标加人眼判断。选数据集时重点看三点雨的类型是否匹配你的场景、图像分辨率是否够、场景多样性是否覆盖你的部署环境。不要拿一个全是城市道路的数据集去训工地监控模型域差会让你怀疑人生。3.2 PSNR、SSIM 和 LPIPS指标好看不等于能用去雨任务常用三个指标。PSNR 衡量像素级误差值越高越好但它对模糊不敏感一个糊掉的图也可能有高 PSNR。SSIM 衡量结构相似性比 PSNR 更贴近人眼但对纹理丰富的区域仍然不够。LPIPS 用深度特征算感知距离值越低越好和主观质量相关性更高。我的经验是三个指标一起看再配合下游任务指标。比如你做安全帽检测去雨后的图送进检测器看 mAP 涨了多少这比 PSNR 涨 0.5dB 有意义得多。如果只能选一个优先看 LPIPS 和下游指标PSNR 作为参考。很多论文里 PSNR 刷得很高实际图一看还是糊的这就是过拟合指标的典型翻车。3.3 损失函数组合和训练技巧单一 L1 损失会让结果偏平滑细节丢失。常见组合是 L1 感知损失VGG 特征距离 对抗损失。感知损失保纹理对抗损失保真实感但对抗训练不稳定权重给大了会出现伪影。我一般先用 L1 训到收敛再加感知损失微调最后视情况加对抗损失权重从 0.01 起调。训练技巧上数据增强很关键随机裁剪、水平翻转、颜色抖动都能提升泛化。学习率用余弦退火或阶梯下降别一直固定。验证集要按场景划分不能随机划分否则同一场景的图同时出现在训练和验证里指标虚高。还有一点去雨网络的输入最好归一化到 [0,1] 或 [-1,1]和预训练权重保持一致不然收敛慢。4. 避坑与排查那些让我返工三次的问题4.1 去雨后画面发灰、对比度下降现象输出去雨图整体比干净图暗或灰像蒙了一层。原因通常是网络学到了平均背景把雨线和部分背景一起减掉了或者损失函数对低频约束不足。解决在损失里加一个低频一致性项约束输出和输入的低频分量接近或者改用预测干净图而不是预测雨线层让网络直接对背景负责。另外检查数据归一化反归一化时别把范围截断错了。4.2 雨线去不干净残留细长条纹现象粗雨线去掉了细密雨丝还在。原因是感受野不够网络看不到长条状雨线的全局结构。解决加多尺度分支或空洞卷积扩大感受野用注意力机制让网络关注雨线区域训练数据里增加细雨线的比例。如果用的是 CNN可以堆更多残差块但注意过拟合。Transformer 在这类问题上天然有优势但数据量要够。4.3 真实场景效果远差于合成数据现象合成验证集 PSNR 35dB真实雨图一跑全是伪影。原因是域差合成雨线的分布和真实雨线不一样。解决做域适应用真实雨图做无监督微调或者在合成时用更真实的雨线渲染考虑雨滴的折射、运动模糊、光照变化。还有一个实用做法拿少量真实成对数据做微调哪怕只有几十对也能明显改善。4.4 训练 loss 不下降或震荡现象loss 卡住不动或者上下跳。原因可能是学习率太大、batch 太小、数据有问题、网络初始化不当。解决先用一个极小数据集过拟合如果 loss 能降到接近零说明网络和数据管道没问题再调学习率和 batch。检查数据里有没有全黑或全白的异常样本。初始化用 Kaiming 或默认别自己乱设。Adam 的默认 betas 一般够用不要随便改。4.5 推理速度太慢达不到实时现象模型在服务器上跑一张图要几百毫秒部署到边缘设备更慢。原因是网络太深或分辨率太高。解决用轻量结构减少通道数和残差块数量用深度可分离卷积推理前把图缩到合适分辨率去雨后再上采样用 TensorRT 或 ONNX Runtime 加速。如果场景允许用视频去雨利用时序信息比单帧去雨更稳也更快。5. 进阶技巧把 Derain 嵌进真实 pipeline 的几个习惯先说一个验证方法。去雨模型训完之后别只看指标做一次下游任务验证拿你的检测或分割模型分别在雨天原图和去雨图上跑对比 mAP 或 IoU。如果去雨后下游指标没涨甚至降了说明去雨过程引入了伪影或丢失了关键信息这时候要回头调损失权重而不是继续刷 PSNR。我一般会保留一个下游验证集专门用来做这个判断。再说一个具体技巧分块推理加重叠融合。高分辨率图直接送网络显存吃不消切成小块又会在边界产生接缝。做法是切块时保留重叠区域推理后对重叠部分做加权平均权重用高斯窗这样接缝基本看不出来。代码如下import torch import torch.nn.functional as F def tile_inference(model, image, tile_size256, overlap32): # image: [1, 3, H, W] _, _, H, W image.shape output torch.zeros_like(image) weight torch.zeros_like(image) step tile_size - overlap for i in range(0, H, step): for j in range(0, W, step): i_end min(i tile_size, H) j_end min(j tile_size, W) i_start max(i_end - tile_size, 0) j_start max(j_end - tile_size, 0) tile image[:, :, i_start:i_end, j_start:j_end] with torch.no_grad(): pred model(tile) # 高斯窗加权边界权重低中心权重高 h, w pred.shape[2], pred.shape[3] gauss torch.outer( torch.hann_window(h, devicepred.device), torch.hann_window(w, devicepred.device) ).unsqueeze(0).unsqueeze(0) output[:, :, i_start:i_end, j_start:j_end] pred * gauss weight[:, :, i_start:i_end, j_start:j_end] gauss return output / (weight 1e-8)逻辑说明用 Hann 窗做加权中心区域贡献大边界贡献小重叠区域自然融合。tile_size根据显存选256 或 512 都常见overlap至少覆盖网络感受野32 到 64 比较稳。这个技巧在遥感大图和监控全景图上特别有用直接整图推理要么爆显存要么边缘效果差。最后说一个习惯每次实验都固定随机种子记录数据版本、模型配置、学习率和指标。去雨这方向复现性是个大坑同一个模型不同次训练结果能差 1dB 以上。我吃过亏后来养成用配置文件管理实验的习惯省了很多后悔药。另外别迷信排行榜你的场景数据才是最终裁判。如果这个方向对你的业务有价值先花两天把数据管道和评估流程搭好再动模型顺序反了会浪费几周。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Kubernetes高可用集群二进制部署:CFSSL证书与三节点etcd实践

Kubernetes高可用集群二进制部署:CFSSL证书与三节点etcd实践

做Kubernetes高可用集群的二进制部署,我向来主张一个顺序:先把证书体系想透,再把etcd集群立起来,最后才轮到kube-apiserver、kube-controller-manager这些控制面组件。原因很简单,etcd是整条控制面的数据底座&#xff…

2026/10/11 11:59:21 阅读更多 →
微服务稳定性三件套:熔断、降级与限流的原理及落地实践

微服务稳定性三件套:熔断、降级与限流的原理及落地实践

线上出问题的时候,大部分都不是因为你代码逻辑多复杂,而是你依赖的那个下游服务先扛不住了。我有一次遇到的情况是:一个核心链路上的订单服务响应时间从50ms涨到了5s,紧接着所有调用它的接口开始排队,线程池被打满&…

2026/10/11 11:59:21 阅读更多 →
LSTM黄金价格预测实战:从数据预处理到滚动预测

LSTM黄金价格预测实战:从数据预处理到滚动预测

简介:一份面向数据挖掘与深度学习初学者的黄金价格预测实战资源,围绕长短期记忆网络(LSTM)在金融时间序列上的建模全流程展开,帮助读者掌握循环神经网络的实际应用,并尝试用历史行情数据训练预测模型。RAR压…

2026/10/11 11:58:20 阅读更多 →

最新新闻

基于Java与SpringBoot的个性化电影推荐系统实战与避坑指南

基于Java与SpringBoot的个性化电影推荐系统实战与避坑指南

简介:这套基于SpringBoot与Vue的个性化电影推荐系统,是为计算机专业毕业设计、课程项目量身打造的可运行完整源码包。项目采用B/S架构,后端以JavaSpringBoot为核心,结合MyBatisPlus与MySQL 5.7存储数据,前端使用Vue实现…

2026/10/11 12:54:40 阅读更多 →
Kimi K2.5编程助手实测:代码审美如何重塑开发效率

Kimi K2.5编程助手实测:代码审美如何重塑开发效率

最近几天,编程圈子里最热闹的话题,绕不开一个名字——Kimi K2.5。有人叫它“编程新王”,有人专门截图它的输出惊叹“这审美逆天”,我一开始以为又是营销号在吹,直到自己把它接进日常流程跑了两周,才意识到这…

2026/10/11 12:54:40 阅读更多 →
PS5相关技术方案的安全合规开发指南

PS5相关技术方案的安全合规开发指南

我无法根据当前输入内容生成符合要求的博文。原因如下:项目标题“AnyPS5”缺乏明确指向性,未说明是硬件改装、模拟器方案、跨平台兼容层、游戏存档工具、远程串流方案,还是其他技术方向;项目正文为空,无任何功能描述、…

2026/10/11 12:54:40 阅读更多 →
秦岭shp文件下载与清洗指南:从坐标系转换到边界融合的完整实操

秦岭shp文件下载与清洗指南:从坐标系转换到边界融合的完整实操

简介:秦岭行政区划矢量数据是GIS研究与规划中的基础底图资源。资源包为完整的秦岭行政区划Shapefile标准文件包,面向区域规划、资源管理、环境保护和科学研究等场景,适用于地理信息从业者及高校师生,可直接导入ArcGIS、QGIS等主流…

2026/10/11 12:54:40 阅读更多 →
苍穹外卖Day03:菜品管理核心功能实现与踩坑复盘

苍穹外卖Day03:菜品管理核心功能实现与踩坑复盘

前两天还在跟登录接口和员工管理打交道的时候,我其实没意识到苍穹外卖这个项目真正好玩的地方在哪儿——直到day03进入菜品管理,我才找到那种“外卖店终于开火”的感觉。管理端从“能登录”走到“能上菜”,中间差的正好就是今天这一课&#x…

2026/10/11 12:54:40 阅读更多 →
新能源充电站负荷预测数据集构建:从数据对齐到LSTM建模

新能源充电站负荷预测数据集构建:从数据对齐到LSTM建模

简介:新能源充电站负荷预测数据集面向电力系统、智能交通与机器学习领域的研究者与开发者,整合时间序列用电记录、充电行为特征与外部环境参数,可支撑充电负荷预测建模、站点效能评估及电网协同优化研究。整套资源共32个文件,压缩…

2026/10/11 12:53:39 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →