资讯动态

YOLO工业指针仪表检测数据集:1000张真实场景图片,三种标签格式与训练教程

发布时间:2026/10/5 4:01:10 来源:尧图企业网站定制
简介这份资源面向工业视觉检测方向的算法工程师、学生与科研人员提供一套可直接用于YOLO系列目标检测训练的工业指针仪表数据集帮助解决真实产线场景下仪表读数识别样本不足、标注格式不统一的问题。压缩包共2000个文件约427.86MB包含1000张真实场景采集的高质量图片以及对应的vocxml、cocojson与yolotxt三种格式标签另附yaml配置文件、划分脚本与教程页面方便按需转换与训练。资源还提供训练集、验证集、测试集划分脚本以及Windows与Linux双平台的YOLO环境搭建和训练案例教程读者可据此快速复现训练流程并迁移到自有数据。目前已有259人学习下载适合作为工业仪表检测项目的起步数据与实操参考。1. 工业指针仪表检测为什么值得单独做一份数据集做过变电站、化工厂或者产线巡检项目的朋友应该都有体会指针式仪表看着简单真要让模型稳定读数难点根本不在网络结构而在数据。表盘反光、指针细、刻度密、拍摄角度偏、光照忽明忽暗这些因素叠加起来通用 COCO 预训练权重直接拿来用mAP 往往掉得很难看。这份 YOLO 工业指针仪表检测数据集就是冲着这个场景来的——1000 张真实场景图片用 labelImg 标注同时给了 VOCxml、COCOjson、YOLOtxt三种格式标签还附了环境搭建、训练教程和划分脚本。它适合两类人一类是想快速跑通 YOLO 工业检测流程的新手另一类是手里有巡检项目、需要一个能直接改的基线数据集的从业者。下面我按「拿到手怎么用 → 参数怎么设 → 哪里会翻车」的顺序拆一遍。2. 三种标签格式怎么选VOC、COCO、YOLO 的差异与转换逻辑2.1 先搞清楚三种格式各自长什么样很多人拿到压缩包第一反应是「三个文件夹我该用哪个」。答案取决于你用的框架和训练脚本。这份数据集把三种格式分文件夹存放本质是同一批标注的不同序列化方式坐标含义完全一致只是组织方式不同。VOC 格式是每张图对应一个同名 xml里面用bndbox记录xmin/ymin/xmax/ymax坐标是绝对像素值原点在左上角。它的好处是可读性强labelImg 默认就吐这个格式方便人工复核。COCO 格式是一个大的 json包含images、annotations、categories三个核心数组bbox 是[x, y, width, height]注意这里是左上角坐标加宽高不是右下角。COCO 的类别 id 从 1 开始0 通常留给背景这点和 YOLO 差别很大。YOLO 格式是每张图一个 txt每行class_id cx cy w h全部是归一化到 0~1 的相对值cx cy是框中心点。它没有单独的类别文件类别靠data.yaml里的names列表顺序对应。格式文件形态坐标类型类别 id 起点典型用途VOC每图一个 xml绝对像素 xmin/ymin/xmax/ymax按 name 字符串labelImg 复核、转其他格式COCO单个 json绝对像素 x/y/w/h从 1 开始mmdetection、COCO 评测YOLO每图一个 txt归一化 cx/cy/w/h从 0 开始ultralytics YOLO 系列训练2.2 用脚本在三种格式之间转换如果你拿到的原始标注是 VOC但训练要用 YOLO就得转。下面这个脚本是我常用的 VOC 转 YOLO 写法逻辑清晰也方便你按自己类别改。import os import xml.etree.ElementTree as ET # 类别列表顺序决定 class_id必须和 data.yaml 的 names 完全一致 classes [meter] def voc_to_yolo(xml_dir, img_dir, out_dir): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() # 用图片实际尺寸做归一化不要用 xml 里的 size有些标注工具会写错 img_name xml_file.replace(.xml, .jpg) from PIL import Image w, h Image.open(os.path.join(img_dir, img_name)).size lines [] for obj in root.iter(object): cls obj.find(name).text if cls not in classes: continue cls_id classes.index(cls) bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) # 转成中心点 宽高再归一化 cx (xmin xmax) / 2.0 / w cy (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) with open(os.path.join(out_dir, xml_file.replace(.xml, .txt)), w) as f: f.write(\n.join(lines)) voc_to_yolo(Annotations, JPEGImages, labels)这段代码有三个关键点值得说。第一归一化用的是PIL读出来的真实图片尺寸而不是 xml 里size节点写的宽高——labelImg 偶尔会因为图片被替换而留下过时的 size直接用会得到错误的归一化坐标模型学出来的框会整体偏移。第二classes列表的顺序就是最终class_id一旦定了就不要改改了等于把之前训练的标签全废掉。第三if cls not in classes这行是过滤防止标注里混进拼写错误的类别名导致脚本崩溃。反过来如果你要把 YOLO 转回 VOC 做可视化复核核心就是乘回宽高、再算 xmin/ymin/xmax/ymax思路一样这里不重复贴。2.3 类别映射与 data.yaml 的对应关系YOLO 训练时读的是data.yaml它把图片路径、类别数、类别名绑在一起。这份数据集如果只有「指针仪表」一个类nc就是 1。常见错误是nc写成 2 但names只有一个训练不报错但评估时类别对不上mAP 直接归零。path: ./dataset train: images/train val: images/val test: images/test nc: 1 names: [meter]提示names的顺序必须和生成 txt 时classes列表的顺序一模一样差一个位置模型学到的就是错的类别。3. 数据集划分脚本怎么用train/val/test 与 ImageSets 两条路线3.1 两种划分脚本的适用场景压缩包里给了三个划分脚本名字分别是「训练集、验证集、测试集划分脚本」「训练集、验证集划分脚本」和「split_train_val 生成 ImageSets 下 txt 文件划分脚本」。前两个是直接把图片和标签复制/移动到新文件夹适合 ultralytics 这类按目录读数据的框架第三个是生成ImageSets/Main下的 txt 列表文件适合 VOC 风格或需要自己写 Dataset 类的场景。选哪个取决于你的训练代码怎么读数据。用 YOLOv8/v11 官方训练入口直接选前两个它会按images/train、labels/train这种目录结构找。用自己写的 PyTorch Dataset往往更习惯读一个 txt 列表那就用第三个。3.2 按目录划分的脚本执行流程以「训练集、验证集、测试集划分脚本」为例典型用法是把它和图片、标签放同级目录然后命令行传比例。# 假设目录结构images/ 放所有图labels/ 放所有 txt # 脚本会按 8:1:1 划分并把文件复制到 train/val/test 子目录 python split_train_val_test.py --img_dir ./images --label_dir ./labels --ratio 8 1 1执行后你会得到images/train、images/val、images/test和对应的labels/...。这里有个血泪经验脚本默认是复制不是移动所以原始images/里的图还在训练时如果data.yaml的train路径写错指到了总目录会把验证集图片也当训练数据喂进去指标虚高。跑完一定ls一下确认目录里只有划分后的子文件夹被引用。3.3 生成 ImageSets 列表的脚本与 train_list.txt第三个脚本生成的是ImageSets/Main/train.txt、val.txt这类文件每行一个图片名不带扩展名。压缩包里还带了一个train_list.txt可以理解成已经生成好的示例列表。如果你要自己写 Dataset读法大致是这样import os from PIL import Image class MeterDataset: def __init__(self, list_file, img_root, label_root, classes): self.classes classes with open(list_file) as f: # 去掉空行每行是一个图片名 self.names [x.strip() for x in f if x.strip()] self.img_root img_root self.label_root label_root def __getitem__(self, idx): name self.names[idx] img Image.open(os.path.join(self.img_root, name .jpg)).convert(RGB) # 标签路径按同名 txt 找 label_path os.path.join(self.label_root, name .txt) boxes [] if os.path.exists(label_path): with open(label_path) as f: for line in f: c, cx, cy, w, h map(float, line.split()) boxes.append([c, cx, cy, w, h]) return img, boxes参数说明list_file就是train.txt或val.txtimg_root是图片总目录label_root是标签总目录。注意name .jpg这里写死了扩展名如果你的图片是 png要么改代码要么在生成列表时统一扩展名。这是新手最容易卡住的地方——列表里存的是不带扩展名的名字读图时扩展名对不上就报 FileNotFound。3.4 划分比例与随机种子的坑划分脚本一般会带随机打乱。如果你没固定随机种子每次跑划分结果都不一样两次实验之间就没法公平对比。常见做法是在脚本里加random.seed(42)。另外工业仪表数据如果来自不同电站或不同批次最好按批次划分而不是纯随机——同一块表的不同角度照片如果同时进了训练和验证集验证指标会偏乐观实际部署到新表上就翻车。这一点在数据集只有 1000 张时尤其要注意。4. 环境搭建与训练Windows 和 Linux 两条线的实操要点4.1 环境搭建教程覆盖了什么压缩包里 Windows 和 Linux 各有一份环境搭建 htmlLinux 那份还带了 Ubuntu 安装教程。按常见做法YOLO 训练环境核心就三样Python 3.8~3.10、PyTorch带 CUDA、ultralytics 或对应版本的 YOLO 仓库。教程里给的是案例流程你照着装完用python -c import torch; print(torch.cuda.is_available())验证一下返回 True 才算 GPU 可用。Windows 上最容易出问题的是 CUDA 版本和 PyTorch 版本对不上装完torch.cuda.is_available()返回 False训练默默跑在 CPU 上1000 张图一个 epoch 能跑半小时。Linux 上相对顺但要注意驱动版本nvidia-smi右上角显示的 CUDA 版本是驱动支持的上限不是你必须装的版本装 PyTorch 时按官网给的组合来。4.2 用案例改自己的数据集教程的核心思路是「拿官方案例改路径和类别」。以 ultralytics 为例训练命令就一行yolo detect train data./data.yaml modelyolov8n.pt epochs100 imgsz640 batch16参数逐个说data指向你的 yamlmodel是预训练权重工业小数据集强烈建议从预训练起步别从零训epochs100 起步1000 张图通常 100~200 轮收敛imgsz640 是常规选择如果仪表在图中占比很小可以提到 960 或 1280但显存要够batch按显存调8G 显存 640 分辨率大概能到 16。改案例时最容易漏的是data.yaml里的路径。教程里的路径是相对官方案例写的你换成自己的绝对路径最稳省得被工作目录坑。4.3 训练日志里该盯哪几个指标跑起来之后别干等盯box_loss、cls_loss和验证集的mAP50。box_loss前期下降快是正常的cls_loss如果一直不降多半是类别映射错了或者标签里有脏数据。mAP50在工业仪表这种单类任务上数据干净的话 50 轮内应该能看到明显上升。如果 30 轮还趴着不动先别调参回去查标签——十有八九是归一化坐标越界或者类别 id 对不上。注意验证集 mAP 高不代表能读数。检测框准只是第一步指针角度回归是另一个问题这份数据集解决的是「找到表盘」读数逻辑要自己接。5. 避坑与排查这份数据集落地时最容易翻车的五件事5.1 标签坐标越界导致训练报错或静默失效现象训练启动就报AssertionError或者坐标相关异常或者不报错但 mAP 一直是 0。 原因VOC 转 YOLO 时如果用了 xml 里错误的size归一化后 cx/cy 可能大于 1 或小于 0。YOLO 对越界坐标有的版本直接断言失败有的版本静默裁剪后者更坑。 解决转换后加一步校验遍历所有 txt任何一行出现坐标不在 [0,1] 就打印文件名和行号人工回去看原图。import os for txt in os.listdir(labels): with open(os.path.join(labels, txt)) as f: for i, line in enumerate(f): parts line.split() if len(parts) ! 5: print(字段数不对, txt, i); continue vals list(map(float, parts[1:])) if any(v 0 or v 1 for v in vals): print(坐标越界, txt, i, vals)5.2 图片和标签文件名对不上现象训练时提示找不到标签或者某张图被跳过。 原因划分脚本复制文件时图片和标签的扩展名处理不一致比如图是.JPG大写标签是.txt脚本按小写匹配就漏了。 解决统一扩展名或者在脚本里做大小写无关匹配。跑完划分后统计一下images/train和labels/train的文件数量两者必须相等。5.3 类别 id 从 0 还是 1 开始搞混现象COCO 格式转 YOLO 后所有框都标成了背景或者错类。 原因COCO 的 category_id 从 1 开始YOLO 从 0 开始。直接拿 COCO 的 id 当 YOLO 的 class_id整体偏移一位。 解决转换时建一个coco_id - yolo_id的映射表别偷懒直接减一因为 COCO 的 id 可能不连续。5.4 验证集混入训练集导致指标虚高现象验证 mAP 0.95部署到新图上惨不忍睹。 原因划分时没按场景/批次分同一块表的多角度照片被随机分到了训练和验证两边。 解决按拍摄批次或设备编号分组划分保证验证集里的表在训练集里没出现过。1000 张图如果来自几十块表按表划分比按图随机划分靠谱得多。5.5 显存不足导致 batch 自动缩小现象设了 batch16日志里显示实际 batch 是 4训练变慢。 原因ultralytics 在显存不够时会自动降 batch不报错但影响收敛节奏。 解决要么降imgsz要么换更小的模型n 换 s 是反向n 最小要么老老实实把 batch 设成显存扛得住的真实值别让它偷偷降。6. 从检测框到指针读数一个可验证的进阶思路数据集把「找到表盘」这件事解决了但工业巡检真正要的是读数。这里给一个我实际用过的衔接思路不展开成完整项目但足够你验证数据集训出来的模型能不能往下走。第一步用训好的 YOLO 模型对整图推理拿到表盘 bbox 后裁剪出来。裁剪时往外扩 5%~10%避免表盘边缘被切掉导致后续刻度定位失败。第二步在裁剪图上做表盘圆心和刻度的定位。常见做法是霍夫圆检测找表盘外圆再按角度采样找刻度线。这一步对光照敏感建议先做直方图均衡或者 CLAHE。第三步指针检测。指针是细长目标用检测框回归角度不如用语义分割或者关键点。如果只有检测框可以取框的中心点连线和圆心的夹角作为指针方向但精度有限。第四步角度到读数的映射。指针式仪表刻度通常是线性的记录指针指向最小刻度和最大刻度时的角度做线性插值即可。非线性刻度的表比如某些压力表需要分段标定。import cv2 import numpy as np def read_meter(crop_img, angle_min, angle_max, val_min, val_max): # 灰度 自适应阈值突出指针 gray cv2.cvtColor(crop_img, cv2.COLOR_BGR2GRAY) gray cv2.equalizeHist(gray) # 霍夫圆找表盘 circles cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, gray.shape[0] / 8, param1100, param230, minRadiusint(gray.shape[0] * 0.3), maxRadiusint(gray.shape[0] * 0.5)) if circles is None: return None cx, cy, r circles[0][0] # 指针角度检测这里省略实际用轮廓或直线检测 # 假设已得到指针角度 pointer_angle pointer_angle 0 # 占位 # 线性映射到读数 ratio (pointer_angle - angle_min) / (angle_max - angle_min) return val_min ratio * (val_max - val_min)参数说明angle_min/angle_max是指针在最小/最大刻度时的角度需要你拿几张标注图手动量一次val_min/val_max是仪表量程。这段代码里指针角度检测是占位的实际项目里我用的是先二值化再找最长直线或者干脆训一个关键点模型。之所以把它写出来是想说明检测数据集和读数之间还隔着一层别指望 YOLO 直接输出读数。验证方法很简单挑 20 张没参与训练的表盘图人工读一遍数再跑一遍上面流程误差在满量程 2% 以内就算可用。超过 5% 就得回去看是指针检测偏了还是角度映射标定错了。从那以后我每次拿到新的仪表数据集都会先抽 10 张把标签画回原图上看一眼确认框和类别都对再开始训。这个习惯帮我省了无数次白跑一晚上的电费。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑