ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

道路障碍物检测数据集详解:YOLO标注格式、可视化与训练配置

道路障碍物检测数据集详解:YOLO标注格式、可视化与训练配置 简介面向道路障碍物检测任务的YOLO格式数据集涵盖障碍物、小动物、路障、减速带四个常见类别适用于自动驾驶环境感知、辅助驾驶预警以及道路安全监控等场景。数据已按照YOLOv5目录结构完成划分训练集包含1337张图片与对应txt标签验证集包含572张图片与对应txt标签图像均为640×640分辨率的RGB大图每张含多个完整边界框标注采用YOLO相对坐标格式类别、中心点x、中心点y、宽、高。资源文件总数为2000个其中包含标注与类别信息在内的txt文件共1910个JPEG原图89张另附1个可直接运行的可视化Python脚本压缩包整体124.8MB解压后即可开始训练无需额外处理或格式转换。可视化脚本支持随机读取单张图片快速绘制边界框可直观校验标注质量便于用户检查数据集效果。目前已有151人浏览学习对需要现成道路障碍物数据集的开发者或研究者而言能直接满足模型训练、算法评估与实验验证需求。1. 为什么路面上这四个目标最难检测做车载视觉或者路口监控的同行应该都有体会障碍物、小动物、路障、减速带这四类目标在YOLO系模型里属于典型的“小目标类间混淆”组合。减速带和路障在低分辨率下几乎长一个样小动物在夜间或逆光场景下轮廓极淡而“障碍物”这个类别的边界本身就很模糊——纸箱、锥桶、石块都算。这套路上障碍物检测数据集共1909张640x640 RGB图像训练集1337张、验证集572张全部按YOLOv5的datasets/images/labels结构存放标注格式为标准YOLO相对坐标类别ID、中心点x、中心点y、宽、高。对正在跑YOLOv5/v8训练、想省掉数据清洗和格式转换步骤的工程师来说这份数据可以直接喂给训练脚本配合附带的class文件和可视化脚本从校验数据到跑通第一个epoch半小时内能完成。2. 数据集结构与YOLO标注格式的细节2.1 目录组织与文件对应关系这个数据集保存为YOLO标准目录不需要额外转换。拿到手之后目录结构是这样的datasets/ ├── images/ │ ├── train/ # 1337张 .jpg │ └── val/ # 572张 .jpg ├── labels/ │ ├── train/ # 1337个 .txt │ └── val/ # 572个 .txt ├── classes.txt # 4个类别 └── visualize.py # 可视化脚本对应关系要求严格IMG_4035_mov-3_jpg.rf.8bc0deb8f831eb863fb86a2c49087499.jpg的同名txt文件必须存在且内容非空。从文件名里的.rf.可以看出这些图片经由Roboflow导出文件名保留了原始视频帧的来源信息比如IMG_4035_mov-3表示来自IMG_4035这段视频的第3帧这种命名方式在排查训练数据泄漏时非常有用——如果你同时有几段视频帧混在一起通过文件前缀就能快速识别哪些帧来自同一视频避免训练集和验证集出现同源帧。验证数据集是不是完整可用不需要写复杂脚本直接两行bash检查# 统计图片数量与标签数量是否一一对应 find datasets/images/train -name *.jpg | wc -l # 应为1337 find datasets/labels/train -name *.txt | wc -l # 应为1337如果数量对不上优先检查是否包含classes.txt中未定义的类别ID。2.2 标注文件内容解析类别ID与归一化坐标每个txt文件对应一张图片每行代表一个目标框格式为class_id x_centre y_centre width height所有坐标值均归一化到0~1区间。比如某个标注文件的内容可能是0 0.621094 0.453125 0.078125 0.062500 1 0.773438 0.583984 0.050781 0.044922 2 0.341797 0.660156 0.142578 0.125000 3 0.502344 0.714844 0.043750 0.023438这里0代表障碍物、1代表小动物、2代表路障、3代表减速带以classes.txt实际顺序为准。0.621094是目标中心点的x方向比例位置0.453125是中心点y方向比例后面两个分别是目标宽度和高度占图片尺寸的比例。用绝对像素计算时比如图片宽度640那么目标左上角x_pixel (0.621094 - 0.078125/2) * 640 372.5这个换算逻辑在可视化脚本和验证mAP时都要用到。注意YOLO格式和COCO的[x_min, y_min, w, h]不同是中心点坐标写转换脚本时最容易在这里出错。2.3 四个类别的分布观察用Python快速统计一下每个类别的标签数量看看有没有严重的类别不平衡import os from collections import Counter label_dir datasets/labels/train class_counter Counter() boxes_per_image [] for txt_file in os.listdir(label_dir): boxes 0 with open(os.path.join(label_dir, txt_file), r) as f: for line in f: parts line.strip().split() if len(parts) 5: class_counter[parts[0]] 1 boxes 1 boxes_per_image.append(boxes) print(各类别目标数量:, dict(class_counter)) print(平均每张图目标数:, sum(boxes_per_image) / len(boxes_per_image))这段代码把每个类别出现的总次数和单张图的平均目标数打印出来。如果某个类别目标数量明显偏少比如小动物只有几百个实例而障碍物有几千个训练时就需要考虑类别权重或者针对性数据增强否则模型会天然偏向样本多的类别。3. 数据可视化脚本的运行与二次开发3.1 直接运行的命令与预期输出项目附带的visualize.py设计得比较省事不需要修改任何路径或参数直接执行即可。它会自动读取datasets/images/val下的一张随机图片绘制标注框并保存到当前目录。python visualize.py运行后当前目录下会生成一张visualized.jpg或类似命名的图片每个目标框上会显示类别名和置信度如果脚本中绘制了置信度的话。我拿到后通常会先看验证集的可视化结果因为训练集是模型见过的数据看训练集看不出真问题验证集才反映模型没见过的新样本。3.2 脚本内部的绘制逻辑拆解虽然脚本能直接跑通但建议把内部逻辑过一遍方便按需扩展。典型的实现思路如下import cv2 import random import os def load_yolo_label(label_path, img_w, img_h): boxes [] with open(label_path, r) as f: for line in f: parts line.strip().split() class_id int(parts[0]) x_c, y_c, w, h map(float, parts[1:5]) # YOLO格式为归一化中心点坐标转回像素坐标 x1 int((x_c - w / 2) * img_w) y1 int((y_c - h / 2) * img_h) x2 int((x_c w / 2) * img_w) y2 int((y_c h / 2) * img_h) boxes.append((class_id, x1, y1, x2, y2)) return boxes img_path random.choice(os.listdir(datasets/images/val)) image cv2.imread(os.path.join(datasets/images/val, img_path)) h, w image.shape[:2] label_path os.path.join(datasets/labels/val, img_path.replace(.jpg, .txt)) boxes load_yolo_label(label_path, w, h) colors [(0, 255, 0), (0, 165, 255), (255, 0, 0), (0, 255, 255)] class_names [obstacle, animal, barrier, speed_bump] for class_id, x1, y1, x2, y2 in boxes: color colors[class_id % len(colors)] cv2.rectangle(image, (x1, y1), (x2, y2), color, 2) cv2.putText(image, class_names[class_id], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.imwrite(visualized.jpg, image) print(fSaved visualized.jpg, source: {img_path})坐标换算的核心是x1 (x_c - w/2) * img_w因为YOLO标注存的是中心点和宽高比例要画OpenCV的矩形框必须转成左上角宽高的像素坐标。cv2.putText绘制类别名时y方向要减5到10个像素否则文字会和框线重叠。颜色列表按类别ID取模确保4个类别各有不同颜色。3.3 可视化脚本的检查价值可视化不只是“看一眼标得对不对”它承担三层作用第一检查坐标有没有越界如果某个框的x2超过了图像宽度说明标注数据本身有问题第二检查类别和目标的对应关系比如路障类别的框如果画到了人行横道上说明类别定义和数据标注之间存在偏差第三观察小目标的比例如果大量目标框的宽度只有图片宽度的5%到10%训练时就需要专门针对小目标调整anchor或增强策略。我习惯把random.choice改成遍历目录中前50张图把每张图的可视化结果拼成网格图这样能快速抓出标注异常比一张张看高效得多。4. YOLOv5/v8训练加载与超参数配置4.1 数据集YAML配置文件的编写有了现成的目录结构训练前只需要写一个数据配置文件。以YOLOv5为例在项目根目录创建road_obstacle.yaml# road_obstacle.yaml train: datasets/images/train val: datasets/images/val nc: 4 names: [obstacle, animal, barrier, speed_bump]train和val字段指向图片目录YOLO训练脚本会根据images路径自动关联同名的labels目录将images替换为labels。nc: 4是类别总数names列表的顺序必须与标注文件中的类别ID严格一致——比如标注里ID为2的类别对应的是barrier那么names列表的索引2就必须是barrier顺序错位会导致模型把路障学成减速带而且这类错误在训练日志里不容易被发现。4.2 模型选择与训练命令根据硬件情况选择模型规模。显存8GB以下推荐yolov5s显存16GB以上可以上yolov5m或yolov8m。这是用YOLOv5s做迁移学习的常用命令python train.py --data road_obstacle.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 100 --workers 4--img 640保持输入尺寸与数据集图像分辨率一致避免resize带来的额外形变。--batch 16在8GB显存下基本是上限如果显存溢出就改成8。--weights yolov5s.pt用的是COCO预训练权重前面的基础层已经学会了通用纹理和边缘特征这比从零训练要快得多、收敛也更稳。训练完成后看runs/train/exp/下的results.csv重点关注val_obj_loss和mAP0.5两个指标。4.3 超参数调整的三个关键方向第一是anchor size。预训练权重的anchor是为COCO的80类目标设计的COCO里中大型目标占比高而本数据集里减速带和路障往往在画面下方属于中小目标。用YOLOv5自动化anchor检查python utils/autoanchor.py --data road_obstacle.yaml --img 640脚本会输出当前anchor的recall如果低于0.9建议重新计算anchor并保存到yaml文件。第二是类别不平衡策略。如果第2.3节统计发现小动物类别样本很少可以在loss上做文章。YOLOv8里设置model YOLO(yolov8s.pt) model.train(dataroad_obstacle.yaml, epochs100, imgsz640, class_weights{1: 1.5, 0: 1.0, 2: 1.0, 3: 1.0})class_weights参数把类别1的loss权重提高到1.5倍模型对小动物的误检会相应减少。不过权重不要设置超过2.0否则容易过拟合到少数类。第三是mosaic数据增强的关闭时机。YOLOv5默认前70%的epoch开启mosaic后30%自动关闭。因为mosaic拼接的图片中目标位置分布和真实场景有差异最后阶段用真实全图微调可以缓解域偏移。保持默认即可不需要额外改动。5. 验证指标解读与错误检测的进阶技巧5.1 混淆矩阵的实际用法训练结束后runs/train/exp/下会生成confusion_matrix.png这张图比mAP数字更有诊断价值。重点关注两类错误一是路障被误判为减速带的概率这两个类别形状高度相似如果混淆率超过20%建议提高输入分辨率到960如果显存允许或者增加负样本难例挖掘二是障碍物类的漏检率也就是背景类被预测为障碍物的比率如果这个值偏高说明正样本边界框之外还存在大量类似纹理的区域此时需要更严格的置信度阈值。# 用test模式跑验证集输出详细指标 python val.py --data road_obstacle.yaml --weights runs/train/exp/weights/best.pt --img 640 --conf-thres 0.001 --iou-thres 0.6--conf-thres 0.001让模型输出大量低置信度检测框此时系统会统计多少目标是“根本没有框出来”的这个数比常规阈值下的漏检率更能暴露模型短板。如果低置信度下召回也不高说明问题不在阈值而在于特征学习不充分。5.2 标签噪声的自动化清洗边界框标注偶尔会有偏差。写一个简单的清洗脚本把高度或宽度小于图片尺寸1%的框打印出来import os label_dir datasets/labels/train min_ratio 0.01 for txt_file in os.listdir(label_dir): with open(os.path.join(label_dir, txt_file), r) as f: for line in f: parts line.strip().split() if len(parts) ! 5: print(f格式异常: {txt_file}: {line.strip()}) continue _, _, _, w, h map(float, parts) if w min_ratio or h min_ratio: print(f疑似过小目标: {txt_file} w{w} h{h})过小目标框如果宽度比例小于0.01在640x640分辨率下就是不到6个像素的目标模型几乎不可能学会检测。这类框要么是标注噪声要么是需要特殊处理的极小目标。建议人工确认后将这类目标从标签中删除或者单独用tiling策略切图放大后训练。标签清洗和可视化检查应该交替进行两轮第一轮删掉不完整的框第二轮检查类别混淆之后再进入训练环节可以省下不少调试时间。本文还有配套的精品资源点击获取
返回列表