简介这份无人机频射信号检测数据集面向从事无人机侦测、频谱感知与目标识别的研究人员及算法工程师可用于训练和评估射频信号下的无人机检测模型解决复杂电磁环境中无人机信号难以准确识别的问题。资源包共729个文件包含364张jpg原始图像、364个对应的txt标注文件以及1个yaml配置文件压缩包约136.82MB标注格式兼容YOLOv11可直接接入主流目标检测训练流程。数据集覆盖多类无人机频射信号样本平均正确识别率可达94.3%适合作为模型训练、对比实验与性能验证的基础数据。目前已有632人学习下载具备一定参考热度。读者可借助完整图像与标注快速搭建检测任务验证算法在射频信号场景下的表现并在此基础上进行数据增强、模型调优与迁移学习为无人机监测相关研究提供可复用的数据支撑。1. 频射信号检测遇上 YOLOv11364 张图的数据集到底能不能打第一次拿到这个无人机频射信号检测数据集时我盯着文件名里那串kong-29-_jpg.rf.9cd17aec...愣了几秒——kong系列加上Mini3Pro_5-8GHZ命名里已经透出了采集设备的味道。这不是普通的航拍图而是把无人机遥控链路的频射信号做成了时频图spectrogram再用目标检测的思路去框出信号所在的位置。数据集一共 364 张原始图片标注直接对齐 YOLOv11 格式官方给出的平均正确识别率是 94.3%。如果你正在做无人机频射信号检测、drone id 识别码相关的课题或者想找一个能直接喂给 YOLOv11 训练的小规模数据集跑通全流程这份资源值得先拆开看看。它解决的核心问题是把看不见的射频信号变成可标注、可训练、可复现的视觉检测任务省掉你自己做时频变换和标注的功夫。2. 频射信号怎么变成 YOLOv11 能吃的图原理与格式拆解2.1 从 IQ 采样到时频图信号视觉化的关键一步无人机频射信号本质上是时域上的 IQ 采样流直接丢给检测网络没有意义。常见做法是先做短时傅里叶变换STFT把一维时序转成二维时频图横轴是时间、纵轴是频率、像素亮度代表该时刻该频点的能量强度。数据集里那些kong-*.jpg.rf.*.jpg的文件名rf大概率就是 radio frequency 的缩写说明图片已经完成了这一步转换。你拿到手的是成品图不需要再碰 GNU Radio 或 MATLAB 的时频分析脚本。这里有个选型理由值得说清楚为什么用 STFT 而不是小波变换STFT 的窗长和重叠率参数直接决定时频分辨率窗太长频率分辨率高但时间定位糊窗太短反过来。数据集既然已经固定了图片说明采集方在某个窗长下做了取舍。你后续如果要自己扩充数据得保持同样的 STFT 参数否则新旧图片的时频纹理分布不一致模型会学偏。我一般会先拿几张图做傅里叶逆变换的 sanity check确认信号带宽和Mini3Pro_5-8GHZ这个命名对得上——5.8GHz 频段对应大疆 Mini3 Pro 的图传链路这个先验知识能帮你判断标注框的位置是否合理。2.2 YOLOv11 标注格式txt 文件里到底存了什么YOLOv11 沿用了 YOLO 系列的标注规范每张图片对应一个同名.txt文件每行一个目标格式是class_id x_center y_center width height其中坐标全部是归一化到 0~1 的相对值x_center和y_center是框中心点width和height是框的宽高。假设一张图是 640×640某个信号框的像素坐标是左上角 (120, 200)、右下角 (400, 480)那么中心点像素 ((120400)/2, (200480)/2) (260, 340)归一化中心 (260/640, 340/640) (0.40625, 0.53125)宽高像素 (280, 280)归一化 (0.4375, 0.4375)对应 txt 行就是0 0.40625 0.53125 0.4375 0.4375。数据集里如果只有一个信号类别class_id全是 0如果区分了不同机型或不同频段就会有多个 id。拿到数据后第一件事是统计所有 txt 里的 class_id 分布确认类别数和你data.yaml里的nc对得上这是最常见的翻车点之一。2.3 目录结构怎么摆YOLOv11 训练前的硬性要求YOLOv11 对目录结构有固定预期常见做法是dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamlimages/train/放训练图labels/train/放对应的 txt文件名必须一一对应只是扩展名不同。364 张图按 8:2 切训练集约 291 张、验证集约 73 张。如果原始数据没有划分可以用脚本按随机种子切分保证可复现import os import random import shutil random.seed(42) # 固定种子保证每次划分一致 img_dir raw_images lbl_dir raw_labels out_root dataset imgs [f for f in os.listdir(img_dir) if f.endswith(.jpg)] random.shuffle(imgs) split int(len(imgs) * 0.8) train_imgs, val_imgs imgs[:split], imgs[split:] for subset, files in [(train, train_imgs), (val, val_imgs)]: os.makedirs(f{out_root}/images/{subset}, exist_okTrue) os.makedirs(f{out_root}/labels/{subset}, exist_okTrue) for f in files: shutil.copy(os.path.join(img_dir, f), f{out_root}/images/{subset}/{f}) txt os.path.splitext(f)[0] .txt shutil.copy(os.path.join(lbl_dir, txt), f{out_root}/labels/{subset}/{txt})这段脚本的逻辑很直白先固定随机种子打乱图片列表按 80% 切分然后分别拷贝图片和同名标注到对应子目录。参数上唯一要改的是img_dir和lbl_dir指向你解压后的实际路径。注意random.seed(42)这行别省否则每次跑出来的划分不同实验没法对比。2.4 data.yaml 怎么写路径、类别数、类别名data.yaml是 YOLOv11 训练的入口配置内容大致如下path: /abs/path/to/dataset train: images/train val: images/val nc: 1 names: [rf_signal]path建议写绝对路径避免相对路径在不同工作目录下解析出错。nc是类别数names是类别名列表长度必须等于nc。如果数据集区分了多种信号类型这里要相应扩展。写完 yaml 后用一行命令快速验证路径是否通python -c from ultralytics import YOLO; YOLO(yolo11n.pt).train(datadata.yaml, epochs1, imgsz640)跑 1 个 epoch 能启动就说明数据加载没问题不用等它跑完CtrlC 中断即可。这一步能提前暴露 90% 的路径和格式错误。3. 用 YOLOv11 跑通训练从环境配置到 94.3% 识别率复现3.1 环境配置ultralytics 装完先别急着训YOLOv11 的官方实现已经并入ultralytics包安装就一行pip install ultralytics但血泪经验是装完先跑yolo checks看环境自检yolo checks它会输出 Python 版本、PyTorch 版本、CUDA 是否可用、依赖包版本。如果 CUDA 显示不可用但你确实有 GPU大概率是 PyTorch 装成了 CPU 版需要去 PyTorch 官网按 CUDA 版本重装。364 张图用 CPU 训也能跑但 100 个 epoch 可能要几个小时GPU 上十几分钟就完事。另外ultralytics更新频繁建议锁定版本pip install ultralytics8.3.0版本号按你实际能装到的稳定版来别盲目追最新新版本有时会改默认超参导致复现结果对不上。3.2 训练命令与关键参数epochs、imgsz、batch 怎么定启动训练的命令yolo detect train \ datadataset/data.yaml \ modelyolo11n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/rf_detect \ nameexp1逐个说参数modelyolo11n.pt是 nano 版预训练权重364 张图属于小数据集用大模型容易过拟合nano 或 small 版更稳。epochs100配合patience20表示 20 轮验证指标不提升就早停避免无效训练。imgsz640是输入分辨率如果你的时频图原始尺寸远大于 640可以适当调大但显存占用会平方级增长。batch16在 8GB 显存上跑 640 分辨率基本安全显存不够就降到 8。lr00.01是初始学习率小数据集上如果 loss 震荡厉害可以降到 0.001。训练过程中重点看mAP50和mAP50-95两个指标。官方说的 94.3% 平均正确识别率大概率对应的是mAP50或某个置信度阈值下的准确率。你复现时如果mAP50在 0.90 以上说明流程基本对了如果只有 0.6 左右先查标注格式和类别数再查图片和标注是否错位。3.3 推理与结果保存怎么把检测框画回时频图训练完用最佳权重推理yolo detect predict \ modelruns/rf_detect/exp1/weights/best.pt \ sourcedataset/images/val \ conf0.25 \ saveTrue \ projectruns/rf_detect \ nameval_resultconf0.25是置信度阈值低于这个值的框不输出。频射信号检测里如果信号微弱、背景噪声大可以降到 0.1 看召回但误检会增多。saveTrue会把画了框的图片存到runs/rf_detect/val_result/下。想进一步拿到每个框的坐标做后续分析加save_txtTrue会在同目录生成对应的 txt。推理结果里如果发现框大量偏移或漏检别急着调模型先把saveTrue的图打开肉眼比对确认是标注问题还是模型问题——这一步能省掉很多瞎调参的时间。3.4 94.3% 这个数字怎么理解指标口径与验证方法94.3% 这个数字脱离口径谈没有意义。目标检测里常见的口径有几种mAP50IoU0.5 时的平均精度、mAP50-95IoU 从 0.5 到 0.95 取平均、或者某个固定置信度下的分类准确率。364 张图的小数据集验证集只有 70 多张单张图的波动就能让指标跳几个点。我一般会做三件事来验证第一用不同随机种子切分数据跑三次看指标方差第二把验证集推理结果导出来逐张看漏检和误检的分布第三如果可能找一批完全没参与训练的图做外部验证。只有这三步都过了94.3% 才站得住。如果只是训练日志里某一轮的峰值那参考价值有限。4. 避坑与排查频射信号数据集训练中最容易翻车的五件事4.1 图片和标注文件名对不上训练直接报错现象启动训练后报No labels found或Image not found或者训练 loss 一直是 nan。原因YOLOv11 按文件名匹配图片和标注kong-29-_jpg.rf.9cd17aec...jpg对应的标注必须是kong-29-_jpg.rf.9cd17aec...txt。如果标注文件在生成时被重命名、或者扩展名大小写不一致.JPGvs.jpg匹配就会失败。解决写个脚本批量检查两边文件名集合是否一致import os imgs {os.path.splitext(f)[0] for f in os.listdir(dataset/images/train)} lbls {os.path.splitext(f)[0] for f in os.listdir(dataset/labels/train)} print(图片无标注:, imgs - lbls) print(标注无图片:, lbls - imgs)两个集合都为空才说明配对正确。有差异就手动补齐或删除孤儿文件。4.2 标注坐标超出 0~1 范围框飞到图外现象训练能跑但可视化时框跑到图片外面或者 mAP 异常低。原因标注生成时如果用了像素坐标没归一化或者归一化时除错了基准尺寸比如用 416 除了 640 的图坐标就会越界。YOLOv11 对越界坐标不会报错但会静默影响训练。解决遍历所有 txt检查每行后四个数是否都在 [0,1] 区间import os bad [] for f in os.listdir(dataset/labels/train): with open(fdataset/labels/train/{f}) as fp: for i, line in enumerate(fp): parts line.strip().split() if len(parts) ! 5: bad.append((f, i, 字段数不对)) continue vals list(map(float, parts[1:])) if any(v 0 or v 1 for v in vals): bad.append((f, i, vals)) print(bad[:20])发现越界就回退到标注生成环节重做别试图在训练时裁剪裁剪会改变框和信号的对应关系。4.3 类别数配置错误模型输出维度对不上现象训练时报IndexError或AssertionError提示类别索引超范围。原因data.yaml里nc写成了 1但标注 txt 里出现了class_id2或者反过来实际有 3 类但nc1。YOLOv11 的分类头维度由nc决定标注里的 id 超过nc-1就会崩。解决统计所有标注里的 class_id 最大值cat dataset/labels/train/*.txt | awk {print $1} | sort -u输出里有几个不同的值nc就至少是几。同时确认names列表长度和nc一致。4.4 时频图分辨率与 imgsz 不匹配小信号被 resize 抹掉现象训练指标尚可但推理时小信号漏检严重。原因原始时频图可能是 1024×1024 甚至更大训练时imgsz640会把图缩小原本只占几十个像素的微弱信号被压缩到几个像素特征丢失。解决先看原始图片尺寸python -c from PIL import Image; print(Image.open(dataset/images/train/xxx.jpg).size)如果远大于 640要么把imgsz调大到 1024显存够的话要么在预处理时把大图裁成小块分别标注。小目标检测本身是 YOLOv11 的弱项频射信号又常常是小目标这一步不能偷懒。4.5 验证集指标虚高换一批图就崩现象验证集 mAP50 有 0.94但拿新采集的图一测漏检误检一大堆。原因364 张图如果来自同一台设备、同一时段、同一环境训练集和验证集分布几乎一样模型学到的是这批数据的特定噪声模式不是通用的信号特征。换设备、换环境分布偏移就暴露了。解决如果条件允许留出一部分不同日期或不同地点采集的图做测试集不参与训练和调参。如果数据全来自同一批至少在报告指标时注明适用范围别把 94.3% 当成通用性能。我一般会在论文或报告里写清楚「在该数据集同分布验证集上」这个限定避免误导。5. 小数据集提效技巧从 364 张图里榨出更多信息364 张图在目标检测里算很小了直接训容易过拟合。我常用的几个手段按性价比排序。第一是数据增强。YOLOv11 默认开了 mosaic、HSV 抖动、随机翻转但对时频图来说水平翻转要慎用——时频图的横轴是时间翻转后时间倒流物理上不合理。垂直翻转频率轴翻转同样要谨慎因为不同频段的信号特征不同。我一般会关掉上下翻转保留 mosaic 和轻微的亮度对比度抖动。在训练命令里加yolo detect train datadataset/data.yaml modelyolo11n.pt epochs150 \ fliplr0.0 flipud0.0 mosaic1.0 hsv_v0.3fliplr0.0和flipud0.0关掉翻转hsv_v0.3控制亮度抖动幅度。这样增强出来的图仍然符合时频图的物理意义。第二是迁移学习的层冻结策略。yolo11n.pt是在 COCO 上预训练的底层卷积学的是通用边缘纹理这些对时频图也有用。前 10 个 epoch 可以冻结 backbone只训检测头让模型先适应新任务再解冻全量微调yolo detect train datadataset/data.yaml modelyolo11n.pt epochs150 \ freeze10freeze10表示冻结前 10 层。小数据集上这招能明显稳住早期训练减少 loss 震荡。第三是交叉验证。364 张图做 5 折交叉验证每折验证集约 73 张虽然单折指标波动大但 5 折平均能给出更可靠的性能估计。做法是把数据切 5 份轮流做验证import numpy as np from sklearn.model_selection import KFold files np.array(sorted(os.listdir(raw_images))) kf KFold(n_splits5, shuffleTrue, random_state42) for fold, (tr, va) in enumerate(kf.split(files)): print(fFold {fold}: train{len(tr)}, val{len(va)}) # 按索引拷贝到 fold_{fold}/ 目录再分别训练跑完 5 折看 mAP 的均值和标准差。如果标准差超过 0.05说明数据分布不均或样本太少指标参考价值要打折扣。最后说一个验证技巧把推理结果按置信度排序人工检查最低置信度的 20 个框和漏检的图。低置信度框里如果混着真实信号说明阈值设高了漏检的图如果信号本身就很弱说明数据难度分布不均。这个习惯我从第一次做信号检测就养成了每次训完模型都强制走一遍比盯着 loss 曲线有用得多。希望帮到你。本文还有配套的精品资源点击获取
