无人机雾天航拍挑战:11,600张雾霾场景目标检测数据集全解析
雾霾天气下,无人机视觉系统常面临"看不清、测不准"的困境------图像对比度骤降、目标纹理模糊,导致检测模型性能断崖式下跌。学术界与工业界亟需能覆盖合成雾 与真实雾的多样化基准数据集。本文深度解读一个包含11,600张图像、38万+标注实例的雾霾场景目标检测数据集,并提供基于Detectron2和YOLOv8的鲁棒性训练代码与域适应策略,助力复杂天气下的无人机智能感知。


📊 数据集核心档案
| 属性 | 详情 |
|---|---|
| 数据集名称 | 无人机雾霾场景目标检测数据集 |
| 数据总量 | 11,600张图像 (约33.5 GB) |
| 标注实例数 | 约383,689个边界框 |
| 数据模态 | 清晰图像、合成雾霾图像、真实雾霾图像 |
| 主要目标 | 车辆(低空遥感视角) |
| 标注格式 | COCO JSON (水平矩形框) |
| 推荐输入尺寸 | 1333×800 (训练时Resize) |
| 任务类型 | 目标检测 (Object Detection) |


🔍 数据集深度剖析
🌫️ 三重模态,覆盖从实验室到真实场景
该数据集的最大特色在于三模态共存设计:
- 清晰图像 (Clear):作为基础参考,提供无退化条件下的目标特征。
- 合成雾霾图像 (Synthetic Fog) :基于物理大气散射模型,对清晰图像叠加不同浓度、均匀性的雾效。优点是可批量生成、雾浓度可控,便于进行鲁棒性预训练 和消融实验。
- 真实雾霾图像 (Real Fog) :在实际雾霾天气下由无人机采集,包含真实环境中雾气浓度不均、光照复杂等特性,是验证模型实际泛化能力的试金石。
这种设计支持丰富的实验范式:清晰→合成雾 (模拟退化)、合成雾→真实雾 (域适应)、以及清晰+合成雾+真实雾联合训练 (数据增广)。
🎯 专注低空车辆检测,任务聚焦
数据集专注于车辆 这一单一类别,但视角为低空遥感俯视图,车辆呈现尺度小、密度高、方向各异的特点,对检测器的细粒度特征提取和抗干扰能力提出更高要求。标注采用COCO格式的矩形框,便于接入主流检测框架。
🚀 实战代码:鲁棒性检测训练与域适应
以下提供基于Detectron2 (Faster R-CNN) 和 YOLOv8 的训练配置与核心代码,重点展示如何处理多模态数据、评估雾天鲁棒性。
1. 环境准备
bash
# 安装Detectron2 (PyTorch 1.8+)
pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu113/torch1.10/index.html
# 或安装YOLOv8
pip install ultralytics
2. 数据准备与COCO格式转换
假设原始数据按以下结构存放:
data/
├── clear/ # 清晰图
├── synthetic_fog/ # 合成雾图
├── real_fog/ # 真实雾图
└── annotations/ # 对应的三个COCO JSON文件
编写脚本将三个子集合并或分别生成train/val的JSON文件。关键代码:为每个标注添加fog_type字段,便于分析。
python
import json
def add_fog_type_to_json(json_path, fog_type):
with open(json_path, 'r') as f:
data = json.load(f)
# 为每张图像添加自定义字段(可选)
for img in data['images']:
img['fog_type'] = fog_type
# 保存新JSON
with open(f"{fog_type}_annotations.json", 'w') as f:
json.dump(data, f)
# 调用示例
add_fog_type_to_json('annotations/clear.json', 'clear')
3. Detectron2 训练配置 (支持多模态混合训练)
以下配置展示如何加载包含清晰和合成雾的混合数据集,并引入数据增强中的合成雾模拟,进一步提升鲁棒性。
python
# ============================================================
# 场景:无人机雾霾场景车辆检测 - 基于Detectron2 (Faster R-CNN)
# 功能:支持多模态数据加载、雾天鲁棒性评估
# 依赖:detectron2, torch, opencv-python
# ============================================================
from detectron2.engine import DefaultTrainer
from detectron2.config import get_cfg
from detectron2 import model_zoo
from detectron2.data import DatasetCatalog, MetadataCatalog
from detectron2.data import transforms as T
from detectron2.data import detection_utils as utils
from detectron2.data import build_detection_train_loader
import detectron2.data.transforms as T
import os, json, cv2
import numpy as np
# -------------------- 1. 注册数据集 --------------------
def get_fog_dicts(json_file, img_dir):
"""读取COCO格式JSON,返回Detectron2所需的list of dict"""
with open(json_file, 'r') as f:
data = json.load(f)
dataset_dicts = []
for img_info in data['images']:
record = {}
record["file_name"] = os.path.join(img_dir, img_info['file_name'])
record["image_id"] = img_info['id']
record["height"] = img_info['height']
record["width"] = img_info['width']
# 获取标注
annos = [anno for anno in data['annotations'] if anno['image_id'] == img_info['id']]
objs = []
for anno in annos:
bbox = anno['bbox'] # [x, y, w, h]
bbox = [bbox[0], bbox[1], bbox[0]+bbox[2], bbox[1]+bbox[3]] # 转为[x1,y1,x2,y2]
objs.append({
"bbox": bbox,
"bbox_mode": BoxMode.XYXY_ABS,
"category_id": 0, # 仅车辆一类
"iscrowd": 0
})
record["annotations"] = objs
dataset_dicts.append(record)
return dataset_dicts
# 注册训练集(混合清晰+合成雾)
for d in ["train", "val"]:
DatasetCatalog.register(f"fog_{d}", lambda d=d: get_fog_dicts(
f"data/annotations/{d}.json", f"data/{d}_images"
))
MetadataCatalog.get(f"fog_{d}").set(thing_classes=["vehicle"])
# -------------------- 2. 自定义增强:在线合成雾 (关键鲁棒性策略) --------------------
class RandomSyntheticFog(T.Transform):
"""在训练时随机对清晰图像叠加物理雾效,模拟域随机化"""
def __init__(self, img, beta_range=(0.5, 2.0), A=0.8):
self.beta = np.random.uniform(*beta_range) # 散射系数
self.A = A # 大气光强度
def apply_image(self, img):
# 实现大气散射模型: I(x) = J(x)*t(x) + A*(1-t(x)), t=exp(-beta*depth)
# 需要深度图,此处简化:假设深度与像素位置相关(底部近、顶部远)
h, w = img.shape[:2]
depth = np.linspace(0, 1, h).reshape(h, 1) # 简单垂直深度分布
depth = np.tile(depth, (1, w))
t = np.exp(-self.beta * depth)
t = np.clip(t, 0.2, 1.0) # 防止透射率过小
# 雾化
foggy = img * t[..., np.newaxis] + self.A * (1 - t[..., np.newaxis]) * 255
return foggy.astype(np.uint8)
def apply_coords(self, coords):
return coords
class MyMapper:
"""自定义数据映射器,在标准增强后添加合成雾"""
def __init__(self, cfg, is_train=True):
self.cfg = cfg
self.is_train = is_train
# 标准增强: 随机翻转、缩放、裁剪等
self.tfm_gens = utils.build_transform_gen(cfg, is_train)
def __call__(self, dataset_dict):
# 读取图像
img = cv2.imread(dataset_dict["file_name"])
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 应用标准增强
aug_input = T.AugInput(img)
transforms = T.TransformList(self.tfm_gens)
img = transforms(aug_input).image
# 以50%概率添加合成雾 (仅训练时)
if self.is_train and np.random.rand() > 0.5:
fog_transform = RandomSyntheticFog(img, beta_range=(0.3, 1.8))
img = fog_transform.apply_image(img)
# 转换格式
image = torch.as_tensor(np.ascontiguousarray(img.transpose(2, 0, 1)))
dataset_dict["image"] = image
# 更新标注坐标 (略,需根据transforms调整)
return dataset_dict
# 在Trainer中替换loader
class FogTrainer(DefaultTrainer):
@classmethod
def build_train_loader(cls, cfg):
return build_detection_train_loader(cfg, mapper=MyMapper(cfg, is_train=True))
# -------------------- 3. 模型训练 --------------------
cfg = get_cfg()
cfg.merge_from_file(model_zoo.get_config_file("COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml"))
cfg.DATASETS.TRAIN = ("fog_train",)
cfg.DATASETS.TEST = ("fog_val",)
cfg.DATALOADER.NUM_WORKERS = 4
cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml")
cfg.SOLVER.IMS_PER_BATCH = 8
cfg.SOLVER.BASE_LR = 0.0025
cfg.SOLVER.MAX_ITER = 6000
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1
cfg.TEST.EVAL_PERIOD = 1000
os.makedirs("./output", exist_ok=True)
trainer = FogTrainer(cfg)
trainer.resume_or_load(resume=False)
trainer.train()
# -------------------- 4. 评估雾天泛化性 --------------------
# 在真实雾天测试集上评估
cfg.DATASETS.TEST = ("fog_real_val",)
cfg.MODEL.WEIGHTS = os.path.join("./output", "model_final.pth")
evaluator = COCOEvaluator("fog_real_val", cfg, False, output_dir="./eval_real_fog/")
val_loader = build_detection_test_loader(cfg, "fog_real_val")
print(inference_on_dataset(trainer.model, val_loader, evaluator))
# ==================== 结束 ====================
4. YOLOv8 快速训练与域适应
对于YOLOv8,可使用其原生支持的多数据集训练,并引入域适应损失(如通过对抗训练)。此处给出训练脚本与评估命令。
python
# train_yolov8_fog.py
from ultralytics import YOLO
# 加载预训练模型
model = YOLO('yolov8x.pt')
# 数据配置文件 (定义清晰、合成雾、真实雾三个数据集)
data_yaml = """
path: ./data
train:
- clear/images/train
- synthetic_fog/images/train
val: real_fog/images/val
nc: 1
names: ['vehicle']
"""
# 训练 (使用多尺度、Mosaic增强)
results = model.train(
data=data_yaml,
epochs=30,
imgsz=1333,
batch=16,
device=0,
augment=True,
mosaic=1.0,
mixup=0.2,
copy_paste=0.3,
# 关键:保留训练日志
project='foggy_detection',
name='yolov8_fog_mix'
)
# 评估模型在真实雾上的表现
metrics = model.val(data='./data/real_fog/test.yaml', split='test')
print(f"Real Fog mAP@0.5: {metrics.box.map50:.4f}")
📝 关键注释与优化建议
- 域适应策略 :若真实雾数据稀少,可采用无监督域适应 (UDA) 。在Detectron2中可尝试引入
DAFaster,通过梯度反转层 (GRL) 对齐清晰域与雾域的特征分布。 - 小目标检测优化 :无人机视角车辆多为小目标。可在训练时使用切块检测 (SAHI) 策略,或在数据加载中增加随机裁剪放大 (RandomCrop with resize) 增强。
- 去雾预处理 :作为对比实验,可加载预训练的去雾网络 (如AOD-Net) 对输入图像进行复原,再送入检测器,观察mAP提升。
- 评估指标细化 :务必分别报告模型在 清晰、合成雾、真实雾 三个子集上的mAP,以量化鲁棒性。真实雾上的性能下降幅度 (Drop) 是衡量模型实用性的核心指标。
🏷️ 拓展思考与行业趋势
- 物理模型与数据驱动结合:未来方向是将大气散射模型作为可微分模块嵌入网络,实现端到端的去雾检测联合优化。
- 多传感器融合:雾天时可见光受限,融合红外或毫米波雷达数据是提升系统鲁棒性的重要路径,多模态数据集将成为新热点。
- 边缘端部署:将训练好的模型通过TensorRT或NCNN部署到无人机机载计算单元 (如Jetson Orin),需进行量化与剪枝,并测试实际雾天环境下的推理帧率。
🔖 文章标签
#无人机巡检 #雾天数据集 #目标检测 #域适应 #Detectron2 #YOLOv8 #低照度图像 #鲁棒性评估 #复杂天气感知 #自动驾驶