1. 项目概述:频域-时域融合的雾检测算法
去年在做一个高速公路监控项目时,遇到雾天能见度检测的难题。传统基于对比度的检测方法在夜间完全失效,而单纯依赖深度学习又需要海量标注数据。经过三个月实验,我们最终采用YOLOv11框架结合频域分析,开发出这套融合算法。实测在浓雾场景下,检测准确率比纯时域方法提升23.6%,特别是在能见度低于50米的极端场景仍保持78%以上的召回率。
这个方案的核心创新点在于:通过离散余弦变换(DCT)提取图像频域特征,与YOLOv11的时域检测结果进行自适应加权融合。频域特征主要捕捉图像清晰度退化规律——雾气会导致高频分量显著衰减,这个物理特性在不同光照条件下都保持稳定。而时域检测则利用YOLOv11改进后的特征金字塔网络(FPN)捕捉物体形态特征。
2. 核心算法原理拆解
2.1 频域特征提取模块
我们采用8×8分块的DCT变换,计算每个块的能量分布。具体实现时:
python复制import cv2
import numpy as np
def extract_dct_features(img):
# 转换为灰度图并归一化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY).astype(np.float32) / 255.0
# 8x8分块DCT
blocks = [gray[j:j+8, i:i+8]
for j in range(0, gray.shape[0], 8)
for i in range(0, gray.shape[1], 8)]
dct_features = []
for block in blocks:
dct_block = cv2.dct(block)
# 提取低频到高频的能谱分布
zigzag = [dct_block[i,j] for i,j in zigzag_indices(8)]
dct_features.append(zigzag)
return np.array(dct_features)
def zigzag_indices(size):
# 生成Zigzag扫描顺序索引
...
关键参数选择依据:
- 分块大小8×8:平衡计算效率和特征粒度
- 取前16个DCT系数:覆盖90%以上的能量信息
- 使用Zigzag扫描顺序:符合JPEG标准的人眼敏感度排序
2.2 YOLOv11的改进点
我们在原始YOLOv11基础上做了三处关键修改:
-
特征金字塔增强:
- 新增P2层(1/4尺度)提升小目标检测
- 采用BiFPN结构优化特征融合
- 添加可变形卷积适应雾天目标形变
-
损失函数调整:
python复制class FogAwareLoss(nn.Module): def __init__(self): super().__init__() self.obj_loss = nn.BCEWithLogitsLoss(pos_weight=torch.tensor([3.0])) self.fog_weight = nn.Parameter(torch.ones(1)) def forward(self, pred, target, fog_score): # 雾浓度越高,分类损失权重越大 cls_loss = F.cross_entropy(pred[..., 5:], target[..., 5:], reduction='none') * (1 + self.fog_weight * fog_score) ... -
数据增强策略:
- 物理雾模拟:基于大气散射模型生成合成雾图
- 频域混合增强:在DCT域交换不同图像的频段
3. 融合策略实现细节
3.1 自适应权重计算
融合权重根据图像信噪比(SNR)动态调整:
code复制权重 = σ(α·SNR + β)
其中:
- SNR = 高频能量 / 低频能量
- α=-0.8, β=1.2(通过网格搜索确定)
- σ为sigmoid函数
实测发现:当SNR>2.5时(清晰图像),时域权重占优(约0.7);当SNR<1.2时(浓雾),频域权重提升至0.6
3.2 多尺度特征融合

(注:示意图展示DCT特征与CNN特征在三个尺度上的融合过程)
具体实现时需要注意:
- 频域特征需通过反DCT转换回空间域
- 使用1×1卷积统一通道数
- 融合前进行BatchNorm处理
4. 训练与优化技巧
4.1 数据集构建要点
我们收集了包含不同雾浓度的12626张道路图像,标注时特别注意:
- 雾浓度标签:使用专业能见度仪同步测量
- 边界框标注:雾天目标边缘需人工修正
- 数据平衡:确保各能见度等级样本均匀
4.2 模型训练技巧
-
两阶段训练策略:
- 第一阶段:仅训练YOLOv11主干(冻结频域分支)
- 第二阶段:联合训练,学习率降低为1/5
-
学习率调整:
bash复制# 使用余弦退火配合热重启 python train.py --lr 0.01 --cosine-annealing --t-mult 2 -
梯度裁剪:
频域分支的梯度幅值较大,需单独设置阈值:python复制torch.nn.utils.clip_grad_norm_(model.freq_branch.parameters(), 0.5)
5. 部署优化与实测效果
5.1 边缘设备优化
在Jetson Xavier上测试时,发现DCT计算是瓶颈。通过以下优化将推理速度提升3倍:
- 使用OpenCV的IPP加速DCT
- 将8×8分块改为16×16(精度损失<2%)
- 频域特征量化到INT8
5.2 实际场景测试
在G4京港澳高速某路段部署后,对比传统方法:
| 指标 | 本文方法 | 纯YOLOv11 | 传统图像法 |
|---|---|---|---|
| 白天准确率 | 92.3% | 89.7% | 76.5% |
| 夜间准确率 | 85.1% | 72.4% | 41.2% |
| 能见度<50m召回率 | 78.6% | 55.3% | 32.8% |
| 推理耗时(ms) | 38 | 28 | 15 |
6. 常见问题解决方案
6.1 频域特征失效场景
当遇到以下情况时,需降低频域权重:
- 强降雨天气(水滴产生高频噪声)
- 摄像头脏污(局部高频衰减)
- 低分辨率图像(频域信息不足)
解决方案:
python复制def adaptive_weight(snr, rain_flag, dirt_score):
base_weight = torch.sigmoid(snr * -0.8 + 1.2)
return base_weight * (1 - 0.3*rain_flag) * (1 - 0.5*dirt_score)
6.2 模型误检分析
主要误检类型及应对:
-
团雾误判:
- 现象:将局部雾气识别为障碍物
- 解决:增加空间连续性约束
-
阴影误判:
- 现象:将阴影识别为雾区
- 解决:结合色度信息过滤
-
远距离漏检:
- 现象:200米外目标检测率骤降
- 解决:引入超分辨率预处理
这套系统目前已在三个省份的智慧高速项目落地,最长的连续运行时间超过400天。一个意外收获是,频域特征对夜间车灯眩光也有很好的抑制效果。后续计划将算法移植到车载端,正在与某新能源车企联合开发前向碰撞预警系统。
