RM雷达站数据集构建与YOLO训练部署全流程指南
简介这份资源面向RoboMaster雷达站方向的参赛选手与算法开发者汇总了雷达数据集与多所高校的开源程序帮助解决数据来源零散、参考方案难找的问题。内容涵盖大疆官方数据集、Damon2019/RM-DATASET、华农数据集等并整理了上海交通大学、沈阳航空航天大学、中国石油大学华东、华中科技大学等队伍的雷达站程序以及YOLOv5模型剪枝、高性能推理加速模块等技术还收录了2024赛季厦门理工与辽宁科技的最新开源项目展示如何通过规则应用降低成本并提升效果。资源包共3个文件以inscode工程配置、html页面与gitignore忽略规则为主压缩包约6KB属于轻量级索引与入口型资料便于快速定位各数据集与开源仓库。目前已有223人学习下载适合希望系统梳理雷达站技术路线、对比不同队伍实现思路并寻找可复用模块的读者参考。1. RM雷达站数据集与开源源码从数据到检测的一条完整链路做 RoboMaster 视觉算法的同学大概率都经历过这个阶段装甲板检测模型在实验室灯光下跑得挺好一到赛场就各种误识别、漏识别尤其是雷达站视角下目标小、背景杂、光照变化剧烈模型直接“翻车”。问题的根子往往不在网络结构而在数据集——你用的训练数据跟雷达站实际看到的画面分布差太远。RM 雷达站数据集与开源源码这个方向解决的就是“拿什么数据训、用什么代码跑、怎么部署到雷达站”这条链路。它适合已经能跑通 YOLO 基础训练、想针对雷达站场景做专项优化的视觉组成员也适合想理解“数据集怎么从零构建”的算法新手。下面按数据获取、格式转换、训练调参、部署验证的顺序拆开讲。2. 雷达站数据集长什么样采集视角、标注规范与类别定义2.1 雷达站视角和步兵视角的数据差异在哪很多人第一次拿到雷达站数据集会愣一下怎么目标这么小原因在于雷达站相机通常架设在高处俯视全场一辆步兵车在画面里可能只占几十个像素。这跟步兵第一视角下装甲板占画面三分之一的情况完全不同。具体差异体现在三个维度目标尺度雷达站视角下装甲板宽度普遍在 20~60 像素步兵视角常在 150~400 像素。背景复杂度雷达站能看到整个场地包括场地边缘、观众区、其他机器人干扰物远多于步兵视角。光照条件雷达站相机固定但赛场灯光会在不同时段变化加上场地反光同一目标在不同帧的亮度差异很大。这意味着你不能直接拿步兵视角的数据集去训雷达站模型mAP 会掉得很厉害。常见做法是单独采集雷达站视角数据或者在训练时加入大量小目标增强。2.2 标注规范类别怎么定、框怎么画RM 雷达站数据集的标注通常围绕“装甲板”和“机器人”两个层级展开。我一般建议按以下规范来标注对象类别名框选范围备注装甲板armor紧贴装甲板发光区域外沿不包含车体机器人整体robot包含车体装甲板用于粗定位能量机关rune包含整个机关如果雷达站需要检测基地base基地装甲板区域部分数据集有标注时最容易踩的坑是“框画太大”。有人觉得目标小就把框画得比实际大一圈结果模型学到的边界模糊推理时框抖动严重。正确做法是紧贴目标边缘宁可小一点也不要大。另外遮挡超过 50% 的目标建议标为“difficult”或者直接不标否则模型会学到错误的特征。2.3 数据集目录结构怎么组织一个可复用的雷达站数据集目录建议这样组织rm_radar_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── data.yaml └── README.mddata.yaml是 YOLO 系列训练的入口文件内容大致如下# data.yaml path: ./rm_radar_dataset train: images/train val: images/val test: images/test nc: 2 names: 0: armor 1: robot这里nc是类别数names按索引对应类别名。注意索引必须从 0 开始连续否则训练时会报类别越界。path用相对路径时训练脚本的工作目录要和它对齐不然会找不到图片。提示如果数据集里同时有装甲板和机器人两类建议先确认标注时没有把同一个目标重复标成两类否则模型会学到矛盾标签。3. 从原始视频到 YOLO 格式抽帧、清洗与转换脚本3.1 抽帧策略多少帧够用、怎么避免冗余雷达站数据通常来自录制的比赛视频或训练录像。直接按固定间隔抽帧会导致大量相似帧训练时模型见过太多重复样本泛化能力反而下降。我一般用“运动幅度时间间隔”双条件抽帧import cv2 import os def extract_frames(video_path, out_dir, interval15, diff_thresh8.0): 按时间间隔抽帧同时用帧差过滤静止画面 interval: 每多少帧取一帧 diff_thresh: 帧差均值阈值低于此值认为画面无变化跳过 os.makedirs(out_dir, exist_okTrue) cap cv2.VideoCapture(video_path) prev_gray None idx 0 saved 0 while True: ret, frame cap.read() if not ret: break if idx % interval 0: gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) if prev_gray is not None: diff cv2.absdiff(gray, prev_gray).mean() if diff diff_thresh: idx 1 continue prev_gray gray cv2.imwrite(os.path.join(out_dir, fframe_{saved:05d}.jpg), frame) saved 1 idx 1 cap.release() print(f共保存 {saved} 帧)interval15在 30fps 视频里约等于每 0.5 秒取一帧diff_thresh8.0是经验值画面变化小的时候跳过。这两个参数根据视频长度和目标出现频率调整比赛视频目标多可以interval10训练录像目标少interval20甚至更大。3.2 清洗模糊帧、无目标帧怎么筛抽完帧不能直接标先过一遍自动清洗。模糊帧用拉普拉斯方差判断无目标帧可以用一个预训练模型粗筛import cv2 import numpy as np def is_blurry(image_path, threshold100): 拉普拉斯方差低于阈值认为模糊 img cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if img is None: return True return cv2.Laplacian(img, cv2.CV_64F).var() threshold def filter_blurry(img_dir, move_dir): 把模糊帧移到单独目录不删除方便复查 import shutil os.makedirs(move_dir, exist_okTrue) for fname in os.listdir(img_dir): fpath os.path.join(img_dir, fname) if is_blurry(fpath): shutil.move(fpath, os.path.join(move_dir, fname))threshold100是常见起点雷达站画面如果整体偏暗可以降到 60~80。模糊帧不要直接删移到单独目录标注时如果发现漏了目标还能找回来。3.3 格式转换VOC 转 YOLO 的四个边界坑很多开源数据集是 VOC 格式XML 标注转 YOLO 格式txt时容易出问题。转换脚本核心逻辑import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, out_txt_path, class_map): class_map: {armor: 0, robot: 1} tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_map: continue xmlbox obj.find(bndbox) x1 float(xmlbox.find(xmin).text) y1 float(xmlbox.find(ymin).text) x2 float(xmlbox.find(xmax).text) y2 float(xmlbox.find(ymax).text) # 边界裁剪防止坐标越界 x1 max(0, min(x1, w)) y1 max(0, min(y1, h)) x2 max(0, min(x2, w)) y2 max(0, min(y2, h)) if x2 x1 or y2 y1: continue cx (x1 x2) / 2.0 / w cy (y1 y2) / 2.0 / h bw (x2 - x1) / w bh (y2 - y1) / h lines.append(f{class_map[cls_name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines))四个边界坑坐标越界x2 超过图片宽度、宽高为负x2x1、类别名不在映射表里、图片尺寸和 XML 记录不一致。前两个用max/min和条件判断解决第三个靠class_map过滤第四个需要在转换前核对图片实际尺寸不一致的样本直接丢弃。4. 训练调参小目标检测在雷达站场景的必调参数4.1 输入分辨率为什么 640 不够用雷达站目标小YOLO 默认imgsz640时一个 30 像素的装甲板缩到 640 后可能只剩十几像素特征几乎消失。我一般会把输入分辨率提到imgsz1280甚至1536。代价是显存占用翻倍训练速度下降但 mAP 提升明显。如果显存不够可以用imgsz1024折中同时把batch降到 4 或 8。# YOLOv8 训练命令示例 yolo detect train \ datarm_radar_dataset/data.yaml \ modelyolov8s.pt \ imgsz1280 \ epochs200 \ batch8 \ lr00.01 \ lrf0.01 \ mosaic1.0 \ scale0.5 \ degrees10.0 \ projectruns/radar \ nameexp01mosaic1.0开启马赛克增强对小目标检测帮助很大scale0.5允许随机缩放增加尺度多样性degrees10.0做小角度旋转模拟雷达站视角的轻微倾斜。lr00.01是初始学习率lrf0.01是最终学习率系数配合余弦退火。4.2 锚框和损失函数什么时候需要改YOLOv8 默认用无锚框anchor-free方式不需要手动设锚框。但如果你用的是 YOLOv5 或更早版本雷达站小目标需要重新聚类锚框。用kmeans对训练集标注框做聚类把结果写进配置文件。损失函数方面小目标建议关注box_loss和cls_loss的平衡如果分类损失远大于框回归损失说明类别不平衡可以给装甲板类加权。4.3 数据增强哪些增强有用、哪些会帮倒忙雷达站场景下有用的增强包括马赛克mosaic、随机缩放scale、小角度旋转degrees、亮度对比度扰动hsv。要慎用的是大角度旋转超过 30 度、垂直翻转雷达站视角不会倒过来、随机裁剪可能把目标裁掉。我一般把hsv_h0.015、hsv_s0.7、hsv_v0.4作为起点赛场光照变化大的话再往上调。注意增强参数不是越大越好。scale0.9会让目标缩得太小模型学不到有效特征degrees45会产生现实中不存在的姿态反而降低泛化。5. 避坑与排查雷达站数据集训练中最容易翻车的五件事5.1 现象训练 loss 正常下降但验证集 mAP 始终为 0原因通常是标注格式不对。YOLO 要求 txt 里每行是class cx cy w h且坐标归一化到 0~1。如果误用了 VOC 的绝对坐标或者类别索引从 1 开始模型输出和标签对不上mAP 自然为 0。解决方法是随机抽几个 txt 文件用脚本把框画回图片上肉眼检查。5.2 现象模型在验证集上表现好一到雷达站实机就漏检这是典型的域偏移。验证集如果和训练集来自同一段视频分布太接近评估结果偏乐观。解决办法是单独留一段不同时间、不同场地的视频做测试集训练时完全不碰。如果测试集 mAP 比验证集低 20 个点以上说明数据多样性不够需要补采。5.3 现象推理时框抖动严重同一目标相邻帧框大小跳变原因可能是标注框不一致。不同标注员对同一个目标的框选习惯不同有的紧有的松模型学到的边界模糊。解决办法是统一标注规范或者用--rect推理模式减少 padding 带来的尺度变化。另外后处理时加 NMS 的iou_thres调到 0.5~0.6避免重叠框反复横跳。5.4 现象训练到一半显存溢出OOMimgsz1280加batch8在 8G 显存上很容易 OOM。解决方法是开混合精度ampTrue或者用梯度累积nbs64模拟大 batch。如果还不行降到imgsz1024、batch4。不要盲目加显存先把输入分辨率降下来看 mAP 损失多少再决定值不值得升级硬件。5.5 现象数据集里混入了非雷达站视角的图片有人为了省事把步兵视角的数据也扔进训练集结果模型学到的目标尺度分布混乱雷达站小目标检测反而变差。解决办法是严格按视角分数据集步兵数据单独训一个模型雷达站用专属数据。如果非要混合至少保证雷达站数据占比超过 70%。6. 从训练到部署雷达站实机验证与一个提点技巧训练完模型只是第一步雷达站实机部署才是真正的考验。我一般会先在本地用录制的雷达站视频做离线验证确认 mAP 和推理速度达标再上实机。离线验证时重点关注两个指标小目标召回率装甲板类和误检率背景干扰物被误认为目标。召回率低于 0.85 或者误检率高于 5%都不建议直接上机。实机部署时推理框架的选择很关键。如果雷达站用的是 NVIDIA Jetson 系列TensorRT 是首选FP16 量化后速度能提升 2~3 倍精度损失通常在 1 个点以内。如果是 x86 工控机ONNX Runtime 或 OpenVINO 都行。下面是一个 TensorRT 导出的最小命令# 导出 ONNX yolo export modelruns/radar/exp01/weights/best.pt formatonnx opset12 imgsz1280 # 用 trtexec 转 TensorRTJetson 上 trtexec --onnxbest.onnx --saveEnginebest.engine --fp16 --workspace2048opset12兼容性较好--fp16开启半精度--workspace2048给 2G 显存做优化空间。转完后用trtexec --loadEnginebest.engine --shapesimages:1x3x1280x1280跑一下速度确认单帧推理时间在可接受范围内。最后分享一个提点技巧雷达站场景下目标在画面中的位置有规律——装甲板通常出现在场地中央区域边缘区域出现的大多是干扰物。可以在后处理阶段加一个位置先验对画面边缘的检测框降低置信度或者直接过滤。这个操作不需要重新训练只在推理后处理里加几行代码def filter_by_position(boxes, img_w, img_h, margin_ratio0.1): 过滤画面边缘的检测框 margin_ratio: 边缘区域占画面宽高的比例 margin_x img_w * margin_ratio margin_y img_h * margin_ratio keep [] for box in boxes: x1, y1, x2, y2 box[:4] cx (x1 x2) / 2 cy (y1 y2) / 2 if margin_x cx img_w - margin_x and margin_y cy img_h - margin_y: keep.append(box) return keepmargin_ratio0.1表示画面四周 10% 的区域视为边缘。这个值根据实际场地调整如果雷达站视野里目标确实会出现在边缘就调小到 0.05 或者干脆不用。我自己的习惯是先在验证集上跑一遍看边缘区域的误检占比再决定要不要加这个过滤。这套流程走下来从数据集构建到实机部署大概需要两到三周其中标注和清洗占一半时间。别想着跳过数据直接调模型雷达站场景下数据质量比网络结构重要得多。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →