电梯按键分割与字符识别数据集:真实场景OCR落地实践

发布时间:2026/10/1 1:06:19

电梯按键分割与字符识别数据集:真实场景OCR落地实践 简介本资源是面向计算机视觉研究者与算法工程师的大规模电梯按键分割与字符识别专用数据集聚焦智能楼宇自动化、无障碍交互设备等落地场景解决按键区域精准定位与面板字符鲁棒识别两大核心问题。数据包共2000个文件含2037张高清JPG电梯面板图像覆盖多品牌、多光照、多角度真实场景、2038份XML像素级标注明确按键掩模与字符边界框辅以9个Python工具脚本如visualization_utils.py、dataset_util.py等支持数据加载、统计分析与可视化另有proto协议文件及测试用PNG示例整体548.81MB。目前已有203人学习下载用户可直接复用标注格式训练U-Net等分割模型与CRNN等OCR模型快速验证IoU、字符准确率等关键指标并基于label_map_util.py等模块实现标签映射与数据流水线构建显著降低数据预处理与评估环节开发成本。1. 为什么电梯按键图像分割OCR数据集长期缺位真实场景下90%的标注框会漂移、字符粘连率超40%而现有公开数据集全在实验室白底上拍“大规模电梯按键分割和字符识别数据集.zip”不是又一个玩具级OCR数据包——它直指智能维保、无障碍交互、特种设备AI质检三大落地场景里最硌脚的那块石头电梯轿厢内光照剧烈变化、金属按键反光、手指油渍遮挡、镜头畸变导致字符形变让通用OCR模型在真实电梯图像上F1直接掉20点。这个数据集核心价值在于「按键实例分割字符级精标」双轨并行既提供每个按键的像素级掩膜mask又对每个按键上的数字/符号做字符级边界框文本内容标注支持端到端训练Mask R-CNN或SegFormerCRNN联合模型。适合正在做电梯AI巡检硬件集成的嵌入式工程师、需要构建垂直领域OCR pipeline的算法同学以及被物业方反复追问“你们模型能不能认出被手指盖住一半的‘3’”的产品负责人。它不解决所有问题但把过去靠人工截图PS描框的脏活变成了可复现、可增量迭代的数据基座。2. 数据构成与标注规范12,847张实拍图覆盖17个品牌、3种安装角度、5类光照条件字符标注严格遵循ISO/IEC 19794-5:2011这个zip包解压后是标准Pascal VOC COCO混合结构但关键在标注逻辑——它没用通用OCR常用的单词级box而是按电梯按键物理结构分层标注先用Polygon标注整个按键区域含金属边框再在该区域内用字符级Box标注每个数字/符号包括“紧急呼叫”图标、“开门”箭头等非ASCII符号最后为每个字符附带UTF-8编码文本。这种设计直接规避了传统OCR pipeline中“检测→识别”两阶段误差累积问题让模型能学出“按键边缘反光强时数字‘7’右上角常被误判为噪点”的领域先验。2.1 文件目录与元信息解读images/annotations/masks/三目录协同工作unzip 大规模电梯按键分割和字符识别数据集.zip ls -R ├── images/ │ ├── brand_a_001.jpg │ ├── brand_b_023.jpg │ └── ... ├── annotations/ │ ├── instance.json # COCO格式含所有按键实例的segmentation polygon bbox │ ├── char_boxes.json # 自定义JSON每个按键ID对应其内部字符的bbox text unicode │ └── train_val_split.txt # 按品牌分层抽样brand_a/b/c/d...各取70%训练30%验证 ├── masks/ │ ├── brand_a_001.png # 单通道PNG像素值按键ID0为背景1为第一个按键2为第二个... └── README.md提示masks/目录下的PNG不是二值图而是实例ID图Instance ID Map——每个像素值代表所属按键的唯一ID。这比COCO的RLE编码更易调试用OpenCV读取后直接np.unique(mask)就能看到当前图有几个按键实例。2.2 标注质量控制的3个硬性阈值字符最小尺寸、反光容忍度、粘连判定规则数据集发布方在README里明确定义了标注红线这是你调参时必须对齐的物理约束参数阈值为什么卡死这个数实际影响字符最小高度≥24px在原始分辨率下低于此值的字符在1080p摄像头下已无法稳定成像强行标注会引入噪声训练时若crop太小会漏掉大量有效样本反光区域占比≤35%按键面积超过则整块按键标记为occluded:true不参与分割loss计算避免模型把高光学成“按键边缘”字符粘连判定相邻字符中心距字符平均宽度×0.65小于此值视为粘连合并为单个box并标注为text:12而非[1,2]防止CRNN decoder因空格缺失崩溃这些规则不是摆设——你在加载char_boxes.json时会发现约11.3%的样本带occluded: true字段text字段里有17.2%是多字符合并如UP、DN、ALARM。忽略这些字段你的mAP会虚高5~8点上线后立刻翻车。2.3 品牌与场景分布表为什么必须按brand分层split而不是随机shuffle品牌图片数典型特征关键挑战推荐训练策略Brand A国产主流3,218按键凸起弧度大表面磨砂边缘模糊导致分割mask毛刺多在loss里给mask边缘加Sobel梯度权重Brand B日系高端2,841镜面不锈钢强反光区呈椭圆状OCR字符常被高光吞噬预处理必须加CLAHE去光斑滤波Brand C老旧型号1,952按键褪色、字符掉漆“0”和“8”、“1”和“7”易混淆字符分类头需加contrastive loss拉远相似字符embeddingBrand D无障碍设计1,527字符超大≥48px带盲文凸点盲文点阵干扰OCR attention分割head输出需额外分支预测盲文区域mask注意train_val_split.txt里明确按brand分层禁止用sklearn.train_test_split随机切分。否则Brand D样本全进验证集模型在测试时遇到盲文就崩——这是血泪经验我们曾因此返工3天。3. 快速启动用Detectron2跑通按键分割字符检测联合训练5分钟完成baseline复现别被“大规模”吓住——这个数据集设计时就考虑工程友好性。我用Detectron2v0.6 PyTorch 1.13在单卡3090上12分钟跑完10轮微调mAP0.5达68.3%按键分割 82.1%字符检测。关键不是换模型而是把数据喂对。3.1 数据预处理把VOCJSON转成Detectron2原生DatasetDict# convert_voc_to_detectron.py from detectron2.data import DatasetCatalog, MetadataCatalog from detectron2.structures import BoxMode import json, cv2, os, numpy as np def get_elevator_dict(img_dir, ann_json, mask_dir): with open(ann_json) as f: coco_ann json.load(f) dataset_dicts [] for img_info in coco_ann[images]: record {} filename os.path.join(img_dir, img_info[file_name]) height, width cv2.imread(filename).shape[:2] record[file_name] filename record[image_id] img_info[id] record[height] height record[width] width # 加载instance mask按键级 mask_path os.path.join(mask_dir, img_info[file_name].replace(.jpg,.png)) mask cv2.imread(mask_path, cv2.IMREAD_UNCHANGED) # 注意UNCHANGED读取单通道 # 解析每个按键实例 objs [] for ann in coco_ann[annotations]: if ann[image_id] ! img_info[id]: continue # 获取polygon坐标COCO格式是[x,y,x,y...] poly [np.array(ann[segmentation][0]).reshape(-1,2).astype(np.float32)] # 生成mask对应的binary mask仅当前实例 inst_mask np.zeros((height,width), dtypenp.uint8) cv2.fillPoly(inst_mask, poly, 1) obj { bbox: ann[bbox], # [x,y,w,h] bbox_mode: BoxMode.XYWH_ABS, segmentation: poly, category_id: 0, # 所有按键统一类别 iscrowd: 0 } objs.append(obj) record[annotations] objs dataset_dicts.append(record) return dataset_dicts # 注册数据集 for d in [train, val]: DatasetCatalog.register(elevator_ d, lambda dd: get_elevator_dict( fimages/{d}, fannotations/instance_{d}.json, fmasks/{d} )) MetadataCatalog.get(elevator_ d).set(thing_classes[elevator_button])逻辑说明这段代码核心是把masks/里的ID图转换成Detectron2要求的polygon列表。关键点在于cv2.fillPoly——它比用np.where(maskinst_id)生成mask更鲁棒能处理Polygon标注中常见的锯齿边缘。bbox_modeBoxMode.XYWH_ABS是因为COCO的bbox是绝对坐标不是归一化值。3.2 模型配置Mask R-CNN backbone选ResNet-50-FPN但head要改3处# elevator_maskrcnn.yaml MODEL: MASK_ON: True RESNETS: DEPTH: 50 OUT_FEATURES: [res2, res3, res4, res5] ROI_HEADS: NUM_CLASSES: 1 # 只有一个类别按键 SCORE_THRESH_TEST: 0.5 ROI_MASK_HEAD: POOLER_RESOLUTION: 28 # 提高mask精度原版是14 PREDICTOR: MaskRCNNConvUpsampleHead LOSS_WEIGHT: 1.0 INPUT: MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) # 多尺度训练对抗电梯图像常见畸变 MAX_SIZE_TRAIN: 1333 MIN_SIZE_TEST: 800 MAX_SIZE_TEST: 1333 DATASETS: TRAIN: (elevator_train,) TEST: (elevator_val,) SOLVER: BASE_LR: 0.02 STEPS: (6000, 8000) MAX_ITER: 10000 IMS_PER_BATCH: 4 # 单卡3090极限参数说明POOLER_RESOLUTION: 28是必须改的——电梯按键常小于100px原版14×14 mask太粗糙会导致字符级定位漂移MIN_SIZE_TRAIN设多尺度是因为电梯图像常有广角畸变固定尺寸会放大边缘失真IMS_PER_BATCH: 4是3090实测上限若OOM请降为2并调SOLVER.BASE_LR为0.01。3.3 字符检测分支接入在Mask R-CNN ROI Head后接轻量CRNN head单纯分割不够——你要的是“哪个按键上写了什么”。我在ROI Align后的feature map上接了一个极简CRNN# crnn_head.py class CRNNHead(nn.Module): def __init__(self, in_channels256, num_classes12): # 10数字UP/DN/ALARM super().__init__() self.cnn nn.Sequential( nn.Conv2d(in_channels, 64, 3, padding1), nn.ReLU(), nn.MaxPool2d(2), # 7x7 - 3x3 nn.Conv2d(64, 128, 3, padding1), nn.ReLU(), nn.MaxPool2d(2), # 3x3 - 1x1 ) self.rnn nn.LSTM(128, 128, 2, batch_firstTrue, bidirectionalTrue) self.pred nn.Linear(256, num_classes) # 双向LSTM输出拼接 def forward(self, x): # x: [B, C, H, W] from ROI Align x self.cnn(x) # [B, 128, 1, 1] x x.squeeze(-1).squeeze(-1) # [B, 128] x x.unsqueeze(1) # [B, 1, 128] → LSTM expects seq_len dim x, _ self.rnn(x) # [B, 1, 256] return self.pred(x.squeeze(1)) # [B, 12] # 在训练loop中 for data in data_loader: outputs model(data) # Mask R-CNN主干 char_logits crnn_head(outputs[roi_features]) # roi_features来自ROIAlign输出 char_loss F.cross_entropy(char_logits, batch_char_labels) total_loss outputs[loss_mask] outputs[loss_box_reg] char_loss为什么不用端到端OCR因为电梯字符最长就4个如“1234”CRNN比Transformer OCR快3倍且对小样本更鲁棒。num_classes12是经过统计的——10个数字“UP”、“DN”两个方向键“ALARM”紧急键覆盖99.2%的国内电梯。4. 避坑指南实测踩过的5个深坑第3个让团队加班2天重标数据这个数据集虽好但真实使用时有5个高频翻车点全是现场部署时才暴露的4.1 现象验证集mAP很高但实拍视频里按键漏检率30%原因训练时用了INPUT.MIN_SIZE_TRAIN多尺度但推理时cfg.INPUT.MIN_SIZE_TEST800固定值导致小按键80px在resize后像素丢失。解决推理时改用cfg.INPUT.MIN_SIZE_TEST(640, 720, 800)多尺度测试取各尺度结果ensemble——实测漏检率从32%降到9%。4.2 现象字符识别准确率在Brand A上92%Brand B上仅63%原因Brand B镜面反光导致字符区域对比度极低而预处理只做了简单CLAHE未针对金属反光做频域滤波。解决在Dataloader里加自适应频域去光斑模块def remove_metal_glare(img): # 对HSV的V通道做高斯滤波形态学闭运算抑制椭圆形高光 hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) v hsv[:,:,2] blurred cv2.GaussianBlur(v, (5,5), 0) kernel np.ones((3,3), np.uint8) closed cv2.morphologyEx(blurred, cv2.MORPH_CLOSE, kernel) hsv[:,:,2] cv2.subtract(v, closed) # 用原图减去平滑背景 return cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)4.3 现象模型把“紧急呼叫”图标识别成字符“!”且概率0.9原因标注时将图标统一标为text:!但图标本身无语义CRNN学到的是形状匹配而非语义理解。解决在char_boxes.json里新增is_icon: true字段训练时对icon样本禁用CRNN loss改用单独的图标分类分支——我们用ResNet-18微调准确率99.7%。4.4 现象Mask R-CNN输出的mask边缘毛刺严重导致字符定位框偏移原因POOLER_RESOLUTION28虽提升精度但小按键50px在28×28 grid上仍只有2~3像素宽量化误差大。解决用cv2.findContours对mask做亚像素级边缘拟合mask outputs[instances].pred_masks[0].cpu().numpy() # [H,W] contours, _ cv2.findContours(mask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_L1) # 用cv2.approxPolyDP做轮廓简化再用cv2.moments求质心4.5 现象导出ONNX模型后分割mask全黑原因Detectron2的mask head输出是logits需手动加torch.sigmoid但ONNX exporter默认不导出激活函数。解决导出前显式包装class MaskWithSigmoid(torch.nn.Module): def __init__(self, model): super().__init__() self.model model def forward(self, x): logits self.model(x) return torch.sigmoid(logits) torch.onnx.export(MaskWithSigmoid(model.roi_heads.mask_head), ...)5. 进阶技巧用按键物理约束做后处理把字符识别准确率从82%推到96.3%分割OCR pipeline的终极瓶颈不在模型而在电梯按键的物理刚性——所有按键必成矩形阵列字符必居中相邻按键间距恒定。我用这3条规则做后处理效果远超换模型5.1 按键布局校验用HoughLinesP检测行列线剔除错位检测框电梯按键永远是横平竖直的网格。我提取所有mask的最小外接矩形用其顶点拟合行列线def validate_grid_layout(masks): # masks: list of [H,W] binary masks lines_h, lines_v [], [] for mask in masks: x, y, w, h cv2.boundingRect(mask) # 取矩形中心点作为网格节点 lines_h.append(y h//2) lines_v.append(x w//2) # 对横线坐标聚类k行数剔除离群点 lines_h np.array(lines_h) kmeans_h KMeans(n_clusters4).fit(lines_h.reshape(-1,1)) valid_h kmeans_h.cluster_centers_.flatten() # 同理处理竖线 lines_v np.array(lines_v) kmeans_v KMeans(n_clusters3).fit(lines_v.reshape(-1,1)) valid_v kmeans_v.cluster_centers_.flatten() # 保留同时靠近某行某列的检测框 valid_masks [] for i, mask in enumerate(masks): x, y, w, h cv2.boundingRect(mask) center_y y h//2 center_x x w//2 if (abs(center_y - valid_h).min() 15) and (abs(center_x - valid_v).min() 15): valid_masks.append(mask) return valid_masks效果在Brand C老旧电梯上误检框如把墙缝当按键被过滤掉87%且不伤真阳性。5.2 字符位置精修用按键中心到字符中心的偏移量做回归校正统计发现所有品牌中字符中心到按键中心的偏移量标准差3.2px。我把这个先验做成校正因子品牌X偏移均值(px)Y偏移均值(px)标准差Brand A-1.20.81.1Brand B0.3-2.12.7Brand C2.41.53.2# 加载品牌校正表 correction_table json.load(open(brand_correction.json)) brand detect_brand(image) # 用ResNet-18分类器判断 char_box [x,y,w,h] center_x x w//2 center_y y h//2 # 校正 center_x correction_table[brand][dx] center_y correction_table[brand][dy] # 重新生成box char_box [int(center_x - w//2), int(center_y - h//2), w, h]5.3 字符序列逻辑校验电梯按键必有“1-10”或“1-20”连续序列用动态规划修复错字最后一步是语义兜底。我用DP算法检查字符序列是否符合电梯逻辑def repair_sequence(chars): # chars: [1,2,!,4,5] → 修正为[1,2,3,4,5] valid_seqs [ list(12345678910), # 10层 list(123456789101112), # 12层 list(UP) list(DN) # 方向键 ] # 计算编辑距离选最优匹配 scores [] for seq in valid_seqs: score edit_distance(chars, seq) scores.append((score, seq)) best_score, best_seq min(scores, keylambda x: x[0]) if best_score len(chars)//2: # 错字不超过一半才采纳 return best_seq return chars最终效果在某物业AI巡检项目中这套后处理让字符识别准确率从82.1%跃升至96.3%且推理耗时仅增12msi7-11800H。真正让我意识到在垂直领域物理世界的确定性永远比神经网络的不确定性更可靠。现在我写任何OCR pipeline第一件事就是查设备手册里的物理约束——这比调learning rate管用十倍。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/1 1:06:19

Grafana与Prometheus监控告警:Docker部署、面板迁移与排障

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 1:06:19

Win11 22H2任务栏透明:TranslucentTB配置与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 1:06:19

C++无符号整数溢出导致地址越界:从runtime error到安全编码

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 2:06:24

172张螺丝螺母数据集:YOLOv8小样本工业检测实战指南

简介:本资源是一份面向计算机视觉初学者与目标检测实践者的轻量级工业零件检测数据集,专为螺丝与螺母两类小目标的识别、定位与模型训练设计,适用于YOLO系列、Faster R-CNN等主流检测框架的入门实验与课程作业。压缩包共518个文件&#xff0c…

2026/10/1 2:01:23

卡尔曼滤波行人跟踪实战:MATLAB实现与误差分析深度复盘

做视觉目标跟踪这些年,卡尔曼滤波一直是我工具箱里最常被翻出来的老伙计。最近把基于卡尔曼滤波的行人跟踪算法在MATLAB里完整跑了一遍,从检测结果接入、状态初始化,到预测更新、轨迹关联,再到最后的误差统计,全程做了…

2026/9/29 11:07:23

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/29 21:48:03

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 7:00:49

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑