
简介一套面向计算机视觉、智能交通与自动驾驶感知领域开发者和研究者的道路圆石墩检测数据集主要解决道路圆石墩目标检测任务中训练样本不足、数据标注成本高的问题。压缩包共一千三百八十八个文件包含四百六十二张JPG原图、四百六十二个VOC格式的XML标注文件以及四百六十四个YOLO格式的TXT标注文件整体体积约二百一十五点七三MB。图片合计标注了一千七百九十八个球形路障目标框全部使用labelImg绘制矩形框完成标注标注信息准确合理可直接用于YOLO、Faster R-CNN等常见目标检测模型的训练与评估。同时提供VOC与YOLO两种常用格式省去转换成本便于在不同算法框架间迁移试用。目前共有一百三十六人浏览学习适合作为道路障碍物识别、模型效果验证与算法比对的实用基准数据。1. 道路圆石墩检测数据集461 张图、VOCYOLO 双格式目标检测的第一份燃料道路巡检视频里最容易漏看也最需要盯住的小目标就是圆石墩它立在机非隔离带端头、人行道入口和桥墩四周被车辆剐蹭移位后隐患很大人工回放几十路监控成本实在太高通常交给目标检测模型先筛一遍。标题里的「道路圆石墩检测数据集」就是这份差事的第一份燃料461 张现场图、单一类别同时打包了 VOC 的 XML 标注和 YOLO 的 TXT 标注压缩在 7z 包里。VOC YOLO 双格式的意义在于省掉最脏的格式转换可视化检查时读 XML训练时读 TXT两边还能互相校验。461 张属于典型小样本但足够跑通「解压体检 → 格式校验 → 参数训练 → 增强验证」全流程。下文按这个顺序展开适合道路养护方向的算法工程师、拿真实场景数据练手的入门开发者以及要快速验证单类检测器的测试人员。2. 拿到 .7z 后的第一件事Linux 下解压、数据体检与标注完整性检查2.1 为什么数据集分发偏爱 7z 压缩目标检测数据集里 JPEG 图像占比极高冗余度大7z 的 LZMA2 算法在这类数据上通常比 zip 再小 30% 到 50%。所以公开下载的数据集、团队内部流转的标注包越来越多直接以 .7z 分发「linux解压7z文件」成了训练前置的固定环节。解压和训练基本都在 Linux 服务器上完成第一步是确认 p7zip 工具链存在很多精简安装的服务器默认没有这个命令。# Debian/Ubuntu 系安装 sudo apt install p7zip-full # CentOS/RHEL 系安装 sudo yum install p7zip # 只列出压缩包内部结构不实际解压 7z l 道路圆石墩检测数据集VOCYOLO格式461张1类别.7z7z l这一步值得养成习惯。它能在不落盘的情况下看到包内目录层级确认有没有顶层文件夹、图片和标注怎么分放避免解压后才发觉文件散落各处。正式解压用7z x它会保留包内目录结构是数据集场景下最安全的选择。7z x 道路圆石墩检测数据集VOCYOLO格式461张1类别.7z -o./road_bollard参数说明-o指定输出目录注意-o与路径之间没有空格这是 7z 命令里最容易写错的地方不加-o就解压到当前目录。命令里的中文文件名最好用引号包起来避免 shell 对空格或特殊字符的额外解释。解压后先看顶层布局常见的有两种一是 images/ 与 annotations/ 平级annotations 下再分 VOC 与 YOLO 两个子目录二是 XML 与 TXT 各一个目录并列。先看清楚再写脚本比拿到哪份样例就照抄路径要省心。提示7z 报「cannot find archive」时先怀疑下载完整性。用sha256sum 文件名.7z和发布方给出的校验值对比比对不上就重新下载不要反复解压浪费时间。2.2 数据体检图像、XML、TXT 数量与解码验证解压完直接开训是常见的翻车姿势。单类小数据集最怕三类问题图片解码失败、标注文件缺失、类别名跟预期不一致。461 张的体量没必要靠人眼抽查脚本几十毫秒就能把所有文件过一遍。# 数量对齐检查三个数字都应等于 461 find images -type f -name *.jpg | wc -l find VOC -type f -name *.xml | wc -l find YOLO -type f -name *.txt | wc -l三个数字一致只说明文件层面一一对应还要确认图片能真正被解码。这点容易被忽略部分从爬虫或批量转换流程里出来的 JPEG系统预览能显示但 cv2.imread 会返回 None训练时轻则丢样本重则 loss 在某一步跳变排查成本很高。import cv2, glob bad [] for p in glob.glob(images/*.jpg): img cv2.imread(p) if img is None: bad.append(p) print(不可解码图片数量:, len(bad)) for p in bad: print(p)这段逻辑很直白逐个路径用 cv2.imread 读图返回 None 就记录路径。跑完后最好顺手统计图像宽高分布道路圆石墩数据经常混了不同摄像头的画面1920x1080 与 1280x720 并存很常见。知道尺寸分布再决定训练时的 imgsz比盲目套 640 更合理。2.3 按 YOLO 生态标准整理目录并划分训练验证集体检通过后把数据整理成 yolov8、yolov5 通用读取的目录结构train 和 val 两个集合各自包含 images 和 labels 子目录。这个动作对应「yolov8训练自己的数据集」和「yolo目标检测流程」的公共前提。划分比例常见做法是 8:2固定随机种子保证可复现。import glob, os, shutil from sklearn.model_selection import train_test_split imgs sorted(glob.glob(images/*.jpg)) train_imgs, val_imgs train_test_split( imgs, test_size0.2, random_state42) def organize(img, split): stem os.path.basename(img)[:-4] dst_img fdataset/{split}/images/{stem}.jpg dst_txt fdataset/{split}/labels/{stem}.txt os.makedirs(os.path.dirname(dst_img), exist_okTrue) shutil.copy(img, dst_img) shutil.copy(fYOLO/{stem}.txt, dst_txt) for img in train_imgs: organize(img, train) for img in val_imgs: organize(img, val) print(train 图片数:, len(train_imgs)) print(val 图片数:, len(val_imgs))train_test_split 默认按 8:2 切分random_state 固定为 42 保证多次运行结果一致对复现实验、对比消融结果很重要。这里用 shutil.copy 而不是符号链接因为数据量小复制不占空间而且训练阶段的任何意外都不会改到原始文件。划分完 train 应为 369 张、val 为 92 张对不上就回头看文件命名是否带中文或空格这类文件名在部分框架里兼容性差建议统一重命名为 seq_0001.jpg 这种纯 ASCII 格式。3. VOC 与 YOLO 双格式的坐标换算逻辑与一致性校验3.1 VOC 的 XML 里存的是像素坐标VOC 格式的标注是一个 XML 文件文件与图片同名扩展名 .xml。根节点是 annotation核心信息在 size 和 object 两个子节点里。size 记录图片宽度、高度和通道数object 描述目标类别和位置bndbox 里的 xmin、ymin、xmax、ymax 是像素级绝对坐标。圆石墩数据集只有一类object 通常只有一个但少数图里一个画面出现多个石墩时object 节点会重复出现。annotation size width1920/width height1080/height depth3/depth /size object nameround_pier/name bndbox xmin412/xmin ymin356/ymin xmax518/xmax ymax489/ymax /bndbox /object /annotation这里 name 就是类别名单类数据集通常叫 round_pier 或 bollard训练前要跟 data.yaml 里的 names 对齐。bndbox 四个值是整数像素坐标左上角 (412, 356)右下角 (518, 489)框宽 106、高 133这些数值严格依赖图片本身的宽高换一张尺寸的图就失效。VOC 格式的可读性好LabelImg 标注后默认输出这种结构很多可视化调试工具直接解析 XML这也是它到现在仍是数据集交付标配的原因。3.2 YOLO 的 TXT 里存的是归一化坐标YOLO 的 txt 每行一个目标格式固定为 class_id center_x center_y width height。后四个值都是相对于图片宽高的比例范围 0 到 1。同一个框在 YOLO 格式里写成一行0 0.242187 0.391204 0.055208 0.123148对照上面的 XML中心点 x (412518)/2/1920 0.242187中心点 y (356489)/2/1080 0.391204框宽 (518-412)/1920 0.055208框高 (489-356)/1080 0.123148。一个容易忽略的细节是 YOLO 的 txt 里不携带图片尺寸信息单独看一个 txt 文件无法还原像素坐标这正是双格式并存的实际价值XML 保留绝对几何TXT 方便训练时快速读取。3.3 双格式换算公式与一致性校验脚本两套格式的换算公式很固定。设图片宽为 W、高为 H则中心点 x 为 (xmin xmax) / 2 / W中心点 y 为 (ymin ymax) / 2 / H框宽为 (xmax - xmin) / W框高为 (ymax - ymin) / H。反向换算把比例乘回去再取整即可。训练前做一次双向一致性校验成本很低却能拦住数据发布或拷贝阶段引入的错误比如归一化时漏除以图宽、类别 id 从 1 开始而不是 0。两套格式的差异可以归纳成一张表对比项VOC / XMLYOLO / TXT坐标基准像素绝对值归一化比例数值类型整数浮点0~1图片尺寸信息size 节点自带不携带单目标存储XML 多行标签一行 5 个数字解析方式ElementTree / lxml按空格 split校验脚本以 VOC 作为基准逐图读取 XML 的 bndbox换算成 YOLO 坐标后与 txt 里的值逐项对比import glob, os, xml.etree.ElementTree as ET def voc_to_yolo(xml_path): root ET.parse(xml_path).getroot() W int(root.find(size/width).text) H int(root.find(size/height).text) boxes [] for obj in root.findall(object): bb obj.find(bndbox) xmin float(bb.find(xmin).text) ymin float(bb.find(ymin).text) xmax float(bb.find(xmax).text) ymax float(bb.find(ymax).text) boxes.append(((xmin xmax) / 2 / W, (ymin ymax) / 2 / H, (xmax - xmin) / W, (ymax - ymin) / H)) return boxes for xml_path in sorted(glob.glob(VOC/*.xml)): stem os.path.splitext(os.path.basename(xml_path))[0] txt_path fYOLO/{stem}.txt if not os.path.exists(txt_path): print(缺失对应 txt:, stem) continue voc_boxes voc_to_yolo(xml_path) txt_lines [] with open(txt_path) as f: for line in f: txt_lines.append(list(map(float, line.strip().split()))) if len(voc_boxes) ! len(txt_lines): print(目标数量不一致:, stem) continue for vb, tb in zip(voc_boxes, txt_lines): err max(abs(a - b) for a, b in zip(vb, tb[1:])) if err 1e-3: print(f坐标偏差过大: {stem}, err{err:.5f})这段脚本输出三类异常缺 txt、目标数量不一致、坐标偏差过大。findall(object) 用循环处理同图多目标比只取第一个更可靠。tb[1:] 跳过类别 id只比较四个坐标值。误差阈值我一般取 1e-3浮点计算本身有微小舍入差超过这个量级基本就是有人手工改过标注。461 对文件对完如果没有任何输出说明两套格式可信可以进训练环节。4. 用 YOLO 数据训练圆石墩检测器data.yaml、训练命令与参数边界4.1 data.yaml 的写法与类别对齐YOLO 生态统一通过 data.yaml 描述数据集路径和类别定义。高频踩坑点是配置文件里的 names 顺序必须和 txt 里的 class_id 一一对应。单类数据集 class_id 只有 0names 列表只放一个元素。# data.yaml path: /data/road_bollard/dataset train: train/images val: val/images nc: 1 names: [round_pier]path 是数据集根目录的绝对路径train 和 val 写相对于 path 的子路径这是 ultralytics 的推荐写法绝对路径可以避免切换工作目录后找不到数据。nc 为类别数单类就写 1。names 只在可视化推理和导出时影响显示名不参与 loss 计算但如果 txt 里的 class_id 写成 1 而这里只声明了 1 个类别训练时索引越界直接报错所以核对 txt 第一列的实际取值也是体检的一部分。注意报「No labels found in ...」时先检查 data.yaml 的 path 是不是绝对路径其次检查 labels 子目录是否存在最后检查 txt 里是不是有空文件。空文件会让训练器认为这张图没有标注静默跳过该样本。4.2 最小训练命令与直观解释目录整理好、data.yaml 写好之后训练命令短到可以一行完成。常见选择是 yolov8 系列生态和文档最成熟社区里问「yolo第几代了」时大多数回答仍然建议至少先跑通 v8 再谈新版本因为标注格式、配置方式在 v8、v11 以及更新版本之间是兼容的这套 TXT 可以直接喂进去。yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs100 imgsz640 batch16 \ namebollard_run1逐项说明modelyolov8n.pt使用 nano 尺寸预训练权重461 张小数据集从 nano 起步最划算显存占用低且收敛快imgsz640是训练分辨率如果你的图片主要是 1920x1080可以提到 800 或 832 换取小目标召回但训练时间会同步上升batch16在 12GB 显存上比较稳显存紧张就降到 8。习惯用 yolov5 的话命令换成python train.py --data data.yaml --weights yolov5nu.pt --img 640 --batch 16 --epochs 100即可TXT 标注完全通用。4.3 关键参数表与调整边界小样本数据集的参数调节优先级和 COCO 大模型不一样epochs、patience、imgsz 这三个最值得花时间其余保持默认即可。常用参数边界整理成一张表参数建议值边界与说明epochs100~200461 张单类100 轮已能观察趋势超过 200 轮收益递减patience30验证集指标连续 30 轮不提升则早停防止过拟合imgsz640 / 832必须能被 32 整除这是多数 YOLO 版本的下采样硬约束batch8 / 16显存不足报 CUDA OOM 时优先降 batch不要先降 imgszlr00.01预训练随机初始化从头训练要降到 0.001否则前几轮 loss 爆炸cacheTrue461 张图整体缓存进内存首轮训练速度提升明显逐条解释边界epochs 对单类小数据很容易在 60 轮左右进入平台期设太高浪费算力patience 就是用来兜底的imgsz 与原始图宽高比例差异太大会导致拉伸变形选值前先看 2.2 节统计的尺寸分布batch 和显存的关系最直接OOM 报错会指明哪一层分配失败此时直接减 batch 不要犹豫lr0 是很多人忽视的一项用预训练权重沿用 0.01 没问题换成随机初始化还不降学习率第一轮 loss 可能直接变成 NaN。4.4 训练过程中看什么损失函数的下落曲线训练时终端每轮会打印 box_loss、cls_loss、dfl_loss 三个损失值。对单类检测器cls_loss 会很快降到很低因为分类任务只有一正一负真正要盯的是 box_loss 和 dfl_loss它们反映框回归质量。判断依据有三条三者整体下降并在 patience 窗口内波动说明模型在学习box_loss 下降但验证指标不动说明过拟合早于收敛优先增强数据而不是加 epochloss 出现突然尖峰先回看是不是混入了解码失败的坏图而不是急着调学习率。# 训练结束后查看指标记录文件 ls runs/detect/bollard_run1/ head -3 runs/detect/bollard_run1/results.csvresults.csv 里记录了每轮的三种 loss、precision、recall、mAP50 和 mAP50-95用 pandas 读出来画两条曲线能直观看到收敛节点和过拟合起点。对 461 张的小数据集mAP50 达到 0.9 以上是正常水平mAP50-95 更多反映标注框质量不必追求极致。5. 461 张图不够用时的增强边界与漏检定位5.1 在线增强参数怎么给小样本场景下ultralytics 的在线增强默认开启但默认参数是为 COCO 这种大而全的数据设计的对道路圆石墩要主动收敛。圆石墩是立在地面的物体不会倒置flipud 必须关掉水平翻转 flip 保持 0.5。光照才是这条数据的主要变化维度把 hsv_h 提到 0.02、hsv_s 提到 0.7模拟早晚和阴晴的变化。yolo detect train \ datadata.yaml modelyolov8n.pt \ epochs100 imgsz640 batch16 \ flipud0.0 hsv_h0.02 hsv_s0.7 \ scale0.3 translate0.1scale 给到 0.3 用来模拟不同拍摄距离下石墩的大小变化translate 0.1 模拟目标出现在画面边缘的情况。mosaic 保持默认开启对小数据集帮助很大它把四张图拼成一张相当于变相扩充了上下文多样性也能缓解单类目标分布单一的问题。5.2 用混淆矩阵定位漏检而不是只看 mAP单类检测最容易出现的情况是 mAP50 很高但现场跑起来偏偏漏掉远处的小石墩。要定位这类问题训练结束后看运行目录下的 confusion_matrix.png 和 PR 曲线。混淆矩阵里重点关注 background 列如果石墩被预测成背景的比例明显偏高说明置信度阈值设置不合理或者远距离小目标特征不足。# 用 best.pt 对验证集做推理输出带框结果图 yolo detect predict \ modelruns/detect/bollard_run1/weights/best.pt \ sourcedataset/val/images saveTruepredict 后会在 runs/detect/predict 下生成带预测框的图片逐个翻这些图比盯指标更直接。漏检的图如果几乎都集中在远景小尺寸石墩就去检查训练集里小目标占比统计 txt 中框宽高占图宽高的比例分布低于 0.05 的小框如果数量明显偏少模型天然偏向大目标。这时更有效的做法是对远距离样本做离线裁剪增强把远处石墩裁出来作为附加训练样本再重新划分训练验证集而不是只调置信度阈值。本文还有配套的精品资源点击获取