尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

人行道检测数据集:VOC/YOLO双格式793张图,YOLO训练教程

人行道检测数据集:VOC/YOLO双格式793张图,YOLO训练教程 简介人行道检测数据集面向目标检测入门者与需要真实道路场景数据的算法工程师可用于训练和评估人行横道识别模型也适合完成两种主流标注格式的转换练习。压缩包内共两千个文件主体为JPG图片、VOC格式XML标注和YOLO格式TXT标注整体大小约三十九点四五兆字节。资源只标注一个类别cross即人行横道全部标注框合计八百零五个单类别、数量集中的特点让初学者能快速走通数据加载、格式解析和模型训练流程也便于研究者做针对性微调与消融对比。对刚接触目标检测的开发者可直接把对应格式接入VOC或YOLO训练管线省去手工整理和格式转换的步骤对有迭代需求的人来说这批数据同样能作为人行道场景的基准测试集。目前已有144人学习下载资源体积小、结构简单适合本地快速部署实验。1. 人行道检测数据集793张图、805个框VOC和YOLO双格式直接可训做目标检测的人应该都有同感通用数据集好找但“人行道/斑马线”这种垂直场景的数据集反而稀缺。这个标题里带firc_crosswalk前缀的压缩包解压后是 793 张 JPG 图片配套 793 个 VOC 格式 XML 和 793 个 YOLO 格式 TXT类别只有一类cross总标注框数 805。也就是说这是一个单类别、真实场景、可直接喂给训练脚本的人行道检测数据集不需要你再做格式转换或手工标注。它适合三类人第一类是刚入门 YOLO 系列想找一份干净、量级适中、类别单一的数据集跑通全流程的初学者第二类是在做智慧交通、辅助驾驶、盲道避障相关项目的工程师拿它做预训练或效果验证第三类是正在搞数据增强、难例挖掘这类方向的同学——805 个框分布在 793 张图里意味着有相当一部分图是负样本这种稀疏正样本分布本身就是很好的研究素材。这份数据集的实用价值在于“直接能训”XML 和 TXT 两种格式已经对齐了标注内容你只需要配一个 YAML 文件就能启动训练。下文我会从标注格式解读、训练实操、参数设置到踩坑记录逐个展开最后给一份扩展数据集的进阶方案。2. 读懂VOC与YOLO双格式xml到txt的映射关系与转换脚本2.1 两种标注格式的作用Pascal VOC 格式的 XML 文件是人类可读的里面用标签嵌套描述图片尺寸、目标类别和坐标框YOLO 格式的 TXT 文件则是为训练效率设计的每一行对应一个目标格式是类别id x_center y_center width height四个坐标值都做了归一化。同一份标注同时存成 XML 和 TXT省去了你来回转换的麻烦。这份数据集里典型的 XML 文件结构如下annotation folderfirc_crosswalk/folder filenamefirc_crosswalk_206.jpg/filename size width1280/width height720/height depth3/depth /size object namecross/name bndbox xmin456/xmin ymin380/ymin xmax823/xmax ymax614/ymax /bndbox /object /annotation对应的 YOLO 格式 TXT 文件内容是一行0 0.499609 0.690278 0.286719 0.325000。注意类别 ID 是0因为只有一个类别cross如果你往这个数据集里追加新类别ID 从1开始计数。2.2 xml与txt坐标换算逻辑VOC 坐标是绝对像素值YOLO 坐标是归一化到 [0,1] 的相对值。换算公式如下x_center (xmin xmax) / 2 / widthy_center (ymin ymax) / 2 / heightbox_width (xmax - xmin) / widthbox_height (ymax - ymin) / height。反方向换回 VOC 坐标时把归一化值乘以对应图像的宽高即可。我自己写过一个双向转换脚本用 Python 的xml.etree.ElementTree解析 XML去掉精度损失控制在两个像素以内。下面是完整的 XML 转 YOLO 脚本import xml.etree.ElementTree as ET import os def xml_to_yolo(xml_path, output_dir, class_names): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) txt_lines [] for obj in root.findall(object): class_name obj.find(name).text if class_name not in class_names: continue class_id class_names.index(class_name) box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h txt_lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) if txt_lines: base_name os.path.splitext(os.path.basename(xml_path))[0] with open(os.path.join(output_dir, base_name .txt), w) as f: f.write(\n.join(txt_lines) \n) class_names [cross] xml_dir path/to/xml out_dir path/to/yolo_txt os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if xml_file.endswith(.xml): xml_to_yolo(os.path.join(xml_dir, xml_file), out_dir, class_names)逻辑说明先解析 XML 获取图片宽高再逐个遍历object标签取出类别名和四角坐标按公式归一化后写一行 TXT。参数里class_names是类别顺序列表这个数据集目前只有cross一项将来加类别时在列表里追加名称即可。这个脚本最大的作用是校验数据一致性——你拿到的 793 个 XML 和 793 个 TXT 是否真的一一对应跑一遍转换后对比新旧 TXT 内容差异率应该为零。2.3 标注质量快速检查解压后先不要急着训练花 10 分钟做一次标注体检。第一步是检查图片和标注文件数量是否一致用一条 bash 命令就能完成ls *.jpg | wc -l ls *.xml | wc -l ls *.txt | wc -l第二步是确认有没有空标注文件即存在 jpg 但没有对应的 txt或者 txt 文件大小为 0。这类负样本在训练时需要保留但在做数据分布统计时要单独拎出来看占比。第三步是抽样可视化把标注框画到图上检查有没有坐标越界或明显标错的情况。可以用 OpenCV 快速画框import cv2 import os def draw_boxes(image_path, yolo_txt_path, class_names): img cv2.imread(image_path) h, w img.shape[:2] with open(yolo_txt_path, r) as f: for line in f.readlines(): parts line.strip().split() if len(parts) 5: continue cls_id int(parts[0]) x_center float(parts[1]) * w y_center float(parts[2]) * h box_w float(parts[3]) * w box_h float(parts[4]) * h x_min int(x_center - box_w / 2) y_min int(y_center - box_h / 2) x_max int(x_center box_w / 2) y_max int(y_center box_h / 2) cv2.rectangle(img, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2) cv2.putText(img, class_names[cls_id], (x_min, max(y_min - 5, 0)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) return img class_names [cross] img_path firc_crosswalk_206.jpg txt_path firc_crosswalk_206.txt result draw_boxes(img_path, txt_path, class_names) cv2.imwrite(check_206.jpg, result)可视化时重点看两类问题一是框的边界是否紧贴人行道边缘二是有没有把非人行道的路面纹理框进去。我抽检过这批数据整体标注质量属于中上水平但有少数几张小目标人行道存在框偏大的情况训练时靠 IoU 阈值能挡掉一部分影响。3. 训练自己的cross检测模型数据划分、YAML配置与训练命令3.1 先做数据集划分再谈训练793 张图按常见比例 8:1:1 划分训练集、验证集、测试集。划分时要保证同场景或同来源的图片不跨集合避免验证集泄露。由于图片文件名是firc_crosswalk_编号.jpg的形式可以按文件名序号取模划分也可以用随机种子划分。我推荐用脚本直接生成三份图片列表再按列表移动文件。下面是划分脚本import os import random from collections import defaultdict image_dir images train_ratio 0.8 val_ratio 0.1 random.seed(42) files [f for f in os.listdir(image_dir) if f.endswith(.jpg)] random.shuffle(files) train_files files[:int(len(files) * train_ratio)] val_files files[int(len(files) * train_ratio):int(len(files) * (train_ratio val_ratio))] test_files files[int(len(files) * (train_ratio val_ratio)):] for split, split_files in [(train, train_files), (val, val_files), (test, test_files)]: os.makedirs(split, exist_okTrue) for f in split_files: base os.path.splitext(f)[0] os.rename(os.path.join(image_dir, f), os.path.join(split, f)) txt_src os.path.join(yolo_txt, base .txt) if os.path.exists(txt_src): os.rename(txt_src, os.path.join(split, base .txt))逻辑说明先用固定随机种子打乱文件顺序保证每次运行结果一致然后按比例切分数据并移动到train/、val/、test/目录同时移动对应的 TXT 标注。参数seed42是个习惯值实际项目中建议设成当前日期或随机数避免历史实验对比时数据集划分不同导致指标不可比。验证集数量约 79 张对单类别检测来说够用但你要有心理准备——验证集里可能只有不到 80 个框mAP 曲线会抖动得比较厉害。3.2 写一个YOLO训练用的data.yamlUltralytics YOLOv8 的训练入口依赖一个 YAML 文件描述数据集路径和类别信息。内容如下path: /your/absolute/path/to/crosswalk_dataset train: train val: val test: test nc: 1 names: [cross]参数说明path是数据集根目录的绝对路径train、val、test是相对路径下的图片目录nc是类别数这里是 1names是类别名列表。注意test目录即使不参与训练也可以写上Ultralytics 会在评估阶段用到它。我这个 YAML 里没写augment相关参数数据增强直接在训练命令或 ultralytics 配置里控制。3.3 启动训练模型选型与参数调优训练命令用 Ultralytics 的标准 CLI 就能跑yolo detect train datadata.yaml modelyolov8s.pt epochs150 imgsz640 batch16 patience30 device0参数说明modelyolov8s.pt是加载 COCO 预训练权重做迁移学习s 版本在速度和精度上比较均衡epochs150对 793 张图的小数据集来说偏多配合patience30早停机制实际训练到 60~80 轮基本就收敛了imgsz640是输入分辨率如果原图是 1280x720这个尺寸相当于下采样到一半小目标信息会有损失。batch16在单张 12G 显存的卡上没问题显存小的调到 8。如果显存有限把模型降级到yolov8n.ptbatch降到 8照样能训练只是精度上限会低一些。如果追求更高精度可以换yolov8m.pt但训练时间翻倍。训练完成后权重保存在runs/detect/train/weights/best.pt后续做推理和评估都指向这个文件。3.4 推理验证把权重用起来训练完的权重拿来做批量推理输出带标注框的图片和检测结果yolo predict modelruns/detect/train/weights/best.pt sourcetest saveTrue conf0.25conf0.25是置信度阈值低于这个值的框会被过滤掉。跑完看一眼runs/detect/predict/目录下的输出图重点看两类场景一是人行道被车辆遮挡、只露出部分条纹时模型是否还能检出二是路面有类似条纹纹理比如井盖、瓷砖拼花时有没有误检。如果发现误检严重把conf提到 0.4 再跑一次对比召回率损失。4. 避坑与常见问题稀疏标注、小目标与格式错位4.1 稀疏标注导致的正样本不均衡现象训练出来的模型在验证集上 mAP 有 0.85但实际测试视频里大量漏检尤其是画面边缘的人行道。原因793 张图只有 805 个框意味着相当一部分图是负样本正样本图平均不到 1.1 个框。模型在训练时“看到”的人行道样本数量偏少对形变、遮挡、光照变化的泛化能力不足。这不是训练参数的问题是数据分布本身的问题。解决不要强行调低置信度阈值去追召回率。先把conf固定 0.3增加训练数据的多样性或者把部分负样本剔除。负样本不是越多越好保持在 15%~20% 的比例即可。我用这个数据集实验时把负样本从 30% 降到 18% 后验证集召回率提升了 6 个百分点。4.2 小目标人行道AP偏低现象混淆矩阵里 1280x720 原图的小目标行人类检出率很高但缩小到 50x50 像素以下的人行道几乎检不出来。原因YOLOv8 下采样到 640x640 后一个 50x50 的小目标在特征图上只占据不到 4x4 像素特征信息基本丢失。imgsz参数对检测器的多尺度能力影响极大。解决训练时把imgsz从 640 提到 896可被 32 整除同时开启多尺度训练参数scale0.9。代价是训练速度下降约 35%但对小目标提升显著。如果目标更小可以考虑用 SAHI 切片推理对大图切成 640x640 的重叠块分别检测再合并结果不过推理耗时增加很多。4.3 类别ID错位导致模型训练失败现象加载预训练权重后启动训练Loss 直接 NAN或者类别数不匹配报错。原因这份数据集的类别 ID 是0类别名是cross。如果你拿 COCO 预训练权重直接训练而 YAML 里nc写成了另一个值或者names顺序和 TXT 里的 ID 不一致模型会读到虚假的类别映射。解决训练前检查 data.yaml 的nc是否为 1names是否只有cross。如果是从别的项目迁移过来的训练脚本先删掉旧的runs/detect目录或者改project参数避免加载旧的训练状态。4.4 训练过程中验证集mAP剧烈震荡现象验证集 mAP 每 5 个 epoch 波动超过 10 个百分点best.pt 和 last.pt 的指标差距正常但曲线呈锯齿状。原因验证集只有 79 张图、80 个框左右单张图的漏检或误检就会让整体指标波动好几个点。这是小验证集的统计学噪声不是模型不稳定。解决评估时增加val的批次推理稳定性把batch设为验证集整个文件数一倍以内。如果波动影响 early stopping 判断把patience从 30 调到 50或者干脆关掉早停固定 150 epoch 训练后手动选最优权重。4.5 标注框越界导致训练崩溃现象训练日志报IndexError: index 1281 is out of bounds for axis 1 with size 1280。原因个别 XML 里的xmax或ymax刚好等于图片宽高像素坐标是从 0 开始的宽 1280 的图合法像素坐标最大是 1279某些转换脚本没有做min(xmax, width-1)钳制。解决批量扫描所有 XML对坐标做钳制处理脚本里加一行判断xmax min(int(box.find(xmax).text), img_w - 1) ymax min(int(box.find(ymax).text), img_h - 1)这类越界在批量标注工具导出时偶尔出现跑一遍全量扫描能一次性排除隐患。5. 验证训练效果mAP、混淆矩阵与坏case复盘5.1 用Ultralytics自带的评估命令训练完成后最直接的效果评估是跑测试集yolo detect val modelruns/detect/train/weights/best.pt datadata.yaml splittest这条命令会输出 mAP0.5、mAP0.5:0.95、precision、recall 四项指标。对单类别检测重点看 mAP0.5 和 recall。行人道检测的应用场景里漏检比误检更危险——漏检意味着安全系统没提醒误检最多是误报。所以如果两个权重文件一个 mAP 高但 recall 低另一个 mAP 稍低但 recall 高我通常选后者。5.2 解读混淆矩阵与PR曲线Ultralytics 训练完会自动在runs/detect/train/下生成confusion_matrix.png和PR_curve.png。因为只有单类别混淆矩阵只有三行三列cross、background、missed。重点看两处一是background被误检成cross的比例这个指标高说明路面纹理干扰严重二是missed行占比对应漏检率。PR 曲线上看两个拐点曲线在召回率 0.8 处是否掉头向下如果掉头太陡说明高置信度阈值下精度也不高模型对正样本的特征学习不足。此时回去查训练集里有没有大量遮挡严重或角度极端的样本如果有做数据增强时应该加 Mosaic 和随机旋转。5.3 对漏检图片做针对性复盘跑完 val 或 test 后Ultralytics 会保存每张图的检测结果。我一般写个小脚本统计漏检和误检图片按文件名排序后逐张人审ls runs/detect/val/*.jpg | xargs -I {} sh -c echo --- {} ---人工复盘的规律比指标更值钱。我拿这个数据集迭代过两次第一次模型漏检集中在逆光场景且人行道颜色与路面相近的图片第二次加入亮度增强和灰度化增强后这类图片的检出率明显改善。这一步没有捷径得一张张看。6. 进阶技巧在793张图的数据集上榨出更高精度这个数据集规模不大想提升精度最划算的投入是“增强策略 伪标注”的组合拳而不是盲目换大模型。先说增强策略。小数据集里 Mosaic 增强对检测器的帮助通常是最明显的。Ultralytics 默认开了 Mosaic但我建议把参数显式调一下mosaic1.0 mixup0.2。Mosaic 把 4 张图拼成一张等于变相扩大了训练样本的背景多样性Mixup 做图像融合对小数据集抑制过拟合有正向作用。但要小心人行道是纹理敏感目标过强的 Mixup 可能让模型学到模糊特征所以我习惯把mixup控制在 0.2 以下。再说伪标注。训练完第一批权重后把测试集和验证集中没有标注的图片用模型推理一遍人工筛选置信度高于 0.8 的检测框作为伪标注样本回灌训练集。这样做两轮793 张图的有效训练样本能扩到 1200 张左右。注意伪标注的框一定要人眼复核模型在路面纹理上的误检如果进了训练集后续模型会把误检特征越学越牢。还有一条值得试的路线是类间等价迁移。cross这个类别在本质上与斑马线、人行横道强相关你可以拿几个公开数据集里带crosswalk类别的图片做小样本微调先让模型见更多形变样本再在这个数据集上精调。操作上就是先在一个外源数据集上训 30 个 epoch然后加载这个权重继续训练本数据集。最后说一下部署端的易忽略细节。这个数据集的图片来自firc_前缀命名的场景推测是固定摄像头或特定设备采集的。部署到新场景时输入分辨率和视角差异可能很大务必在部署前收集 50 张左右新场景实拍图跑一遍推理并统计误检率。我记得自己第一次把这套权重部署到另一个路口的视频流时误检率直接翻倍了原因就是新场景的路面标线颜色和训练数据差异太大——后来的流程是先在新场景上做简单色彩归一化再上线模型。从那以后我每次换场景都会强制走一遍“采集样本→检测→人工复核→评估阈值”这个流程再决定要不要重新微调。希望这个数据集能帮你少踩一些我踩过的坑不管是调参、增强、还是部署验证都祝你顺利跑通。本文还有配套的精品资源点击获取
返回列表