简介机甲大师赛比赛数据集是一份面向赛事视觉任务的数据包适合参赛队伍、机器人开发者及计算机视觉初学者训练目标检测与自瞄识别模型。压缩包共 107.62MB内含 2009 个文件其中 729 张 jpg 图像来自比赛实际场景1264 个 txt 文件提供对应的标注框和类别信息两者结合可用于 YOLO 等主流模型的训练与验证另有 4 个 markdown 文档说明数据组织方式3 个 Python 脚本辅助完成格式转换与数据预览。数据集按不同场景和类别分目录存放结构清楚便于划分训练集、验证集txt 标注文件与 jpg 图像共同构成训练样本稍作整理即可接入常见检测框架。压缩包采用 zip 格式下载解压即可快速使用。目前已有 349 人学习下载能大幅降低自行采集和标注图像的时间成本是备赛调参、算法复现和视觉方案迭代的实用基础资源。1. RoboMaster比赛数据集这个zip里装的不是普通图片RoboMaster比赛数据集这名字听起来挺正式但解压后你会看到一堆.DS_Store和一张000666.jpg甚至还有配套的“比赛项目源码”样式的处理脚本跟我第一次拿到时的反应一样就这其实这份zip的核心不是那些花哨的算法而是从真实比赛场地采集的装甲板图像样本用来训练机器人视觉识别。它主要解决两个问题一是模拟赛场光照、反光、运动模糊下装甲板检测怎么做二是给你一个不需要自己扛相机去场地拍的起点。适合正在捣鼓RoboMaster视觉方案、或者拿无人机/小车做目标检测的新手和进阶玩家。数据量不大但坑不少下面从解包开始一步步说。2. 先摸底解包、统计与看清数据集的真实结构2.1 解压并清理Mac系统垃圾文件拿到zip第一步当然是解压。我习惯在Linux下用命令行避免Windows下内置解压隐藏文件不彻底的问题。RoboMaster数据集经常在macOS上打包里面会混入.DS_Store这类系统文件。虽然它对模型训练没有直接影响但会在文件遍历和生成list时报一堆看不懂的错尤其是当你把数据集给别的同学用他们的环境是Windows或Linux时这种垃圾文件会引发路径和编码问题。先解压再清理。unzip Robomaster比赛数据集.zip -d robomaster_data cd robomaster_data find . -name .DS_Store -type f -delete这里unzip的-d参数指定输出目录避免文件直接洒在根目录。find在目录里递归查找名为.DS_Store的普通文件并删除。RoboMaster这类比赛数据集经常附带一些Mac的隐藏元数据文件比如.开头的AppleDouble文件同样可以用find -name .* -type f -delete清理。清理之后目录干净很多后续用Python遍历时也不会把隐藏文件算进图片数量里。需要注意的是如果你在Windows上右键解压可能看不到.DS_Store因为系统隐藏了以点开头的文件。这时候用git bash或者PowerShell的ls -Force就能看见。我自己经历过一次在Windows上解压跑训练脚本glob出来的图片路径里混进一个“._000666.jpg”OpenCV无法读取程序直接崩溃。所以先删除这些文件能节省后面大量调试时间。2.2 用Python统计图片数量和尺寸分布清理之后我们先把家底摸清楚。RoboMaster数据集的图片可能来自不同相机、不同分辨率有些是1080p截图有些是640x480的旧图。写一个快速统计脚本知道图片总数和尺寸范围才能决定训练时输入分辨率设多少。import cv2 import glob paths glob.glob(robomaster_data/**/*.jpg, recursiveTrue) print(f图片总数: {len(paths)}) widths, heights [], [] bad [] for p in paths: img cv2.imread(p) if img is None: bad.append(p) continue h, w img.shape[:2] widths.append(w) heights.append(h) print(f宽度范围: {min(widths)}~{max(widths)}) print(f高度范围: {min(heights)}~{max(heights)}) print(f平均宽度: {sum(widths)/len(widths):.1f}) print(f损坏图片: {len(bad)}) if bad: print(bad[:10])代码里glob用recursiveTrue会递归子目录找出所有jpg。如果图片很大且数量多也可以用os.walk避免一次性把路径全放内存但一般数据集几百张glob够用。cv2.imread读不出来会返回None我们把这些文件放进bad列表。统计尺寸时用img.shapeOpenCV返回的是(height, width, channels)所以h在w前面。得到尺寸分布后如果大多数图是1280x720那训练时用640或者800就够如果出现了4K截图那说明数据集里混入了渲染图需要单独处理。顺便说一下我还会检查通道范围。所有图的通道数都要是3如果是灰度图后续训练会输入通道不匹配框架报错。判断方式很简单img.shape[2]不等于3就进bad。RoboMaster的官方渲染图最常出现这类问题一张png转jpg后显示“RGB”实际读出来是灰度。2.3 用亮度分布评估拍摄条件RoboMaster场地里光照变化大尤其是室外场地的阳光直射和室内场地的灯光频闪。在标注之前有必要先看一眼亮度分布因为亮度太低或过曝的图片会影响标注准确度。注意我们做的是数据摸底不是数据增强这一步只是决定哪些图片要人工重点关注。import numpy as np import cv2 gray_values [] for p in paths[:500]: img cv2.imread(p) if img is None: continue gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray_values.append(gray.mean()) gray_values np.array(gray_values) print(fmean brightness: {gray_values.mean():.1f}) print(flow 50: {(gray_values 50).sum()}) print(fhigh 200: {(gray_values 200).sum()})这里用cvtColor把BGR转成灰度然后取整张图的平均值。阈值50和200是经验值你完全可以按自己的场景调整。如果低亮度图片比例超过10%说明数据集里有很多昏暗场景标注时要小心低对比度边缘如果高亮度图片多说明反光严重装甲板的灯条可能已经过曝成白色框的边缘会虚。遇到这种情况我一般会在后面训练时增加亮度增强同时把过曝严重的图拿出来重新标注。为什么只看前500张因为循环遍历所有图片会拖慢而且亮度分布不会因为后面几十张改变太多。快速摸个底就行。2.4 决定目录结构images和labels分开RoboMaster数据集的图片如果只有jpg那我们需要为后续标注、训练铺好目录。最稳定的是把图片和标注分开避免训练框架在一个目录里同时扫描图片和txt产生冲突。下面是我惯用的结构。robomaster_data/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── classes.txt在动手标注前先建好这些空目录。有的同学把图片和标注放同一个文件夹靠后缀区分用YOLO训练时虽然能跑但做数据增强或格式转换时会遇到很多“找到了jpg但没有对应txt”的麻烦。我一般建议把images和labels完全分开后面写自定义Dataset时也更清晰。classes.txt里每行写一个类别名比如armor、light、base或outpost顺序就是类别ID后续标注和训练都用这个文件千万别中途改顺序。这套结构不是我自己拍脑袋定的而是对接YOLOv8 data.yaml时它默认就认这个路径。dataset.yaml里写train: images/trainval: images/val它会自动去labels目录找同名txt。如果你非要把图片和标注放一起也不是不行但要重新定义datasets的loader反而更麻烦。新手期我踩过一次后来就老实分开了。3. 标注与格式转换从jpg到可训练数据3.1 手工标注装甲板先定边界再动鼠标这份zip如果只包含jpg那就需要自己标注。RoboMaster视觉任务里核心目标一般是装甲板armor也就是机器人正面那块贴着数字的矩形灯条区域。如果检测灯条可以分别标灯条如果检测数字就标数字但装甲板通常用一个矩形框住整个目标。标注原则是框的边界要紧贴灯条外侧不要包含周围背景太多也不要把数字切掉一半。我使用LabelImg因为它轻量且能直接输出VOC格式XML。打开一张1280x720的图框选时尽量放大图片保证框线贴合。如果目标很小宁可多标几次也不要让框只有巴掌大。RoboMaster图像里装甲板一般占画面的百分之几手工标注一帧需要大约10秒一个300张的小数据集半天能标完。如果你有连续视频帧相邻帧的目标位置变化不大可以先用上一帧的框初始化再微调速度会快很多。这里有个容易犯的错把装甲板和能量机关的“风车叶片”混在一起。前者是矩形后者是旋转的扇形在静态图片里看起来像矩形的一部分。标注时要按照任务定义来如果模型只需要识别装甲板那能量机关区域就不要标否则类别边界混淆训练时loss很难下降。我一般会先和拿数据集的同学确认任务边界避免返工。3.2 VOC转YOLO脚本里加防呆检查手工标注完成后一般会得到一批XML。YOLO系列框架需要txt格式我们得写个转换脚本。前面已经给过一段基本代码但这里我再强调几个细节。import os import xml.etree.ElementTree as ET classes [armor, light] def voc_to_yolo(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) with open(out_path, w) as f: for obj in root.iter(object): name obj.find(name).text if name not in classes: continue cls_id classes.index(name) box obj.find(bndbox) xmin int(float(box.find(xmin).text)) ymin int(float(box.find(ymin).text)) xmax int(float(box.find(xmax).text)) ymax int(float(box.find(ymax).text)) # 计算YOLO格式的归一化中心点和宽高 xc (xmin xmax) / 2 / width yc (ymin ymax) / 2 / height bw (xmax - xmin) / width bh (ymax - ymin) / height if xc 0 or xc 1 or yc 0 or yc 1 or bw 0 or bh 0: print(f异常框: {xml_path}, {name}, {xmin},{ymin},{xmax},{ymax}) continue f.write(f{cls_id} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}\n)转换后的txt需要和图片同名例如000666.jpg对应的txt就叫000666.txt。实际运行前我习惯把classes列表用一个独立classes.txt读进来免得写死在脚本里后面加类别时还要改脚本。脚本里的异常检查很重要归一化坐标如果越界说明原始坐标超出了图片尺寸这种框训练时会被忽略但不会报错导致模型莫名其妙漏检。打印出来能提醒你回去修复XML。另外代码里有注释的那一行是关键公式中心点坐标用(xminxmax)/2再除以宽度宽高用差值和原图尺寸做除法顺序不能乱。3.3 可视化检查不叠框的标注都是耍流氓转换完成后一定不要立刻开训练。先随机抽几十张图用脚本画框眼睛扫一遍。import cv2 import numpy as np def draw_boxes(img_path, txt_path, classes): img cv2.imread(img_path) h, w img.shape[:2] with open(txt_path) as f: lines f.readlines() for line in lines: parts line.strip().split() if len(parts) 5: continue cls_id int(parts[0]) xc, yc, bw, bh map(float, parts[1:5]) x1 int((xc - bw/2) * w) y1 int((yc - bh/2) * h) x2 int((xc bw/2) * w) y2 int((yc bh/2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, classes[cls_id], (x1, max(0, y1-8)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2) return img常见异常有框的左上角比右下角大说明坐标公式用反了框没有贴住目标说明标注时状态不对框的类别明显错误比如把灯条标成了装甲板。可视化检查是性价比最高的步骤花了二十分钟但能省出后面几小时的排错时间。我见过有人跳过检查直接训练跑了一个晚上最后发现txt里标注坐标全是1mAP为零后悔药都没得吃。画框时注意x1、y1可能为负数的情况代码里用max(0, y1-8)防止文字超出图片。3.4 数据增强针对RoboMaster光照和模糊数据集小往往只有几百张图直接训练容易过拟合。RoboMaster场景里模型最常见的干扰是光照突变、运动模糊和镜头失焦所以增强也要往这几个方向打。我一般用albumentations库它比直接调OpenCV方便而且能和PyTorch配合。import albumentations as A transform A.Compose([ A.RandomBrightnessContrast(brightness_limit0.3, contrast_limit0.3, p0.8), A.MotionBlur(blur_limit7, p0.3), A.GaussianBlur(blur_limit(3, 5), p0.2), A.HueSaturationValue(hue_shift_limit10, sat_shift_limit20, val_shift_limit20, p0.5), A.RandomResizedCrop(size(640, 640), scale(0.5, 1.0), ratio(0.8, 1.2), p0.5), ])这里RandomBrightnessContrast模拟场地里不同朝向的灯光变化MotionBlur模拟机器人移动时图像拖影GaussianBlur模拟镜头失焦HueSaturationValue模拟灯条颜色偏差RandomResizedCrop能自动放大缩小目标。注意数据增强要作用在图像和标注框上albumentations的Compose如果传了bbox_params它会自动同步变换框。如果你手写增强千万别只处理图像忘记框的新位置。RoboMaster比赛里装甲板尺寸小RandomResizedCrop配合p0.5能变相生成多尺度的目标有助于小目标检测。3.5 验证增强后的标注是否仍然对齐增强不是点完就完我一般会抽一组增强后的图片和标注可视化一下。albumentations的ReplayCompose可以保存变换参数方便调试。如果发现增强后框和灯条错位多半是你没指定bbox_params。transform A.Compose([ A.RandomBrightnessContrast(brightness_limit0.3, p0.8), A.MotionBlur(blur_limit7, p0.3), ], bbox_paramsA.BboxParams(formatyolo, label_fields[class_labels]))BboxParams里formatyolo是为了告诉库给定的标注是归一化的中心点宽高格式label_fields[class_labels]是要确保category id跟着框一起走。如果不设置这两个参数库会把框当成普通数组增强后框就飘了。很多同学在这里翻车增强后mAP反而更低其实就是框没对齐。所以增强之后至少要跑一次可视化检查确认增强前后框的位置和大小与目标一致。4. 训练前处理与参数设置消失的Loss和飘忽的mAP4.1 划分训练集/验证集别让连续帧串门RoboMaster比赛数据集通常由一段一段的视频抽帧得到相邻帧之间背景和装甲板位置都高度相似。如果直接把所有图片随机分成train和val那么同一段视频的画面会同时出现在训练集和验证集里。模型在训练时见过这个背景和灯条位置验证时几乎是在开卷考试mAP会虚高好几个点。等到了真实赛场光照和视角变化一大模型立刻露馅。所以划分必须考虑时间连续性。import os from pathlib import Path base Path(robomaster_data/images) train_dir base / train val_dir base / val train_dir.mkdir(parentsTrue, exist_okTrue) val_dir.mkdir(parentsTrue, exist_okTrue) files sorted([p for p in base.glob(*.jpg)]) cut int(len(files) * 0.8) for i, p in enumerate(files): if i cut: p.rename(train_dir / p.name) else: p.rename(val_dir / p.name)这里按文件名排序后前80%放进train后20%放进val。如果文件名是连续编号比如从000001到001000这个方案就能顺理成章切断连续帧。如果文件名带有拍摄时间戳或视频片段号还可以先按片段分组把整个片段的图片分到同一边。更严谨的做法是用视频ID构建一个分组列表用stratified split保证不同场地的图片都被分到两边但RoboMaster数据集一般没有那么多场地顺序切分就够了。许多YOLO框架的data.yaml里可以设置train和val路径但框架内部不一定帮你切断连续帧所以要在数据准备阶段就划分好不要依赖训练框架的随机划分。4.2 训练命令与关键参数从nano起步我用YOLOv8或YOLOv9比较多RoboMaster数据集不大用nano或small版本就够了不需要large。模型太大在嵌入式设备上跑不起来反而影响部署。这里以YOLOv8为例yolo train datadataset.yaml modelyolov8n.pt epochs200 imgsz640 batch16 lr00.01 patience20dataset.yaml至少要包含三部分路径、类别数、类别名。一个可用的配置如下path: ./robomaster_data train: images/train val: images/val nc: 1 names: [armor]如果你标了灯条nc就改成2names就改成[armor,light]。imgsz640意味着训练时把原始图像随机缩放到640x640RoboMaster的图片大多是1280x720缩放后小目标信息有损失。如果装甲板在图中本来就小于40x40像素建议imgsz改成960或1024。显存不够就把batch从16降到8否则OOM跑不起来。lr00.01是初始学习率用Adam时习惯设0.001用SGD时0.01很常见。这里实际流行的是YOLOv8默认优化器建议保持默认只调lr0和imgsz。epochs设成200但不用真的训满。patience20表示如果验证集指标连续20轮不提升就早停能省时间。RoboMaster数据集图片数量少可能跑到第100轮就开始过拟合早停比守着固定epoch更实用。4.3 观察训练日志loss不是越低越好训练时你会看到类似这样的一行输出Epoch 48: train_loss0.532, val_loss0.611, mAP500.871, mAP50-950.623我简要解释下这些值。train_loss是训练集上的总lossval_loss是验证集上的mAP50是在IoU阈值0.5下所有类别的平均精度mAP50-95是IoU从0.5到0.95每0.05算一次然后取平均。RoboMaster装甲板检测mAP50到了0.85以上基本能用mAP50-95到了0.6说明框位置比较准。如果你看到训练loss不断下降但val_loss在某个epoch后开始上升说明过拟合了这时应该有早停机制截断。如果你看到mAP50一直在0.3以下先不要调超参数回去检查标注和划分是不是正确。为了记录曲线可以用ultralytics自带的日志也可以直接用TensorBoardtensorboard --logdir runs/detect在浏览器里看到loss和mAP曲线比看终端舒服得多。关键不是追求loss越低越好而是保持train_loss和val_loss差距不过大。如果差距超过0.3说明模型在背训练集而不是学泛化特征。RoboMaster场景下图像背景简单增强不够时最容易过拟合这时应该增加增强强度而不是增加模型复杂度。另外RoboMaster图像中装甲板通常只占整个图像很小的区域默认的类别权重会让模型更关注背景。可以在训练后检查每个类别的AP如果armor类别的recall低但precision高说明模型比较保守可以降低置信度阈值反过来降低NMS阈值。4.4 导出模型并检查部署尺寸训练完best.pt还只是一个PyTorch权重文件上场比赛一般要导出成ONNX或者TensorRT引擎加速推理。YOLOv8导出很方便yolo export modelruns/detect/train/weights/best.pt formatonnx opset12 imgsz640导出后我习惯再跑一次onnxruntime推理确认和pt的结果一致。如果发现导出后精度掉了几个点常见原因是opset版本太高或动态维度设置不对。RoboMaster比赛用的一些开发板对TensorRT的FP16支持更好但我个人建议先验证FP32再试FP16。因为他在比赛现场最怕的不是速度慢而是检测漂移FP16在某些显卡上会让小目标漏检率升高。导出这一步虽然不算训练但提前做好能省去比赛前夜手忙脚乱。导出时还要注意输入张量的动态尺寸如果你的imgsz是640那导出的模型就固定接收640x640输入推理时不能随意改成其他尺寸需要重新导出。5. 避坑指南RoboMaster数据集最常见的五个坑5.1 解压后的图片没法读取训练直接中断现象训练跑到一半报错“could not read image”或者脚本训练前检查图片时发现找不到某些路径。原因这个zip是在macOS上打包的里面带了.DS_Store、._开头的AppleDouble文件还有个别jpg文件头损坏。尤其是._开头的文件会被glob当成图片但OpenCV读到的是无效数据。虽然我们第一轮清理了.DS_Store但._文件不一定被删除而且因为文件名带后缀有些同学直接用endswith(.jpg)没排除就命中了。解决写一个健壮的图片清洁脚本把cv2.imread返回None的文件直接删除或移到bad目录同时清理所有隐藏文件。我在2.2节的代码里已经加了None检测但要养成习惯对于每个新数据集第一步先跑一遍这个脚本不要嫌麻烦。还有遍历图片时用glob的recursiveTrue可能会把随zip附带的缩略图目录也扫进来所以最好明确路径结构只扫描images目录。5.2 训练loss降了验证mAP却飘忽不定现象epoch 10时mAP50是0.75epoch 20变成0.6epoch 30又回到0.75曲线一直上下抖动没有稳定上升的迹象。原因除了连续帧划分问题外还有一个常见原因是验证集太小。RoboMaster数据集如果只有200张图按20%划分只有40张验证图每个epoch统计mAP时随机性很大个别难样本会引起大幅波动。这跟模型本身关系不大。解决增加验证集数量至少留100张。如果总共就200张图那可以用K折交叉验证或者把验证集固定住避免每次跑结果差异大。另外训练时设置seed0可复现否则每次随机初始化导致结果不同。我一般会在训练命令里加seed0并固定数据加载器的shuffle随机种子。这样跑实验才有可比性。不要因为一两次抖动就急着改模型结构先排查数据分割和随机种子。5.3 可视化时发现标注框整体偏左上现象用叠框脚本看图片装甲板明明在图像中央画出来的框却跑到左上角而且框的宽高比不对。原因VOC转YOLO时使用了错误的宽度和高度。有的XML里size节点虽然写着1280x720但代码读的是字符串没有转int计算结果全部变成无权重的浮点数其实更常见的是把VOC的xmin和ymin当成中心点直接归一化公式错了。另外某些标注工具输出的坐标是相对于标注类别而不是原图也会导致整体偏移。解决回到转换脚本逐一检查坐标换算。最简单的方法是用一张你手工核实过的图在excel里算一遍归一化值再比对脚本输出。我习惯在每个转换脚本里写一个assert检查所有归一化坐标都在(0,1)区间任何越界立刻报错。这样能快速暴露公式错误而不是等到训练完才发现。注意检查脚本里是否先取了size节点再参与运算如果size节点没找到说明XML版本是旧格式需要用另一个自定义解析。5.4 小装甲板目标长时间检测不到现象模型能稳定识别距离近的大装甲板但图像远端的小装甲板几乎全部漏检召回率很低。原因小目标在缩放后信息丢失严重。imgsz640时原始图中30x30的装甲板变成大约15x15像素特征几乎被背景淹没。另外RoboMaster图像中目标数量少每张图只有一两个框默认的anchor配置可能不适合这种尺度分布。解决提高输入分辨率比如imgsz960或1280增加Mosaic增强让目标在拼接图里呈现更多尺度如果可能使用支持上下文聚合的模型结构比如增加P2层或使用CSP扩展。你也可以尝试把图像切片把大图切块后每个小块作为一个输入缺点是推理翻倍。我自己的做法是先统计小目标占比如果小目标比例超过20%就会专门跑一组高分辨率训练实验对比mAP变化。还要注意增强时不要过度缩放否则小目标会被裁剪掉。5.5 训练一开始loss就是NaN现象第一个epoch输出log里loss显示NaN或者验证时mAP直接为0。原因标注文件里有非法值比如class id比classes列表长度大归一化坐标里有负数或者宽高是0。YOLO框架在计算损失时会对这些非法坐标做log运算一旦遇到0会产生无穷大显示NaN。有时也可能因为学习率太高导致梯度爆炸但更大概率是数据问题。解决训练前写一个独立的“数据规范检查”脚本。遍历所有txt检查每一行的class id是否在0到nc-1之间检查xc,yc是否在0到1之间检查bw,bh是否大于0且小于等于1不合格的直接打印文件名和行号。这个脚本跑一次只要几秒但能避免花一晚上等待训练崩掉。我还会把检查脚本和convert脚本放在同一个目录每次生成新数据集都先执行已经养成了肌肉记忆。如果检查完数据没问题再考虑降低学习率重试。6. 进阶验证模型可迁移性的三个小方法6.1 用真实场地图像做回环测试训练完模型最怕的就是换一个场地、换一种光照就失效。我的习惯是刻意留出20张跟训练集完全不同场景的图片比如白天室外、傍晚室内、加了逆光的照片单独写一个回环测试脚本把推理结果打印出来看类别和置信度。不要用验证集因为验证集已经参与选模型了只能证明拟合不能证明泛化。RoboMaster场地反光严重置信度低于0.5的框我会直接丢弃因为在实战里低置信度往往就是误判。6.2 用视频帧连续测试抑制抖动单帧准确不代表视频流稳定。RoboMaster视觉要处理的是连续图像模型在某一帧丢失目标很正常但它在紧邻的几帧里来回跳动就说明不稳定。我一般把测试视频的连续帧按5帧一组跑一遍如果同一个目标在5帧里至少4帧出现就认为目标稳定反之低于3帧的就当作漏检。代码不复杂就是累积历史框做一个简单的IoU匹配。prev_boxes [] for frame_id, frame in enumerate(video): boxes model.predict(frame, conf0.5) stable_count 0 for box in boxes: for prev in prev_boxes: if iou(box[:4], prev[:4]) 0.5: stable_count 1 print(fframe {frame_id}: stable{stable_count}/{len(boxes)}) prev_boxes [box[:4] for box in boxes]这里的思考方式很关键模型参数重要但在比赛里真正区分胜败的是帧间稳定性。我在一次测试中发现模型单帧mAP很高但视频抖动严重后来降低了置信度阈值并提高NMS阈值才压住。这类问题在单张图上完全看不出来必须用视频流模拟场地真实输入。6.3 备份数据集版本与训练配置最后一件小事每次训练前把数据集版本、标注文件、data.yaml、训练命令都记录在一个markdown文件里。别嫌麻烦因为RoboMaster数据集的图片会不断更新今天加了20张新图明天改了classes顺序没有备份你根本不知道最佳模型是用哪个版本训练的也只能一遍遍重训相当痛苦。从那以后我每次都会用git管理整个数据集目录哪怕只更新一张jpg也会提交一次。希望帮到你。本文还有配套的精品资源点击获取