1. 项目缘起与准备工作大家好我是老张一个在AI和计算机视觉领域摸爬滚打了十来年的“老码农”。今天想和大家聊聊一个非常经典且实用的项目——车牌检测。你可能在停车场、高速路口或者小区门禁都见过它的身影感觉很高大上但其实只要你跟着我的步骤用一台普通的电脑花上几个小时就能亲手训练出一个属于自己的车牌检测模型。这个项目特别适合那些已经对Python和深度学习有初步了解想找个实战项目练手的朋友。它不像人脸识别那样对数据要求苛刻也不像自动驾驶那么复杂车牌检测目标明确、场景固定是入门目标检测的绝佳选择。我们这次会使用目前工业界最流行的YOLO系列模型具体是Ultralytics公司开源的YOLOv11。别被版本号吓到它的使用方式非常友好而且性能强悍。在开始之前我们需要把“战场”打扫干净也就是搭建好开发环境。我强烈建议使用Anaconda来管理Python环境它能帮你避免各种依赖包版本冲突的“玄学”问题。下面是我的环境配置清单你照着来基本不会出错。首先创建一个新的Conda环境我习惯用Python 3.10这个版本比较稳定兼容性也好。conda create -n plate_det python3.10.15 -y conda activate plate_det激活环境后我们来安装核心的依赖包。这里的关键是版本匹配尤其是PyTorch和其对应的torchvision。我根据CUDA 11.8的环境选择了以下版本组合如果你没有GPU或者CUDA版本不同可以去PyTorch官网选择对应的安装命令。pip install torch2.5.1 torchvision0.20.1 pip install ultralytics8.3.43 opencv-python4.10.0.84 pip install tqdm4.67.1 pandas2.2.3 numpy1.26.4 albumentations1.3.0简单解释一下这几个包ultralytics是YOLO官方维护的库封装了训练、验证、预测的全流程是我们这次的主力工具。opencv-python用来处理图像读写和可视化。albumentations是一个强大的数据增强库能自动给训练图片做各种变换比如模糊、调整亮度等让模型更健壮。安装完成后你可以运行python -c “import torch; print(torch.cuda.is_available())”来确认GPU是否可用如果返回True恭喜你训练速度将会大大提升。2. 深入理解与处理CCPD数据集工欲善其事必先利其器。数据集就是我们模型的“粮食”粮食的好坏直接决定了模型的上限。在车牌检测领域CCPD数据集是目前中文场景下最权威、规模最大的开源数据集。它由国内高校收集并公开包含了各种天气、光照、角度和模糊情况下的车牌图片非常贴近真实世界。这个数据集主要包含两个部分CCPD2019蓝色普通车牌和CCPD2020绿色新能源车牌。总数据量超过25万张而且每张图片都只包含一个车牌这简化了我们检测的任务。数据集还细分为多个子集比如模糊的blur、有挑战性的challenge、不同亮度的db、远近不一的fn、甚至是没有车牌的np用于减少误检考虑得非常周全。我第一次用这个数据集时发现了一个“小机关”它没有单独的标注文件比如常见的.txt或.xml文件。它的所有标注信息都巧妙地藏在图片文件名里这听起来有点奇怪但用起来其实很方便。举个例子一个典型的文件名是这样的3061158854166666665-97_100-159434_586578-558578_173523_159434_586474-0_0_3_24_33_32_28_30-64-233.jpg。我们用“-”把文件名拆开就能得到所有信息。其中第三部分159434_586578就是车牌边界框的左上角和右下角坐标。第四部分558578_173523_159434_586474是车牌四个顶点的坐标注意它的顺序是从右下角开始顺时针排列的。我们需要写一个小脚本把这些信息解析出来并转换成YOLO模型需要的格式。YOLO需要的标注格式是归一化的即所有坐标值都要除以图片的宽度或高度变成0到1之间的小数。我写了一个完整的处理脚本gen_yolo_format_data.py它的核心工作流程是这样的遍历所有图片解析文件名得到原始坐标然后将其归一化并按照8:2的比例随机划分成训练集和验证集最后分别保存图片和对应的标签文件。标签文件里第一位数是类别ID我们只有“车牌”一类所以是0接着是边界框的中心点x、中心点y、宽度w、高度h最后是四个顶点的x, y坐标。这里我选择使用YOLO的Pose姿态估计模式来同时检测边界框和四个顶点因为顶点信息对于后续可能的车牌矫正很有帮助。如果你只关心车牌在哪用Detect模式只检测框就够了。运行脚本后你会得到一个结构清晰的data/ccpd_yolo文件夹里面images和labels文件夹下各有train和val子目录。最后我们需要创建一个YAML配置文件license_plate-pose.yaml告诉YOLO我们的数据在哪、类别是什么、关键点顶点的格式如何。这个配置文件是连接数据和模型的桥梁一定要写对。3. YOLO模型训练实战与调参心得环境好了数据也准备好了接下来就是最激动人心的环节——训练模型。我们使用YOLOv11n-pose这个预训练模型作为起点。用预训练模型就像学骑车先用带辅助轮的车它能大大缩短训练时间并提高最终性能。你可以从Ultralytics的官方GitHub页面下载这个yolo11n-pose.pt文件。训练命令看起来很简单但里面每个参数都值得琢磨yolo taskpose modetrain datadata/ccpd_yolo/license_plate-pose.yaml modelpretrain_models/yolo11n-pose.pt epochs30 imgsz640 batch16 workers4我解释一下这几个关键参数taskpose指定是姿态估计任务兼顾检测和关键点。modetrain是训练模式。data指向我们刚才写的配置文件。model指定预训练模型的路径。epochs30代表把所有训练数据“看”30遍。imgsz640是把输入图片统一缩放到640x640像素这是YOLO系列的经典输入尺寸。batch16是一次扔进GPU的图片数量如果你的显卡显存小比如8G可以调成8甚至4。workers4是数据加载的进程数可以加快数据读取速度。训练开始后控制台会刷刷地输出日志。别被那一行行数字吓到我教你重点看什么。最开始几行是模型结构摘要告诉你这个模型有多少层、多少参数。接着每个epoch结束后会输出一系列损失loss值和评估指标。损失值如box_loss,pose_loss是模型在训练集上犯的错误我们希望它们随着训练持续下降。我提供的训练日志里你可以看到box_loss从1.027降到了0.742pose_loss从0.5361降到了0.01862这说明模型确实在学习。更重要的是看验证集上的评估指标比如mAP50和mAP50-95。mAP50是交并比IoU阈值设为0.5时的平均精度可以理解为“检测得准不准”mAP50-95是IoU阈值从0.5到0.95的平均值更严格衡量“检测得精不精”。我们的模型在30轮训练后边界框和关键点的mAP50都达到了0.994以上mAP50-95也达到了0.85左右这个成绩对于实际应用来说已经非常优秀了。训练过程中可能会遇到一些问题我分享几个我踩过的“坑”。第一是“过拟合”如果发现训练集损失一直降但验证集指标早就不动了甚至下降那就是模型只“背会”了训练集没学会泛化。解决办法是增加数据增强的强度或者在配置文件中调整dropout参数。第二是“显存不足”如果报错“CUDA out of memory”就把batch调小或者把imgsz从640降到512。第三是“训练震荡”损失值上蹿下跳不稳定可以尝试调小学习率lr0参数或者使用cos学习率调度器让学习率随着训练平滑下降。4. 模型推理测试与效果优化训练完成模型权重会保存在runs/pose/train/weights/目录下其中best.pt是在验证集上表现最好的模型。现在是时候检验我们的劳动成果了。我们用几张网上找的、模型从未见过的图片来测试一下。推理的代码非常简单Ultralytics库封装得非常好from ultralytics import YOLO import cv2 # 加载训练好的最佳模型 model YOLO(‘runs/pose/train/weights/best.pt’) # 对单张图片进行预测 results model(‘your_test_image.jpg’) # 可视化结果并保存 annotated_frame results[0].plot() cv2.imwrite(‘result.jpg’, annotated_frame)运行后你会看到图片上车牌被一个绿色的框圈了出来四个角还有红色的点。这就是我们模型同时输出的边界框和顶点。如果效果不错恭喜你但很多时候第一次训练出来的模型可能在某些场景下表现不佳比如远处的小车牌没检测到或者把一些方形广告牌误认成车牌。这时候就需要进行效果优化。首先分析bad case。把模型预测错误的图片都找出来看看是哪些情况。是车牌太小太模糊还是倾斜角度太大然后针对性补充数据。如果小车牌检测不好就从CCPD的CCPD-fn远距离子集里多拿一些数据加入训练。如果误检多可以把CCPD-np无车牌子集也加入训练让模型学会什么是“非车牌”。最后可以尝试调整模型参数。比如对于小目标可以把imgsz适当增大如768或者在模型配置中修改detect层的anchor尺寸让其更适应小目标。还有一个高级技巧是模型集成。你可以用不同的数据增强策略、不同的初始权重训练2-3个模型推理时让它们“投票”决定往往能提升鲁棒性。不过对于新手我建议先把手头这个模型调优到满意为止。5. 从实验到部署下一步的思考模型在测试集上表现良好这只是一个开始。真正的挑战在于如何让它在一个真实的、持续运行的系统里稳定工作。这就涉及到模型部署。目前最主流的部署方式有两种ONNX Runtime和TensorRT。ONNX是一种开放的模型格式几乎可以被所有主流推理框架支持。使用Ultralytics可以很方便地将PyTorch模型导出为ONNX格式model.export(format‘onnx’)。导出的ONNX模型可以在CPU用ONNX Runtime或GPU用TensorRT上高效推理而且摆脱了对Python环境和PyTorch库的依赖更适合集成到C或Java开发的服务中。如果你追求极致的推理速度尤其是在NVIDIA GPU上那么TensorRT是你不二的选择。它是NVIDIA推出的高性能深度学习推理SDK可以对模型进行图优化、层融合、精度校准FP16/INT8量化从而大幅提升吞吐量降低延迟。将YOLO模型转换为TensorRT引擎需要一些步骤但网上有丰富的教程和脚本可以参考。在部署时我们还需要考虑预处理和后处理的优化。在训练时ultralytics帮我们自动完成了图像的缩放、归一化等操作。在部署时我们需要自己用C或Python实现完全相同的预处理流程确保输入数据格式一致。后处理即从模型输出张量中解析出框和类别的信息也需要仔细实现尤其是在批量处理图片时要处理好不同图片检测到不同数量目标的情况。最后我想说这个车牌检测项目是一个完美的起点。掌握了它你就打通了目标检测从数据准备、模型训练到评估测试的全流程。你可以举一反三用同样的方法去训练一个检测猫狗、检测货架商品的模型。深度学习的乐趣就在于这种“创造”的成就感。希望你能享受这个过程如果在实践中遇到任何问题欢迎随时交流讨论。记住每一个跑通的模型都是你技术栈里一块坚实的砖。