尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

VOC转YOLO格式全流程:基于892张城市道路垃圾数据集的YOLOv8训练实战

发布时间:2026/9/3 18:30:09

资讯中心
01
ARTICLE

VOC转YOLO格式全流程:基于892张城市道路垃圾数据集的YOLOv8训练实战

VOC转YOLO格式全流程:基于892张城市道路垃圾数据集的YOLOv8训练实战
简介本资源是面向计算机视觉初学者与实战开发者的城市道路垃圾检测专用数据集适用于YOLO系列模型训练及Pascal VOC格式目标检测任务研究。数据集共1785个文件包含892张高质量JPG道路实景图像与严格对齐的892份XML标注文件全部采用labelImg工具按规范矩形框标注仅含单类别“trash”总计1155个有效标注框覆盖城市道路、绿化带等典型场景其中81张为常见塑料瓶样本具备较强现实泛化基础。压缩包大小983.57MB结构简洁无冗余不含YOLO格式转换文件或分割路径便于用户自主完成格式转换与数据增强。目前已有1089人学习下载可直接用于模型训练、评估与算法对比实验节省从零采集标注的时间成本特别适合课程设计、毕业项目及轻量级工业检测原型开发。1. 项目背景与数据集价值解析最近在整理一个关于城市道路垃圾检测的数据集总共892张图片格式是经典的VOC可以直接用来训练YOLO系列的目标检测模型。这个项目听起来简单但背后涉及到的数据准备、格式转换、模型训练和实际部署每一步都有不少门道。如果你正打算做一个类似的环保监控或者城市管理相关的AI项目比如用摄像头自动识别路面上的塑料袋、饮料瓶、废弃家具等垃圾那么这个数据集和接下来的流程应该能给你提供一个非常扎实的起点。为什么城市道路垃圾检测值得一做从实际应用来看它远不止是一个学术练习。想象一下市政环卫部门如果能在垃圾刚出现时就通过路边的监控摄像头自动发现并上报调度清洁车辆前往处理效率会提升多少。或者在自动驾驶的感知系统中如果能准确识别出路面上的障碍物比如一个被风吹过来的大纸箱对行车安全也是至关重要的补充。这个892张的数据集虽然规模不算巨大但作为原型验证、算法对比或者教学演示已经完全足够了。它的核心价值在于提供了一个“开箱即用”的基准让你能快速跑通从数据到模型的完整链路把精力集中在模型优化和业务逻辑上而不是在数据收集和标注上耗费大量时间。2. VOC格式详解与YOLO训练适配原理拿到一个VOC格式的数据集我们首先得彻底搞懂它里面到底有什么以及为什么YOLO能“吃”下它。VOCVisual Object Classes格式是目标检测领域一个非常古老但生命力顽强的标准它的结构清晰被绝大多数框架和工具所支持。2.1 VOC数据集的核心文件结构一个标准的VOC格式数据集通常包含以下几个关键目录和文件JPEGImages/: 这里存放着所有的原始图片文件比如000001.jpg,000002.jpg... 我们这个数据集的892张图片就放在这里。Annotations/: 这是标注信息的核心所在。里面存放着与图片一一对应的XML文件。每个XML文件详细描述了对应图片中所有目标物体的位置和类别。ImageSets/: 这个目录下通常还有一个Main/子目录里面存放着一些文本文件如train.txt,val.txt,test.txt这些文件列出了用于训练、验证和测试的图片名称不含路径和扩展名。对于只有892张图的数据集我们可能不会看到非常复杂的ImageSets划分有时甚至只有一个trainval.txt包含所有图片。这没关系我们可以自己按比例划分。2.2 深入解读Annotation XML文件理解XML文件的内容是后续一切操作的基础。我们打开一个典型的000001.xml看看annotation folderJPEGImages/folder filename000001.jpg/filename size width1920/width height1080/height depth3/depth /size segmented0/segmented object nameplastic_bag/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin445/xmin ymin300/ymin xmax520/xmax ymax400/ymax /bndbox /object object namebottle/name poseUnspecified/pose truncated1/truncated difficult0/difficult bndbox xmin800/xmin ymin650/ymin xmax850/xmax ymax720/ymax /bndbox /object /annotation这里有几个关键字段需要特别注意size: 图片的宽、高和通道数。这一点至关重要因为YOLO需要根据图像尺寸对标注框坐标进行归一化。object: 每个object标签对应一个目标实例。name: 类别名称如plastic_bag塑料袋、bottle瓶子。这是我们需要映射到数字ID的信息。bndbox: 边界框采用(xmin, ymin, xmax, ymax)的格式表示左上角和右下角的像素坐标。truncated: 目标是否被截断部分在图像外。值为1时在评估模型时有时会特殊处理。difficult: 目标是否难以识别。通常难以识别的目标在评估时不计入统计。2.3 YOLO格式的“胃口”与转换逻辑YOLO以YOLOv5/v8为例需要的标注格式则简洁得多。每个图片对应一个同名的.txt文件每行代表一个目标格式为class_id x_center y_center width height这里的坐标是归一化后的即x_center (xmin xmax) / 2 / image_widthwidth (xmax - xmin) / image_width y轴同理。class_id是从0开始的整数索引。所以从VOC到YOLO格式转换的核心过程就是解析每个XML文件获取图片宽高 (image_width,image_height)。对于每个object 读取name和bndbox。将name映射到我们定义的class_id例如plastic_bag-0,bottle-1。将像素坐标的(xmin, ymin, xmax, ymax)转换为归一化坐标的(x_center, y_center, width, height)。将结果写入图片名.txt文件。注意转换前务必检查XML中的width和height是否与真实图片尺寸一致。我曾遇到过标注文件里的尺寸是缩略图的尺寸而训练时用的是原图导致所有标注框错位模型完全无法学习。一个简单的验证方法是用Python的PIL或OpenCV库读取图片打印其shape 与XML中的尺寸进行对比。3. 从VOC到YOLO完整的数据预处理与增强流水线有了理论基础我们现在来搭建一个健壮的数据处理流水线。这个过程不仅仅是格式转换还包括数据检查、数据集划分和数据增强策略的制定。3.1 步骤一环境准备与目录结构搭建我习惯在项目根目录下创建清晰的结构。假设我们的项目叫road_litter_detectionroad_litter_detection/ ├── datasets/ │ └── voc_format/ # 原始VOC数据集 │ ├── JPEGImages/ # 892张图片 │ ├── Annotations/ # 892个XML文件 │ └── ImageSets/ │ └── Main/ │ └── (可能有的trainval.txt) ├── yolov8_format/ # 转换后的YOLO格式数据集目标目录 │ ├── images/ │ │ ├── train/ # 训练集图片 │ │ └── val/ # 验证集图片 │ └── labels/ │ ├── train/ # 训练集标签 │ └── val/ # 验证集标签 ├── scripts/ │ ├── convert_voc_to_yolo.py # 格式转换脚本 │ └── split_dataset.py # 数据集划分脚本 ├── data.yaml # YOLO模型配置文件 └── (其他模型训练文件)3.2 步骤二编写格式转换脚本下面是一个功能完善的convert_voc_to_yolo.py脚本它包含了类别映射、尺寸验证和错误处理import xml.etree.ElementTree as ET import os from pathlib import Path import shutil from sklearn.model_selection import train_test_split # 配置路径 voc_images_dir Path(./datasets/voc_format/JPEGImages) voc_annotations_dir Path(./datasets/voc_format/Annotations) output_dir Path(./yolov8_format) # 定义类别映射根据你的数据集XML中的name字段修改 CLASS_MAPPING { plastic_bag: 0, bottle: 1, cardboard: 2, can: 3, # ... 添加你的所有类别 } def convert_box(size, box): 将VOC的(xmin, ymin, xmax, ymax)转换为YOLO的归一化(x_center, y_center, width, height) dw 1. / size[0] dh 1. / size[1] x (box[0] box[2]) / 2.0 y (box[1] box[3]) / 2.0 w box[2] - box[0] h box[3] - box[1] x x * dw w w * dw y y * dh h h * dh return (x, y, w, h) def convert_annotation(xml_file, output_label_dir): 转换单个XML文件 tree ET.parse(xml_file) root tree.getroot() # 获取图片尺寸 size root.find(size) if size is None: print(f警告: {xml_file} 中没有找到size标签尝试从图片读取...) # 这里可以添加从图片读取尺寸的代码为了简洁先跳过 return False w int(size.find(width).text) h int(size.find(height).text) # 准备写入YOLO格式内容 txt_filename xml_file.stem .txt txt_path output_label_dir / txt_filename with open(txt_path, w) as f: for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in CLASS_MAPPING: print(f警告: {xml_file} 中发现未知类别 {cls_name}已跳过。) continue cls_id CLASS_MAPPING[cls_name] xmlbox obj.find(bndbox) if xmlbox is None: continue b (float(xmlbox.find(xmin).text), float(xmlbox.find(ymin).text), float(xmlbox.find(xmax).text), float(xmlbox.find(ymax).text)) # 边界框检查 if b[2] b[0] or b[3] b[1]: print(f警告: {xml_file} 中物体 {cls_name} 的边界框坐标无效已跳过。) continue if b[0] 0 or b[1] 0 or b[2] w or b[3] h: print(f警告: {xml_file} 中物体 {cls_name} 的边界框超出图像范围已进行裁剪处理。) b (max(0, b[0]), max(0, b[1]), min(w, b[2]), min(h, b[3])) bb convert_box((w, h), b) f.write(f{cls_id} {bb[0]:.6f} {bb[1]:.6f} {bb[2]:.6f} {bb[3]:.6f}\n) return True def main(): # 创建输出目录 (output_dir / labels).mkdir(parentsTrue, exist_okTrue) # 获取所有XML文件 xml_files list(voc_annotations_dir.glob(*.xml)) print(f找到 {len(xml_files)} 个XML标注文件。) # 转换所有标注 success_count 0 for xml_file in xml_files: if convert_annotation(xml_file, output_dir / labels): success_count 1 print(f转换完成。成功转换 {success_count}/{len(xml_files)} 个文件。) # 复制图片到输出目录保持结构后续再划分 (output_dir / images).mkdir(parentsTrue, exist_okTrue) for img_file in voc_images_dir.glob(*.*): if img_file.suffix.lower() in [.jpg, .jpeg, .png]: shutil.copy2(img_file, output_dir / images / img_file.name) print(图片复制完成。) if __name__ __main__: main()3.3 步骤三数据集划分与YAML配置文件生成转换后所有图片和标签都在images和labels根目录下。我们需要将其按比例如8:2划分为训练集和验证集并生成YOLO所需的data.yaml文件。# scripts/split_dataset.py import os from pathlib import Path import shutil from sklearn.model_selection import train_test_split # 路径配置 base_dir Path(./yolov8_format) image_files list((base_dir / images).glob(*.*)) image_files [f for f in image_files if f.suffix.lower() in [.jpg, .jpeg, .png]] # 按文件名排序确保可复现 image_names sorted([f.stem for f in image_files]) print(f总共 {len(image_names)} 张图片。) # 划分训练集和验证集 (80%训练20%验证) train_names, val_names train_test_split(image_names, test_size0.2, random_state42, shuffleTrue) # 创建子目录 for split in [train, val]: (base_dir / images / split).mkdir(parentsTrue, exist_okTrue) (base_dir / labels / split).mkdir(parentsTrue, exist_okTrue) # 移动文件 def move_files(names, split): for name in names: # 移动图片 src_img base_dir / images / f{name}.jpg # 假设是jpg可根据实际情况调整 if not src_img.exists(): # 尝试其他格式 for ext in [.png, .jpeg]: src_img base_dir / images / f{name}{ext} if src_img.exists(): break if src_img.exists(): dst_img base_dir / images / split / src_img.name shutil.move(str(src_img), str(dst_img)) # 移动标签 src_label base_dir / labels / f{name}.txt if src_label.exists(): dst_label base_dir / labels / split / src_label.name shutil.move(str(src_label), str(dst_label)) move_files(train_names, train) move_files(val_names, val) print(f划分完成训练集 {len(train_names)} 张验证集 {len(val_names)} 张。) # 生成 data.yaml 文件 yaml_content f# 城市道路垃圾检测数据集 path: {str(base_dir.absolute())} # 数据集根目录 train: images/train # 训练集图片相对路径 val: images/val # 验证集图片相对路径 # 类别数量 nc: {len(CLASS_MAPPING)} # 根据你的CLASS_MAPPING长度自动生成 # 类别名称列表 names: {list(CLASS_MAPPING.keys())} with open(data.yaml, w) as f: f.write(yaml_content) print(data.yaml 配置文件已生成。)运行这两个脚本后你就得到了一个标准YOLO格式的数据集和对应的配置文件。data.yaml是连接数据和模型的桥梁训练时必须指定它。4. 基于YOLOv8的模型训练、验证与调优实战数据准备好了我们进入核心的模型训练环节。这里我以 Ultralytics YOLOv8 为例因为它生态完善文档清晰非常适合快速上手和部署。4.1 环境搭建与模型选择首先安装YOLOv8pip install ultralyticsYOLOv8提供了不同尺寸的预训练模型从轻量到高精度yolov8n.pt(nano): 参数量最小速度最快适合移动端或边缘设备。yolov8s.pt(small): 平衡了速度和精度是很多实际项目的起点。yolov8m.pt(medium)yolov8l.pt(large)yolov8x.pt(extra large): 精度最高但速度最慢参数量最大。对于892张图的数据集我建议从yolov8s或yolov8m开始。模型太大容易在小数据集上过拟合太小则可能学习能力不足。4.2 启动训练与关键参数解析最基础的训练命令只需要一行yolo taskdetect modetrain modelyolov8s.pt datadata.yaml epochs100 imgsz640但这只是开始。要获得好模型必须理解并调整关键参数。下面是一个更详细的训练示例包含了常用配置# train.py from ultralytics import YOLO # 加载一个预训练模型 model YOLO(yolov8s.pt) # 也可以从头开始训练: YOLO(yolov8s.yaml) # 开始训练 results model.train( datadata.yaml, # 数据集配置文件路径 epochs150, # 训练轮数小数据集可以适当增加 patience30, # 早停耐心值如果验证集指标连续30轮没有提升则停止训练 batch16, # 批次大小根据你的GPU显存调整 (8, 16, 32...) imgsz640, # 输入图像尺寸必须是32的倍数 workers4, # 数据加载的线程数根据CPU核心数调整 device0, # 使用GPU 0如果是CPU则设为 cpu多卡可以用 0,1 seed42, # 固定随机种子确保实验可复现 lr00.01, # 初始学习率 lrf0.01, # 最终学习率因子 (lr0 * lrf) momentum0.937, # SGD动量 weight_decay0.0005, # 权重衰减防止过拟合 warmup_epochs3.0, # 学习率预热轮数 warmup_momentum0.8, # 预热期动量 box7.5, # 边界框损失权重 cls0.5, # 分类损失权重 dfl1.5, # DFL损失权重 (v8特有) hsv_h0.015, # 色调增强幅度 hsv_s0.7, # 饱和度增强幅度 hsv_v0.4, # 明度增强幅度 degrees0.0, # 旋转角度范围小数据集可设为0或很小值 translate0.1, # 平移幅度 scale0.5, # 缩放幅度 shear0.0, # 剪切幅度 perspective0.0, # 透视变换幅度 flipud0.0, # 上下翻转概率 fliplr0.5, # 左右翻转概率 mosaic1.0, # Mosaic数据增强概率 (1.0表示100%使用) mixup0.0, # MixUp数据增强概率小数据集慎用或调低 copy_paste0.0, # 复制粘贴增强概率 erasing0.4, # 随机擦除概率 crop_fraction1.0, # 图像裁剪比例 resumeFalse, # 是否从上次的检查点恢复训练 ampTrue, # 是否使用自动混合精度训练节省显存并加速 projectruns/detect, # 结果保存目录 nameexp, # 实验名称 exist_okTrue, # 允许覆盖已存在的实验目录 pretrainedTrue, # 是否使用预训练权重 optimizerauto, # 优化器可选 SGD, Adam, AdamW, NAdam... verboseTrue, # 打印详细信息 valTrue, # 训练中是否进行验证 saveTrue, # 是否保存训练检查点和最终模型 save_period-1, # 每隔多少轮保存一次检查点 (-1为每轮保存) deterministicTrue, # 是否启用确定性模式保证可复现性 )关键参数经验谈epochs: 对于892张图150-300轮是合理的起点。一定要配合patience早停使用避免无效训练。imgsz: 640是速度和精度的良好平衡。如果你的原始图片分辨率很高如1920x1080可以尝试增大到960甚至1280但会显著增加显存消耗和训练时间。数据增强: 对于小数据集增强至关重要。hsv_h/s/v调整颜色fliplr左右翻转非常有效且安全。但degrees旋转和perspective透视对于道路场景的垃圾要谨慎因为垃圾在路面上的视角变化是有限的过度增强可能引入不真实的样本。mosaic增强能极大地丰富背景强烈建议开启。batch: 在显存允许的情况下尽可能设大。如果出现CUDA out of memory错误减小batch或imgsz。resume: 训练意外中断时可以设置resumeTrue并指定上次的权重路径如resumeruns/detect/exp/weights/last.pt来继续训练。4.3 训练过程监控与指标解读训练开始后YOLOv8会在runs/detect/exp目录下生成大量有用的文件weights/best.pt: 验证集上表现最好的模型。weights/last.pt: 最后一轮的模型。args.yaml: 本次训练的所有参数配置。results.csv和results.png: 训练过程的指标日志和可视化图表。你需要重点关注results.png中的几条曲线损失函数 (loss):train/box_loss,train/cls_loss,train/dfl_loss: 训练集损失。理想情况下应平稳下降并最终收敛。val/box_loss,val/cls_loss: 验证集损失。应在训练集损失附近且没有明显上升趋势否则可能过拟合。性能指标 (metrics):metrics/mAP50-95(B): 这是核心指标表示在IoU阈值从0.5到0.95步长0.05区间内的平均精度mAP均值。值越高越好是衡量模型综合检测能力的关键。metrics/mAP50(B): 在IoU阈值为0.5时的mAP这个指标相对宽松通常比mAP50-95高。metrics/precision(B),metrics/recall(B): 精确率和召回率。需要根据你的业务需求权衡。如果要求“宁可漏检不可错检”如自动罚款系统则追求高精确率如果要求“尽可能发现所有垃圾”如环卫巡检则追求高召回率。注意训练初期指标可能会有剧烈波动这是正常的。大约在10-20个epoch后曲线会逐渐平滑。如果验证集损失很早就开始上升而训练集损失持续下降这是典型的过拟合信号。你需要立即采取行动增加数据增强但要合理、使用更强的正则化如增大weight_decay、或者减少模型复杂度换用更小的模型如yolov8n。4.4 模型验证与性能分析训练结束后使用最佳模型在验证集上进行全面评估yolo taskdetect modeval modelruns/detect/exp/weights/best.pt datadata.yaml这个命令会输出详细的评估表格包括每个类别的精确率、召回率、mAP50和mAP50-95。仔细分析这个表格哪个类别表现最差可能是该类别样本数量太少需要数据增强或收集更多数据或者该类别与其他类别特征相似如“塑料瓶”和“易拉罐”。混淆矩阵 (confusion_matrix.png)查看模型最容易将哪个类别误判为另一个类别。这能给你提供改进标注质量或调整类别定义的思路。4.5 模型测试与推理演示最后用训练好的模型看看实际效果# 在单张图片上测试 yolo taskdetect modepredict modelruns/detect/exp/weights/best.pt sourcepath/to/test_image.jpg saveTrue # 在视频上测试 yolo taskdetect modepredict modelruns/detect/exp/weights/best.pt sourcepath/to/video.mp4 saveTrue # 使用摄像头实时检测 yolo taskdetect modepredict modelruns/detect/exp/weights/best.pt source0 showTrue预测结果会保存在runs/detect/predict目录下。这是最有成就感的环节你可以直观地看到模型在你关心的场景下的表现。5. 小数据集训练的挑战、技巧与进阶优化只有892张图片在深度学习领域确实属于“小数据集”。直接训练很容易过拟合模型只记住了训练集而无法泛化到新图片。除了上面提到的调整数据增强和正则化参数还有几个进阶技巧可以尝试5.1 利用预训练权重与冻结层训练YOLOv8的.pt文件是在COCO等大型数据集上预训练好的其特征提取器已经学会了识别通用物体边缘、纹理、形状等。对于小数据集微调 (Fine-tuning)是必须的。更精细的策略是分阶段冻结训练阶段一冻结骨干网络。只训练检测头Head让模型先适应我们数据集的特定类别。# 这个功能可能需要通过修改代码或使用train.py参数实现YOLOv8 CLI暂未直接提供。 # 一种思路是加载模型后手动设置部分参数的 requires_gradFalse然后进行训练。实际操作中对于小数据集直接使用较低的lr0如0.001进行全网络微调通常也能取得不错的效果且更简单。5.2 针对性的数据增强策略对于道路垃圾检测我们可以设计更贴合场景的增强模拟天气变化适度增加hsv_v明度的扰动模拟阴天或傍晚光线变暗增加hsv_s饱和度扰动模拟不同色温的光照。模拟拍摄角度微小的shear剪切和perspective透视可以模拟摄像头不是绝对水平的情况。模拟遮挡合理使用erasing随机擦除或cutout模拟垃圾被部分遮挡的场景。谨慎使用旋转道路垃圾通常不会“倒立”或大角度旋转所以degrees最好设为0或一个很小的值如5.0。5.3 类别不平衡问题处理检查你的数据集很可能“塑料袋”的样本远多于“废旧家具”。类别不平衡会导致模型偏向于多数类。解决方法数据层面对少数类图片进行过采样重复使用或使用Mosaic、MixUp增强时有意识地多使用少数类图片。损失函数层面YOLOv8默认使用带标签平滑的交叉熵和DFL损失。对于严重不平衡可以尝试在model.train()中调整cls_pw分类正样本权重参数但需谨慎。5.4 模型集成与测试时增强 (TTA)如果计算资源允许训练多个不同初始化或不同数据增强版本的模型然后将它们的预测结果进行集成如加权平均往往能提升最终精度。此外测试时增强 (Test Time Augmentation, TTA)也是一种有效的后处理技巧它会在推理时对输入图像进行多种变换翻转、缩放等然后将所有变换的预测结果合并通常能提升mAP但会显著增加推理时间。yolo predict modelbest.pt sourcetest.jpg imgsz640 augmentTrue5.5 实际部署中的精度-速度权衡训练出的模型最终要部署。你需要根据硬件平台服务器、边缘计算盒子、手机来权衡。服务器端对延迟不敏感可以选用yolov8l甚至yolov8x并开启TTA追求最高精度。边缘设备 (如Jetson Nano)对速度和功耗敏感应选用yolov8n或yolov8s并将imgsz降到416或320同时使用TensorRT或ONNX Runtime进行加速。量化与压缩使用PyTorch的量化工具或Ultralytics提供的导出功能将FP32模型转换为INT8模型可以大幅减少模型体积和提升推理速度精度损失通常很小。从892张VOC格式的图片开始到训练出一个能实际检测城市道路垃圾的YOLO模型这个过程涵盖了目标检测项目绝大部分的核心环节。数据是基础理解格式转换的细节能避免很多低级错误训练是核心耐心调整参数、监控指标、分析结果决定了模型的上限而针对小数据集的优化技巧和部署考量则是一个项目从“跑通”到“好用”的关键。这个数据集虽然不大但作为一个完整的实践案例其价值在于提供了一个可复现的闭环。你可以在此基础上尝试收集更多场景的数据如雨天、夜间增加新的垃圾类别或者尝试集成到更复杂的业务系统中让这个模型真正产生价值。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。