
简介面向无人机频射信号检测与目标识别任务的数据集包含364张jpg原始图片和364个xml标注文件采用Pascal VOC格式存储压缩包共728个文件大小约136.89MB。图片与标注一一对应标注信息含目标类别与边界框坐标可直接用于YOLO、Faster R-CNN等主流目标检测模型的训练、验证和性能对比基于该数据集训练的检测模型平均正确识别率达到94.3%说明其标注质量和样本分布具备良好的训练支撑价值。图像命名携带场景与无人机型号/频段信息便于按需筛选或做类别细分实验完整的图片与标注配对结构也能降低数据预处理成本省去自行整理标注的步骤适合科研人员、算法工程师及深度学习学习者用于算法验证、课程设计或竞赛实验。目前已有700人学习下载是开展无人机视觉检测相关工作的实用数据集。1. 无人机频射信号检测一份能直接喂给YOLO的Pascal VOC标注数据集先说结论这份数据集解决的不是“无人机长什么样”而是“无人机在天上飞时它的遥控频射信号长什么样”。364张原始图片标注格式直接给到Pascal VOC XML平均正确识别率能到94.3%——这个数字放在频射信号检测场景里不算虚高因为频射信号在频谱图上的纹理特征比光学图像更稳定没有光照、遮挡、姿态变化这些干扰。适合谁用做无人机反制、低空安防、频谱监测的算法工程师以及想自己训一个频射检测模型但不想从零采集数据的从业者。你拿到的不是一堆裸图而是一套带标注的、可以直接进训练流程的数据资产。2. 先读懂这364张图文件命名、类别构成与标注格式细节2.1 从文件名反推数据来源kong系列与Mini3Pro的频段特征拿到数据集第一件事不是解压就跑而是先看文件名。这364张原始图片的命名规律很值得玩味一部分是kong-29-_jpg.rf.9cd17aec4f296710e6d97856d96ce807.jpg这种带kong-前缀的另一部分是Mini3Pro_5-8GHZ-6-_jpg.rf.c9651ebbaa817b0aec20839ff8022921.jpg这种带机型名和频段名的。.rf.后面跟一长串哈希这是 Roboflow 导出的标准命名特征——也就是说这批数据大概率经过 Roboflow 平台的清洗和增强处理。文件名直接透露了两个关键信息。第一数据覆盖了至少两类目标一类是kong系列代指某类无人机或某类射频模块另一类是Mini3Pro这种具体机型而且 Mini3Pro 明确标注了5-8GHZ频段也就是5.8GHz遥控图传频段。第二这两类目标的频射特征差异足够大模型有区分空间。kong-系列如果是指大疆的某款老机型它的跳频策略、信号带宽和 Mini3Pro 的O3图传协议在频谱图上的形态完全不同这对训练二分类检测器是好事。从标注角度看这种命名方式已经帮你预分割了类别语义。但我建议你拿到手后还是逐张过一遍原始图片确认每张图是频谱瀑布图、时域波形图还是星座图——这三类图在检测时的预处理方式差别很大。泛泛而谈如果是瀑布图模型学的是时频纹理如果是时域波形模型学的是脉冲包络。这份数据的具体图片形态以实际解压内容为准但命名里的频段信息足以支撑你设计预处理管线。2.2 Pascal VOC XML标注结构坐标原点、格式与类别标签的核对方法标题里写的pasical voc xml其实就是 Pascal VOC XML 的常见笔误或口语化写法本质是同一个东西。Pascal VOC 的XML标注文件是和图片同名的后缀从.jpg换成.xml。打开一个XML里面主要看四个字段filename、size、object的name和bndbox的xmin/ymin/xmax/ymax。我这里按这个数据集标注一个典型XML结构如下annotation folderdrone_rf_dataset/folder filenamekong-29-_jpg.rf.9cd17aec4f296710e6d97856d96ce807.jpg/filename size width1280/width height720/height depth3/depth /size object namekong/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin412/xmin ymin268/ymin xmax683/xmax ymax447/ymax /bndbox /object /annotation上面的结构是把这份数据集里单目标图片的标注逻辑还原一下实际内容以解压后的XML为基准。需要核对的不是这份示例XML而是你自己解压出来的文件。动手核对时有几个关键点。坐标是像素值不是归一化值xmin/ymin是左上角xmax/ymax是右下角且xmax xmin、ymax yminVOC格式不允许出现负坐标或宽高为零的框。depth是3说明是RGB彩图但频射频谱图常常是伪彩色训练时转灰度或保留RGB影响不大——需要用实验验证。我一般会用一段小脚本批量校验所有XML的完整性排查空标注、越界坐标和类别名拼写不一致的问题。import xml.etree.ElementTree as ET import os from glob import glob xml_dir annotations errors [] for xml_path in glob(os.path.join(xml_dir, *.xml)): tree ET.parse(xml_path) root tree.getroot() filename root.find(filename).text for obj in root.iter(object): name obj.find(name).text bndbox obj.find(bndbox) xmin int(bndbox.find(xmin).text) ymin int(bndbox.find(ymin).text) xmax int(bndbox.find(xmax).text) ymax int(bndbox.find(ymax).text) if xmax xmin or ymax ymin: errors.append(f{xml_path}: 无效框 {name} {xmin},{ymin},{xmax},{ymax}) if errors: print(发现 %d 个问题标注 % len(errors)) for e in errors[:10]: print(e) else: print(全部XML校验通过)这段脚本的逻辑是遍历一个目录下所有XML逐个取filename、object/name和bndbox四个坐标检查框的宽高是否为正。脚本会先报出有问题的XML和对应类别便于你决定是手动修标注还是直接删掉坏样本。filename字段没在参数里主要是核对用训练时如果你的数据划分是按文件名匹配这个字段的准确性一定要保证。正则核对类别名的方式也对但更省事的做法是统计所有XML里name标签的去重集合确认只有kong和Mini3Pro或者你看到的实际类别名两类。如果出现第三个名字打开对应XML看是不是标注员把背景噪声框进去了。3. 把Pascal VOC XML变成训练燃料数据划分与格式转换3.1 按文件级划分:train/val/test的科学拆分逻辑364张图片的数据集规模不大划分比例和划分方式直接决定你最后报出来的94.3%可信度。这里有个容易翻车的点:不能按XML文件内容去随机切分,必须按图片文件名整体划分,保证同一张图对应的图片和XML永远在同一侧。常见做法是 7:2:1,即254张训练、73张验证、37张测试。但我实际跑这类小数据集时,更倾向于 8:1:1 并配合K折交叉验证——364张的基数下,测试集只有36张,单次划分的指标方差会很大。数据划分脚本如下:import os import random import shutil random.seed(42) img_dir images xml_dir annotations train_dir dataset/train val_dir dataset/val test_dir dataset/test for d in [train_dir, val_dir, test_dir]: os.makedirs(os.path.join(d, images), exist_okTrue) os.makedirs(os.path.join(d, labels), exist_okTrue) imgs [f for f in os.listdir(img_dir) if f.endswith(.jpg)] random.shuffle(imgs) n len(imgs) n_train int(n * 0.8) n_val int(n * 0.1) for i, img_name in enumerate(imgs): base os.path.splitext(img_name)[0] xml_name base .xml xml_path os.path.join(xml_dir, xml_name) if not os.path.exists(xml_path): print(f警告: {img_name} 缺少对应XML,已跳过) continue if i n_train: dest train_dir elif i n_train n_val: dest val_dir else: dest test_dir shutil.copy(os.path.join(img_dir, img_name), os.path.join(dest, images, img_name)) shutil.copy(xml_path, os.path.join(dest, labels, xml_name))这段脚本做的事是:固定随机种子(保证可复现),读入所有jpg文件名,按8:1:1分配到三个目录,同时把同名XML拷贝过去。关键是加了存在性检查——如果某张图没有对应XML,就打印警告并跳过,避免后续训练时报“找不到标注文件”的错。64镜经我遇到过几次这种缺标注的图,大多数是标注平台导出时漏了,数量不多,跳过不影响整体训练,但要在日志里记下来。宽度对齐、类别映射表这两件事也要在这个阶段做。.txt格式的类别索引从0开始,如果你有两个类别,约定kong0、Mini3Pro1,这个映射要在训练配置里保持一致,不能变来变去。3.2 XML转YOLO格式:归一化坐标与类别ID映射的完整脚本如果你打算直接用YOLOv8或YOLOv5训练,还得把Pascal VOC XML转成YOLO的txt标注格式。YOLO格式要求:每行是一个目标,格式为class_id x_center y_center width height,四个坐标值全部归一化到0~1之间。转换脚本如下:import xml.etree.ElementTree as ET import os from glob import glob class_map {kong: 0, Mini3Pro: 1} def convert_annotation(xml_path, out_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) width int(size.find(width).text) height int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_map: print(f跳过未知类别: {name} in {xml_path}) continue cls_id class_map[name] bndbox obj.find(bndbox) xmin int(bndbox.find(xmin).text) ymin int(bndbox.find(ymin).text) xmax int(bndbox.find(xmax).text) ymax int(bndbox.find(ymax).text) x_center (xmin xmax) / 2.0 / width y_center (ymin ymax) / 2.0 / height box_width (xmax - xmin) / width box_height (ymax - ymin) / height lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {box_width:.6f} {box_height:.6f}) with open(out_path, w) as f: f.write(\n.join(lines)) xml_dir annotations txt_dir labels_yolo os.makedirs(txt_dir, exist_okTrue) for xml_path in glob(os.path.join(xml_dir, *.xml)): base os.path.splitext(os.path.basename(xml_path))[0] out_path os.path.join(txt_dir, base .txt) convert_annotation(xml_path, out_path) print(f转换完成,输出目录: {txt_dir})转换脚本的逻辑分三步:先从XML的size取图像宽高;再遍历所有object,把bndbox的四个像素坐标换算成归一化的中心点坐标和宽高;最后按class_id x_center y_center width height写入txt。三个细节注意:坐标计算时除以的是图像宽高,不是某个固定分辨率;归一化值保留6位小数,精度足够且避免浮点误差累积;未知类别名直接跳过而不是报错,因为频射数据里偶尔有标注员手滑多写的标签,跳过能让转换流程不被单条脏数据阻断。转换完成后可以做个快速抽查:随机挑一张图和它对应的txt,把坐标反算回像素画框,和原图叠在一起看看框的位置对不对。东北话讲这叫“对缝”,别嫌土,这一步能发现50%以上的转换错误。4. 频射信号检测训练配置:模型选型、超参数与评估指标4.1 为什么选YOLOv8而不是Faster R-CNN:小数据量下的务实选择这份数据集只有364张图,属于典型的小样本目标检测场景。Faster R-CNN这类两阶段检测器理论上精度上限高,但需要大量数据支撑才能发挥优势,在小数据集上反而容易过拟合,而且训练和推理速度都不占优。YOLOv8单阶段检测器在小数据集上的收敛速度更快,数据增强的容错空间更大,推理延迟也更适合频射检测这类可能需要实时响应的场景。更关键的是,频射信号在频谱图上的目标形态通常是紧凑的斑块或细长的波形带,没有复杂的空间结构,单阶段检测器完全够用。我在这类数据集上的习惯是先跑YOLOv8s,如果mAP0.5已经到0.9以上,就没必要上更大的模型——94.3%的识别率用YOLOv8s做到完全合理。反过来如果卡在0.8上不去,再考虑换YOLOv8m或调anchor,而不是一上来就堆参数量。4.2 一份能直接跑的YOLOv8训练配置:yaml与命令行参数详解用YOLOv8训练这份数据,需要准备两个文件:一个是数据集描述drone_rf.yaml,一个是模型配置文件(直接用官方自带的yolov8s.yaml即可,不需要改结构)。先看数据集描述文件:# drone_rf.yaml path: /your/absolute/path/drone_rf_dataset train: train/images val: val/images test: test/images nc: 2 names: [kong, Mini3Pro]这个yaml的要点是path必须写成绝对路径,YOLOv8对相对路径的解析经常踩坑;train/val/test指向的目录里包含图片,YOLOv8会自动找同名txt标签。结构上不用写names以外的任何参数。训练命令:yolo detect train \ datadrone_rf.yaml \ modelyolov8s.yaml \ pretrainedyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ augmentTrue \ patience15 \ seed42 \ projectruns/drone_rf参数含义逐个说清楚:epochs100对小数据集是合理起点,配合patience15做早停,如果验证集指标连续15轮不涨就自动停,省时间;imgsz640是输入尺寸,如果原图是1280或更高,建议先用640跑通流程,再试1280看有没有精度提升——频射信号的频谱纹理比较细,分辨率翻倍通常有收益但训练时间也翻倍;batch16取决于显存,显存小的调到8;lr00.01是初始学习率,YOLOv8自带warmup和余弦退火,一般不用动;pretrainedyolov8s.pt会在COCO预训练权重上做迁移学习,对小数据集非常关键,千万别从零开始训练;seed42固定随机种子,保证复现。训练过程中重点盯两个日志:训练loss曲线和验证集的mAP0.5。频射数据集如果loss下降正常、mAP能到0.85以上,说明标注质量和数据划分没问题;如果loss震荡明显,第一反应是学习率太高或批次太小,而不是怀疑数据。4.3 评估指标的读法:94.3%的正确识别率到底对应哪个指标标题里的94.3%需要澄清一个边界:它大概率是测试集上的平均准确率(Average Precision)或带置信度阈值下的F1分数,具体定义以训练时的评估脚本为准。但无论哪种定义,你都要自己重新评估一遍,别直接拿宣称数字当结果。我一般用测试集做一次严格评估,报告三个数:mAP0.5、mAP0.5:0.95、以及置信度0.25下的precision/recall。如果你的场景更关注“有无人机频射就一定要抓出来”,那recall优先;如果更关注“误报会带来误触反制动作”,那precision优先。频射检测领域的常见做法是卡在0.25置信度下看F1。5. 避坑:频射信号数据集里五个最容易翻车的现场5.1 现象:模型把背景噪声框成目标训练完第一次推理,发现模型在没有任何目标的位置输出了高置信度检测框,框的还是频谱图上的雪花噪点或电磁干扰条纹。原因:标注数据里部分difficult0的目标实际标注得过大,框内包含了大量背景纹理,模型学到的是“这段区域纹理杂乱”而非“这是无人机频射”。解决:把训练集里置信度低于0.5的检测结果对应的GT框逐个调出来看,凡是框内背景占比超过30%的,手动收缩坐标,重新标注后补训一个epoch。5.2 现象:验证集mAP很高,测试集掉点严重364张图,训练集占了约290张,测试只有36张。可能训练评估时开的augmentTrue导致验证集也做了增强,分数虚高。解决:评估阶段强制关闭增强:model.val(splittest, augmentFalse)。另外一个常见做法是直接对测试集不做任何预处理地推理,用最朴素的参数跑一遍,拿这个数当基准线。5.3 现象:同源图片泄漏导致精度虚高很多频射信号数据集来自连续录制的视频抽帧,同一段无人机飞行画面的前后帧高度相似。如果划分时随机打乱了文件名,相似帧就会同时出现在训练和测试集,模型等于见过“几乎答案”的图。解决:按“采集时间/采集片段”进行分层划分,比如把文件名按前缀分组,一组进训练,另一组整体进测试,宁可让测试集小一点也不能泄漏。泛泛而谈的正确划分思路:先分组再切分。5.4 现象:XML里坐标小数被截断,框整体偏移部分标注工具导出时把坐标四舍五入成了整数,而你的预处理做了缩放或归一化,导致框在放大检视时偏移几个像素。频射目标本身小,几十像素的偏移就可能让标注框偏离目标主体。解决:XML解析时统一用float()而不是int()读坐标,或者在归一化前先做一次坐标取整,保证前后一致。我习惯在转换脚本里把坐标转回原图尺寸再做可视化比对。5.5 现象:两个类别在特定频段上互相混淆kong和Mini3Pro在2.4GHz附近都可能有信号,如果原图是时域波形而非瀑布图,波形形态学特征高度相似,模型就会出现混淆。解决:先把类别分离度做个可视化——取两类样本各20张,用t-SNE看特征分布是否重叠。如果重叠严重,考虑改成单类检测,或者对原图做频段裁剪,只保留5.8GHz附近的区域。6. 落地前的最后一步:模型验证、量化与数据增强闭环训练完模型,先别急着部署。真正决定这个94.3%能不能在你的实际环境里复现的,是你自己跑一遍端到端验证。我的习惯是写一个独立的验证脚本,不依赖YOLO训练框架,直接用训练好的权重做推理,再对比GT算指标。from ultralytics import YOLO import os import numpy as np model YOLO(runs/drone_rf/weights/best.pt) test_imgs [f for f in os.listdir(dataset/test/images) if f.endswith(.jpg)] tp fp fn 0 conf_thres 0.25 iou_thres 0.5 for img_name in test_imgs: results model.predict( os.path.join(dataset/test/images, img_name), confconf_thres, iouiou_thres, verboseFalse ) pred_boxes results[0].boxes pred_xyxy pred_boxes.xyxy.cpu().numpy() if pred_boxes is not None else np.empty((0, 4)) pred_cls pred_boxes.cls.cpu().numpy() if pred_boxes is not None else np.empty((0,)) # 这里简化为单目标场景的统计,多目标用一般目标检测评估库更稳妥 has_gt True # 实际使用中需要解析GTXML判断这张图有没有目标 if has_gt and len(pred_xyxy) 1: tp 1 elif not has_gt and len(pred_xyxy) 1: fp 1 elif has_gt and len(pred_xyxy) 0: fn 1 precision tp / (tp fp 1e-6) recall tp / (tp fn 1e-6) f1 2 * precision * recall / (precision recall 1e-6) print(fPrecision{precision:.3f} Recall{recall:.3f} F1{f1:.3f})这个脚本的逻辑是逐张测试图推理,统计真正例、假正例、假负例,最后算precision、recall和F1。单目标简化场景下够用,如果你的GT里一张图有多个目标,就得用torchmetrics.detection这类标准库来算。参数上conf_thres0.25是常见默认,实际部署时按你的误报容忍度调:conf_thres拉高到0.5会降低误报但也可能漏掉弱信号,拉低到0.1则反过来。验证完之后,考虑两步优化再封板。第一步是模型量化:model.export(formatonnx)导出ONNX,再用onnxruntime或TensorRT做INT8量化。频射检测经常部署在边缘设备上,量化后推理速度能提2~3倍,但min精度可能有1~2个点的回落,必须在量化后用同样的验证脚本复测。第二步是数据增强闭环:训练时YOLOv8自带的augmentTrue已经包含随机翻转、色彩抖动等,但频射信号特定的增强——比如加随机高斯噪声、做频率偏移——是通用的图像增强管线的知识,不是官方文档明写的东西。如果你发现模型在低信噪比场景下频繁漏检,建议在训练集里手动合成一部分低信噪比样本,把频谱图叠上噪声背景重新标注,这种“脏数据”增强对小数据集往往比调参更管用。从那以后我每次拿到一份频射检测数据集,都强制走一遍“校验XML、分组划分、转YOLO格式、训基线、跑独立验证脚本”的全流程,任何一个环节不过关都推倒重来。这套流程说不上精巧,但能让94.3%这个数字经得起你自己重新验证一遍。希望帮到你。本文还有配套的精品资源点击获取