恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
LED数码管数据集构建与YOLOv8检测实战:从采集标注到边缘部署
首页
资讯中心
/
LED数码管数据集构建与YOLOv8检测实战:从采集标注到边缘部署
LED数码管数据集构建与YOLOv8检测实战:从采集标注到边缘部署
发布时间:2026/10/12 3:08:53
简介LED数码管数据集面向从事计算机视觉与数字识别方向的机器学习学习者与开发者聚焦ATM屏幕读取、仪表盘读数识别等需要解析七段数码管显示的实际场景。资源包共2000个文件以18901张jpg图像为主体辅以o、xml、makefile及rundetector等构建与配置文件压缩包约19.12MB图像像素直接对应各段LED的亮灭状态便于开展灰度化、二值化与边缘检测等预处理实验。目前已有2016人学习下载。数据集可用于训练CNN、SVM等模型覆盖图像归一化、数据增强、交叉验证、准确率与F1评估及正则化防过拟合等完整流程帮助读者从零搭建数码管数字识别系统并部署到工业自动化或智能家居读数场景。1. LED数码管数据集从采集到标注一个被低估的视觉落地场景工业现场里有一类识别需求长期被低估仪表盘上的 LED 数码管读数。它不像人脸识别那样有成熟的开源生态也不像通用目标检测那样随便找个预训练权重就能跑。但只要你进过配电房、水表间、老旧产线就会发现大量设备还在用七段数码管显示温度、压力、流量、电量。把这些读数自动采集上来是很多数字化改造项目绕不开的第一步。LED数码管数据集就是为这类任务准备的基础资源——它解决的不是“能不能识别”而是“在反光、倾斜、缺笔画、多位数连排的情况下还能不能稳定识别”。适合做工业巡检、边缘视觉、仪表自动抄录的开发者也适合想找一个真实场景练手 OCR 与检测组合拳的人。2. 先搞清楚七段数码管的数据长什么样采集、标注与格式选型2.1 为什么通用 OCR 在数码管上经常翻车通用 OCR 模型大多在自然场景文字上训练字符有笔画粗细变化、有上下文语义。七段数码管恰恰相反每个数字由固定位置的 7 段发光条组合而成笔画是离散的、有间隙的而且发光区域和背景对比度极高。这导致两个问题第一通用 OCR 会把“1”和“7”、“5”和“6”、“0”和“8”混淆因为它们的段组合差异在模型眼里只是几个像素块的开关第二数码管常有红色、绿色、黄色滤光片加上表面反光字符边缘会出现光晕通用 OCR 的预处理链路往往直接把它当噪声滤掉。我一般会建议把任务拆成两步先检测数码管区域再对区域做字符分割或序列识别。这样数据集也要对应两种标注粒度——检测框和字符级标签。如果只做端到端识别数据集里必须包含足够多的多位数连排样本否则模型学不会“位与位之间的边界”。2.2 采集时最容易忽略的四个变量采集 LED 数码管图像不是拿手机拍几张就完事。下面四个变量直接决定数据集能不能支撑落地变量建议覆盖范围不覆盖的后果拍摄角度0°、15°、30°、45° 倾斜模型只认正视图现场装歪就废光照条件白天自然光、夜间补光、强逆光反光导致笔画断裂识别率骤降数码管颜色红、绿、黄、白单一颜色训练换设备就翻车显示位数1位、2位、3位、4位及以上多位数边界切不准读数拼接错位采集时还要注意不要只拍“正常显示”的样本。缺笔画、闪烁瞬间、小数点常亮、负号显示这些边缘情况才是现场的真实分布。我见过一个项目训练集里全是完整数字上线后遇到一位数码管坏了半段模型直接把“8”读成“0”导致温度报警阈值判断错误。2.3 标注格式怎么选VOC、COCO 还是 YOLO标注格式取决于你下游用什么框架。如果做检测YOLO 系列用 txtMMDetection 用 COCO 或 VOC。如果做识别可以额外存一份字符级标签。下面是一个把 VOC 格式转成 YOLO 格式的脚本示例假设你已经用 labelImg 标好了检测框import xml.etree.ElementTree as ET import os # 类别映射0 表示数码管区域 CLASS_MAP {led_display: 0} def voc_to_yolo(xml_path, img_w, img_h, out_path): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in CLASS_MAP: continue cls_id CLASS_MAP[cls_name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # YOLO 格式中心点 x,y 和宽高全部归一化到 0-1 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines)) # 批量转换 for xml_file in os.listdir(annotations): if xml_file.endswith(.xml): # 这里需要根据文件名找到对应图片尺寸实际使用时从图片读取 img_w, img_h 1920, 1080 # 示例值务必替换为真实尺寸 voc_to_yolo( os.path.join(annotations, xml_file), img_w, img_h, os.path.join(labels, xml_file.replace(.xml, .txt)) )这段代码的关键点在于归一化坐标的计算。x_center和y_center是框中心点除以图像宽高w和h是框宽高除以图像宽高。参数CLASS_MAP里只保留你真正要检测的类别其他标注直接跳过。实际使用时图像尺寸必须从对应图片读取不能写死否则不同分辨率的样本会全部错位。另外如果一张图里有多个数码管每行一个框不要合并。2.4 数据集划分别让同一台设备的照片同时出现在训练和验证集这是血泪经验。很多人按 8:1:1 随机划分结果同一台仪表的不同角度照片被分到训练集和验证集验证指标虚高上线就崩。正确做法是按设备或按采集批次划分比如 10 台设备8 台进训练1 台验证1 台测试。如果设备数量不够至少按采集日期划分确保验证集里的光照、角度分布和训练集不重叠。# 按设备编号划分的目录结构示例 dataset/ ├── train/ │ ├── device_01/ │ ├── device_02/ │ └── ... ├── val/ │ └── device_09/ └── test/ └── device_10/这种划分方式能真实反映模型在“没见过的新设备”上的表现。如果验证集指标比训练集低很多别急着调模型先检查是不是划分方式有问题。3. 用 YOLOv8 跑通 LED 数码管检测从环境到推理的完整链路3.1 环境准备与数据配置文件假设你已经按上面的结构整理好了数据集接下来用 YOLOv8 做检测。环境安装不复杂但要注意版本匹配# 创建虚拟环境避免污染全局 python -m venv led_env source led_env/bin/activate # Windows 用 led_env\Scripts\activate # 安装 ultralytics它会自动拉取 torch 等依赖 pip install ultralytics # 验证安装 yolo checks然后创建数据配置文件led_dataset.yaml# 数据集根路径建议用绝对路径避免相对路径找不到 path: /data/led_display_dataset train: train/images val: val/images test: test/images # 类别数这里只有数码管区域一个类 nc: 1 names: 0: led_displaypath是数据集根目录train、val、test是相对路径。nc必须和标注文件里的类别 id 数量一致多一个少一个都会报错。names的顺序要和标注时的类别映射一致否则模型学出来的类别会错位。3.2 训练参数怎么设小目标场景的四个关键调整LED 数码管在整张图里往往只占很小一块属于典型小目标检测。默认参数直接跑召回率会很难看。下面是我一般会改的几个参数from ultralytics import YOLO # 加载预训练权重从 COCO 迁移过来比从头训练快得多 model YOLO(yolov8n.pt) # 开始训练 results model.train( dataled_dataset.yaml, epochs150, # 小目标需要更多轮次收敛 imgsz640, # 输入尺寸如果数码管特别小可以提到 1280 batch16, # 根据显存调整显存不够就降到 8 lr00.01, # 初始学习率迁移学习用 0.01 比较稳 lrf0.001, # 最终学习率余弦退火到初始的 1/10 patience30, # 30 轮没提升就早停省时间 augmentTrue, # 开启默认增强包括马赛克、翻转 mosaic1.0, # 马赛克增强概率小目标建议保持 1.0 scale0.5, # 随机缩放幅度模拟不同距离拍摄 device0 # 用第一块 GPU没有 GPU 写 cpu )imgsz是最关键的参数。如果数码管在原图里只有 50x20 像素缩到 640 后可能只剩 10x4特征几乎消失。这时候要么提高imgsz到 1280要么在标注时把数码管区域裁出来单独训练。mosaic增强对小目标有帮助因为它把四张图拼成一张变相增加了小目标的出现频率。scale设 0.5 表示随机缩放 50%模拟远近变化。3.3 推理与后处理把检测框变成可读数字训练完之后检测框只是第一步。要得到最终读数还需要在框内做字符识别。下面是一个推理加简单后处理的示例from ultralytics import YOLO import cv2 model YOLO(runs/detect/train/weights/best.pt) # 读取一张测试图 img cv2.imread(test_device.jpg) results model(img, conf0.5, iou0.45) # 遍历检测结果 for r in results: boxes r.boxes for box in boxes: # 获取框坐标 x1, y1, x2, y2 box.xyxy[0].tolist() conf box.conf[0].item() cls int(box.cls[0].item()) # 裁剪数码管区域 roi img[int(y1):int(y2), int(x1):int(x2)] # 这里可以接字符识别模型或传统分割方法 # 保存 roi 供后续处理 cv2.imwrite(froi_{conf:.2f}.jpg, roi) print(f检测到数码管区域置信度 {conf:.2f}坐标 ({x1:.0f},{y1:.0f})-({x2:.0f},{y2:.0f}))conf0.5是置信度阈值低于这个值的框直接丢弃。iou0.45是 NMS 的 IoU 阈值控制重叠框的合并程度。如果发现同一个数码管被检出多个框把iou调低如果漏检严重把conf调低但会引入误检。实际调参时建议画 PR 曲线找召回和精确率的平衡点。3.4 字符识别部分传统分割与轻量分类器的组合检测框出来之后识别数字有两种常见路线。一种是七段分割法把 ROI 二值化按固定位置切出 7 个段区域判断每段亮灭查表得到数字。这种方法可解释性强但依赖几何对齐倾斜或透视变形时容易错。另一种是训练一个轻量分类器把 ROI 缩放到固定尺寸直接分类 0-9 和小数点。我一般会先用分割法快速验证如果准确率不够再上分类器。import cv2 import numpy as np def segment_digits(roi): # 转灰度并二值化数码管发光区域为亮 gray cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) _, binary cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) # 按列投影找字符边界 col_sum np.sum(binary, axis0) # 找到连续非零区域作为单个数字 boundaries [] in_char False start 0 for i, v in enumerate(col_sum): if v 0 and not in_char: in_char True start i elif v 0 and in_char: in_char False boundaries.append((start, i)) # 对每个字符区域做七段判断或送入分类器 digits [] for s, e in boundaries: char_img binary[:, s:e] # 这里省略七段判断逻辑实际需要按比例切分七个段区域 digits.append(char_img) return digits这段代码只做了字符分割没有做段判断。实际使用时boundaries可能因为小数点或噪声产生多余区域需要根据宽高比过滤。如果数码管是连排的列投影可能分不开这时候要用连通域分析或垂直投影的谷值来切分。4. 避坑与排查LED数码管数据集训练中最容易翻车的五个点4.1 现象训练 loss 正常下降但验证集 mAP 始终为 0原因通常是类别映射错了。YOLO 要求标注文件里的类别 id 从 0 开始且和 yaml 里的names顺序一致。如果标注时用了 1 作为起始 id或者 yaml 里写了多个类别但标注只有一种验证时计算 mAP 会直接失败。解决方法是打开一个标注 txt 文件确认第一列数字和 yaml 里的nc对得上。另外如果验证集图片路径写错YOLO 会静默跳过表现为 mAP 为 0 但不报错。4.2 现象模型在训练集上表现很好换一台设备就识别错这是典型的过拟合到设备特征。数码管的外壳颜色、滤光片、背景纹理在不同设备上差异很大如果训练集只覆盖一两台设备模型会学到“外壳特征”而不是“数字特征”。解决办法是在采集阶段就覆盖多台设备或者在训练时加颜色抖动、随机裁剪、背景替换等增强。我一般会在augment里额外加hsv_h0.015、hsv_s0.7、hsv_v0.4让模型对颜色变化更鲁棒。4.3 现象反光导致笔画断裂模型把“8”读成“0”反光是 LED 数码管采集中最常见的干扰。强光打在滤光片上会在笔画中间形成白色高光二值化后笔画断开。解决分两个层面采集时尽量避开直射光用偏振片或调整角度训练时在数据增强里加随机亮度和对比度扰动让模型见过“断笔画”的样本。如果已经训练完可以在推理前做一次形态学闭运算把断裂的笔画连起来kernel cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) closed cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)闭运算的核大小要根据笔画宽度调太大糊成一团太小连不上。4.4 现象多位数数码管被检测成一个大框字符切不开YOLO 检测的是“数码管区域”如果一张图里有 4 位连排标注时如果只标一个大框模型就学不会分位。正确做法是每个数字单独标一个框或者标整个区域但在后处理时用投影法切分。如果选择投影法要注意数码管之间的间距很小列投影的谷值可能不明显。这时候可以先用检测框把整个区域裁出来再在 ROI 内做垂直投影配合固定宽度假设来切分。4.5 现象训练到一半显存爆了或者速度突然变慢显存问题通常出在imgsz或batch设太大。YOLOv8n 在 640 尺寸下 batch16 大约占 4-6GB 显存如果同时开了mosaic和mixup峰值会更高。解决方法是先降batch到 8再考虑降imgsz。速度变慢可能是数据加载瓶颈检查图片是不是放在机械硬盘上或者标注文件里有损坏的 XML 导致解析卡住。用yolo train时加workers4可以多进程加载但 Windows 下有时会出问题设成 0 用主进程加载更稳。5. 把数据集用出复利合成数据、主动学习与边缘部署的取舍真实场景采集成本高尤其是多位数、多颜色、多角度的组合拍几千张可能覆盖不全。这时候合成数据是一个值得投入的方向。用 OpenCV 或 Blender 渲染七段数码管可以精确控制每一位的亮灭、颜色、倾斜角度和背景纹理。合成数据的优势是标签免费且绝对准确劣势是域差距——渲染的光晕、反光、噪声和真实相机拍出来的不一样。我一般会按 1:1 混合真实和合成数据在合成数据上做预训练再用真实数据微调。实测下来合成数据能把冷启动阶段的标注需求降低一半左右但完全替代真实数据不现实。主动学习是另一个提效手段。先用少量真实数据训一个初始模型在未标注的采集池里跑推理把置信度低或检测框重叠严重的样本挑出来人工标注再加入训练集。这样每一轮标注都花在模型最不确定的样本上比随机标注效率高。实现上可以用model.predict输出置信度按置信度升序排列取前 10% 送标。边缘部署时YOLOv8n 量化到 INT8 后模型大小约 3MB在瑞芯微或树莓派上能跑到 10-15 FPS足够应付大多数仪表抄录场景。但要注意量化后的模型对小目标更敏感如果数码管在画面里占比很小建议先裁剪 ROI 再送入模型而不是整图推理。裁剪可以用运动检测或固定区域触发减少无效计算。最后说一个我自己的习惯每次训练完不要只看 mAP一定要把验证集里置信度最低的 20 张图导出来肉眼过一遍。模型犯的错往往有规律比如特定角度、特定颜色、特定背景这些规律在指标上看不出来但直接决定上线后会不会翻车。数据集不是标完就完了它是一个需要持续迭代的资产每一轮现场反馈都应该变成下一轮的数据补充。希望帮到你。本文还有配套的精品资源点击获取