ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

夜间无人机车辆检测数据集:VOC/COCO/YOLO三格式与YOLO11训练解析

2026/10/5 10:33:19 拓冰建站 浏览量
夜间无人机车辆检测数据集:VOC/COCO/YOLO三格式与YOLO11训练解析 简介这是一份面向无人机夜间车辆检测项目开发者的配套数据集获取指南以PDF形式呈现。资料依托真实夜间无人机场景的1000张高质量车辆图片覆盖城市道路行驶、道边停车、停车场、小区及严重遮挡等丰富情境统一标注为car类别并整理为VOC、COCO、YOLO三种标准格式可直接用于YOLO等算法训练。同时附带YOLO11一键训练脚本支持GPU、CPU、Mac(M芯片)多平台运行并给出博主训练结果日志作参考。资源共1个文件PDF大小4.13MB已有373人学习。通过该PDF可获取百度网盘中的完整数据集及详细说明适合作为夜间无人机车辆检测项目的数据补充与实战训练参考。1. 夜间无人机车辆检测1000张图加三格式标签这个数据集能让你少走两周弯路夜间无人机视角下的车辆检测和白天地面视角完全是两个问题。相机噪点多、车灯过曝、车身和沥青路面几乎一个灰度白天跑得好好的模型到晚上经常漏检。这份数据集就是冲这个场景来的1000张真实夜间无人机视角图片覆盖城市道路行驶、道边停车、停车场、小区、车辆遮挡和严重遮挡几类典型情况不区分轿车、SUV或货车统一标成一个car类别。配套给了 VOC(xml)、COCO(json)、YOLO(txt) 三种格式标签外加一套支持 GPU(GPUs)、CPU、Mac(M芯片) 三平台跑的 YOLO11 一键训练脚本。适合正在做无人机夜间巡检、安防监控、智慧交通项目的人也适合想把现有检测模型往夜间场景扩的工程团队——拿到手可以直接开训不用再从零标数据。2. 三种标注格式与类别设计VOC/COCO/YOLO 的结构差异和选用逻辑2.1 为什么只保留 car 一个类别类别合并的工程考量这个数据集最反直觉的地方是它故意不区分轿车、SUV、货车全部框成car。第一次用的人可能会觉得这是偷懒实际做夜间检测项目时你会发现这个决定很务实。夜间无人机俯视视角下轿车和 SUV 的轮廓差异本来就小车顶反光又经常遮掉局部特征强行分三类只会让标注噪声变大、类别间特征重叠严重模型训练时反而容易在轿车和 SUV 之间反复摇摆。货车虽然长一点但夜间车灯和车身灰度特征并不稳定。合并成单一car类别之后模型只需要回答「这里有没有车」不需要回答「这是什么车」对巡检、计数、违停检测这类业务场景完全够用训练收敛也快得多。另外一个实际好处是标注一致性。供数据集的人用的是 labelimg画框的人如果要在三种车型间反复判断1000 张图很容易标出前后矛盾的结果。单类别把标注难度拉低质量反而更容易保证。你在自己的项目里如果遇到类别噪声大的情况也可以考虑做类似的合并操作——先保证检测率再谈细分类。2.2 VOC 的 XML 与 COCO 的 JSON 怎么读标注字段逐个拆三种格式里VOC 的 XML 最好读结构直白一个文件对应一张图。labelimg 标注后自动生成 XML核心内容就是object节点下的name和bndbox。annotation foldernight_vehicle/folder filenameDJI_00123.jpg/filename size width1920/width height1080/height depth3/depth /size object namecar/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin824/xmin ymin412/ymin xmax1106/xmax ymax655/ymax /bndbox /object /annotation注意truncated和difficult这两个字段。truncated1 表示目标在图像边缘被截断difficult1 表示难识别目标。这个数据集的遮挡车场景里部分车辆的框就是 truncated1。训练时如果发现模型对边缘车辆漏检严重可以统计一下这两个字段的分布决定是保留还是清洗。COCO 格式是一个大 JSON 文件搞定所有图片核心是images、annotations、categories三段。images里存宽高和文件名annotations里每条记录对应一个目标框bbox字段的格式是[x, y, width, height]注意是左上角坐标加宽高不是中心点。import json with open(night_vehicle_coco/annotations.json, r, encodingutf-8) as f: coco json.load(f) cat_id_map {c[id]: c[name] for c in coco[categories]} print(类别映射:, cat_id_map) # 统计每张图的标注数量 from collections import Counter img_ann_cnt Counter() for ann in coco[annotations]: img_ann_cnt[ann[image_id]] 1 # 找出标注数最多的前 5 张图 top5 img_ann_cnt.most_common(5) print(标注最多的前5张图:, top5)这段脚本用来快速检查 COCO 标注有没有漏掉整张图的情况。返回的top5里如果出现某张图标注数量异常多比如超过 30大概率是这张图里有大量小目标或者是标框重叠严重需要打开原图复查。初次拿到任何 COCO 格式数据集第一步建议先跑这个统计确认categories里的类别 id 和实际标注对得上。2.3 YOLO 的 TXT 最省心但最容易错归一化坐标的换算逻辑YOLO 格式在三种标注里最简洁每个 txt 文件一行一个目标五个数字分别是class_id, x_center, y_center, width, height全部是相对图片宽高的归一化值。这个格式的问题在于一旦从 VOC 或 COCO 转过来坐标换算错一步框就全偏了。0 0.589583 0.495370 0.218750 0.169444 0 0.425000 0.740741 0.153125 0.219444第一行的0.589583表示目标中心点的 x 坐标占图片宽度的 58.96%0.218750是框宽占图片宽度的 21.87%。从 VOC 的像素坐标转成 YOLO 归一化公式是x_center (xmin xmax) / 2 / widthbox_width (xmax - xmin) / width。很多转换脚本出错就出在一个地方——分母用了原图宽但实际跑了resize或letterbox预处理导致归一化坐标和目标在训练图上的实际位置不一致。读取 YOLO txt 时有一个高频坑txt 文件里第一行第一列是class_id不是类别名。labelimg 导出 YOLO 格式时需要先设置类别列表如果设置顺序和训练脚本里的data.yaml类别顺序不一致模型会把所有框都当成错误类别。后面避坑章节会专门讲这个。2.4 格式转换的常见做法与校验方法拿到数据集后不管最终训练用什么框架都建议先把三种格式全部读取一遍交叉校验坐标能不能对上。常见做法是写一个统一的标注解析函数把 VOC、COCO、YOLO 都转成同一个中间结构再对比边界框面积差异。import xml.etree.ElementTree as ET def read_voc(xml_path): tree ET.parse(xml_path) root tree.getroot() boxes [] for obj in root.iter(object): name obj.find(name).text bnd obj.find(bndbox) xmin int(float(bnd.find(xmin).text)) ymin int(float(bnd.find(ymin).text)) xmax int(float(bnd.find(xmax).text)) ymax int(float(bnd.find(ymax).text)) boxes.append((name, xmin, ymin, xmax, ymax)) return boxes def voc_to_yolo_line(box, img_w, img_h, class_id): name, xmin, ymin, xmax, ymax box x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h return f{class_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}read_voc返回的是像素坐标的边界框voc_to_yolo_line负责转成归一化格式。这里两个函数分开写是有意的——校验的时候先读 VOC 原始框再读 YOLO 转回去的结果对比xmin和xmax误差超过 2 个像素就要查转换脚本。这类误差通常来自浮点精度丢失如果超过 5 个像素基本可以断定是归一化时把宽高搞反了。如果是自己从零转格式最省事的路线是先转成 COCO JSON再用现成的转换工具转 YOLO。COCO 是中间格式里字段最完整的转成 VOC 或 YOLO 都不容易丢信息。反过来从 YOLO 直接转 COCO 反而容易出问题因为 YOLO 里没有 category 名称只有 idid 映射表一旦错位就全错。这个数据集里三种格式都配好了你不需要自己做转换但理解这条链路能帮你快速判断标签文件是否被误改过。3. YOLO11 一键训练脚本拆解GPU/CPU/Mac 三平台环境配置与参数说明3.1 环境准备ultralytics 版本与依赖的选择数据集的训练脚本基于 YOLO11也就是 ultralytics 库维护的 yolo11 系列模型。环境准备本身不复杂但三平台各有各的坑先列一个对照表再细说。平台训练设备关键依赖显存要求GPU 服务器NVIDIA 显卡torch CUDA 版单卡建议 8G 以上CPU 笔记本无显卡torch CPU 版无但速度慢 10~20 倍Mac M 芯片MPS 后端torch 官方 Mac 版统一内存16G 起步实际项目里GPU 平台基本是 Linux NVIDIA 驱动装好 CUDA 后直接用pip install ultralytics就行。CPU 平台的坑在于 torch 默认装的是 CUDA 版即使没有 NVIDIA 显卡也会把 CUDA 相关库拉进来影响启动速度更推荐用pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu单独装 CPU 版。Mac M 芯片最顺的是pip install ultralyticstorch 会自动带上 MPS 后端支持不需要额外配置。这个数据集配套的脚本里训练入口通常会封装一个参数解析层自动判断当前平台的可用设备。当你拿到脚本先别急着跑打开看一眼device参数是怎么传的——很多人直接在 Mac 上跑 GPU 平台的命令结果模型一直在 CPU 上龟速训练白等几个小时。3.2 三平台训练脚本的核心差异device 参数与 MPS 后端一键训练脚本最核心的部分就是 device 参数的三平台适配。常见做法是写一个自动检测函数检查torch.cuda.is_available()和torch.backends.mps.is_available()按优先级选择训练设备。import torch def auto_device(): if torch.cuda.is_available(): device 0 # 使用第一张显卡 print(f使用 GPU: {torch.cuda.get_device_name(0)}) elif torch.backends.mps.is_available(): device mps print(使用 Mac MPS 后端) else: device cpu print(使用 CPU训练速度会慢很多) return device # 关键参数说明 # device0 是 ultralytics 的写法代表第一张显卡 # device0,1 代表两张显卡并行数据并行 # devicemps 走 Apple Silicon 的 Metal 后端 # devicecpu 纯 CPU 训练只适合验证流程auto_device返回的字符串直接传给 ultralytics 的model.train(devicedevice)。要注意 MPS 后端虽然能用但有些操作符还没完全支持比如某些版本的torch.nn.Upsample在 MPS 上有实现问题。如果训练中途报not implemented的算子错误最直接的办法是回退到 CPU 跑通全流程确认不是数据集问题后再考虑换 GPU 平台。GPU 多卡场景里脚本通常会有--device 0,1的写法ultralytics 会自动做数据并行。这里有个经验值——两张卡训练时 batch size 可以翻倍但学习率也要相应调大lr0.01 * 卡数否则收敛速度没有提升反而因为 batch 变大导致精度波动。3.3 关键超参数怎么给imgsz、batch、epochs、patience 的经验值训练脚本里预设的超参数直接决定你第一次训练跑出来的结果。这个数据集场景是夜间小目标检测参数不能照搬白天 COCO 的默认值。参数推荐值说明imgsz640无人机俯瞰图目标较小640 是速度和精度的平衡点目标太小时可以试 960但训练时间翻倍约 2.5 倍batchGPU 16 / CPU 8 / Mac 8显存不够先降 batch不要降 imgszepochs1001000 张图单类别100 轮足够收敛再多容易过拟合patience20验证集 mAP 连续 20 轮不涨就早停防止无效训练浪费时间lr00.01预训练权重迁移0.01 是安全值0.001 更保守但收敛慢workers4~8数据加载线程数Windows 下注意不要超过 CPU 核心数batch 参数是翻车重灾区。很多人喜欢一次性把显存吃满但夜间图像噪点多梯度本身波动大batch 太大反而不利于模型学习车灯这类高对比度特征。我一般先按batch16跑一轮显存不够就降到 8 或 4。如果 batch 降到 4 还爆显存再看是不是cacheTrue参数把图片缓存到显存里了关掉改成cacheFalse就能省出好几个 G。epochs100 看起来不多但这个数据集只有 1000 张图、单类别目标边界简单基本 60~80 轮就收敛了。如果训练到 80 轮mAP50还在明显上升说明模型容量不够或者学习率太保守优先调的是lr0而不是继续加 epochs。注意 patience20 的意义——早停机制会在验证集指标连续 20 轮不刷新时自动截断训练如果你用 GPU 排队训练这个参数能省下不少机时。3.4 训练日志与结果验证跑完看什么数据集附带博主训练结果日志这个日志值得仔细看因为里面记录了别人在这个数据集上的真实表现。跑完train.py后ultralytics 会在runs/detect/train/目录下生成一组结果文件。runs/detect/train/ ├── weights/ │ ├── best.pt │ └── last.pt ├── results.csv ├── results.png ├── confusion_matrix.png ├── val_batch0_labels.jpg ├── val_batch0_pred.jpg └── args.yaml优先看results.png里的mAP50和val/box_loss曲线。mAP50 曲线在训练后期应该是平缓上升的val loss 不能持续上升——如果 val loss 从某个 epoch 开始回头往上走而 mAP 还在涨或停滞说明过拟合了需要加weight_decay或增大mosaic概率。confusion_matrix.png里关注car类别所在行列的值如果大量把背景判成 car说明夜间场景的误检率高要检查是不是图片里车灯反光被当成了车。日志文件如果只给了一部分训练轮次的截图你也可以用来反推数据质量。比如 mAP50 起步值很高超过 0.5说明预训练权重和夜间场景的分布比较接近起步值很低低于 0.2则说明场景迁移较大需要更多的训练轮次或者做图像增强。4. 避坑夜间小目标检测的五个常见问题与排查记录4.1 误把白天车辆检测的预训练权重直接拿来续训现象用yolo11n.pt或yolo11s.pt这种在 COCO 上预训练的权重直接训练这个夜间数据集前几轮 loss 下降很快但到 30 轮以后 mAP50 卡在 0.3 左右上不去。原因COCO 里白天车辆图像的特征分布和夜间无人机俯视差异很大。预训练权重里的浅层特征边缘、纹理还能用但深层语义特征全是白天的夜间图像经过几次下采样后车身灰度信息和暗部噪声混在一起深层特征基本失效。模型需要大量轮次重新学习夜间特征100 轮并不够。解决改用yolo11m.pt或yolo11l.pt起步增大模型容量来容纳夜间特征。同时把lr0从 0.01 调到 0.005让模型在迁移初期慢一点别把预训练权重里的通用特征冲掉。如果手头有之前跑过的夜间检测模型哪怕场景不完全一致优先用它做预训练权重比用 COCO 权重效果好得多。4.2 labelimg 导出 YOLO 格式时类别编号错位现象用脚本训练时报错class index out of range或者训练能启动但 loss 不降检查标签发现car类别的 id 标成了 1而data.yaml里只有 1 个类别 id0。原因labelimg 在导出 YOLO 格式前需要先加载classes.txt或者手动输入类别列表。很多人直接新建标注类别列表顺序是[car, truck]或从上一个项目残留下来导致导出的 txt 里 class_id 不是从 0 开始的连续编号。单类别数据集如果 class_id1训练脚本直接把样本都忽略掉。解决拿到标签后先跑一遍类别统计脚本检查所有 txt 文件里的 class_id 最小值是否为 0、最大值是否小于类别总数。数据集的 YOLO 标签如果是从 VOC 转换的转换脚本没有做类别映射偏移也会出现这个问题。任何情况下都不要信任 labelimg 的默认导出开工前强制检查类别 id 分布。4.3 Mac 上用 MPS 训练突然 OOM 或者算子不支持现象Mac 上devicemps启动训练前 100 个 iteration 正常中途报RuntimeError: MPS does not support this operation或者直接被杀进程提示内存不足。原因MPS 后端对个别算子支持不完整尤其是带动态形状的操作比如某些版本的torchvision.ops.nms在 MPS 上的实现有 bug。另外 YOLO11 训练过程中的cache机制会把图片缓存到统一内存里1000 张 1080p 图像很快吃满 8G 内存。解决先用cacheFalse关掉图像缓存这是 Mac 爆内存的头号原因。算子报错的话第一步查 torch 版本pip install --upgrade torch torchvision升到最新版大概率能解决。如果升级后还报错直接devicecpu训练——Mac 的 CPU 训练虽然慢但稳定1000 张图、100 轮、640 分辨率约 4 到 8 小时能跑完比排查 MPS 算子问题省时间。4.4 夜间图像对比度低导致 mAP 虚高但实际漏检现象训练日志里 mAP50 到了 0.85看起来很好但在无人机实测视频上漏检率很高尤其是停在树荫下或者深色柏油路上的车辆。原因夜间图像对比度低车和背景的灰度值接近。测试集里的图片和训练集同源分布非常接近mAP 指标虚高。实际部署时的拍摄角度、高度、光线条件稍有变化模型立刻失灵。这不是数据集的问题是训练策略的问题——没有对夜间场景做足够的数据增强模型学到的可能是特定灰度分布而不是车辆的语义特征。解决训练时开hsv_h0.05, hsv_s0.5, hsv_v0.3这类颜色增强参数模拟不同光线下的夜间环境。关键是有意识地留出一部分图片不参与训练专门当验证集这些验证图要和训练图在场景上尽量不同。如果验证集 mAP 比训练集低超过 5 个百分点说明模型过拟合到了特定场景。4.5 把遮挡车辆标注删除导致模型学不会遮挡场景现象训练时把严重遮挡的车辆标注过滤掉因为觉得这些框「不干净」。结果模型在遮挡场景下不仅漏检连正常的停车检测也变差了。原因遮挡车辆的样本虽然标签框不准但它提供了「车辆部分可见」的重要特征。删掉这些样本等于告诉模型——车辆必须是完整出现的。夜间场景遮挡本来就多树冠、路灯杆、其他车辆都会挡住车身模型没见过部分车辆特征自然学不会。解决保留遮挡标注重点要看的是标注框是否包含足够的车身像素。如果标注框里 80% 以上是树或建筑这种框确实该清洗但框里能明显看到车灯、车顶边缘或车身轮廓的应该保留。数据集的「车辆严重遮挡」场景就是这个用途——补充模型对部分可见目标的识别能力。清洗标准是框内前景占比不是遮挡面积。5. 验证模型效果从训练日志到夜间场景实测的完整闭环5.1 用混淆矩阵和训练曲线判断过拟合与漏检方向训练结束后不要只看总 mAP要把results.png里的曲线图分开读。val/box_loss和val/cls_loss是判断过拟合的两个关键指标。如果 box_loss 在训练后期持续下降但 val_loss 开始回升说明模型开始死记训练样本的精确框位置泛化能力反而下降。此时最划算的操作是直接使用早停前那个 epoch 的权重而不是 last.pt。混淆矩阵里有一块单独的「background」行和列这是夜间误检的重灾区。如果car列里混入大量 background 分值说明模型把车灯、路面反光当成车辆。一个有效的补救办法是在推理时把conf阈值从默认的 0.25 提高到 0.45误检会显著下降但要注意 mAP 也会同步降低需要根据业务场景权衡。5.2 用小批量夜间视频帧做可视化验证训练日志指标再漂亮也只是在标注数据上的表现。真实场景里无人机飞行高度、拍摄角度、云台稳定性都会影响检测效果。常见做法是从实测视频里抽帧抽出 100~200 张没有标注的图跑一遍推理把结果可视化出来。from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) results model.predict( sourcenight_frames/, conf0.35, # 检测置信度阈值夜间建议 0.3~0.4 iou0.5, # NMS 的 IoU 阈值 saveTrue, # 保存可视化结果 imgsz640, # 推理尺寸与训练时保持一致 device0, # GPU / CPU / mps 按需修改 ) # 检查结果中是否有漏检和误检 for r in results: boxes r.boxes if len(boxes) 0: print(f漏检帧: {r.path})这个脚本有几个值得留意的点。imgsz必须和训练时保持一致否则小目标的尺度分布会变化导致检测不稳定。conf阈值在夜间场景建议先设 0.35 跑一遍看误检和漏检的比例再上下微调。可视化结果直接看框的贴合程度——如果大量框比实际车身大一圈说明回归分支没有学好需要回训练阶段调box_loss的权重或者增加高分辨率训练轮次。5.3 推理速度与部署参数的取舍验证完精度之后还要测推理速度。GPU 上 YOLO11s 跑 640 分辨率大概 2~4ms 一帧CPU 上可能在 100ms 以上Mac 的 MPS 介于两者之间。如果你做的巡检项目要求实时处理就要确定模型尺寸的选择逻辑。yolo11nnano和 yolo11ssmall在夜间小目标上的差异没有白天那么明显因为夜间目标本身特征少模型层数深一些收益有限。实测中如果发现 yolo11s 和 yolo11n 的 mAP 只差 2~3 个点直接上 yolo11n 换推理速度。如果差到 8 个点以上说明夜间特征确实复杂值得保住精度。从那以后我每次拿到夜间检测数据集都强制先做一遍标签格式校验和类别 id 统计再跑 20 轮短训练看曲线走向最后才上完整训练。这套流程看起来多花几个小时但能避掉上面绝大多数坑。希望帮到你。本文还有配套的精品资源点击获取