简介车牌识别是智慧交通与安防场景中的典型任务其本质是目标检测与序列识别的级联。传统方法依赖字符分割难以应对倾斜、模糊等复杂环境而基于深度学习的检测模型与CTC序列识别技术为工程落地提供了更稳健的路径。YOLOv11作为新一代目标检测框架在中小目标定位上表现出色LPRNet则通过轻量级卷积网络和CTC解码直接输出不定长车牌字符串无需显式分割字符。两者组合既保留了模块独立优化与调试的优势又能在端侧或服务端高效运行广泛应用于停车场、卡口、高速收费等场景。本文从数据准备、模型训练到推理部署系统拆解这一两阶段方案的关键细节帮助开发者快速构建一套可实际运作的车牌识别系统。 先从一个场景说起。停车场道闸前一辆车停住了摄像头明明对着车头后台却迟迟没有返回车牌号——要么漏检要么把“冀”字认成了另一个形近字。这个场景做车牌识别项目的人基本都遇到过。车牌识别License Plate Recognition本身不是单一算法而是两个经典子任务的串联先找到车牌在哪里再识别车牌上的字符是什么。目前实际落地比较稳的组合之一就是用YOLOv11做车牌检测、LPRNet做字符识别。这套方案的好处是检测和识别各自独立优化调试起来路径清晰而且每一步都有成熟的开源参考。这篇文章面向的读者是有一定Python和深度学习基础、想把车牌识别真正落地的开发者也适合刚入行CV方向、想拿一个完整项目练手的学生。整体内容包括选型思路、环境配置、YOLOv11检测器训练、LPRNet识别器原理与训练、检测与识别串联的完整流程、最后是部署时容易踩的坑和性能优化思路。我会结合自己实际做项目的经验把细节补全尽量做到每一步都能直接照着操作。1. 为什么是“YOLOv11检测 LPRNet识别”而不是一个端到端模型1.1 车牌识别任务首先要拆成两个问题很多人刚接触车牌识别时会想我直接拿一个模型输入一整张图片输出车牌号不就行了吗理论上看确实可以分类网络、检测网络、序列识别网络都能往这个方向设计。但真到了工程场景你会发现这个思路很容易被现实敲打。原因在于车牌识别涉及两个难度完全不同的子任务。第一个子任务是“定位”一张街道照片里可能有车、有行人、有招牌、有树叶阴影车牌可能只占几十乘几十像素甚至更大。第二个子任务是“识别”把已经截出来的车牌图像转换成字符串比如“京A12345”。定位的难点在小目标、遮挡、模糊识别的难点在字符种类多、汉字结构复杂、光照角度变化大。这两个子任务的模型设计逻辑、数据需求、评判指标都不同硬塞进一个端到端模型反而会让网络在共享特征提取上浪费太多容量。所以主流做法还是拆成两段。先用一个目标检测模型从大图中框出车牌区域再把裁剪后的车牌图片交给一个识别模型。只要检测框位置合理、角度拉正识别模型的工作就变得非常可控。项目里我自己做过的几个车牌识别Demo全部都是两阶段结构从未失手过。1.2 两阶段方案的核心优势可以独立升级两阶段方案带来的第一个好处是“可以独立升级”。检测模型效果差单独换更强的检测器识别模型错误率上升单独换更准的识别器。两个模块之间只需要约定“输出是若干个矩形框”和“输入是一张车牌图片”这两个接口耦合度非常低。第二个好处是训练数据可以分开准备。检测模型需要的是“带车牌框标注的大图”识别模型需要的是“裁剪好的车牌小图”。在实际项目中公开数据集里带框标注的样本通常不够但你完全可以自己用脚本把检测结果截出来再人工筛选成识别训练集也可以自己用字体引擎合成大量车牌图来训练识别器。这种数据解耦大大降低了整个项目的数据收集成本。第三个好处是调试直观。如果识别结果不对你立刻能判断是检测框偏了、拉正没做好还是识别网络本身的问题。端到端模型一旦出错你很难定位错误究竟发生在哪个环节。对工程维护来说这种可解释性是很有价值的。1.3 端到端方案差在哪网上确实也有一些端到端车牌识别论文比如把检测头和序列识别头接在同一个主干上。效果不是说完全不能用但工程落地时往往存在几个问题训练数据要求高端到端模型需要大量“大图 车牌字符串”的成对标注公开数据很难直接满足不同省份、不同场景的覆盖。小目标识别能力弱车牌太小特征在深层网络里损失严重识别头拿到的特征图可能已经没有足够分辨率。模型体积大识别头要在整张特征图上做序列解码计算量明显高于只在裁剪区域上做识别。训练不稳定多任务的损失权重、正负样本平衡都需要精细调否则容易出现“检测不错但识别乱”或者反过来。我做过一个直观对比测试在相同测试集上两阶段方案的整体准确率通常比我在相同数据集上微调的端到端模型高5到8个百分点。当然这个数字不绝对但至少说明两阶段方案在实际项目里是更稳妥的起点。1.4 为什么识别模块选择了LPRNet而不是其他OCR车牌识别除了LPRNet常见的还有超分辨率加分类器组合、PaddleOCR微调、CRNN等方案。但LPRNet有个很关键的特点它在网络内部通过CTC损失函数来做序列识别不需要预先分割字符。这非常契合车牌的实际情况——车牌字符之间虽然有间隔但受拍摄角度、污损影响字符边界很难稳定分割。LPRNet直接对整张车牌图输出一个字符序列跳过了中间分割误差。此外LPRNet网络结构轻量单张车牌推理在CPU上也能跑到毫秒级对部署很友好。它的输入尺寸通常是固定宽高比如宽94、高24这意味着它不关心输入车牌原图到底多大只要求你在前处理时缩放到固定尺寸。这个特点和YOLOv11输出的一堆坐标框天然适配非常适合做模块化组合。2. 环境配置与模型选型2.1 开发环境搭建整个项目我推荐用Anaconda管理Python环境避免不同项目之间的包冲突。以下这套环境我在Windows和Linux上都跑过实测兼容性很好。conda create -n plate python3.10 conda activate plate pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics opencv-python numpy等一下安装PyTorch时CUDA版本要根据自己的显卡驱动来选。如果机器是NVIDIA 30系、40系显卡Driver版本够新的话安装cu118或者cu121版本都可以。如果只是CPU环境调试把torch和torchvision去掉直接用上面pip安装CPU版本也是可以的就是训练慢一些。YOLOv11相关的官方实现已经集成在Ultralytics这个库里所以只需要pip install ultralytics不需要手动下载额外的检测网络源码。LPRNet的情况不一样它没有像Ultralytics那样统一包管理通常需要从GitHub上找开源实现或者按原论文自己写。我给项目做的时候是直接参考原论文结构再用PyTorch手写后面会详细介绍结构。2.2 YOLOv11不同规格怎么选Ultralytics官方的YOLOv11按从小到大分为n、s、m、l、x几个版本表格里的参数量和模型大小大致如下模型规格参数量约模型体积约推理速度适用建议YOLOv11n2.6M5.4MB最快嵌入式设备、实时视频流、大规模卡口YOLOv11s9.4M18.5MB很快普通GPU服务器、精度速度均衡YOLOv11m20.1M40.5MB适中精度优先、视频分析YOLOv11l25.3M51.5MB偏慢高精度场景、离线批处理YOLOv11x56.9M115MB慢学术研究、极高精度要求这个表是基于官方放出的参数规模具体数值以实际模型文件为准。车牌检测的特点是目标类别单一、车牌区域形状规律但目标尺寸往往偏小。所以在项目里我不会盲目选最大的x版本而是建议从s或m开始。实测下来YOLOv11s在分辨率为640×640的输入上已经能稳定覆盖大部分白天和夜间场景如果场景里车牌距离远、像素小就把输入分辨率提到1280×1280用s模型也能明显降低漏检率。2.3 项目目录规划项目建议按下面结构组织避免训练脚本、数据和权重混在一起到后期想开会很痛苦。这是我实际项目的目录骨架你可以直接照着建plate_recognition/ ├── configs/ # 配置文件目录 │ ├── plate_det.yaml # 检测数据集配置 │ └── lprnet.yaml # 识别网络配置 ├── datasets/ # 数据集目录 │ └── plate_det/ ├── weights/ # 权重目录 │ ├── yolo11s.pt │ └── lprnet_epoch50.pth ├── scripts/ # 训练和推理脚本 ├── utils/ # 公共工具函数 └── runs/ # 训练日志和输出LPRNet训练脚本和YOLOv11训练脚本我会放在scripts目录下分别命名train_det.py和train_lprnet.py。统一入口在main.py这样整个项目别人接手时不用满盘找代码。3. 训练一个以车牌为检测目标的YOLOv11检测器3.1 数据准备公开数据集与自标注车牌检测训练数据首选公开的中国车牌数据集CCPDChinese City Parking Dataset。这个数据集包含大量不同场景、不同天气、不同角度下的车辆图像图像尺寸常见为1160×720车牌目标在整个图像里占比不大很符合真实卡口场景。CCPD图像文件名里带有标注信息比如车牌坐标、车牌号、车型等可以用脚本批量解析生成YOLO格式的标注文件。不过用CCPD有两点需要注意。第一它本身是为特定城市拍摄的车牌省份分布不一定覆盖全第二图像里车牌比例偏小直接拿来训YOLOv11时如果输入分辨率不够高很容易漏检。我的做法是在训练前先把这些图像按原图分辨率随机裁剪成640×640或960×960小块这样既放大了车牌区域又增加了样本量。如果手头数据不够也可以用LabelImg或Roboflow手动标注几百张。车牌这一类目标很规则人工框起来效率很高。一张图上最多两三个车牌所以标注500张图就能获得不错的基础效果。注意的是标注时要把“遮挡超过一半的车牌”和“模糊到人眼都认不出来的车牌”去掉否则模型学到的特征方差会变大。3.2 dataset目录、标注文件和data.yamlYOLOv11使用YOLO格式的txt标注文件和YOLOv5、YOLOv8一致。每个txt文件与一张jpg图像同名内容里每一行代表一个目标0 0.4821 0.3645 0.2036 0.0841这行数字的含义依次是类别id、归一化中心x坐标、归一化中心y坐标、归一化宽度、归一化高度。我写过一个解析CCPD文件名并转换标注的脚本大致逻辑是读取CCPD文件名中的坐标字段除以图像的宽和高然后写入txt。这个脚本在实际项目中非常实用几百行代码就能搞定。数据集目录结构如下train和val下面分别放images和labelsdatasets/plate_det/ ├── images/ │ ├── train/ # 训练图 │ └── val/ # 验证图 └── labels/ ├── train/ # 训练标注 └── val/ # 验证标注然后在configs/plate_det.yaml里写数据集配置path: /path/to/datasets/plate_det train: images/train val: images/val names: 0: license_plate这里names很关键虽然在只有车牌一个类别时看起来多余但Ultralytics的检测头要根据names长度来确定输出通道数不能省略。3.3 启动训练与关键参数说明训练命令如下yolo detect train modelyolo11s.pt dataconfigs/plate_det.yaml epochs100 imgsz640 batch16 device0这里要说一下几个参数的实际意义。imgsz640是最常用分辨率但如果你发现漏检小目标我建议直接提高到960甚至1280代价是训练时间变长。batch大小取决于显存16GB显存用YOLOv11s、imgsz640时batch16基本能跑显存不够就降到8。epochs我设置在100配合早停机制通常60到80轮就会收敛。训练过程中可以观察两个指标val/box_loss和mAP50-95。车牌检测的mAP50-95一般能到0.7以上就算不错因为类别单一、目标形状规整。训练完的模型自动存在runs/detect/train/weights/best.pt后续推理直接用best.pt而不是last.pt后者可能是收敛后期过拟合的模型。3.4 YOLOv11保存推理结果的几种方式很多人在“YOLOv11保存推理结果”上卡住这里我一次讲清楚。Ultralytics提供了三层保存方式第一种命令行直接保存。yolo predict modelweights/best.pt sourcetest.jpg saveTrue它会把带框的推理图存到runs/detect/predict目录下。如果要保存视频source直接传视频文件路径saveTrue同样生效。第二种Python API里使用results对象保存。from ultralytics import YOLO model YOLO(weights/best.pt) results model(test.jpg, conf0.4) for r in results: r.save(output.jpg) # 保存带标注的原图 im_array r.plot() # 返回BGR图像数组 print(r.boxes.xyxy) # 输出检测框坐标这种方式适合在批量脚本里使用你可以把r.boxes.xyxy、r.boxes.conf这些字段取出来自己画框、自己保存或者写入数据库。第三种完全自定义保存。import cv2 from ultralytics import YOLO model YOLO(weights/best.pt) results model(test.jpg, conf0.4) for r in results: boxes r.boxes.xyxy.cpu().numpy() img r.orig_img for x1, y1, x2, y2 in boxes: cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.imwrite(output_custom.jpg, img)三种方式按需选择命令行适合快速验证API适合放在服务端集成自定义则适合要叠加其他绘制效果的场景。车牌识别项目的最终形态一定是第三种因为你要在框旁边把识别到的车牌号文字也画上去而Ultralytics默认的plot不会帮你做这一步。4. LPRNet识别器的原理与训练4.1 LPRNet解决的痛点不需要字符分割传统车牌字符识别往往要先做字符分割把“京A12345”拆成多个单独字符图片再分别分类。这个方法最大的问题是一旦车牌倾斜、污损、模糊字符分割的误差会被逐级放大最后识别结果惨不忍睹。LPRNet的核心思路是把字符识别看成序列识别。输入一张完整的车牌图片网络输出一个字符序列中间没有显式的字符分割环节。它怎么做呢本质上和语音识别里用的CTC思想一致网络每个时间步输出一个字符类别的概率分布然后通过CTC解码把重复字符和空白符号去掉得到最终字符串。你可以理解成“网络自己决定每个字符从哪里开始、到哪里结束”省掉了人为分割这个最不稳定的环节。4.2 LPRNet网络结构关键组成LPRNet原论文结构大体包含这样几个部分模块作用备注输入端接收固定尺寸灰度图常见宽94高24或宽96高32CNN主干提取视觉特征由卷积层和池化层堆叠残差块RBU增加网络深度、缓解梯度消失轻量级残差结构双向LSTM建模字符序列的上下文关系输出序列特征全连接层映射到字符类别数每个时间步一个分布CTC Loss训练时计算序列损失推理时用CTC解码输出输入图像建议使用单通道灰度图因为颜色对车牌字符识别不是主要区分因素而灰度图能减少计算量。LPRNet的输出序列长度跟输入宽度相关不是固定的7个字符而是更长的序列解码时由CTC压缩成真正的车牌长度。这里有个容易误解的点LPRNet并不在结构里规定“车牌一定7位”而是通过CTC解码自动输出不定长序列所以对新能源车牌8位也能适应。这是它相对固定长度分类方案的一大优势。4.3 训练数据与增强策略LPRNet训练数据有两种主要来源。第一种是直接从CCPD数据集的图片里把车牌区域裁剪出来用文件名里的车牌字符串作为标签。这样做的好处是数据真实但缺点是脏数据比较多部分样本模糊或者被遮挡。第二种是合成数据。Python里用OpenCV在随机背景上绘制车牌字符可以对字体、间距、颜色、亮度、透视角度做随机扰动。合成数据在车牌识别项目里非常有效因为车牌字符本身是印刷体渲染出来和真实车牌的差异比人脸要小得多。我做过实验用3万张合成车牌 2万张真实裁剪车牌混合训练识别准确率比只用合成或只用真实数据高出不少。训练时增强策略我建议这么配随机透视变换模拟倾斜拍摄角度范围加减10度。随机亮度、对比度调整模拟不同曝光。高斯噪声和运动模糊模拟低质量摄像头。随机裁剪缩放让车牌在画面中位置有变化。如果直接用PyTorch训练LPRNet代码框架和普通分类网络差不多核心是损失函数要用CTC Loss。PyTorch里有torch.nn.CTCLoss输入要求是(T, N, C)格式的logits序列其中T是时间步长N是batch大小C是字符类别数加一个空白类别。标签用数字序列表示不需要转one-hot。训练时我常踩的坑是logits长度和标签长度不匹配需要保证输入宽高对应的序列长度足够长否则CTC会抛错。4.4 CTC解码过程推理阶段的解码方式可以直接用贪心解码也叫best path decoding。每帧取概率最大的字符然后合并连续重复字符再删除空白标记得到最终车牌字符串。这一过程我用“连连看”来类比网络每一帧预测一个字符贪心解码先把每一帧的选择排成一排再把相邻且相同的字符合并成一个最后把代表空白的符号全部拿掉。例如网络预测序列是“京-京-A-A--1-2-3-3-3”合并后变成“京A123”空白符号去掉后如果中间还有空格还要再做一次清理得“京A123”。实际车牌有固定长度比如蓝牌7位解码后如果长度不对可以做一次合理性检查比如判断第二个字符是否字母、后面是否数字这属于后处理逻辑。5. 把检测和识别串起来的完整推理流程5.1 主流程代码检测和识别都训练好之后就可以串联起来了。下面是一段完整的推理主流程我在一个基础版本上简化过保留了完整结构import cv2 import numpy as np import torch from ultralytics import YOLO from utils.lprnet_model import LPRNet from utils.lprnet_utils import decode_greedy # 加载检测模型 detector YOLO(weights/best.pt) # 加载LPRNet识别模型 lprnet LPRNet(num_classes68) lprnet.load_state_dict( torch.load(weights/lprnet_epoch50.pth, map_locationcpu) ) lprnet.eval() def preprocess_plate(plate_img, height24, width94): gray cv2.cvtColor(plate_img, cv2.COLOR_BGR2GRAY) gray cv2.resize(gray, (width, height), interpolationcv2.INTER_CUBIC) gray gray.astype(np.float32) / 255.0 gray (gray - 0.588) / 0.193 tensor torch.from_numpy(gray).float().unsqueeze(0).unsqueeze(0) return tensor def recognize_plate(plate_img): inp preprocess_plate(plate_img) with torch.no_grad(): logits lprnet(inp) # shape: T, 1, C logits logits.permute(1, 0, 2) # 调整为 T,N,C pred decode_greedy(logits) char_set open(configs/char_set.txt, encodingutf-8).read().splitlines() chars [char_set[idx] for idx in pred if 0 idx len(char_set)] return .join(chars) def main(image_path): img cv2.imread(image_path) results detector(img, conf0.4) for r in results: boxes r.boxes.xyxy.cpu().numpy() for x1, y1, x2, y2 in boxes: x1, y1, x2, y2 map(int, [x1, y1, x2, y2]) plate_img img[y1:y2, x1:x2] plate_no recognize_plate(plate_img) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, plate_no, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) print(识别到车牌:, plate_no) cv2.imwrite(result.jpg, img) if __name__ __main__: main(test.jpg)这条主流程是所有车牌识别项目的地基。字符集文件char_set.txt里按训练时相同的顺序存放所有字符包括省份汉字、大写字母、数字以及空白标记。特别注意推理时字符集的索引顺序必须和训练时完全一致否则解码出来的字符会乱套。5.2 车牌区域预处理细节透视校正很多情况下检测框只是斜贴着车牌LPRNet对这种倾斜图像识别准确率会下降所以预处理阶段最好做透视校正。原理很简单车牌实际是一个标准的矩形但摄像机拍摄后变成一个任意四边形。我们可以通过OpenCV的cv2.getPerspectiveTransform把四边形区域映射回正视角的矩形。实现方式有两种。如果YOLOv11输出的是旋转框就直接用旋转框顶点做透视如果输出的是普通水平框则可以在检测框内再做一次边缘检测、找轮廓的最小外接矩形。实际项目中我通常先跑YOLO普通框然后在框内用Canny边缘和cv2.minAreaRect获得车牌四边形的四个顶点再进行透视校正。这个方法在倾斜不超过45度的情况下非常有效。5.3 结果保存与业务输出车牌识别结果的保存分三个层次。第一个层次是图像层。上面代码里的cv2.imwrite(result.jpg, img)保存了带检测框和车牌号的完整画面适合可视化调试。第二个层次是结构化数据层。把识别结果保存成CSV或者JSON便于后续统计分析。比如import json record {image: test.jpg, plate: plate_no, confidence: float(conf)} with open(result.json, w, encodingutf-8) as f: json.dump(record, f, ensure_asciiFalse, indent2)第三个层次是业务层。在停车场系统中识别结果会直接用于开闸、计费、车辆绑定通常要写入数据库或者调用服务端API。这里要注意的是识别结果不能只过一遍就完事一般要结合多帧投票决定最终结果避免单帧误识别造成开闸错误。5.4 双行车牌的兼容问题新能源大巴、挂车等车型的车牌可能是两行的。直接把整个两行区域压扁成24×94字符会被拉变形识别率很差。处理办法是先根据车牌高度和宽度比例判断是不是双行如果是就把车牌区域水平切成上下两半分别识别再把结果拼接成“上排 下排”。判断阈值可以按高度比宽度是否超过0.35来定具体数值可以按实际应用微调。这个方法实现起来不难但往往被忽略。如果你用CCPD原始训练测试双行车牌的样本本身少模型对双行车牌天然不友好。建议在训练LPRNet时把双行车牌单独合成一批数据并标注成“上排字符 下排字符”的拼接形式这样推理时就不需要额外切分逻辑了。6. 项目落地中的常见坑与性能优化6.1 YOLOv11容易漏检小目标车牌车牌在整幅图中的面积占比很小尤其卡口相机视角广阔的图像里远处的车可能只有几十像素大小。YOLOv11虽然有注意力机制但对极端小目标依然不够稳。我实际踩过的坑是用640×640分辨率训练夜间场景里距离30米以外的车检测框经常丢。解决办法有这几招把imgsz从640提高到1280小目标的特征在深层特征图中保留更多。使用SAHI切片推理库把大图切成多个小块分别检测再拼接专门处理小目标。数据增强里增加Copy-Paste策略把车牌贴到不同背景上增加小目标样本数量。如果项目是固定摄像头的卡口场景还可以更“暴力”一点直接限定检测区域只在画面中路的固定区域搜索车牌减少全图扫描带来的漏检和误检。6.2 LPRNet识别错误集中在哪些字符车牌字符集里省份汉字数量多、字形接近是整个识别系统里最容易出错的部分。比如“冀”和“翼”、“赣”和“干”、“皖”和“晚”这类形近字即使在人类看来都可能产生混淆。数字和字母里“0”和“O”、“1”和“I”也很典型虽然中国车牌已经把I和O从字母集中排除了但某些特殊车牌或者印刷字体变形时依然会干扰模型。针对这个问题我的做法是加一个后处理白名单校验。车牌字符串的第2位是省份字母时强制从合法字母集里选择第3位到第7位如果是数字区域就把识别结果里不是数字的字符按概率重新排序选出最大概率的合法结果。这种规则性后处理成本极低但能把整体准确率提升2到3个百分点。6.3 性能优化TensorRT、跟踪、缓存如果车牌识别要部署在带GPU的生产环境性能优化重点有三个方向。第一把YOLOv11导出成TensorRT引擎。Ultralytics官方支持直接导出engine格式命令是yolo export modelweights/best.pt formatengine halfTrue。导出后用engine文件做推理速度通常能比PyTorch原生推理快2到3倍。第二LPRNet模型很小不需要TensorRT也能跑到毫秒级。优化重点反而是不要重复加载模型。如果项目是实时视频流LPRNet模型只加载一次放进全局变量或者单例类里复用千万不要每帧重新load_state_dict。第三用目标跟踪减少重复识别。视频里同一辆车会连续出现在几十帧画面中每次都对整帧做检测加识别是非常浪费的。可以先用ByteTrack跟踪给每个目标分配track_id然后固定一个时间窗口间隔几帧才对同一track_id做一次完整的识别其他帧直接复用上一帧结果。这样整体CPU占用能下降非常多。6.4 一些工程心得整个项目做完之后我最深刻的体会是车牌识别系统真正的难点不在模型结构而在于把数据、前后处理和部署细节打磨到位。模型选YOLOv11还是YOLOv8差别没那么大LPRNet训练多几轮少几轮也只是量变但数据里的脏样本、前处理里少拉正一次透视、后处理里漏做白名单校验这些细节才决定最终上线效果。如果时间紧张可以先跑通完整链路再优化准确率。一个最少可用版本是从CCPD里取500张图片训YOLOv11检测器用合成数据训2万步LPRNet识别器最后用上面的主流程代码串联起来。这个版本足够让你在几天内跑出能看到效果的车牌识别Demo。之后再往里面加透视校正、双行车牌处理、TensorRT优化项目会越来越接近生产可用。本文还有配套的精品资源点击获取