ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python车牌识别系统全解析:从YOLO检测到字符识别的完整实现

Python车牌识别系统全解析:从YOLO检测到字符识别的完整实现 简介这是一套面向Python初学者与课程设计实践者的车牌识别系统完整实现聚焦图像处理与模式识别技术落地适用于智能交通、车辆管理等场景的入门级项目开发与学习。资源包共578个文件含185个核心Python源码涵盖预处理、边缘检测、字符分割、CNN识别等模块、184个编译后pyc文件、60个加速用pyd扩展及25个依赖dll辅以20张测试样图jpg/png/bmp和配置文件整体体积48.2MB。已有1062人下载学习项目结构清晰包含可直接运行的主程序、训练数据占位符及多格式字体/音效等辅助资源便于理解从车牌定位、倾斜校正到颜色与号码双识别的全流程实现逻辑并为后续模型优化与工程化部署提供可扩展基础。 车牌识别这个项目在计算机视觉领域算是一个经典的入门到进阶的完整闭环。它不光是车牌识别本身而是把目标检测、图像预处理、颜色分类、字符分割、字符识别这几个CV核心模块全部串起来了。我在实际做这个项目之前一直觉得车牌识别无非就是“拍个照、读个字”等到真正动手去抠图、去处理各种光线和角度干扰的时候才发现这里面每一个环节都有不少细节值得琢磨。这篇就基于我实现的一个Python版车牌识别系统从设计思路、技术选型、核心实现到排查经验完整拆解一遍。这个系统做的事情很明确输入一张包含车辆的图片程序自动把车牌区域从整张图中“抠”出来然后判断车牌颜色蓝、黄、绿、白等最后识别出车牌上的字符。它可以作为独立项目运行也可以作为后续智慧停车、交通管理、安防监控等系统的一个子模块。1. 项目整体设计与技术选型拆解1.1 车牌识别到底在解决什么问题很多人第一次接触车牌识别觉得不就是OCR光学字符识别吗直接把图片丢给OCR引擎不就行了如果真这么干结果会非常惨。因为在整张车辆图片中车牌只是画面里很小的一块周围有车灯、保险杠、车身颜色、地面倒影、甚至路人等各种干扰。直接用OCR识别整张图模型根本不知道“该看哪里”而且车牌字符的字体、间距、排列方式也和普通文本不一样通用OCR很难直接出效果。所以车牌的识别流程必须拆解成几个独立任务从复杂背景中找到车牌的位置这叫车牌检测或定位把检测到的车牌区域从原图中切出来并尽可能矫正角度这叫抠图与矫正判断车牌是什么颜色这叫颜色识别把车牌区域进一步切成单个字符的图这叫字符分割最后对每个字符图像分类输出具体的省份简称、字母和数字这叫字符识别这个项目之所以有价值就是因为它把这五个环节串成了一条完整流水线。任何一个环节做不好最终结果都会出错所以它特别适合用来系统理解CV工程的完整链路。1.2 为什么用Python而不是C或Matlab如果是做工业级部署C确实是主流选择性能高、内存可控。但做项目学习、快速验证和算法迭代Python的优势太明显了。首先Python的OpenCV接口和底层C完全一致API调用一模一样你可以在Python里把算法调到满意再翻译成C版本用于部署开发效率翻倍。其次Python生态里有PyTorch、TensorFlow、ultralytics这些深度学习框架做目标检测可以直接用训练好的YOLO模型几十行代码就能完成推理。如果用C光是编译OpenCV、配置深度学习推理引擎就能劝退一大半人。再者这个项目的瓶颈根本不在语言层面而是在图像质量和模型精度上。即便用Python单张图片从检测到识别的时间也能控制在几百毫秒级别完全满足非实时场景的需求。所以我个人觉得只要不是做千万级并发或者嵌入式硬实时系统Python完全够用这也是我最终的选型结果。1.3 检测方案选型传统图像处理还是YOLO车牌检测是整个系统里最核心的环节因为后面所有步骤都依赖于“车牌到底在哪”这个前提。检测方案市面上主要分两派。传统图像处理方法的核心思路是先转灰度图用Sobel、Canny等算子做边缘检测再用形态学闭运算把相邻边缘连接成块最后通过轮廓查找、长宽比筛选、颜色特征验证来定位车牌。这套方法在十年前是主流优点是不依赖训练数据、不需要GPU、代码跑得快在背景相对干净、车牌清晰的图片上效果不错。缺点是抗干扰能力弱遇到复杂背景、强光照、车牌遮挡或者车身颜色和车牌颜色接近的情况容易出现漏检或误检。基于YOLO的深度学习方法把车牌检测看作一个目标检测任务用标注好车牌位置的图片训练模型让模型自动学习车牌的外观特征。它的优势是鲁棒性强能适应复杂场景检测精度高缺点是需要准备训练数据集、模型文件相对大、推理时需要一点算力。我在这个项目里采用的是YOLO方案因为从实际表现来看它的综合效果要稳定得多。如果你想让系统能在“真实场景的图片”上而不是“完美摆拍图”上工作YOLO几乎是必须的选择。传统方法可以用作兜底或者辅助验证但作为主力检测器效果确实不太够看。当然YOLO也有多个版本可选从YOLOv3到现在的YOLOv8、YOLOv9。我最终用了YOLOv5s因为它轻量、推理快、社区资料多遇到问题好查。实际训练时用小批量、低分辨率输入单张图推理在CPU上大概200到300毫秒GPU上几十毫秒完全够用。1.4 系统整体流程设计这系统的完整流程我画在脑子里是这样的读取图片 → 图像预处理 → YOLO检测车牌 → 抠出车牌区域 → 透视矫正 → 颜色识别 → 灰度化与二值化 → 字符分割 → 字符识别 → 输出结果。每个环节的输出都作为下一环节的输入所以模块之间的接口设计很重要。我的做法是定义统一的中间数据结构每步返回标准格式的结果这样后续扩展和调试都方便。举个例子检测模块输出的不只是车牌的坐标框还包括置信度分数。抠图模块根据坐标框裁剪后会先判断是否需要透视矫正矫正完再往下一步传。颜色识别和字符识别是并联关系它们都依赖抠图后的车牌图但互不依赖可以并行处理。这个流程设计的核心逻辑是“先粗后细、逐步聚焦”先从整张图缩小到车牌区域再从车牌区域缩小到单个字符每一次聚焦都减少了干扰、提高了后续模块的输入质量这也是传统图像识别流水线的通用方法论。2. 核心细节解析与实操要点2.1 图像预处理不同光线下的应对策略很多人忽略预处理觉得直接把图片扔给检测模型就行。但实际项目中你拿到的图片光线差异巨大正午强光、夜间路灯、逆光、阴影遮挡……不同环境下同一张车牌拍出来可能完全是两种效果。YOLO模型本身对光照有一定的鲁棒性因为训练时做了数据增强包括亮度调整、对比度调整、噪声注入等。但如果输入图片整体过暗或者过曝检测框的置信度还是会下降。所以我的做法是在送入模型前做一个轻量级的自适应预处理。我的预处理管线包含三步CLAHE限制对比度自适应直方图均衡化把图片转到LAB色彩空间对L通道做CLAHE再转回BGR。这样能增强暗部细节同时防止亮部过曝。降噪用高斯滤波或者双边滤波去除传感器噪声但要注意别把边缘也磨平了。尺寸归一化把图片长边缩放到640或960保持宽高比不足的部分补边这样符合YOLO模型的输入要求。实战中有一个坑要特别注意CLAHE的参数clipLimit和tileGridSize不能随便设。clipLimit太小基本没效果太大容易把噪声也放大tileGridSize决定局部均衡化的粒度一般用8x8比较稳妥。如果发现处理后车牌边缘出现奇怪的伪影优先检查这两个参数。2.2 车牌检测与抠图YOLO模型的使用与推理YOLO模型我用的是ultralytics框架它的接口封装得很干净。加载模型后对预处理好的图片做推理拿到检测结果再筛选出类别为车牌且置信度高于阈值我用0.5的框。这里有个细节实际场景中一辆车可能有前后两个车牌YOLO检测结果可能同时框出两个。此时需要根据业务需求决定取哪一个。比如停车场入口通常拍车头取最大面积的框即可但如果两个框大小接近可以都抠出来分别识别最后取置信度更高的结果。抠图之后还有一个容易被忽略的步骤透视矫正。因为相机不可能是正对着车牌拍的多少会有一点倾斜角度。如果直接把倾斜的车牌送去识别字符分割时会歪识别精度自然下降。透视矫正的做法是找到车牌的四个角点映射到一个固定尺寸的矩形上。如果用YOLO的检测框直接裁剪那是一个轴对齐矩形没法矫正倾斜所以我会再跑一次轮廓检测在抠出的图里精确定位车牌的四条边然后计算透视变换矩阵。透视矫正不是必须每次都做。如果检测框的宽高比接近标准车牌约3.14:1说明倾斜不严重可以跳过如果宽高比明显偏离再触发矫正逻辑。这样能省掉不少计算时间。2.3 车牌颜色识别HSV色彩空间的具体实现车牌颜色是车牌类型的重要标识国内常见的车牌颜色和对应类型大致是这样的颜色常见类型编码特征蓝色小型汽车蓝底白字黄色大型汽车、挂车黄底黑字绿色新能源汽车渐变绿底黑字小型、黄绿双拼底黑字大型白色军车、警车白底黑字或白底红字黑色涉外车辆黑底白字颜色识别最常用的方案是转HSV色彩空间后在色相H和饱和度S上做阈值判断。RGB对光照太敏感同样一个蓝色车牌白天晚上拍出来RGB值能差出一大截但HSV的H分量相对稳定。我实现了一套基于颜色占比的判定逻辑把抠出的车牌图转到HSV空间分别对蓝色、黄色、绿色、白色、黑色建立阈值范围统计每个颜色掩膜的像素占比占比最高的那个颜色就是判定结果。阈值的选取是个经验活。以蓝色车牌为例H通常在100到130之间S要大于60V不能太低绿色新能源车牌由于是渐变设计H在35到85之间都可能出现。如果你发现某类颜色老是被误判最好的办法是把你手上的错误样本的颜色值打出来统计一下分布区间再反向调整阈值。2.4 字符分割投影法与连通域分析字符识别前必须把车牌的7个或8个字符逐个切出来。常用方法有两种垂直投影法和连通域分析。垂直投影法的原理很直观把车牌图转成灰度图做二值化白字变白、底色变黑然后沿垂直方向统计每一列中白色像素的数量形成一条投影曲线。字符之间的间隔处白色像素会明显减少甚至归零根据这些“低谷”就可以切分字符。但直接做垂直投影会遇到两个问题一是铆钉、边框、螺丝等噪声会产生多余的投影峰导致误切二是字符内部的笔画断裂会造成本来连续的字符被切成两块。所以切分前要先做一轮预处理去掉上下边框方法是找水平方向的投影保留字符集中的区域去掉左右边框方法类似用形态学操作开运算去除小的孤立噪声连通域分析是另一种思路对二值图找所有连通区域然后根据每个连通域的位置和尺寸特征筛选出属于字符的区域。这个方法的优点是抗噪能力强缺点是可解释性不如投影法直观。我在项目里用的是“投影法为主、连通域校验为辅”的组合策略。先投影粗切再用连通域尺寸校验去掉太宽、太窄、太高、太低的误切块。二值化的算法选择也很关键。全局阈值Otsu方法在车牌质量和光照比较均匀时效果不错但如果车牌被阴影了一半全局阈值就会出错。遇到这种情况可以用自适应阈值对每个像素根据邻域计算局部阈值效果会好很多。不过自适应阈值计算量更大而且对字符笔画较细的情况容易产生断裂需要配合形态学闭运算修复。2.5 字符识别CNN模型与模板匹配的选择字符分割完成后每个字符都是一张独立的小图接下来就是分类问题。字符集合大约有省份简称31个汉字、24个字母排除I和O、10个数字总体类别数在65个左右。模板匹配是一种朴素方案把所有标准字符的模板图片和输入图片逐像素对比找相似度最高的那个。它的优点是无需训练、实现简单缺点是对字体变化、模糊、倾斜非常敏感稍微有点噪声就匹配错。汉字“鲁”和“豫”这种结构接近的模板匹配很容易翻车。CNN模型是目前的主流方案。输入是字符小图输出是65个类别的概率分布。训练数据可以来自公开数据集也可以从真实车牌图中半自动标注。网络结构不需要很复杂一个轻量的LeNet-5或者简单的两层卷积加全连接就能达到不错的准确率。如果追求更高精度可以用MobileNet或ResNet的预训练模型做迁移学习。我在项目里的做法是先用一个轻量CNN作为主力识别器再用模板匹配做二次校验。当CNN输出的最大概率低于某个阈值比如0.7时说明模型对这张图不太确定此时用模板匹配结果作为参考如果两者一致就输出不一致则标为“待人工确认”。这样既保证了速度也提升了整体稳定性。CNN训练有一个容易踩的坑类别不平衡。省份简称里“京”“苏”“粤”样本多“渝”“藏”样本少模型容易偏向样本多的类别。解决办法是给每个类别设置不同的损失权重或者对样本少的类别做数据增强。3. 实操过程与核心环节实现3.1 环境搭建与依赖安装这个项目需要的依赖不算多主要就是OpenCV、NumPy、PyTorch推理用和ultralytics。我建议用Anaconda创建独立环境避免和系统Python冲突。conda create -n plate_recognition python3.9 conda activate plate_recognition pip install opencv-python numpy torch ultralytics如果只是用CPU推理PyTorch安装CPU版本就够不要默认装CUDA版白白占好几个G空间pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu我最初装环境的时候犯过一个错误就是直接pip install torch把GPU版装上了结果机器没有NVIDIA显卡运行时报“CUDA not available”警告虽然不影响CPU推理但每次启动都在日志里刷警告看着很不舒服。后来重装了CPU版才清净。如果你用的是PyCharm或者VS Code记得把解释器切换到刚才创建的conda环境否则import opencv时会报ModuleNotFoundError。3.2 项目目录结构规划代码组织得清晰调试和维护才会省心。我的项目目录是这样的plate_recognition/ ├── main.py # 主入口串联整个流程 ├── detector.py # YOLO车牌检测模块 ├── color_recognizer.py # 车牌颜色识别模块 ├── char_segmenter.py # 字符分割模块 ├── char_recognizer.py # 字符识别模块 ├── utils.py # 公共工具函数图像增强、透视矫正等 ├── models/ │ ├── plate_detect.pt # YOLO检测权重 │ └── char_cnn.pth # 字符识别权重 ├── data/ │ ├── test_images/ # 测试图片 │ └── train_data/ # 训练数据如果需要微调 └── requirements.txt每个模块的接口都定义得很简洁。detector.py暴露一个detect_plate(image)函数返回车牌的包围盒列表color_recognizer.py暴露recognize_color(plate_img)返回颜色字符串和置信度char_recognizer.py暴露recognize_chars(char_images)返回字符列表。接口统一的好处是后面想替换检测方案比如从YOLOv5换成YOLOv8或者替换字符识别模型只需要改对应模块内部实现主流程代码一行都不用动。3.3 核心代码实现与讲解YOLO检测模块的代码非常简单ultralytics封装得太好了# detector.py from ultralytics import YOLO import cv2 class PlateDetector: def __init__(self, model_pathmodels/plate_detect.pt, conf_thres0.5): self.model YOLO(model_path) self.conf_thres conf_thres def detect_plate(self, image): # image 是 BGR 格式的 numpy 数组 results self.model(image, confself.conf_thres, verboseFalse) boxes [] for result in results: for box in result.boxes: x1, y1, x2, y2 map(int, box.xyxy[0].tolist()) score float(box.conf[0]) boxes.append({bbox: (x1, y1, x2, y2), score: score}) # 按面积排序面积最大的优先 boxes.sort(keylambda b: (b[bbox][2]-b[bbox][0])*(b[bbox][3]-b[bbox][1]), reverseTrue) return boxes写代码时有一个容易忽略的点ultralytics的model()返回的results是一个列表即使只有一张图也要遍历result.boxes不能想当然地直接取results[0].boxes。一开始我就犯过这个错以为返回的是单张图的结果对象结果遍历的时候老是报错。颜色识别模块的核心是HSV阈值和像素占比统计# color_recognizer.py import numpy as np import cv2 def recognize_color(plate_img): hsv cv2.cvtColor(plate_img, cv2.COLOR_BGR2HSV) color_ranges { blue: ([90, 60, 60], [130, 255, 255]), yellow: ([20, 70, 80], [35, 255, 255]), green: ([35, 50, 40], [85, 255, 255]), white: ([0, 0, 180], [180, 30, 255]), black: ([0, 0, 0], [180, 255, 60]), } best_color unknown best_ratio 0 total_pixels plate_img.shape[0] * plate_img.shape[1] for color, (lower, upper) in color_ranges.items(): mask cv2.inRange(hsv, np.array(lower), np.array(upper)) ratio cv2.countNonZero(mask) / total_pixels if ratio best_ratio: best_ratio ratio best_color color return best_color, best_ratio这个逻辑可以跑通但实测下来会有一些细节要调白色车牌的V阈值亮度不能取得太低否则车牌的白色边框会被误判为白色而新能源绿色车牌的渐变设计会让绿色像素占比不如预期高所以绿色识别要特别小心必要时可以结合字符颜色辅助判断。字符分割模块是整条流水线里最脆弱的一环# char_segmenter.py import cv2 import numpy as np def segment_chars(plate_img): # 去除上下边框 gray cv2.cvtColor(plate_img, cv2.COLOR_BGR2GRAY) _, binary cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) # 如果车牌是白底黑字需要反转统一成黑底白字 if np.mean(binary) 127: binary cv2.bitwise_not(binary) # 水平投影确定字符区域的上下边界 horizontal_proj np.sum(binary, axis1) // 255 rows_with_text np.where(horizontal_proj 1)[0] if len(rows_with_text) 0: return [] top, bottom rows_with_text.min(), rows_with_text.max() binary binary[top:bottom1, :] # 垂直投影切割字符 vertical_proj np.sum(binary, axis0) // 255 chars [] in_char False start 0 for i, val in enumerate(vertical_proj): if val 0 and not in_char: in_char True start i elif val 0 and in_char: in_char False width i - start if width 5: # 过滤掉过窄的噪声 chars.append((start, i)) return chars, binary分割这一步是最容易出现问题的因为车牌的字符间隔不是均匀的省份简称和字母之间、字母和数字之间的间距都不同而且有些老车牌固定螺丝正好压在两字符之间投影时会产生一个“假间隔”。我在实际项目中踩过的坑包括车牌的“苏”字因为笔画连笔被切成了两半车牌的螺丝把“0”和“D”之间的间隔堵住了。所以分割后一定要加一个字符数量校验如果切出来的数量不是7个或8个具体看车牌类型说明分割出错需要触发备用方案比如用连通域重新分割。3.4 模型训练与数据集准备YOLO检测模型和字符识别模型都需要训练数据。很多人卡在这一步觉得没有现成的模型文件项目就跑不起来。YOLO检测模型的数据集可以这样准备找几百张包含车辆的图片用标注工具LabelImg或LabelStudio框出车牌位置导出为YOLO格式的txt文件。一张图上可能同时有多个车牌那就标注多个框。训练的时候用预训练的YOLOv5s权重做起点冻结前几层只微调后面几层几百张图就够了。我没有用到几百张那么夸张实际用了400多张图片就训练出了效果不错的模型关键是要保证图片的多样性不同光线、不同角度、不同车型、不同背景。字符识别模型的数据集更简单可以从公开的开源车牌数据集里直接下载分割好的字符图片也可以先从网上找一些车牌图片跑一遍分割流程再人工筛选出质量好的字符图片。一个比较巧妙的扩充方法是用不同的字体渲染字符加上随机的背景噪声、模糊、透视变换生成大量合成样本。合成样本做训练的主干真实样本做验证双管齐下。我在训练时发现一个有意思的现象合成样本训练出来的模型在真实图片上准确率大约在85%到90%之间加上真实样本微调后可以提升到95%以上。说明合成数据解决的是“字符形态”问题真实数据解决的是“图像噪声和退化”问题两者互补缺一不可。3.5 性能测试与结果我用40张测试图片做了一个小规模评测这些图片包含了蓝牌、黄牌、绿牌有正对车牌的、有略微倾斜的、有夜间拍摄的、有车身颜色和车牌颜色接近的。整体结果车牌检测成功率IOU大于0.6达到了97.5%只有一张因为车牌被严重遮挡没检测出来颜色识别准确率92.5%主要错误发生在绿色新能源车牌的渐变区域被误判为蓝色字符识别准确率大约92%左右错误集中在汉字上尤其是“徽”“赣”“湘”这类笔画复杂的字。单张图片从加载到输出结果CPUIntel i5平均耗时约600毫秒其中YOLO推理占了一半左右。如果部署到Web服务做好模型常驻内存可以稳定在每秒处理1到2张图。4. 常见问题与排查技巧实录4.1 环境搭建阶段最容易踩的坑先说一个最普遍的OpenCV的cv2在import时报错。这个通常是因为Python版本和OpenCV版本不兼容或者装了多个Python造成路径混乱。我建议在conda环境里统一管理不要用系统Python。另外注意opencv-python这个包名如果你用的是conda install opencv版本可能比较老建议用pip安装最新版。还有一个很隐蔽的问题如果电脑上装了PyTorch的GPU版但没有NVIDIA驱动或显卡不支持CUDA虽然程序能跑但每次启动都会加载一堆CUDA库拖慢启动速度。如果确定只用CPU就装CPU版的torch。4.2 检测不到车牌或者检测框偏了检测不到车牌先看图片本身的原因。如果车牌本身很小或者图片非常暗可以先做一次简单放大或增强再送检测。如果图片上有大量类似车牌形状的物体比如广告牌、车灯区域模型可能把注意力分散。如果检测框跑偏我的排查顺序是检查置信度阈值如果设得太高比如0.9漏检会增多可以先降到0.3看看效果检查输入图片尺寸YOLO对太小的目标不敏感把长边缩放到960而不是640可能改善小目标检测检查预处理是否过度CLAHE参数太激进会把车身纹理也增强出来增加干扰4.3 字符识别错误率高怎么调字符识别错误优先排查分割环节。分割不准后面的识别模型再强也没用。你可以把分割后的字符图逐个显示出来看看每张图是否完整包含一个字符。如果分割没问题那就是识别模型的问题。最简单有效的优化方向是增加训练数据的多样性对已有的字符图片做随机旋转、缩放、亮度变化、添加噪声等数据增强让模型见过更多“变体”。还有一个很实用的技巧利用车牌格式的先验知识做约束。中国车牌的格式是“省份简称 发牌机关字母 5位号码”其中第一位一定是汉字第二位一定是字母A-Z后五位是字母和数字的组合。如果识别结果的第一位不是常见省份简称或者第二位不是字母那基本可以断定识别有误此时可以返回一个低置信度给上层业务让系统决定是重试还是人工介入。4.4 颜色识别老是误判怎么办颜色误判最常见的是蓝色和绿色混淆尤其是在新能源车牌上。新能源车牌的主色是渐变绿某些光线下像素的H值会落在蓝色区间。我的解决办法是先识别车牌字符的“底纹”和“字符颜色”的对比关系而不是单靠底色判断。比如新能源牌是绿底黑字普通蓝牌是蓝底白字如果抠出的车牌中浅色像素白色占比较高大概率是蓝牌如果深色像素黑色占比较高大概率是绿牌。另一个思路是直接增加颜色检测的样本把车牌的HSV统计结果记录下来做一个小的SVM分类器替代手工阈值。虽然会多写几十行代码但泛化能力比固定阈值好不少。4.5 车牌倾斜、模糊、遮挡的特殊情况真实世界是残酷的测试集做得再漂亮一到实际环境总会冒出各种幺蛾子。倾斜的车牌对检测影响不大YOLO可以检测出倾斜目标但倾斜对字符分割和识别影响很大。我的做法是检测到车牌后先做透视矫正具体是提取车牌的四个角点映射到标准宽高比的矩形。模糊车牌没有太好的根治办法但可以尝试锐化或者超分辨率。OpenCV的filter2D加一个简单的锐化核就能有效改善轻微模糊。如果模糊太严重那就只能降低置信度并在结果里标注“低置信度”不要硬给一个错误答案。遮挡就更头疼。如果车牌被保险杠或者污渍挡住了一部分最负责任的做法是输出“识别不完整”而不是强行识别出一个残缺字符。我在字符分割时加了一个最低连通域数量的判断如果切出的字符数量或字符间宽度明显异常就标记失败这在业务上反而是更可靠的行为。4.6 实测可用的调试小技巧最后分享几个调试经验。第一每个环节都加可视化输出。我会在处理完检测、分割、识别后把中间结果拼成一张图保存出来。这样当识别结果不对时能一眼看出是检测偏了、分割裂了还是识别错了而不是对着几十行日志瞎猜。第二为每个模块准备一组“黄金测试用例”跑完代码后先用这组用例回归一遍。如果分割改了代码导致别的地方崩了回归测试能立刻发现。别觉得自己的项目小就不用做测试这个项目模块多、链路长一处改动引发连锁问题的情况太常见了。第三关注极端输入。比如纯色无车的图片、全黑图片、车牌占满整张图的特写。把这些极端图片丢进去能提前发现很多边界bug。比如我的YOLO检测模块在车牌占满整图时检测框容易超出图片边界裁剪时会报错后来在裁剪前加了对坐标做越界限制的处理问题才解决。车牌识别系统做下来我自己最大的感受是单看每一个模块都不难难的是把它们串起来还能稳定工作。数据质量、参数调优、异常处理这些看不见的功夫才是整个项目的真正主体。这个项目做完之后我再去看其他目标检测或者OCR项目套路都变得很清晰因为你已经知道了最核心的那几条线在哪里。本文还有配套的精品资源点击获取
返回列表