🚗 车辆检测 + 车牌识别:基于 Transformer 的端到端实现
✅ 技术栈:RT-DETR(车辆检测) + TrOCR(车牌识别)
✅ 框架:PaddlePaddle / Hugging Face
✅ 语言:Python 3.8+
✅ 硬件:GPU(推荐 NVIDIA RTX 3060 及以上)
🔧 第一步:环境配置
1. 创建虚拟环境(推荐)
conda create -n vehicle_transformer python=3.9
conda activate vehicle_transformer
2. 安装 PaddlePaddle(RT-DETR 使用 PaddleDetection)
# 安装 PaddlePaddle(CUDA 11.8 示例)
pip install paddlepaddle-gpu==2.6.0.post118 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html
# 安装 PaddleDetection
git clone https://github.com/PaddlePaddle/PaddleDetection.git
cd PaddleDetection
pip install -r requirements.txt
python setup.py install
3. 安装 Hugging Face Transformers(用于 TrOCR)
pip install transformers torch datasets pillow
4. 验证安装
import paddle
import torch
print(paddle.is_compiled_with_cuda()) # 应输出 True
print(torch.cuda.is_available()) # 应输出 True
📁 第二步:准备数据集
场景说明:
我们将构建一个两级系统:
- RT-DETR 检测车辆
- 裁剪出车辆区域 → 用 TrOCR 识别车牌
因此需要两类数据:
- 车辆边界框标注(用于 RT-DETR)
- 车牌图像 + 文本标注(用于 TrOCR)
2.1 车辆检测数据集(RT-DETR)
数据来源(任选其一):
- UA-DETRAC(推荐):http://detrac-db.rit.albany.edu/(交通监控视频,含车辆标注)
- BDD100K:https://www.bdd100k.com/(自动驾驶数据集)
- 自制数据:用 CVAT 或 LabelImg 标注
car
,bus
,truck
等类别
标注格式:
RT-DETR 支持 COCO 或 VOC 格式,推荐使用 COCO JSON 格式。
目录结构:
vehicle_dataset/
├── images/
│ ├── img1.jpg
│ ├── img2.jpg
│ └── ...
├── annotations/
│ ├── train.json
│ └── val.json
💡 使用 CVAT 导出为 COCO 格式即可。
2.2 车牌识别数据集(TrOCR)
数据来源:
- Chinese License Plate Dataset (CLPD):GitHub 可搜
- Synthetic Data:使用 Python 自动生成合成车牌(推荐用于预训练)
合成车牌代码示例:
from PIL import Image, ImageDraw, ImageFont
import random
import string
def generate_plate():
provinces = "京津沪渝冀晋蒙辽吉黑苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云藏陕甘青宁新"
adjs = "ABCDEFGHJKLMNPQRSTUVWXYZ"
chars = string.digits + adjs
plate = random.choice(provinces) + random.choice(adjs) + ''.join(random.choices(chars, k=5))
return plate
def create_plate_image(text="京A88888", save_path="plate.jpg"):
img = Image.new('RGB', (220, 60), color=(255, 255, 255))
draw = ImageDraw.Draw(img)
try:
font = ImageFont.truetype("simsun.ttc", 40) # Windows 可用 simsun.ttc
except:
font = ImageFont.load_default()
draw.text((10, 5), text, font=font, fill=(0, 0, 0))
img.save(save_path)
return img
运行:
img = create_plate_image("京A12345", "plates/京A12345.jpg")
组织数据格式(Hugging Face Dataset):
[
{"image_path": "plates/京A12345.jpg", "text": "京A12345"},
{"image_path": "plates/粤B66666.jpg", "text": "粤B66666"}
]
🚦 第三步:训练 RT-DETR 模型进行车辆检测
1. 下载预训练模型
# 在 PaddleDetection 目录下
wget https://paddledet.bj.bcebos.com/models/rt_detr_r50vd_6x_coco.pdparams
2. 配置文件 configs/rt_detr/rt_detr_r50vd_6x_coco.yml
architecture: RTDETR
batch_size: 8
max_iters: 120000
log_iter: 20
save_dir: output/rt_detr_vehicle
model:
type: RTDETR
depth: 50
num_classes: 3 # car, bus, truck
backbone: ResNet
neck: HybridEncoder
head: RTDETRHead
train_dataset:
!COCODataSet
image_dir: images
anno_path: annotations/train.json
dataset_dir: /path/to/vehicle_dataset
with_background: false
eval_dataset:
!COCODataSet
image_dir: images
anno_path: annotations/val.json
dataset_dir: /path/to/vehicle_dataset
learning_rate:
base_lr: 0.0001
schedulers:
- !LinearWarmup
start_factor: 0.33
steps: 500
- !MultiStepDecay
milestones: [80000, 100000]
gamma: 0.1
3. 开始训练
cd PaddleDetection
python tools/train.py \
-c configs/rt_detr/rt_detr_r50vd_6x_coco.yml \
-o pretrain_weights=rt_detr_r50vd_6x_coco.pdparams
4. 验证模型
python tools/eval.py \
-c configs/rt_detr/rt_detr_r50vd_6x_coco.yml \
-o weights=output/rt_detr_vehicle/model_final.pdparams
🔤 第四步:使用 TrOCR 实现车牌识别
1. 加载预训练 TrOCR 模型(支持中文)
from transformers import TrOCRProcessor, VisionEncoderDecoderModel
from PIL import Image
# 使用中英文通用模型(或微调自己的)
processor = TrOCRProcessor.from_pretrained("microsoft/trocr-base-printed")
model = VisionEncoderDecoderModel.from_pretrained("microsoft/trocr-base-printed")
# 若需中文更强识别,可使用社区微调模型:
# processor = TrOCRProcessor.from_pretrained("bellegroup/trocr-base-zh")
# model = VisionEncoderDecoderModel.from_pretrained("bellegroup/trocr-base-zh")
2. 准备数据集(Hugging Face Dataset)
from datasets import Dataset
import pandas as pd
import os
# 假设你有 plates/ 文件夹和 labels.json
data = pd.read_json("labels.json")
dataset = Dataset.from_pandas(data)
def preprocess(examples):
images = [Image.open(fname).convert("RGB") for fname in examples["image_path"]]
texts = examples["text"]
pixel_values = processor(images, return_tensors="pt").pixel_values
# 这里简化,实际训练需 tokenize labels
return {"pixel_values": pixel_values, "labels": texts}
# dataset = dataset.map(preprocess, batched=True)
3. 推理单张车牌
def recognize_plate(image_path):
image = Image.open(image_path).convert("RGB")
pixel_values = processor(image, return_tensors="pt").pixel_values
generated_ids = model.generate(pixel_values)
transcription = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
return transcription
# 测试
print(recognize_plate("plates/京A12345.jpg")) # 输出:京A12345
🔗 第五步:端到端流水线:检测 + 识别
import cv2
from paddle import inference
from PIL import Image
import numpy as np
def vehicle_and_plate_pipeline(image_path):
# 1. 读取图像
image = cv2.imread(image_path)
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
pil_image = Image.fromarray(rgb_image)
# 2. 使用 RT-DETR 检测车辆
# (使用 Paddle Inference 加速)
config = inference.Config("output/rt_detr_vehicle/model_final.pdmodel",
"output/rt_detr_vehicle/model_final.pdiparams")
config.enable_use_gpu(100, 0)
predictor = inference.create_predictor(config)
# 预处理(参考 PaddleDetection 工具)
from ppdet.data.transform import Compose
transforms = Compose([
# 添加 Resize, Normalize 等
])
tensor = transforms(pil_image)
# 推理
result = predictor.run([tensor])
# 解析结果(简化)
boxes = result[0] # [x1, y1, x2, y2, score, label]
results = []
for box in boxes:
x1, y1, x2, y2, score, label = box
if score < 0.5: continue
# 裁剪车辆区域
car_crop = rgb_image[int(y1):int(y2), int(x1):int(x2)]
car_pil = Image.fromarray(car_crop)
# 假设车牌在车辆下半部分
h, w, _ = car_crop.shape
plate_crop = car_crop[int(0.6*h):h, int(0.1*w):int(0.9*w)]
plate_pil = Image.fromarray(plate_crop)
# 保存临时车牌图
plate_pil.save("temp_plate.jpg")
# 3. 车牌识别
plate_text = recognize_plate("temp_plate.jpg")
results.append({
"vehicle_type": ["car", "bus", "truck"][int(label)],
"bbox": [x1, y1, x2, y2],
"plate": plate_text,
"confidence": float(score)
})
# 可视化
cv2.rectangle(image, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
cv2.putText(image, plate_text, (int(x1), int(y1)-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.9, (255, 0, 0), 2)
cv2.imwrite("result.jpg", image)
return results
# 执行
results = vehicle_and_plate_pipeline("test.jpg")
print(results)
🚀 第六步:部署优化建议
目标 | 方案 |
---|---|
提速 | 使用 TensorRT 编译 RT-DETR,TrOCR 使用 ONNX Runtime |
边缘部署 | 使用 Jetson Orin + DeepStream 集成 |
Web 服务 | Flask API 封装,支持图片上传 |
视频流 | 使用 cv2.VideoCapture 循环处理帧 |
✅ 最终效果
输入:一张交通监控图像
输出:
- 检测出所有车辆(绿色框)
- 识别出车牌号码(蓝色文字)
- 返回结构化 JSON:车辆类型、位置、车牌号、置信度
📚 参考资料
- RT-DETR: https://github.com/PaddlePaddle/PaddleDetection
- TrOCR: https://huggingface.co/docs/transformers/model_doc/trocr
- UA-DETRAC Dataset: http://detrac-db.rit.albany.edu/
- 中文车牌合成:https://github.com/zeusees/HyperLPR
🎯 总结:
通过 RT-DETR + TrOCR 的 Transformer 双模型组合,你可以构建一个高精度、可扩展、语义丰富的车辆与车牌识别系统。相比传统 YOLO+CRNN 方案,它在小目标、遮挡、光照变化等场景下表现更鲁棒。
如果你希望我提供:
- 完整的 Jupyter Notebook
- Flask Web API 接口
- Docker 部署脚本
- 视频实时处理版本