简介:本资源面向工业视觉检测方向的算法工程师与深度学习学习者,提供一套可直接用于YOLO系列目标检测训练的工业指针仪表数据集,帮助解决真实产线场景下仪表读数识别样本不足、标注格式不统一的问题。压缩包共2000个文件,约427.86MB,包含1000张真实场景采集的高质量图片,以及对应的voc(xml)、coco(json)与yolo(txt)三种格式标签,另附yaml配置文件、Python划分脚本与多份html教程文档,覆盖环境搭建、训练流程与数据集划分等环节。资源同时提供训练集、验证集、测试集的划分脚本,可按需自行切分数据,适配不同实验方案。目前已有259人学习下载,适合希望快速复现工业仪表检测任务、验证模型效果或开展课程实践的中高级读者参考使用。
1. 工业指针仪表检测数据集:1000 张真实场景图与三格式标签怎么落地
工厂巡检场景里,指针式仪表读数一直是个老大难。人工抄表效率低、夜间和高压柜场景还有安全风险,用 YOLO 做表盘定位和指针识别是这两年比较常见的落地路径。但真正动手时,卡住大多数人的不是模型结构,而是数据——公开数据集里工业表盘少、标注质量参差、格式还不统一。这份 YOLO 工业指针仪表检测数据集就是冲着这个痛点来的:1000 张真实场景图片,覆盖不同光照、角度和表盘类型,用 labelImg 标注,同时提供 VOC(xml)、COCO(json)、YOLO(txt)三种格式标签,还附了划分脚本和 Linux/Windows 两套环境搭建与训练教程。适合刚接触工业检测的算法工程师、做课程设计的学生,以及需要快速验证表盘检测方案的技术团队。下面按「数据长什么样 → 怎么划分 → 怎么训练 → 坑在哪」的顺序拆一遍。
2. 三格式标签与目录结构:先搞清楚手里有什么
2.1 VOC、COCO、YOLO 三种标签的差异与选用
同一批图片配三套标签,不是重复劳动,而是为了对接不同训练框架和评估工具。VOC 格式是每张图一个 xml,框的坐标是左上角和右下角的绝对像素值;COCO 格式把所有图片的标注汇总成一个 json,框是[x, y, width, height]的绝对坐标,还带类别 id 和图片 id 的映射;YOLO 格式是每张图一个 txt,每行class_id x_center y_center width height,全部归一化到 0~1。
选哪个取决于你的训练入口。用 Ultralytics 的 YOLOv5/v8 系列,直接吃 YOLO txt 最省事;用 Detectron2 或 MMDetection,COCO json 更顺;如果要做数据清洗或转其他格式,VOC xml 可读性最好。这份资源把三套都给了,等于省掉了自己写转换脚本的环节。
| 格式 | 文件组织 | 坐标类型 | 典型框架 |
|---|---|---|---|
| VOC | 每图一个 xml | 绝对像素 | 早期 YOLO、SSD |
| COCO | 单个 json | 绝对像素 | Detectron2、MMDetection |
| YOLO | 每图一个 txt | 归一化 0~1 | YOLOv5/v8、YOLO 系列 |
提示:三种格式的类别顺序必须一致,否则训练出来的类别名会错位。拿到数据后先核对
classes.txt或 json 里的categories。
2.2 目录结构与文件清单核对
解压后建议先别急着跑脚本,花两分钟把目录过一遍。典型结构是图片放一个文件夹,三个标签格式各放一个文件夹,根目录下是划分脚本和教程 html。核对时重点看三件事:图片数量和标签数量是否对得上、有没有空标签文件、类别名是否统一。
# 统计图片数量 find ./images -type f \( -name "*.jpg" -o -name "*.png" \) | wc -l # 统计 YOLO 标签数量 find ./labels_yolo -type f -name "*.txt" | wc -l # 找出空标签文件(可能是漏标或负样本) find ./labels_yolo -type f -name "*.txt" -empty第一行统计图片总数,正常应该是 1000 左右;第二行统计 YOLO 标签数,理论上和图片数一致,如果少了说明有图没标;第三行找空文件,空标签在 YOLO 里表示负样本,但如果是漏标就得补。这三步做完,心里对数据质量就有底了。
2.3 类别定义与标注质量初判
工业指针仪表检测通常只关心一到两个类别,比如「表盘」或者「表盘+指针」。打开几个 xml 或 txt 看看框是不是紧贴表盘边缘,有没有把整个仪表箱都框进去。labelImg 标注的框一般比较规整,但真实场景里如果有遮挡、反光,框的边界可能会有偏差。
import os import glob # 检查 YOLO 标签的坐标是否越界 label_dir = "./labels_yolo" bad_files = [] for txt in glob.glob(os.path.join(label_dir, "*.txt")): with open(txt, "r") as f: for line in f: parts = line.strip().split() if len(parts) != 5: bad_files.append((txt, "字段数不对")) continue cls, x, y, w, h = map(float, parts) if not (0 <= x <= 1 and 0 <= y <= 1 and 0 < w <= 1 and 0 < h <= 1): bad_files.append((txt, "坐标越界")) print(f"异常文件数: {len(bad_files)}") for item in bad_files[:10]: print(item)这段脚本遍历所有 YOLO txt,检查每行是不是 5 个字段、中心点和宽高是否在 0~1 之间。越界的框在训练时会报错或者被静默丢弃,提前查出来能省不少调试时间。如果异常文件多,说明标注或转换环节有问题,得回头处理。
3. 数据集划分脚本:train/val/test 怎么切才不翻车
3.1 三个划分脚本的分工与选用
资源里给了三个划分脚本,名字就能看出区别:训练集、验证集、测试集划分脚本(图片标签划分写入新文件夹).py是把图片和标签一起复制到新的 train/val/test 文件夹;训练集、验证集划分脚本(图片标签划分写入新文件夹).py只切两份;split_train_val生成ImageSets下txt文件划分脚本.py不复制文件,只生成 ImageSets 下的 txt 索引,适合不想动原始文件的场景。
我一般优先用第三个,因为索引方式不占额外磁盘,而且改比例只要重跑脚本,不用删文件夹。但如果你的训练框架只认文件夹结构,那就用前两个。
3.2 按比例划分的脚本实操
以生成 ImageSets 索引的脚本为例,核心逻辑是读所有图片文件名,打乱后按比例切分,写入 train.txt、val.txt、test.txt。
import os import random # 配置路径和比例 image_dir = "./images" output_dir = "./ImageSets" train_ratio = 0.7 val_ratio = 0.2 test_ratio = 0.1 # 收集所有图片名(不带扩展名) names = [os.path.splitext(f)[0] for f in os.listdir(image_dir) if f.lower().endswith((".jpg", ".png", ".jpeg"))] random.seed(42) # 固定随机种子,保证可复现 random.shuffle(names) n = len(names) n_train = int(n * train_ratio) n_val = int(n * val_ratio) train_list = names[:n_train] val_list = names[n_train:n_train + n_val] test_list = names[n_train + n_val:] os.makedirs(output_dir, exist_ok=True) for split, data in [("train", train_list), ("val", val_list), ("test", test_list)]: with open(os.path.join(output_dir, f"{split}.txt"), "w") as f: f.write("\n".join(data)) print(f"{split}: {len(data)} 张")random.seed(42)是关键,固定种子后每次划分结果一致,方便复现实验。比例按 7:2:1 切,如果数据量小可以调成 8:1:1。脚本只写文件名不带路径,训练时在配置文件里拼上图片和标签目录就行。
3.3 划分后的校验与常见比例选择
切完之后别直接开训,先校验一下三个集合有没有重叠、总数对不对。
# 校验划分结果 def load_list(path): with open(path) as f: return set(f.read().strip().split("\n")) train = load_list("./ImageSets/train.txt") val = load_list("./ImageSets/val.txt") test = load_list("./ImageSets/test.txt") print("总数:", len(train) + len(val) + len(test)) print("train∩val:", len(train & val)) print("train∩test:", len(train & test)) print("val∩test:", len(val & test))交集应该全是 0,总数应该等于图片总数。如果交集不为空,说明脚本有 bug 或者文件名有重复。比例方面,工业检测数据量不大时,验证集至少留 100 张以上才有统计意义,测试集可以少留甚至不留,用验证集代替。
注意:划分前一定要打乱,否则如果图片是按时间或批次命名的,顺序切分会导致训练集和验证集分布不一致,验证指标虚高。
4. 环境搭建与训练:Linux 和 Windows 两条路
4.1 Linux/Ubuntu 环境搭建要点
资源里的 Linux 教程覆盖了 Ubuntu 下装显卡驱动、CUDA、cuDNN、Anaconda 和 PyTorch 的流程。实际踩下来,最容易出问题的是驱动版本和 CUDA 版本不匹配。常见做法是先nvidia-smi看驱动支持的 CUDA 上限,再选对应的 PyTorch 版本。
# 查看显卡和驱动 nvidia-smi # 创建 conda 环境 conda create -n yolo python=3.9 -y conda activate yolo # 安装 PyTorch(以 CUDA 11.8 为例,具体按 nvidia-smi 结果调整) pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 验证 GPU 是否可用 python -c "import torch; print(torch.cuda.is_available())"最后一行输出 True 才算环境通了。如果 False,先查驱动,再查 PyTorch 版本和 CUDA 是否对应。这一步不通,后面训练全是 CPU 在跑,速度差几十倍。
4.2 Windows 环境搭建与 Anaconda 配置
Windows 教程的思路类似,用 Anaconda 建环境,装 PyTorch 和 Ultralytics。Windows 上常见的问题是路径里有中文或空格导致各种奇怪报错,建议把数据集和代码都放在纯英文路径下,比如D:\yolo_project\。
# Windows 下同样先建环境 conda create -n yolo python=3.9 -y conda activate yolo pip install ultralytics # 验证 yolo checksyolo checks会输出环境信息,包括 PyTorch 版本、CUDA 是否可用、依赖是否齐全。如果提示缺包,按提示补装即可。
4.3 用自带教程改自己的数据集训练
教程里的案例是改配置文件指向自己的数据。以 YOLOv8 为例,需要写一个 data.yaml,指定 train/val 路径、类别数和类别名。
# data.yaml path: ./dataset train: ImageSets/train.txt val: ImageSets/val.txt nc: 1 names: ["meter"]path是数据集根目录,train和val是索引文件路径,nc是类别数,names是类别名列表。如果用的是文件夹结构而不是 txt 索引,把 train 改成images/train这种目录路径即可。
# 开始训练 yolo detect train data=data.yaml model=yolov8n.pt epochs=100 imgsz=640 batch=16model=yolov8n.pt是预训练权重,小模型适合快速验证;epochs=100根据数据量调整,1000 张图一般 100~200 轮够用;imgsz=640是输入尺寸,表盘目标不大的话可以提到 1280,但显存占用会翻倍。
4.4 训练过程监控与指标解读
训练时重点看三个指标:box_loss 是否稳定下降、mAP50 是否上升、验证集 loss 有没有反弹。如果训练 loss 降但验证 loss 升,说明过拟合,可以加数据增强或减轮数。
# 训练完成后在验证集上评估 yolo detect val model=runs/detect/train/weights/best.pt data=data.yaml输出的 mAP50 和 mAP50-95 是核心指标。工业表盘检测一般 mAP50 到 0.9 以上才算可用,如果低于 0.8,先查标注质量,再考虑调模型或加数据。
5. 避坑与排查:标注、划分、训练里的血泪经验
5.1 标签格式转换后类别错位
现象:训练时类别名显示成class_0或者完全不相干的名称。原因:VOC/COCO/YOLO 三套标签的类别顺序不一致,或者 data.yaml 里的 names 顺序和标签里的 class_id 对不上。解决:打开一个 xml 和一个 txt,核对类别名和 id 的对应关系,确保 data.yaml 的 names 列表顺序和标注时一致。
5.2 图片和标签文件名不匹配
现象:训练报错找不到标签,或者大量图片被跳过。原因:图片是001.jpg,标签是001.txt,但划分脚本生成的索引带了扩展名或者路径前缀。解决:统一用不带扩展名的文件名做索引,训练配置里再拼路径。跑一遍前面的校验脚本,确认图片和标签一一对应。
5.3 验证集指标虚高
现象:验证集 mAP 很高,但实际测试效果差。原因:划分时没打乱,训练集和验证集图片来自同一批次或同一场景,分布太接近。解决:划分前random.shuffle,并且按场景或时间做分层抽样,确保验证集能代表真实分布。
5.4 显存不足导致训练中断
现象:训练几轮后报 CUDA out of memory。原因:imgsz或batch设太大,或者没有及时释放缓存。解决:先把 batch 减半,或者把 imgsz 从 1280 降到 640。如果还不行,用yolo detect train ... cache=False关掉缓存。
5.5 指针和表盘混标导致漏检
现象:模型能框出表盘但读不出指针,或者指针被当成表盘的一部分。原因:标注时只标了表盘外框,没有单独标指针,或者两类目标混在一起。解决:如果任务需要读指针角度,建议把指针单独作为一个类别标注,训练时用多类别检测,后处理再算角度。
6. 进阶技巧:从检测框到指针读数的一步之遥
检测出表盘和指针只是第一步,真正要读数还得算指针角度。我一般会在检测框基础上做两件事:一是用表盘框裁剪出 ROI,减少背景干扰;二是对指针区域做骨架化或直线拟合,算相对 12 点方向的角度。
import cv2 import numpy as np def get_pointer_angle(roi): """输入指针 ROI,返回相对 12 点方向的角度""" gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 骨架化或霍夫直线 lines = cv2.HoughLinesP(binary, 1, np.pi / 180, threshold=50, minLineLength=30, maxLineGap=10) if lines is None: return None # 取最长直线 longest = max(lines, key=lambda l: np.hypot(l[0][2]-l[0][0], l[0][3]-l[0][1])) x1, y1, x2, y2 = longest[0] angle = np.degrees(np.arctan2(x2 - x1, y2 - y1)) return angle % 360这段代码先二值化,再用霍夫变换找直线,取最长的一条算角度。实际用的时候,表盘中心点可以用检测框中心近似,或者单独训练一个中心点检测。角度算出来后,按表盘量程线性映射就能得到读数。
验证方法上,我习惯抽 20 张图人工核对读数,误差超过 5% 就回头查检测框和角度计算。另外,训练时可以把imgsz提到 1280 再训一版,对比 mAP 和实际读数误差,通常小目标提升明显。
从那以后我每次拿到新数据集,都强制先跑一遍格式校验和划分校验,再开训练。这两步花不了十分钟,但能省掉后面几小时的排查。希望帮到你。
本文还有配套的精品资源,点击获取