恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

城市道路井盖破损丢失数据集:双格式标注与YOLOv5训练实战指南

  • 首页
  • 资讯中心
  • /
  • 城市道路井盖破损丢失数据集:双格式标注与YOLOv5训练实战指南

相关资讯

DHUOJ基础题25-27解析:素数判断、整数倒序与回文串的边界处理 2026/10/10 21:26:26
自注册、AST发现与中央分发派系:弹性工具运行时架构解析 2026/10/10 21:26:26
基于YOLOv8的道路病害检测平台:从模型训练到前后端部署全流程 2026/10/10 21:26:26

最新资讯

Claude Code、Codex++、OpenCode 三连击:3.0 Flash 接入全家桶最新姿势
在CentOS7中安装vcs、verdi
基于SpringBoot的个人任务管理系统-附源码
2.5亿次下载里程碑达成:发布多年的句向量老模型,刚刚在中文社区悄悄翻红
一张 3090 就能跑的全栈国产模型:企业本地 AI 办公要变天了?
基于深度学习边缘检测实战:HED模型、BSDS500与PyTorch实现

今日推荐

Codex 总用英文回答?从 AGENTS.md 到 config.toml 的中文输出调优指南
OpenClaw 自定义插件开发完整指南(2026最新版):从 TypeScript 到 npm 发布
基于Spark的电影推荐系统全链路实战:从爬虫到Web展示

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

城市道路井盖破损丢失数据集:双格式标注与YOLOv5训练实战指南

发布时间:2026/10/10 21:31:26
城市道路井盖破损丢失数据集:双格式标注与YOLOv5训练实战指南 简介城市道路井盖破损丢失目标检测数据集面向智慧交通与市政养护场景适合算法工程师与科研人员用于道路安全隐患识别模型训练。数据包含一千三百七十七张实拍井盖图像采用Pascal VOC与YOLO双格式标注覆盖四个类别包括正常井盖、破损井盖、丢失井盖等总计一千七百二十二个标注框类别间样本量从几十到数百不等便于研究真实场景下的类别不均衡问题可直接加载至主流检测框架。压缩包内约有两千个文件包含JPG图像以及配套的XML、TXT标注文件大小约二百一十二点三五兆字节目录结构清晰免去格式转换步骤。标注由LabelImg完成边界框定位精细适合作为基础训练集或评估基准。目前已有四百三十人学习可为井盖破损丢失识别项目提供高质量样本支撑。1. 城市道路井盖破损丢失数据集1377张图、4类别、双格式标注直接能用干过市政巡检或路面病害检测的都知道井盖数据在公开数据集里几乎找不到——要么是单独几张样例图要么混在“道路病害”里被压得特别小。这份资源直接把坑填了1377张jpg图片全部带Pascal VOC格式的xml和YOLO格式的txt标注文件4个类别一共1722个标注框。类别名是缩写jg井盖、jg_ds丢失、jg_nd破损、jg_ps破碎/松散。不用自己做格式转换下载解压就能喂给YOLOv5或YOLOv8训练。适合谁做城市部件检测、道路巡检算法、甚至智慧城市项目的算法工程师和研究生拿来就能当训练集或预训练数据用。2. 四个类别的标注逻辑与数据分布先看懂再动手2.1 类别缩写与判定边界jg_ds和jg_ps不要搞混拿到数据集第一件事不是跑训练是打开labelImg看一眼xml里每个框的类别是怎么标的。从分布上看jg框数872、jg_ps框数623、jg_ds框数177、jg_nd框数50。jg是正常井盖jg_ds是井盖丢失只剩洞或临时围挡jg_ps是破损但还在原位jg_nd我理解为内部断裂或下沉——但这三种边界容易混井盖缺一角算nd还是ps从数据里看ps框数明显多标注时倾向于把“有明显破损”的归入psnd只有50框大概率是“肉眼能看出下陷或断裂但表面相对完整”的极端样本。训练时如果发现这几个类别互相误检先怀疑标注边界不要急着调模型。2.2 VOC和YOLO文件的对应关系三个文件同名不同后缀解压后每个样本有三个同名文件xxx.jpg、xxx.xml、xxx.txt。xml是labelImg的默认输出记录的是xmin/ymin/xmax/ymax绝对像素坐标和类别名txt是YOLO格式每行是class_id x_center y_center width height都是归一化到0-1的小数。用下面的Python脚本可以快速校验txt里的坐标是否和xml一致import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, width640, height640): tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) boxes [] for obj in root.findall(object): name obj.find(name).text bnd obj.find(bndbox) xmin int(bnd.find(xmin).text) ymin int(bnd.find(ymin).text) xmax int(bnd.find(xmax).text) ymax int(bnd.find(ymax).text) x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h boxes.append(f{name} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) return boxes # 用法传一个xml路径返回的是YOLO格式的文本行 # 注意txt里的class_id是数字需要自己维护一个类别到id的映射比如 jg:0, jg_ds:1, jg_nd:2, jg_ps:3这段代码的作用是解析VOC格式的xml提取目标框坐标并归一化。注意txt文件里第一列是类别编号而不是类别名如果你的训练代码里类别顺序和数据集不一致预测结果全乱。我一般会先跑一遍全量对比确保xml和txt坐标误差在0.001以内。2.3 训练集/验证集划分不要直接随机切1377张图说多不多说少不少。如果随机划分类别占比极小的jg_nd50框可能全落到验证集里训练时模型没见过这个类别。常见做法是按“每个类别的框数分布”做分层采样import random from collections import defaultdict # 假设已有 train_files.txt 和 val_files.txt 两个列表 # 按图片包含的类别做分层抽样保证每个类别在训练集里至少有80%的框 random.seed(42) train_ratio 0.8 val_files [] train_files [] category_to_files defaultdict(list) # 先扫描所有txt建立 类别 - 图片路径 的映射 for txt_file in all_txt_files: with open(txt_file, r) as f: lines f.readlines() cats set() for line in lines: cat_id int(line.split()[0]) cats.add(cat_id) for c in cats: category_to_files[c].append(txt_file.replace(.txt, .jpg)) # 从每个类别里抽20%作为验证集避免某个类别全被分到一边 for cat_id, files in category_to_files.items(): random.shuffle(files) split_point int(len(files) * train_ratio) train_files.extend(files[:split_point]) val_files.extend(files[split_point:]) # 去重 train_files list(set(train_files)) val_files list(set(val_files)) print(ftrain: {len(train_files)}, val: {len(val_files)})这段分层采样的核心是避免“稀有类别丢失”。你可能会发现某个类别只有50个框如果按图片比例分验证集里可能只剩10个框mAP算出来方差极大。分层采样后jg_nd在训练集里至少能保留40个框模型还能学到个大概。注意顶层random.seed(42)固定下来方便复现。3. 把VOCYOLO双格式接进YOLOv5训练一条命令不够要改三个文件3.1 数据集yaml配置类别顺序必须和txt里的class_id一致YOLOv5系列训练前要建一个dataset.yaml指定图片路径、标签路径和类别名。这里的坑在于names列表的下标就是txt里class_id的含义数据集里jg是0还是jg_ds是0决定了你的模型预测结果怎么解释。看数据的txt格式常见做法是把类别名按字母序或拼音序映射但这份数据集没有随包给出classes.txt所以要自己先扫一遍txt确认实际id顺序# 在数据集根目录执行统计每个class_id出现的次数 awk {print $1} labels/train/*.txt | sort | uniq -c跑完你就知道class_id 0对应哪个类别了。假设输出是0: 872, 1: 177, 2: 50, 3: 623那names按[jg, jg_ds, jg_nd, jg_ps]写就对了。如果顺序对不上轻则训练正常但评估时类别标签全错位重则loss直接不收敛——这种问题报错还不提示纯粹靠人肉排查。3.2 labelImg标注的隐含习惯某些框可能没贴紧目标用labelImg标注的人习惯不一样有人框得紧贴着目标边缘有人框得松留10-20像素背景。这份数据集的框我抽查时发现部分jg_ds框会把旁边的路沿带进去因为在图片上井盖丢失就是一个黑洞边缘不清晰标注员容易把整个洞加阴影区域框进去。YOLO训练对框的宽容度比Faster R-CNN高但如果你要做部署建议训练前做一次“框紧缩”处理import cv2 import numpy as np def shrink_box(xml_path, ratio0.05, min_size20): # 读取xml并获取所有目标框 tree ET.parse(xml_path) root tree.getroot() for obj in root.findall(object): bnd obj.find(bndbox) xmin int(bnd.find(xmin).text) ymin int(bnd.find(ymin).text) xmax int(bnd.find(xmax).text) ymax int(bnd.find(ymax).text) w xmax - xmin h ymax - ymin if w min_size or h min_size: continue # 小目标不缩避免缩没了 dx int(w * ratio) dy int(h * ratio) bnd.find(xmin).text str(xmin dx) bnd.find(ymin).text str(ymin dy) bnd.find(xmax).text str(xmax - dx) bnd.find(ymax).text str(ymax - dy) tree.write(xml_path, encodingutf-8)这个脚本把每个框向内收缩5%目的是去掉标注时带进来的背景边缘。注意这里只改了xmltxt也要同步改不然训练时YOLO读的是txt等于白改。改完记得重新生成txt或者直接用脚本一并处理。3.3 训练超参建议小数据集别盲抄默认值1377张图、4个类别用YOLOv5s起步。默认的epochs300对这个数据量偏多我建议epochs150加patience20早停。batch-size取决于显存8G显存用1624G显存用32。关键参数在hyp.scratch.yaml里# 训练命令注意 --cache 会把图片加载到内存1377张图大概占2G内存可以开 python train.py \ --data dataset.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 150 \ --cache \ --patience 20 \ --name manhole_cover_run--img 640是训练分辨率如果你的部署环境是边缘设备Jetson Nano之类用--img 416训练和推理对齐模型速度能快30%但小目标检测能力会下降。井盖在街景图里通常占画面比例不小640是安全选择。--patience 20意味着连续20个epoch验证集mAP不涨就停能省不少时间——别小看这个参数默认的patience100在这个数据量下基本是浪费时间。4. 避坑指南训练这1377张图最容易翻车的四个地方4.1 现象loss降不下去mAP一直在0.05附近原因大概率是txt里的class_id和yaml里的names对不上。怎么排查跑一下数据校验脚本把xml里的类别名和txt里的class_id映射打出来逐行对。之前帮人排查过一个问题他下载的数据集txt第一列全是0以为是标注错误后来发现是labelImg导出时勾选了“use default class”结果所有目标都归到类别0。这个数据集本身没这个问题但下载后保不齐被人改过先校验再训练。4.2 现象训练正常但验证时jg_ds的召回率几乎为0原因177个框里很多是远距离小目标井盖丢失后在画面里就是一个暗色小点。YOLO的默认anchor是COCO数据集聚类出来的对中等大小目标友好小目标效果差。解决开启--multi-scale训练或者用k-means重新聚类anchor命令是python utils/autoanchor.py --data dataset.yaml。聚类完把新anchor写进模型yaml再训练一轮通常能把召回率拉起来。4.3 现象jg和jg_ps互相误检严重类别阈值调了也没用原因标注边界模糊——井盖正常和井盖破损在视觉上本身就是一个连续过渡同一个井盖在不同光照、不同拍摄角度下看起来完全不一样。这不是模型问题是标注一致性问题。解决检查训练集里是否存在同一个井盖同时出现在jg和jg_ps两个类别里的情况如果看图片确实分不清建议合并类别只分“完好”和“破损”二类模型会稳定得多。这个数据集的jg_nd只有50框如果它和别的类混着优先合并。4.4 现象验证集mAP高但实际部署时误检一堆原因这个数据集里的图片来源看起来是路面采集车或人工拍摄光照条件相对一致背景也以沥青路面为主。你部署到城市路口遇到雨天反光、井盖被树叶遮挡、或者井盖周围有大量路标文字干扰模型就会虚。解决训练完别急着上生产先跑一遍视频流测试收集误检样本用“难例挖掘”的方式把误检帧加入训练集重新微调。这个循环做一次模型在真实场景的表现能上一个台阶。5. 数据增强与类别均衡50个jg_nd框怎么让它不拖后腿5.1 针对性增强不等于无脑用MosaicYOLOv5默认开Mosaic增强但对小数据集有个副作用Mosaic把4张图拼在一起目标缩小成原来的1/2本来就小的井盖框更小。jg_nd只有50框Mosaic一打有效学习信号更弱。我的做法是关掉Mosaic改用copy-paste增强把井盖实例复制到其他图上随机位置同时复制标注框# 用imgaug库做copy-paste增强的伪代码示例 import imgaug.augmenters as iaa import numpy as np def copy_paste_augment(image, boxes, labels, paste_count1): # boxes格式: [[x1,y1,x2,y2], ...] # 从现有目标里随机选一个井盖实例 for _ in range(paste_count): idx np.random.randint(len(boxes)) x1, y1, x2, y2 boxes[idx] w, h x2 - x1, y2 - y1 # 随机找一个新的放置位置保证不超出图边界 new_x1 np.random.randint(0, image.shape[1] - w) new_y1 np.random.randint(0, image.shape[0] - h) # 把该区域像素复制过去 image[new_y1:new_y1h, new_x1:new_x1w] \ image[y1:y2, x1:x2] # 同步更新boxes和labels return image, boxes, labels注意复制粘贴时不要覆盖原有的其他目标不然模型会学到“井盖总是一前一后挨着”。这个增强对jg_ds井盖丢失视觉上是一个洞效果一般但对jg_ps破损井盖有纹理特征效果很好。跑增强后jg_nd的框数从50能扩到200以上训练稳定性明显提升。5.2 类别权重loss里加权比重复采样更平滑另一个做法是在训练时给稀有类别加权重。YOLOv5不直接支持按类别加权loss但可以在数据集加载时对稀有类别的样本做过采样或者用--cls参数调分类损失的系数。过采样实现简单按类别统计框数对含jg_nd的图片复制一份放进训练列表里让模型每个epoch多看到几次。代码如下import random def oversample_txt_files(txt_files, target_cat_id2, factor3): 对包含稀有类别比如id2的txt文件对应的图片做重复采样 new_list [] for txt in txt_files: with open(txt, r) as f: cat_ids [int(line.split()[0]) for line in f.readlines()] if target_cat_id in cat_ids: # 该图片包含稀有类别重复factor次 new_list.extend([txt] * factor) else: new_list.append(txt) return new_list # 用法把返回的new_list写入train.txtYOLO会按这个列表读图 # 注意factor不是越大越好3-5倍即可太大容易过拟合说到底50个框的类别在训练集里就是接近“边缘存在”的状态靠增强和过采样能让模型“记住”它但别指望它能像jg那样稳。如果你的场景对jg_nd要求很高建议补拍数据或者用迁移学习从别的道路病害数据集里筛选类似样本加进来。6. 验证模型没白训用混淆矩阵和可视化框来验收别只看mAP训练完不是看一眼results.png就算完事。我之前有过一次经历val mAP到了0.82看着不错结果跑视频检测时发现模型把路面上所有圆形的阴影都当成井盖。从那以后我每次训完检测模型都强制自己走一遍下面三个步骤第一步跑val.py导出混淆矩阵。看jg和jg_ps之间的混淆程度如果混淆矩阵里这两个类互为误检的比例超过20%说明标注边界问题在模型里被放大了这时候要么合并类别要么加大这两个类别的样本量和标注精度。混淆矩阵文件一般在runs/val/exp*/confusion_matrix.png一眼能看出问题。第二步挑20张验证集里预测置信度在0.3到0.6之间的“模糊样本”用detect.py标注可视化人工看图判断模型到底是真错还是标注错了。如果模型把井盖周围的圆形污水盖也识别成井盖这是合理的——污水盖本身也是井盖的一种看你的业务要不要区分。如果需要区分就得加类别定义或后处理逻辑。第三步跑一个真实场景的小视频哪怕手机拍的10秒街景把检测结果逐帧保存下来看稳定性。静止图片mAP高不代表连续帧稳定井盖在画面里移动时会出现一帧检测到、下一帧丢失、再下一帧又检出的抖动。这种问题调阈值没用要做序列级别的平滑——常见的做法是维护一个滑动窗口连续N帧都检测到才输出中间丢帧不超过M帧就保持上次输出。代码逻辑不复杂但很多做检测的人根本不往这个方向想。这份数据集本身是干净的格式规范类别覆盖了井盖的主要异常状态但干净的数据也需要正确的使用姿势。把类别边界想清楚、把稀有类别的增强做到位、把验证流程跑扎实1377张图能撑起一个够用的井盖检测模型。希望这份拆解能帮到你省下自己趟坑的时间。本文还有配套的精品资源点击获取

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号