中国车牌数据集全攻略:从检测标注到YOLOv8识别落地
简介车牌识别是计算机视觉领域极具落地价值的应用场景其核心链路包括目标检测与光学字符识别两大环节。做车牌检测识别项目最关键的往往不是模型结构而是一份同时包含检测框与字符标注的高质量中国车牌数据集——检测框负责定位车牌区域字符标注则支撑后续的OCR识别。然而许多开发者误将通用目标检测数据集直接用于车牌项目导致检测与识别效果严重脱节。本文从数据采集、标注规范、类别平衡、数据增强等基础工程问题切入系统梳理了利用YOLOv8训练车牌检测器并串联CRNN/PaddleOCR实现字符识别的完整技术路线。同时结合双层车牌、新能源车牌、夜间反光等真实场景中的落地难点给出可复用的参数配置与踩坑经验为正在从事车牌识别、OCR或相关数据集建设的开发者提供直接参考。 做车牌检测识别项目最头疼的不是模型而是数据集。我前前后后换过三版方案踩了无数坑最后发现一份靠谱的中国车牌数据集必须同时包含检测框和字符识别内容缺一样都白搭。这些年有太多人拿着通用目标检测数据集硬练检测框倒是出来了结果字符识别结果一塌糊涂原因就是数据里根本没有识别层面的标注。这篇文章就围绕“中国车牌数据集包含检测和识别数据”这个主题把我在数据采集、标注、YOLOv8训练和识别串联中的完整思路、参数选择和踩坑经历整理出来给正在做车牌识别、OCR或者想把自己数据集跑通的读者一个可直接抄作业的参考。1. 中国车牌检测识别数据集到底需要哪些东西1.1 检测数据和识别数据两件事不能混为一谈很多刚开始接触车牌项目的朋友会把“检测”和“识别”搅在一起觉得模型能框出车牌就等于能认出车牌这完全是两码事。检测任务关心的是“车牌在图像的哪个位置”输出是一个边界框比如左上角坐标、右下角坐标。识别任务关心的是“这个车牌上的字符到底是什么”输出是一串字符串比如“京A12345”。中国车牌识别项目里检测和识别通常是串联的先用目标检测模型从整张图中定位车牌区域再把车牌区域裁剪出来交给OCR或字符识别模型去解析字符。这就决定了数据集必须同时支持两个环节。如果你只有检测框没有字符标注识别模型就没有训练依据如果你只有字符标注但检测框本身标注得很随意检测模型就只能学到个大概最终端到端效果一定翻车。这也是为什么标题里特意强调“包含检测和识别数据”——这不是一句废话而是整个项目的命根子。我见过不少人从某个开源仓库下载了“车牌数据集”打开一看只有几百张图片和几个VOC标注文件检测框有字符标签却只有中文描述根本没法喂给深度学习模型。这种数据拿来练检测勉强行练识别就抓瞎。1.2 中国车牌的多样性远比想象中复杂中国车牌跟欧美车牌不一样字符体系有省份简称、字母、数字还要区分车牌颜色、单双层、新旧能源。你要是只标“blue plate”和“green plate”识别精度会非常感人。具体来说一份合格的中国车牌数据集需要覆盖这些维度维度具体内容对识别的影响车牌底色蓝色燃油车、绿色新能源、黄色大型车、白色警用、黑色涉外、黄绿双拼新能源大型车检测颜色特征和后续分类字符数量传统蓝牌7位汉字字母5位数字/字母、新能源8位汉字字母6位、双层黄牌上排汉字省份简称下排编号识别网络输出长度需要适配省份汉字全国各省简称不同的“京”“沪”“粤”“苏”等汉字分类类别数量固定但样本分布极不均衡字体与排列各省车牌字体有细微差异有些车牌的字符间距不同字符级特征容易混淆如“0”和“O”环境因素光照过曝、夜间反光、雨雾、泥污、倾斜、模糊、遮挡需要数据增强和图像预处理如果你只拿单一场景的数据集训练比如只有白天高速公路卡口的蓝牌换到地下车库或者雨天城市道路效果断崖式下跌。所以数据集的“覆盖面”比“绝对数量”更重要。1.3 数据集格式与标签结构怎么设计数据集的存储格式直接影响后续训练脚本的编写难度。目前主流的目标检测格式有Pascal VOC XML、YOLO txt、COCO JSON识别部分常见的有单独的字符序列文本或者每个字符一个框的细分标注。我个人的做法是检测部分用YOLO格式每行类别id、中心x、中心y、宽、高归一化识别部分单独建一个txt文件每行对应一张图片格式是“图片名 车牌字符串”。这样训练YOLOv8做检测时直接读txt训练OCR识别时直接读字符串列表两边互不干扰也不用每次转换格式。如果你要做字符级定位识别也就是检测车牌后还要把每个字符单独框出来那就需要更细的标注每个字符的边界框、字符内容、字符顺序。这种数据适合训练像LPRNet这类一步到位的端到端模型但标注成本非常高。我的建议是先决定你要走“检测两阶段识别”还是“端到端”路线再设计标注格式别一上来就想全都要。2. 数据采集与标注一份能用的数据集是怎么来的2.1 公开数据集与自行采集的取舍国内比较有名的公开车牌数据集是CCPDChinese City Parking Dataset包含超过25万张图片覆盖了多种场景和天气条件适合检测任务。但CCPD也有几个问题一是图片分辨率偏高很多车牌在画面中占比很小直接训练检测模型容易漏检二是字符标注存在噪声部分图片是模糊或者严重倾斜的当成识别数据会拉低精度三是版权和许可协议有时不够明确商用前要仔细确认。我自己做项目时会在公开数据集基础上补充自行采集的样本。采集车牌数据有合规问题直接在路上拍别人的车牌涉及隐私所以我的做法是在获得授权的小区、园区内部停车场采集或者用模拟场景生成。网上也有一些模拟车牌生成器比如用Python生成不同背景、字体、颜色的车牌图片用于做识别网络的预训练效果还不错。2.2 标注规范与实操细节标注工具我推荐三个labelImg常规矩形框适合YOLO/VOC、roLabelImg旋转框适合倾斜车牌、labelme多边形标注适合字符级框。如果你的车牌多是水平停车位抓拍用labelImg就够了如果是高速卡口或者道路监控车辆角度变化大车牌可能是斜的用roLabelImg旋转框能减少背景噪声。标注时最容易犯的错有三个只标字符区域不标整个车牌底板。有些车牌的边框、铆钉、螺丝会被误认为字符区域识别时干扰极大。建议检测框范围包括整个车牌底板但不包括车身上的品牌LOGO。字符标注顺序不固定。中国车牌第一位是省份简称第二位是字母剩下的是字母和数字混合。一定要保持从左到右、从上到下的顺序不然OCR输出就是乱码。遮挡车牌要不要标。如果车牌被遮挡了一半目标是检测整个车牌还是检测可见部分我建议只要肉眼能判断有车牌就标整个车牌的理论范围由模型学会在遮挡下推理但如果遮挡严重到看不出是一个车牌就不要标否则反而教坏模型。此外最好在标注结束后做一轮交叉校验。我自己试过两个人标同一批图框的边界可能差5个像素字符可能有人把“I”和“1”搞混。要写一个小脚本对比两份标注文件把不一致的地方挑出来人工确认这一步能避免后续训练时模型学得“左右摇摆”。2.3 数据集的规模、划分与增强很多朋友问车牌数据集到底要多少张才能练出效果我的经验是检测任务至少5000张到10000张起步识别任务则要看字符类别数。中国车牌字符类别大概是31个省份简称、24个字母除去I和O、10个数字总共约65个类别每个类别最好有几百个样本。我习惯把数据集按8:1:1划分为训练集、验证集和测试集。验证集用来调参和早停测试集必须是完全没有参与训练的尤其是那些不同地点、不同光照条件下的图片确保泛化能力。划分的时候要注意同一个车牌的连续帧不要同时出现在训练集和验证集里否则会高估模型效果。数据增强这块YOLOv8训练时会默认启用Mosaic、HSV变换、随机翻转等增强但对车牌场景还不够。我额外增加了三类增强模拟运动模糊用OpenCV的GaussianBlur加随机方向的运动模糊模拟高速行驶时的拖影。模拟雾天和夜间反光用对比度调整、亮度增强、加入高斯噪声让模型见过更恶劣的光照。随机仿射变换旋转角度加±15度轻度透视变换模拟不同角度拍摄的车牌。增强不是越多越好要控制强度。有一次我把旋转角度调大结果检测模型把侧面的非车牌反光区域误检成车牌就是增强过头了。3. 用YOLOv8训练车牌检测器再串起字符识别3.1 数据集格式转换与配置文件我之前用的是Pascal VOC格式的标注但想用YOLOv8跑就需要先转成YOLO格式。转换脚本逻辑很简单读取XML里的bndbox坐标转换为归一化的center_x、center_y、width、height写入同名txt。注意如果用了旋转框就要把四点坐标转成旋转框参数不能直接用普通目标检测脚本来处理。转换完成后在项目目录下建一个data.yaml内容大概是这样train: datasets/train/images val: datasets/val/images test: datasets/test/images nc: 1 names: [license_plate]一个类别就够了。这里有个容易踩的坑如果你还要做车牌颜色分类比如蓝牌、绿牌、黄牌可以把类别扩展成多个比如[blue_plate, green_plate, yellow_plate]这样可以同时完成检测和颜色识别但前提是你的标注里把颜色也标进去。3.2 模型选型与训练参数实测建议YOLOv8发布后我试了n、s、m、l四个规格。在车牌检测这个任务上n和s的速度很快但小目标漏检率偏高特别是画面中车牌宽小于40像素的。m和l的精度明显提升但对算力的要求也更高。我最终的推荐是边缘设备Jetson Nano、RK3588上用yolov8n输入分辨率640能跑到实时。服务器训练部署时用TensorRT加速用yolov8s或者yolov8mmAP50能在0.95以上。如果是极端小目标场景比如远距离卡口用yolov8l并在高分辨率960或1280下训练但推理速度会慢需要trade-off。训练命令很简单yolo train datadata.yaml modelyolov8m.pt epochs150 imgsz640 batch16 device0有几个参数值得细调。imgsz如果设成640对大多数场景够用但车牌目标小我建议在显存允许情况下提升到960。epochs我基本设150配合早停防止过拟合。batch按显存自适应一般先用默认值出现OOM再调小。优化器直接用默认的AdamW学习率往低设置从头训的时候0.001左右用自己的预训练权重接着练则降到0.0001。训练过程中观察loss曲线和验证集mAP。我自己遇到过一个情况mAP50很高mAP50-95却很低这说明模型对大目标的光敏感不错但对小目标、遮挡目标的鲁棒性不足。解决办法就是回数据层面补样本而不是死磕模型参数。3.3 检测与识别的串联方案对比有了检测模型之后识别部分有两条路可选。第一条路是两阶段方案YOLOv8检测车牌区域裁剪出图像再送给OCR识别。OCR既可以用PaddleOCR内置的车牌识别模型也可以用自己训练的CRNN或SVTR。PaddleOCR的好处是开箱即用中文支持好但对特殊车牌双层、新能源的适应性差一些需要微调。自己训练CRNN则更可控输入是车牌裁剪图输出是字符序列。第二条路是端到端方案用LPRNet这种模型直接输入车牌图像输出识别结果。LPRNet参数量小、速度极快适合嵌入式部署。但它不能单独做检测必须配合检测器使用而且对车牌倾斜和模糊的容忍度比CRNN低。我自己的项目里用的是“YOLOv8检测 CRNN识别”。检测模型框出车牌后我还会根据框的宽度和高度比判断是单层还是双层。如果宽高比大于3按单层处理如果小于2大概率是双层或大型车牌就先切成上下两行再分别识别最后拼接结果。这个简单启发式处理比直接丢给识别模型更稳。3.4 识别网络的训练与性能评估识别网络输入建议统一缩放到固定尺寸比如CRNN用高度32、宽度128或168的灰度图。训练时候采用CTC损失字符类别加上一个空位。中国车牌字符数量不固定传统蓝牌7位新能源8位双层车牌可能只有上下两行用CTC可以避免固定的输出长度是一个稳妥的选择。评估识别效果不能只看整体准确率还要拆分看汉字识别准确率各省简称难记样本分布不均最容易出错。字母与数字混淆率比如“0”和“O”、“1”和“I”车牌中一般不会同时出现O和I但模型不该把它们输出为没见过的字符。符号长度错误少一位字符、多一位字符在门禁系统中十分致命。我测试时常用这样一张表来对比不同模型的效果方案单张推理耗时识别准确率备注YOLOv8s PaddleOCR35ms96.2%对新能源支持一般YOLOv8m 自训CRNN28ms97.8%对模糊车牌略差YOLOv8s LPRNet10ms93.5%速度快准确率稍低如果识别准确率卡在97%上不去不要急着换大模型优先观察错误样本的共性。我遇到最多的错误样本是颜色反光导致字符断裂比如蓝牌在强光下蓝色区域和白色字符对比度下降识别出来“A”变“4”。这种问题靠识别模型硬扛很难我在前处理环节加了自适应对比度增强效果立竿见影。4. 实际项目中的坑我替你踩过了4.1 标注不一致导致模型学歪第一次做车牌项目的时候我一个人深夜标了两千张图结果训练完发现验证集上mAP一直上不去。检查之后才发现前期标注的框和后期标注的框标准不统一前期喜欢把车牌的金属边框也框进去后期只框字符区域。模型学到的特征一会儿是“字符区域”一会儿是“整个车牌面板”自然学不好。这事给了我一个教训标注规范必须提前写清楚而且最好是图文版。比如“车牌检测框的左右边界以字符区域向外扩展不超过5个像素包括蓝色底板但不包括螺丝钉”。正式标注前先标20张大家互相看一遍达成共识再批量标注。4.2 省份简称类别不平衡中国车牌省份简称出现频率跟地区经济、道路密度相关有的省份样本特别多有的偏远省份样本很少。如果按原始分布训练识别网络会对高频省份过拟合对低频省份几乎不识别。解决办法有三招第一训练时按类别重采样保证每个省份简称在每轮epoch中出现的次数差不多。第二用数据增强中的mixup把一张“苏A12345”和一张“青A67890”混合让模型被迫关注字符本身。第三用合成车牌数据补充低频样本。我写过一个简单的车牌渲染器随机选择省份简称、字母数字组合用不同字体渲染到真实背景上效果虽然不是完全真实但识别模型能学到特征。4.3 反光、夜间、运动模糊的识别率低这是落地时最崩溃的问题。白天阳光直射下蓝色车牌有时候会白花花一片夜间车灯直射甚至出现光晕车辆高速行驶时车牌不再是清晰锐利的运动模糊会把字符抹成一条线。纯靠数据增强能解决一部分但还不彻底。我在识别前增加了一个轻量的图像预处理模块先用Laplacian算子计算图像清晰度如果低于某个阈值就判定为模糊先做去模糊处理。对于反光用自适应阈值分割把字符区域和背景分离。运动模糊则尝试用OpenCV的逆滤波但要注意逆滤波会放大噪点所以还要配合中值滤波。这里有个取舍预处理步骤越多单帧耗时越长。所以我会做一个简单的图像质量分类器只有低质量的车牌图像才走预处理分支清晰图像直接识别避免拖慢平均速度。4.4 双层车牌和新能源车牌的常见bug双层黄牌主要出现在大货车和挂车上上层是省份简称字母下层是数字编号而且字符较小。如果不做处理识别模型容易把上下两行字符混在一起输出一长串无意义内容。我的处理是检测框出来后先看宽高比。单层车牌宽高比普遍在2.5到4之间双层车牌大概在1.2到2之间。对于双层我把裁剪图水平切成上下两半分别缩放到合适尺寸后送进识别模型最后把两行字符串拼接。还有一个细节双层车牌的上层有时候没有汉字只有省份简称这个在拼接时要保留顺序。新能源车牌的问题主要是字符位数和“D”和“F”开头。传统蓝牌是7位新能源是8位如果识别网络固定输出长度就会在小数点后多出或漏掉一位。用CTC可以解决但要注意训练数据里新能源车牌的比例不能全是蓝牌。我建议数据集中新能源车牌至少占20%。4.5 部署阶段的模型提速训练归训练部署又是另一层地狱。我一开始直接用PyTorch模型推理640分辨率下大概30ms一帧看着够用但在多路视频流并行时CPU和GPU占用率飙升。后来我换成ONNX TensorRTfp16精度下推理时间压到了10ms以下。如果你的部署环境没有TensorRT也可以做其他加速图片预处理阶段先把车牌目标附近的区域放大再识别减少整个画面缩小的信息损失或者用两个模型级联第一个轻量模型快速找出可能的车牌区域第二个高精度模型只对候选区域做精细检测和识别。还要注意线程和显存管理车牌项目经常要跑长时间不间断内存泄漏和显存碎片积累会越来越卡。我习惯每个进程定期重启任务或者用内存池管理图片缓存避免出现OOM。5. 一些值得记录的实操心得车牌检测识别项目做到后面基本上就是拼数据质量和细节处理。模型框架翻来覆去就那几套真正决定上限的是你对数据有多了解。比如“粤”和“苏”在模糊状态下特别像光靠训练集里的对比度可能学不到位要在预处理里增加锐化比如夜间绿色新能源牌在灰图上几乎看不清就得专门做色彩空间转换或者用YOLO直接检测原图颜色再做通道增强。我还有个习惯每轮训练结束后把识别错误的样本连同原图、检测框、预测结果输出到错误集文件夹然后定期人工翻看。别看这个操作土它比任何指标都直观。很多问题在指标上只体现为0.5%但一翻错误集就发现某个特定场景完全没覆盖到。有一次就是发现夜间地库的车牌大量被检测成黄牌问题出在监控屏的白平衡偏黄数据增强里根本没模拟过这种偏色。最后再分享一个小技巧在做车牌数据集的时候可以把采集数据按照“省份”、“场景”、“光照条件”、“车牌颜色”打上标签形成一张数据分布表。后续无论是训练还是测试都能快速知道当前模型在哪个子集中表现差补数据的时候也有的放矢。用一句话总结就是数据集里藏着的不是一张张图片而是整个落地场景的浓缩。做项目时较真一点后面上线就能少熬几个夜。本文还有配套的精品资源点击获取