资讯动态

FOD-A机场异物检测数据集实战:从数据转换到切片推理的完整指南

发布时间:2026/10/26 15:27:20 来源:尧图企业网站定制
简介面向机场跑道异物碎片FOD检测的计算机视觉数据集适合从事目标检测算法研究、模型训练与工程落地的开发者及学生使用可用于构建多类别小目标检测任务并借助光照与天气标注开展鲁棒性分析。资源包共2000个文件以XML标注文件为主对应YOLO与VOC两种标注格式压缩包约367.52MB便于直接接入主流检测框架进行训练与评估。数据集覆盖31个细粒度类别包括电池、螺栓、垫圈、钳子、扳手、螺丝刀、锤子、金属片、软管、岩石、易拉罐、胶带、木块等典型机场异物每个标注实例还进一步划分明亮、昏暗、黑暗三种光照级别以及干燥、潮湿两类天气条件为复杂环境下的检测研究提供条件分层依据。目前已有1424人学习下载适合需要多类别、多场景标注数据来验证模型泛化能力或开展对比实验的读者参考使用。1. 机场跑道异物检测一份 FOD-A 数据集能撑起什么样的检测任务跑道上的螺丝钉、金属片、塑料杯在起降速度下就是一颗子弹。FODForeign Object Debris外来物检测这件事难的不是模型结构而是数据——真实机场不可能让你往跑道上撒钉子拍几千张图。FOD-A 这类机场异物数据集解决的正是这个冷启动问题它把跑道、滑行道、停机坪等场景下的异物目标做成带标注的图像集合让目标检测任务从“没数据可训”变成“有数据可调”。这份资源适合三类人做安防/交通视觉落地的算法工程师、拿目标检测做课程设计或毕设的学生、以及需要快速验证检测 pipeline 的从业者。它不承诺 SOTA但能让你在半天内跑通一条从数据加载到推理可视化的完整链路先把“能不能检出”这件事验证掉再谈精度优化。2. 拆开数据集FOD-A 的目录结构、标注格式与选型理由拿到一个目标检测数据集第一件事不是急着train.py而是把目录翻一遍搞清楚图像放哪、标注长什么样、类别怎么定义。FOD-A 的组织方式属于典型的“图像 单文件标注”结构理解它决定了你后面写 DataLoader 时会不会翻车。2.1 目录结构与文件组织常见做法是图像集中放在一个目录下标注用一个汇总文件如 CSV 或 JSON描述每张图的框信息而不是每张图配一个 XML。这种组织方式对目标检测训练更友好——读取标注只需一次 IO不用为每张图开文件。典型结构大致如下FOD-A/ ├── images/ # 原始图像jpg/png ├── annotations/ # 标注汇总文件 │ └── annotations.csv └── README # 类别与字段说明先跑一遍统计确认图像数量、尺寸分布和类别分布这一步能提前暴露很多问题import os from PIL import Image from collections import Counter img_dir FOD-A/images sizes, exts Counter(), Counter() for name in os.listdir(img_dir): path os.path.join(img_dir, name) if not os.path.isfile(path): continue exts[os.path.splitext(name)[1].lower()] 1 with Image.open(path) as im: sizes[im.size] 1 print(扩展名分布:, exts) print(尺寸种类数:, len(sizes)) print(最常见尺寸:, sizes.most_common(5))这段脚本的作用是摸清数据底细扩展名分布告诉你有没有混入非图像文件尺寸种类数如果很大说明图像分辨率不统一后面 resize 策略要格外小心最常见尺寸则决定你 anchor 或输入尺寸的起点。参数上没什么可调的重点是先看再改别上来就写增强。2.2 标注字段与坐标约定标注文件里通常包含图像文件名、类别标签、边界框坐标。坐标是xyxy左上右下还是xywh中心宽高是像素值还是归一化值这两点必须确认否则训练 loss 会一路飘。用 pandas 快速看一眼import pandas as pd df pd.read_csv(FOD-A/annotations/annotations.csv) print(df.columns.tolist()) print(df.head()) print(类别分布:\n, df[class].value_counts()) print(框坐标范围:, df[[xmin,ymin,xmax,ymax]].describe())逻辑说明columns确认字段名避免硬编码错列value_counts看类别是否严重不均衡——FOD 场景里小目标多、某些类别样本极少是常态describe看坐标最大值是否超过图像宽高超过就说明坐标约定和你以为的不一样。如果坐标最大值在 0~1 之间那是归一化坐标转 YOLO 格式时不用再除图像尺寸如果是几百上千的整数就是像素坐标转换时必须除以宽高。2.3 为什么选它做检测基线选 FOD-A 做基线而不是自己爬图理由很实际异物目标尺寸小、背景单一但纹理重复跑道标线、沥青颗粒这类数据对模型的考验集中在小目标召回和背景误检抑制上正好是目标检测落地时最常翻车的两个点。用它调通一套 pipeline换到工业质检、轨道巡检等场景时数据格式转换和评估逻辑几乎可以平移。需要提醒的是这类数据集的类别定义往往偏粗金属、塑料、石块等大类如果你的业务需要细分材质得自己补标注别指望开箱即用。3. 从原始标注到可训练格式转换脚本与四个边界坑数据看明白了下一步是把它转成训练框架认的格式。以 YOLO 系列为例需要每张图一个.txt每行class cx cy w h全部归一化到 0~1。这一步看着简单坑却集中爆发。3.1 写一个可复用的转换脚本import os import pandas as pd from PIL import Image df pd.read_csv(FOD-A/annotations/annotations.csv) classes sorted(df[class].unique()) cls2id {c: i for i, c in enumerate(classes)} out_dir labels os.makedirs(out_dir, exist_okTrue) for img_name, group in df.groupby(image): img_path os.path.join(FOD-A/images, img_name) if not os.path.exists(img_path): print(缺图跳过:, img_name) continue w, h Image.open(img_path).size lines [] for _, r in group.iterrows(): # 像素坐标转归一化中心点格式 cx (r[xmin] r[xmax]) / 2.0 / w cy (r[ymin] r[ymax]) / 2.0 / h bw (r[xmax] - r[xmin]) / w bh (r[ymax] - r[ymin]) / h # 裁剪到 [0,1]防止越界框污染训练 cx, cy min(max(cx, 0), 1), min(max(cy, 0), 1) bw, bh min(max(bw, 0), 1), min(max(bh, 0), 1) lines.append(f{cls2id[r[class]]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) with open(os.path.join(out_dir, img_name.replace(.jpg, .txt)), w) as f: f.write(\n.join(lines)) print(类别映射:, cls2id)逻辑说明groupby(image)保证一张图的所有框写进同一个 txtcls2id用排序后的类别名生成稳定映射避免每次运行 id 漂移坐标裁剪是后悔药——原始标注里偶尔有框超出图像边界不裁的话归一化后出现负值或大于 1训练时 loss 会异常。参数上.6f保留六位小数足够别用科学计数法。3.2 划分训练集与验证集转换完别急着训先按图像级别划分防止同一张图的框被拆到两个集合造成数据泄漏import random random.seed(42) imgs sorted(os.listdir(FOD-A/images)) random.shuffle(imgs) split int(len(imgs) * 0.8) for name in imgs[:split]: open(train.txt, a).write(fimages/{name}\n) for name in imgs[split:]: open(val.txt, a).write(fimages/{name}\n)seed固定是为了可复现按图像而非按框划分是硬要求否则验证集指标虚高上线就露馅。3.3 四个边界坑第一个坑坐标约定误判。现象是训练 loss 一开始就很大且不下降原因是把xywh当xyxy用了。解决方法是拿一张图把框画出来肉眼核对别信字段名。第二个坑类别 id 不连续。现象是训练报index out of range原因是某些类别在验证集里没出现但模型输出维度按训练集类别数设的。解决方法是类别映射用全量数据生成不要按子集生成。第三个坑小目标被 resize 抹掉。现象是训练正常但小异物召回极低原因是输入尺寸缩得太狠几个像素的目标直接消失。解决方法是输入尺寸不低于 640或对小目标做切片训练。第四个坑文件名大小写与扩展名不一致。现象是部分图找不到标注原因是 csv 里写.jpg、磁盘上是.JPG。解决方法是转换前统一小写比对。4. 训练与评估输入尺寸、增强策略和指标怎么看格式就绪后进入训练。这一章不讲模型结构选型YOLO 系、Faster R-CNN 都能跑只讲和 FOD 数据强相关的参数决策因为这些才是决定你这份数据集能不能出结果的关键。4.1 输入尺寸与小目标召回FOD 目标的像素面积普遍偏小输入尺寸是第一优先级参数。经验值640 起步显存允许就上 960 或 1280。对比一下不同输入尺寸对召回的影响用同一份验证集跑推理统计from ultralytics import YOLO for size in [640, 960]: model YOLO(runs/detect/train/weights/best.pt) metrics model.val(datafod.yaml, imgszsize, conf0.25) print(fimgsz{size} mAP50{metrics.box.map50:.4f} fmAP50-95{metrics.box.map:.4f})逻辑说明imgsz控制推理分辨率conf是置信度阈值。重点看mAP50和小目标子集的召回而不是只看总 mAP——总 mAP 被大目标拉高会掩盖小目标问题。如果 960 相比 640 提升明显说明你的数据确实吃分辨率训练时也该同步调大。4.2 增强策略的取舍跑道背景纹理重复颜色增强HSV 抖动收益有限几何增强随机缩放、平移对小目标帮助更大但慎用 MosaicMosaic 会把四张图拼一起小目标被进一步缩小FOD 场景下容易适得其反。常见做法是训练后期关闭 Mosaic让模型在真实分布上收敛。翻转可以开旋转角度别太大异物没有固定朝向但过度旋转会引入不真实样本。4.3 评估指标的正确读法看三个数precision、recall、以及按尺寸分桶的召回。FOD 业务里漏检代价远高于误检所以阈值选择要偏召回。用混淆矩阵和 PR 曲线定位问题类别metrics model.val(datafod.yaml, imgsz960, conf0.1, plotsTrue) print(metrics.confusion_matrix.matrix)conf0.1是为了看低阈值下的召回上限plotsTrue会输出 PR 曲线和混淆矩阵图。如果某类异物大量被判成背景说明该类样本不足或特征太弱优先补数据而不是调模型。5. 避坑与排查五条血泪经验5.1 验证集指标漂亮实际推理一塌糊涂现象val 的 mAP 很高拿几张新图推理却大量漏检。原因验证集和训练集同源同分布且划分时没按场景分层模型记住了背景而非目标。解决按场景跑道/滑行道/停机坪分层划分并留一批完全没参与训练的图做最终验收。5.2 训练中途 loss 变 NaN现象跑几十个 epoch 后 loss 突然 NaN。原因标注里有零宽或零高的退化框归一化后除零或产生极端值。解决转换脚本里加过滤bw 0 or bh 0的框直接丢弃并记录日志。5.3 显存爆掉但 batch 已经很小现象batch 降到 2 还是 OOM。原因输入尺寸调大后特征图显存占用是平方级增长加上数据加载多进程缓存。解决先降imgsz再降 batch同时把 dataloader 的workers调小用torch.cuda.empty_cache()排查是否有残留。5.4 类别严重不均衡导致小类全漏现象样本多的类别召回正常稀有类别几乎检不出。原因损失被大类主导。解决开启类别权重或 focal loss同时对稀有类别做过采样更稳妥的是先合并过细的类别把任务做粗再逐步细化。5.5 推理速度不达标现象精度够了但帧率上不去。原因输入尺寸过大 后处理 NMS 阈值过松产生大量候选框。解决导出 ONNX 或 TensorRT 加速NMS 的iou阈值从 0.45 起调别一味求召回把候选框堆爆。6. 进阶技巧用切片推理把小异物召回再拉一档前面所有优化做完如果小异物召回还是卡在瓶颈别急着换模型先试切片推理SAHI 思路。原理很直接把大图切成有重叠的小块分别推理再合并框等效于在不增加显存的前提下放大了小目标。实现上不需要重训直接套在已有权重上from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathruns/detect/train/weights/best.pt, confidence_threshold0.2, devicecuda:0, ) result get_sliced_prediction( test_fod.jpg, model, slice_height512, slice_width512, overlap_height_ratio0.2, overlap_width_ratio0.2, ) result.export_visuals(export_dirvis/)参数说明slice_height/width决定切片大小太小会切碎目标、太大会失去放大意义一般取输入尺寸的一半左右overlap_*_ratio是切片重叠比例0.2 是常用起点重叠太小会在切片边界漏检太大则推理耗时翻倍。合并阶段还要处理跨切片的重复框SAHI 内部用 NMS 做但阈值要单独调别沿用全图推理的阈值。这套方法在 FOD 场景的收益很直观原本 640 输入下只有几个像素的螺丝钉切片后变成几十像素特征表达完全不一样。代价是推理耗时成倍增加所以适合离线巡检或对实时性要求不高的场景在线视频流要算清楚帧率和切片数的账。我自己的习惯是任何数据集在正式训之前先抽 20 张图把标注画出来肉眼过一遍再跑一次切片推理和全图推理的对比两个结果差得离谱就说明数据或坐标有问题先修数据再谈调参。这个流程帮我省过不止一次通宵重训。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑