尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

火场灰度图像去烟算法:从物理退化建模到半监督微调实战

火场灰度图像去烟算法:从物理退化建模到半监督微调实战 简介这份PDF文献面向图像处理、计算机视觉方向的研究者与消防信息化技术人员聚焦火场灰度图像中烟雾干扰导致监控画面模糊、对比度下降的问题提出一套基于深度学习的去烟算法方案。资源为单篇学术论文压缩包内仅含1个PDF文件约1.26MB便于快速查阅与引用。论文核心由检测子网络与去除子网络串联构成前者借助残差学习网络定位烟雾区域缓解深层网络梯度消失后者采用密集连接的U型网络通过Dense Block将低层特征复用到高层在保留原始背景的同时去除烟雾。文中还系统比较了直方图均衡化、Retinex等传统增强方法在火场场景下的局限并给出主观视觉与PSNR、SSIM等客观指标的实验对比。目前已有376人学习适合作为深度学习图像复原方向的参考文献与算法设计思路来源。1. 火场灰度图去烟为什么单通道反而比 RGB 更难做消防机器人和无人机回传的画面里烟是最讨厌的东西。可见光摄像头在火场里拍到的图像往往被浓烟压成一片灰白对比度掉到个位数边缘几乎消失。更麻烦的是很多嵌入式前端为了省带宽和算力直接把图像转成灰度再传——单通道8 位没有色彩信息可用。这时候再想去烟就变成了一个纯灰度域的病态逆问题烟是加性散射叠加目标纹理被淹没没有颜色先验可以借力。基于深度学习的火场灰度图像去烟算法要解决的就是这件事输入一张被烟污染的灰度图输出一张烟雾散射被抑制、目标轮廓和纹理恢复的灰度图。它适合两类人一类是做消防视觉、应急感知的工程同学需要在低算力前端上跑通另一类是研究图像复原、想拿火场这种极端场景做实验的算法同学。核心难点不在网络多深而在于灰度域没有色彩冗余模型必须学会从局部对比度和结构先验里猜回被烟吃掉的信息。2. 灰度去烟的数据构造与物理退化建模2.1 为什么不能直接拿清晰图加高斯噪声很多人第一反应是找一批清晰灰度图加噪声训练去噪网络。这条路在火场去烟上基本走不通。烟雾的退化不是独立同分布噪声而是散射介质成像物理上更接近大气散射模型I(x) J(x) * t(x) A * (1 - t(x))其中I是观测到的含烟图J是无烟清晰图t(x)是透射率A是大气光在灰度域就是一个标量亮度。烟越浓t越小图像越接近A这个常数细节全丢。用高斯噪声去模拟网络学到的只是平滑遇到真实浓烟会直接糊掉。常见做法是收集一批无烟火场/建筑灰度图作为J然后按上式合成含烟图。t(x)用随机生成的平滑场比如对低分辨率随机噪声做双三次上采样A取图像亮度的 85% 到 98% 分位数附近。这样合成的样本才带有空间变化的透射率网络才有机会学到去烟而不是去噪。2.2 用 Python 合成灰度含烟样本的最小脚本下面这段代码给出一个可复现的合成流程输入一张清晰灰度图输出含烟图和无烟图配对import cv2 import numpy as np def make_smoke_pair(gray, A_ratio0.92, t_min0.25, t_max0.85, seed0): gray: 单通道 uint8 清晰图 A_ratio: 大气光占最大亮度的比例 t_min/t_max: 透射率范围越小烟越浓 返回: (hazy, clear) 两张 uint8 灰度图 rng np.random.default_rng(seed) h, w gray.shape # 低分辨率随机场 - 上采样得到空间平滑的透射率 low rng.random((h // 32 1, w // 32 1)).astype(np.float32) t cv2.resize(low, (w, h), interpolationcv2.INTER_CUBIC) t (t - t.min()) / (t.max() - t.min() 1e-6) t t_min t * (t_max - t_min) # 映射到 [t_min, t_max] A A_ratio * 255.0 clear gray.astype(np.float32) hazy clear * t A * (1.0 - t) # 大气散射模型 return np.clip(hazy, 0, 255).astype(np.uint8), gray img cv2.imread(clear.png, cv2.IMREAD_GRAYSCALE) hazy, clear make_smoke_pair(img, A_ratio0.92, t_min0.3, t_max0.8, seed42) cv2.imwrite(hazy.png, hazy)逻辑说明t用低分辨率随机场上采样保证透射率在空间上连续变化符合真实烟雾的分布A取 255 的固定比例模拟灰度域的大气光。参数上t_min控制最浓处的烟浓度做训练集时建议在 0.2 到 0.4 之间随机A_ratio建议 0.85 到 0.98 随机避免网络只适应单一亮度。seed固定后样本可复现方便对比不同模型。2.3 训练集、验证集怎么切才不泄漏合成数据最大的坑是泄漏同一张清晰图合成出多张含烟图如果随机划分验证集里会出现训练集用过的清晰图指标虚高。正确做法是按清晰源图划分一张源图的所有含烟变体只能进同一个集合。常见比例是 8:1:1验证集和测试集各留 10% 的源图。另外测试集里最好混入少量真实含烟图哪怕没有对应清晰图只做主观评估用来判断模型是否过拟合到合成分布。数据集划分源图比例每源图变体数用途训练集80%8~12梯度更新验证集10%4~6早停、调参测试集10%4~6最终指标真实烟图独立无配对主观评估提示合成时给每张源图随机不同的t_min、A_ratio和随机种子变体多样性比单纯增加数量更重要。3. 去烟网络结构选型与训练参数配置3.1 灰度去烟为什么常用 U-Net 加残差学习灰度去烟本质是图像到图像的稠密预测输入输出同尺寸U-Net 的编码器-解码器加跳跃连接天然合适。但直接让网络回归清晰图训练初期梯度不稳定收敛慢。更稳的做法是残差学习网络只预测烟层最终输出clear hazy - smoke。因为烟层整体平滑、能量集中网络学起来比直接重建纹理容易得多。编码器可以用轻量卷积堆叠比如 4 个下采样阶段通道从 32 递增到 256解码器对称上采样跳跃连接把浅层的高频细节直接送到对应层弥补下采样丢失的边缘。对于嵌入式部署可以把基础通道压到 16 或 24深度可分离卷积替换标准卷积参数量能降一个数量级。3.2 用 PyTorch 搭一个最小可训练去烟网络import torch import torch.nn as nn class ConvBlock(nn.Module): def __init__(self, cin, cout): super().__init__() self.net nn.Sequential( nn.Conv2d(cin, cout, 3, padding1), nn.ReLU(inplaceTrue), nn.Conv2d(cout, cout, 3, padding1), nn.ReLU(inplaceTrue), ) def forward(self, x): return self.net(x) class SmokeNet(nn.Module): def __init__(self, base32): super().__init__() self.enc1 ConvBlock(1, base) self.enc2 ConvBlock(base, base * 2) self.enc3 ConvBlock(base * 2, base * 4) self.pool nn.MaxPool2d(2) self.up2 nn.ConvTranspose2d(base * 4, base * 2, 2, stride2) self.dec2 ConvBlock(base * 4, base * 2) self.up1 nn.ConvTranspose2d(base * 2, base, 2, stride2) self.dec1 ConvBlock(base * 2, base) self.out nn.Conv2d(base, 1, 1) # 预测烟层 def forward(self, x): e1 self.enc1(x) e2 self.enc2(self.pool(e1)) e3 self.enc3(self.pool(e2)) d2 self.dec2(torch.cat([self.up2(e3), e2], dim1)) d1 self.dec1(torch.cat([self.up1(d2), e1], dim1)) smoke self.out(d1) return x - smoke # 残差输入减烟层逻辑说明enc1到enc3逐级下采样扩大感受野up2、up1上采样恢复分辨率torch.cat把编码器浅层特征和解码器特征拼接保留边缘。最后一层out输出单通道烟层return x - smoke实现残差去烟。参数base控制模型宽度桌面训练用 32嵌入式部署可降到 16。3.3 损失函数与关键训练参数只用 L1 或 L2 损失结果会偏平滑纹理发糊。常见组合是 L1 加结构相似性损失SSIM再 optionally 加一个梯度损失约束边缘def total_loss(pred, target, alpha0.8, beta0.2): l1 nn.functional.l1_loss(pred, target) # 简化 SSIM用局部均值方差近似 mu_p pred.mean(dim(1,2,3), keepdimTrue) mu_t target.mean(dim(1,2,3), keepdimTrue) var_p pred.var(dim(1,2,3), keepdimTrue) var_t target.var(dim(1,2,3), keepdimTrue) cov ((pred - mu_p) * (target - mu_t)).mean(dim(1,2,3), keepdimTrue) c1, c2 0.01**2, 0.03**2 ssim ((2*mu_p*mu_t c1)*(2*cov c2)) / ((mu_p**2 mu_t**2 c1)*(var_p var_t c2)) return alpha * l1 beta * (1 - ssim.mean())参数说明alpha和beta控制 L1 与 SSIM 的权重经验值 0.8/0.2 起步纹理恢复不够就加大beta。训练用 Adam学习率 1e-3配合余弦退火到 1e-5batch size 8 到 16取决于显存。epoch不用盲目堆合成数据上通常 60 到 100 轮就收敛看验证集 PSNR 连续 10 轮不升就早停。参数推荐值作用学习率1e-3 → 1e-5余弦退火batch size8~16显存与稳定性平衡base 通道16~32控制模型容量L1/SSIM 权重0.8 / 0.2保真与结构平衡早停耐心10 轮防过拟合注意灰度域没有颜色约束SSIM 权重过高会让结果过度平滑边缘反而变软调参时以主观边缘锐度为先。4. 推理部署与火场场景下的排错4.1 从训练权重到单张图推理的命令行脚本训练完要能落地下面是一个最小推理脚本读入含烟灰度图输出去烟结果import cv2 import numpy as np import torch from model import SmokeNet device torch.device(cuda if torch.cuda.is_available() else cpu) net SmokeNet(base32).to(device) net.load_state_dict(torch.load(smokenet.pth, map_locationdevice)) net.eval() img cv2.imread(hazy.png, cv2.IMREAD_GRAYSCALE).astype(np.float32) / 255.0 tensor torch.from_numpy(img)[None, None].to(device) # (1,1,H,W) with torch.no_grad(): out net(tensor).clamp(0, 1) out (out[0, 0].cpu().numpy() * 255).astype(np.uint8) cv2.imwrite(dehazed.png, out)逻辑说明输入归一化到 [0,1]加 batch 和通道维度变成(1,1,H,W)torch.no_grad()关闭梯度省显存输出 clamp 到 [0,1] 再还原到 0-255。参数上base必须和训练时一致否则load_state_dict会报维度不匹配。如果部署到嵌入式可以把模型导出为 ONNX 再用推理引擎跑输入尺寸固定后速度更稳。4.2 火场实测常见的四类失败与排查第一类浓烟区域出现块状伪影。多半是透射率合成时t_min设得太低训练分布和真实浓烟不匹配解决方法是把t_min下限提到 0.15 到 0.2并加入真实浓烟图做微调。第二类去烟后整体偏暗。这是残差学习把烟层减多了检查A_ratio是否偏高或者损失里加一个亮度一致性项。第三类边缘出现光晕。跳跃连接把含烟浅层特征直接送进解码器可以在跳跃连接上加一个 1x1 卷积做门控。第四类视频上帧间闪烁。逐帧推理没有时序约束常见做法是加一个轻量时序模块或者对输出做时域平滑。现象可能原因处理块状伪影t_min 过低提高下限混真实图微调整体偏暗烟层减多降 A_ratio加亮度损失边缘光晕跳跃连接直通加门控卷积帧间闪烁无时序约束时域平滑或时序模块4.3 评价指标怎么选才不被合成数据骗PSNR 和 SSIM 在合成测试集上很好看但真实火场里没有配对清晰图这两个指标用不了。工程上更实用的是无参考指标比如对比度增益、暗通道先验的透射率估计变化以及最直接的主观打分。建议在测试时同时报告合成集 PSNR/SSIM 和真实烟图的主观对比避免只报一个漂亮数字。如果要做消融固定随机种子同一批源图跑不同配置差异才可信。5. 用半监督微调把合成模型拉到真实火场合成数据训出来的模型直接上真实火场往往差一口气因为真实烟雾的颗粒感、光照和运动模糊跟合成分布有差距。但真实火场很难拿到配对清晰图全监督微调不现实。一个可落地的技巧是半监督微调用少量真实含烟图配合模型自身输出的伪清晰图做自训练再加一个一致性约束。具体做法是先用合成模型对真实含烟图推理得到伪清晰图然后对同一张图做两种不同增强比如随机裁剪和亮度扰动要求网络对两种增强的输出保持一致。损失由三部分组成合成数据上的监督损失、真实数据上的伪标签损失、以及增强一致性损失。伪标签损失权重从 0.1 起步一致性损失权重 0.05 左右太高会让模型塌缩到平凡解。# 半监督微调核心片段 for hazy_real in real_loader: with torch.no_grad(): pseudo net(hazy_real).detach() # 伪清晰图 aug1, aug2 random_aug(hazy_real), random_aug(hazy_real) out1, out2 net(aug1), net(aug2) loss_pseudo nn.functional.l1_loss(net(hazy_real), pseudo) loss_cons nn.functional.l1_loss(out1, out2) loss loss_sup 0.1 * loss_pseudo 0.05 * loss_cons loss.backward() optimizer.step()参数上伪标签损失权重建议 0.05 到 0.2 之间网格搜索一致性权重不超过 0.1。微调学习率要比预训练低一个数量级用 1e-4 起步避免把合成阶段学到的先验冲掉。验证时重点看真实烟图的主观效果合成集指标只作参考。如果发现伪标签越来越糊说明自训练在放大误差这时候降低伪标签权重或者只对高置信度区域比如透射率估计较高的区域计算伪标签损失。这套流程不需要额外标注适合真实数据稀缺的火场场景也是把实验室模型推到现场的关键一步。本文还有配套的精品资源点击获取
返回列表