简介:街景门牌号数据集是一份面向计算机视觉与深度学习研究者的标准图像识别资源,核心任务是从街景图像中自动识别门牌号码,可用于智能导航、自动驾驶车辆和智慧城市等真实场景的技术验证。压缩包共7个文件、约885MB,其中3个zip分别存放训练、验证与测试图像,2个json对应提供标注信息,2个csv则包含数据列表与样例提交结果,整体结构清晰,便于按模型训练流程取用。该资源对训练卷积神经网络等图像识别模型尤其适用:训练集、验证集与测试集严格分离,可有效防止数据泄漏;JSON标注可辅助完成目标定位与字符识别,样例提交文件则能引导新手上手构建预测结果,配合常用data_loader工具即可完成批量读取与预处理。目前已有517人学习下载,适合希望以真实场景数据开展深度学习实践、进行算法对比或参加相关竞赛的AI学习者与开发者。 先说一个我真实碰到的场景。之前给一个做同城配送的团队做地址纠偏模块,聊到街景门牌号数据集的时候,发现大家的第一反应都是“这东西不就有吗”,可真到用的时候又都摇头。用户填写的地址精确到了“某路某号”,地图上却经常定位到几百米开外,快递员到了附近还得停下来打电话问路。想用模型自动识别门牌号来完成纠偏,翻遍公开的目标检测数据集,几乎找不到专门针对街景门牌号的资源。就算偶尔在通用目标检测集里翻到几张带门牌的街景大图,标注也不统一,要么只画了框没给文本,要么画的框把整面墙都包了进去,根本没法直接用来训练。
所以我自己动手,从数据采集到标注,再到模型训练和部署走了一整轮,做成了一个真正可用的街景门牌号检测数据集。这篇文章会把这条路完整记录下来:数据从哪来、怎么标、清洗时踩过哪些坑、怎么用YOLOv8把检测模型训出来,以及最后怎么接OCR落地。适合正在做目标检测、OCR或者地理信息相关项目的朋友参考,尤其是那些准备从零构建自己数据集的人。
1. 为什么门牌号值得单独做一个数据集:从业务需求和技术特点说起
1.1 门牌号是“最后一公里”场景里最关键的锚点
导航定位解决的是“经纬度在哪”的问题,但现实中绝大多数业务关心的是“这栋楼到底是几号”。外卖和快递员根据坐标到达附近之后,真正要找的是门牌号;市政维护要更新地址库,靠的也是一张一张包含门牌号的街景照片;应急调度需要快速定位报案人说出的地址,同样少不了门牌信息。
问题在于,门牌号是刻在物理世界里的“文本”,定位系统不会自动告诉你这一户是几号。如果能把街景图像里的门牌号自动读到,再和逆地理编码结果做交叉验证,就能把几百米的定位误差压缩到具体楼栋级别。这个能力在物流调度、外卖配送、网约车上下车点推荐里都是刚需。
可惜的是,通用目标检测数据集里没有人认真对待门牌号。因为在一张街景图里,门牌号往往只占几十个甚至十几个像素,属于典型的小目标,数据集的构建者通常也不会专门给门牌号单独做一个类别。就算COCO这类大型数据集里有些样例,数量也不够模型学习到足够强的特征。自己做数据集不是炫技,而是因为业务需要的数据形态,公开市场里根本没有。
1.2 门牌号检测和通用目标检测根本不是一回事
很多初学者会问:直接用现成的YOLO权重,把检测类别从80类改成1类不就行了?实际上没那么简单。门牌号检测有其非常特殊的难点,可以看成是目标检测和OCR的交叉地带。
- 目标尺寸极端:门牌号在街景图里常常只占很小一块区域,YOLO默认特征图对这类小目标不太友好。
- 类内差异极大:同样的门牌号,不同城市、不同年代、不同建筑风格,字体、颜色、材质、悬挂高度完全不同,甚至同一条街上都可能出现白底黑字、铜字、LED灯箱等好几类形态。
- 环境干扰严重:反光、树枝遮挡、车辆停放、墙面污渍、视角偏斜,这些噪声在门牌号场景里是常态。
- 检测和识别需要联动:只画出一个框还不够,业务上需要框里的具体文本,所以数据集不能只标类别,还要转录文本,这给标注工作增加了不少成本。
我整理了一张对比表,方便看清楚差异:
| 维度 | 通用目标检测(人/车等) | 街景门牌号检测 |
|---|---|---|
| 目标尺寸 | 较大,占据画面明显比例 | 极小,常被背景淹没 |
| 类别数 | 几十上百类 | 通常1类,但形态多样 |
| 标注成本 | 画框+类别 | 画框+转录文本+记录属性 |
| 场景复杂度 | 相对固定 | 光照、视角、遮挡变化极大 |
| 下游要求 | 类别正确即可 | 文本内容要准确,关系到地址匹配 |
所以,与其说街景门牌号数据集是一个“目标检测数据集”,不如说它是一个为“检测+OCR”链路专门设计的资源。
2. 数据从哪来:街景影像的采集路径与合规注意事项
2.1 三个主流来源及优缺点
构建数据集第一步是解决图像来源。我试过几种方式,各有取舍:
一是利用地图平台的公开街景影像。现在很多地图产品都提供了街景浏览能力,可以通过官方开放能力获取合规的图像数据。优点是覆盖面广、视角统一,可以很方便地收集不同城市、不同道路等级的数据。缺点是采集时间不一定可控,而且需要仔细阅读平台的服务条款,不能为了做数据集就随意抓取和重分发,更不能把含有人脸、车牌等个人信息的完整街景图直接公开。
二是自己组织采集。用运动相机或手机固定在车前,沿道路行驶拍摄视频,再按帧抽图。这种方式的好处是完全掌握拍摄时机和拍摄路线,可以针对白天、傍晚、阴天等不同条件主动收集;坏处是成本高、周期长,而且自己拍摄的视角通常偏低,门牌号容易被绿化带和停靠车辆挡住。
三是整理已有的开源图像数据。部分开源街景数据集、城市影像数据集提供了可商用的图像,可以筛选出含门牌号的样本。优点是可以快速起步,缺点是标签噪声偏高,往往需要大量人工复查。
我的建议是三条路并行:先用开源数据搭出第一批样本,验证标注规范和训练流程;再用地图平台影像扩充覆盖范围;最后用自采数据补齐特殊场景。这样能在成本和效果之间取得平衡。
2.2 采集的多样性与数量规划
数据量不是越多越好,但多样性不足一定会导致泛化崩盘。我第一版数据集只收了三四个路段的图,训练出来在测试集上表现尚可,换到另一条没见过的街道直接漏检严重。原因是门牌的底色、字体、悬挂方式几乎被限定在了那几条路的风格里。
所以采集阶段要刻意拉开多样性:城市级别(老城区、新城区、郊区)、道路等级(主干道、支路、小区内部路)、建筑类型(居民楼、商铺、写字楼、厂房)、拍摄时段(白天、傍晚、夜间)、天气(晴天、阴天、雨后)。每一维度都要有足够的样本量。
关于数量,我要给一个比较现实的参考值:纯检测模型,最少不能低于3000张含门牌的街景图,标注框总量建议在1.5万个以上;如果后续还要做端到端文本识别,最好再翻一倍。别想着几百张就能训出稳定模型,门牌号的类内差异太大,数据量不够模型只会去死记背景,而不是真正学会“找到墙上那块牌子”。
2.3 合规与隐私处理
这块我会说得很直接:做数据集可以,但前提是符合规范。街景图像天然包含人脸、车牌、行人等大量个人相关信息,如果你有公开发布数据集的计划,必须做到以下几点:
- 只能通过官方开放接口或明确授权渠道获取图像,不爬取、不绕过平台限制。
- 公开前对所有人脸和车牌做模糊化处理。
- 对图像重采样时尽量裁剪掉无关的可识别个人信息。
- 如果数据集用于商业项目,务必确认图像来源的授权范围。
我自己的做法是,只保留对门牌号检测有训练价值的街景区域,并且把整个数据集的访问权限控制在项目内部,对外发布时只提供脱敏后的版本。这样既不影响模型训练,也把风险降到最低。
3. 标注规范设计:门牌号数据集不只是画框
3.1 标注字段设计
很多人以为标注门牌号就是框一下“这里有个号码牌”,这是做这个数据集时最需要扭转的认知。门牌号数据集的核心价值在于“框+文本+上下文属性”三者联动,所以我自己在YOLO标注格式之外,单独维护了一份JSON索引,每个标注对象包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| image_id | string | 图像唯一标识 |
| bbox | [x1, y1, x2, y2] | 门牌号区域坐标,像素级 |
| text | string | 门牌号上的原始文本,例如“12号”“A-203” |
| is_complete | bool | 门牌号是否完整可见 |
| font_type | string | 字体类别,如印刷体、宋体、黑体、艺术字 |
| background | string | 背景类型,如墙面、玻璃、石材、金属 |
| occlusion | string | 遮挡情况:无遮挡、轻微、严重 |
| weather | string | 天气情况,用于后续按条件筛选数据 |
检测时bbox和text是刚需,其他字段初期不必全部标注,但建议在标注工具里增加属性项,方便后续做数据分析和疑难样本挖掘。比如训练后如果发现“玻璃反光”场景下漏检率显著偏高,你就可以通过weather或background字段把对应样本筛出来,针对性补充数据。
3.2 门牌号标注的几种难搞情况
标注规范需要提前定好,否则标到一半就会因为标准不一致返工。我整理了三种最常见的分歧场景:
第一种叫“多门牌并存”。一栋楼入口旁可能挂了多个门牌,或者同一面墙上有新旧两个门牌号。我的规则是:只要清晰可见、语义独立的门牌都分别标注;如果多个号码刻在同一块金属牌上,作为一个整体框处理,text记录完整内容,比如“12-1802”。
第二种叫“斜挂和弧面”。门牌不是正对着镜头是常态,尤其是弧面墙上的门牌,四个角不在同一个平面上。标注时不要为了追求方正而框到背景,应该贴近门牌实际的可视区域,宁可让框稍微包含一点边缘,也不要为了对齐把半个墙面框进去。
第三种叫“遮挡和反光”。如果门牌被树枝或车辆挡了三分之一,但仍能辨认出关键数字,标记is_complete=false,text照常填写;如果完全看不清数字,就不标,不要强行猜测。模板上写“不允许靠脑补做标注”,这是保证数据质量的一条铁律。
3.3 标注工具选型
标注工具我试过LabelImg、X-AnyLabeling和Roboflow。列个对比:
| 工具 | 支持类型 | 效率 | 备注 |
|---|---|---|---|
| LabelImg | 矩形框+类别 | 低 | 适合几十张图的小项目,功能单一 |
| X-AnyLabeling | 矩形框+文本+属性 | 高 | 支持OCR预标注,适合批量做门牌号数据 |
| Roboflow | 全套流程 | 中 | 在线工具,格式转换方便,但数据要上传 |
我在实际项目中用得最多的是X-AnyLabeling。原因在于它内置了OCR能力,可以先用一个已经训练好的文字检测模型自动生成候选框,人工只需确认位置、修正边界并转录文本。这相当于把标注工作从“纯手工画框”变成了“校对”,效率能提升不少。不过要注意,自动生成的候选框经常把广告牌上的电话号、商店招牌里的数字也框进来,这些都是干扰项,需要人工删除。
4. 数据清洗、质量抽检与格式转换:决定模型上限的隐形工作
4.1 清洗规则
标注完成后别急着训练,直接训练大概率会被脏数据带偏。清洗规则我建议按下面几条来:
第一,去除重复图。从视频抽帧得到的数据经常有大量相邻帧高度相似,用感知哈希算法计算图像相似度,把相似度超过阈值的帧剔除,保证训练图像之间没有过强的相关性。
第二,剔除模糊图和严重曝光图。门牌号检测依赖清晰纹理,模糊度和过曝图放进训练集只会让模型学到错误特征,可以直接靠人工快速筛查一遍。
第三,检查标注框偏移。有的框画得大而空,把门牌周围的墙面也包进去了,这种框的IoU与真实目标不匹配,需要在后处理里统一瘦身。
第四,转录错误复查。数字之间的混淆是重灾区,比如“0”和“O”、“1”和“I”、“8”和“B”,需要安排一次全量文本复查,最好让标注人员交叉复核。
4.2 数据集划分策略
训练、验证、测试集划分有个非常容易被忽略的坑:必须按区域划分,不能按图像随机划分。原因在于同一街道的连续帧外观几乎一样,如果训练集和测试集都含有同一条街的图像,模型本质上是在“背”这些场景,验证分数会虚高。真到了新街道上,效果立刻打回原形。
按街道或区域划分之后,训练/验证/测试大致按8:1:1或7:2:1分配,具体要保证验证集里能看到训练时没见过的建筑风格和拍摄角度。
4.3 格式转换与自动检查
标注软件导出的格式五花八门,最后统一转成YOLO检测格式最省心。YOLO每张图对应一个同名txt,每行是“class x_center y_center width height”,坐标归一化到0到1。格式很简单,但批量转换时很容易出问题,我写了个简单的Python脚本做自动校验,核心逻辑是:读取所有txt,检查每个框的坐标是否越界、宽高是否过小、是否存在空的标签文件,有异常就打印文件名和行号。
import os label_dir = "labels" for name in os.listdir(label_dir): if not name.endswith(".txt"): continue path = os.path.join(label_dir, name) lines = [l.strip() for l in open(path, encoding="utf-8")] if not lines: print(f"empty: {name}") continue for line in lines: parts = line.split() if len(parts) != 5: print(f"bad format: {name} -> {line}") continue _, x, y, w, h = parts x, y, w, h = map(float, [x, y, w, h]) if not (0 <= x <= 1 and 0 <= y <= 1 and 0 < w <= 1 and 0 < h <= 1): print(f"out of range: {name} -> {line}") if w * h < 0.001: print(f"too small: {name} -> {line}")这样的脚本花不了多少时间,但能拦住绝大多数低级错误。把这一层质量控制做在前面,后面训练阶段能省下大量排查问题的时间。
5. 基于YOLOv8的训练实战与调参记录
5.1 目录结构与配置文件
清洗好的数据按下面的结构组织:
street-address-dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamldata.yaml配置如下:
path: /path/to/street-address-dataset train: images/train val: images/val test: images/test nc: 1 names: ['house_number']5.2 训练命令与参数选择
我用的是YOLOv8,训练命令如下:
yolo detect train \ data=data.yaml \ model=yolov8m.pt \ imgsz=1280 \ epochs=200 \ batch=16 \ device=0 \ cos_lr=True \ patience=30几个参数需要重点解释一下。
imgsz=1280是我在这个数据集上最重要的调参决定。门牌号在默认的640分辨率下只有二三十个像素,卷积特征提取后基本就没了。把输入分辨率提到1280之后,小目标保留的特征明显增加,mAP50的提升非常可观。代价是显存占用和训练时间都翻倍,如果你的显卡只有8GB显存,建议用m模型加梯度累积,或者对长图做切片训练,而不是硬撑。
model=yolov8m.pt是起点。我试过从yolov8n开始训,速度快但精度明显不够,边框回归偏软;改yolov8l以后精度有提升,但训练周期拉得太长,性价比一般。对于门牌号这种背景规律强、目标对比度相对清晰的对象,m模型已经够用,先把m跑通再决定要不要换更大的模型。
cos_lr=True和patience=30是常规设置。余弦退火可以避免后期学习率震荡,早停则是在验证集指标连续30轮不涨时自动停止,可以省时间。
5.3 训练过程中踩过的坑
第一个坑是数据增强导致的“伪标签噪声”。YOLOv8默认开了Mosaic增强,会把四张图拼接在一起。门牌号的框本来就小,拼接后目标更容易被截断,模型学到不少中间被切断的门牌特征,导致推理时对部分遮挡的门牌更容易漏检。我最后的做法是保留Mosaic但调低概率,同时增加轻微HSV扰动,减少不自然的拼接比例。
第二个坑是类别不平衡被忽略。虽然类别只有1个,但不同字形和背景类型的数量差异非常大。墙面白底黑字占了八成,铜字金属牌只有零星几十个,结果模型对铜字的检测几乎失效。我重新平衡了数据,对少数类样本做了复制和轻微仿射变换,让模型至少能见过足够多的“非典型”门牌。
第三个坑是夜间和逆光场景。白天数据训练出来的模型在夜间街景上效果差得离谱,因为门牌在夜间要么被灯光照亮,要么完全隐没在黑暗里。后来我单独收集了两个小时的夜间视频帧混入训练集,并用图像增强模拟曝光不足的情况,效果才有明显改观。
6. 部署应用与后续迭代:从检测框到可用地址
6.1 检测+OCR联动的落地链路
模型训练完只完成了第一步。业务系统真正需要的是一个字符串“XX路XX号”,所以需要把“门牌号检测”和“文本识别”串起来。
标准链路是:检测模型输出每个门牌号的边界框,裁剪出对应小图,再交给文本识别模型。识别模型我直接用了训练好的PaddleOCR,没有自己重新训,因为门牌号字符集就是数字和少量字母、中文,通用OCR已经能覆盖。这里关键的一步是后处理:检测框经常会把“XX路XX号”里的路名也框进来,需要在文本清洗时只保留数字和必要的连接符,比如“12-203”保留,“XX路”去掉。全角数字转半角、剔除乱码字符这些细节也不能省。
有了识别结果,再和逆地理编码返回的道路信息做拼接,比如逆地理编码给到道路名“建设路”,识别结果是“12号”,最后就能产出“建设路12号”,这就是一个可以直接用于地址库更新的结构化字段。
6.2 实际部署中的失效模式
部署之后一定要监控失败样本。我跑了三周,发现失效模式主要集中在三类:
一类是夜间灯箱门牌。灯箱周围的光晕会让检测框偏大,OCR识别时把发光边框也当成字符的一部分,读出一堆乱码。解决办法是在识别前对裁剪图做二值化预处理,或者提高检测框的IoU阈值。
二类是老旧墙面上的手写门牌。这类门牌颜色和墙面接近,检测模型容易漏检。在部分区域可以接入多帧融合,连续几帧都检测到相似位置的疑似门牌就视为候选,再用OCR确认。
三类是商店招牌上的电话号码被误检成门牌。因为它们也是一串数字、也是贴在临街墙面,特征非常接近。处理方式是在数据集中加入“广告牌电话”负样本,让模型学会区分“门牌号”和“非门牌号数字区域”。这也是为什么我在标注时花了很多精力去清理干扰项,负样本的质量直接影响这个问题的严重程度。
6.3 后续扩展方向
这套数据集和训练流程做扎实之后,后续可以往几个方向扩展。
一是做多任务模型,在检测门牌号的同时预测门牌的背景类型和字体属性,用这些属性辅助文本识别和后处理。比如识别出背景是玻璃,就可以针对玻璃反光做专门的数据增强。
二是跨城市泛化。门牌号的形态在不同城市差别很大,可以按城市划分出测试集,专门评估模型在没有见过的新城市里的表现,用结果指导数据采集方向。
三是尝试端到端方案。检测+OCR串联链路有一个问题,门牌框和文本之间是割裂的,一旦检测框不准,识别结果就崩。后续可以尝试把门牌号检测做成旋转框检测,或者直接用多模态模型把“找门牌号+读文字”合并成一个任务。这些方向都需要在数据集层面提前布局,多保存原始图像和结构化标注,别急着把中间产物删掉。
我个人在这套流程里最深的体会是:数据集的构建过程不是一个一次性的“体力活”,它更像是给模型做一套量身定制的训练环境。标注规范、清洗策略、样本均衡这些环节,每一个单独拿出来都不难,但放到一起就决定了模型最终的上限。门牌号数据集尤其如此,目标小、场景杂、文本信息又极其敏感,不在数据层面死磕,后面无论怎么调参都是在浪费时间和算力。
本文还有配套的精品资源,点击获取