基于Transformer 实现车辆检测与车牌识别(二)

发布于:2025-09-07 ⋅ 阅读:(27) ⋅ 点赞:(0)

🚗 车辆检测 + 车牌识别:基于 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

📁 第二步:准备数据集

场景说明:

我们将构建一个两级系统:

  1. RT-DETR 检测车辆
  2. 裁剪出车辆区域 → 用 TrOCR 识别车牌

因此需要两类数据:

  • 车辆边界框标注(用于 RT-DETR)
  • 车牌图像 + 文本标注(用于 TrOCR)

2.1 车辆检测数据集(RT-DETR)

数据来源(任选其一):
  • UA-DETRAC(推荐):http://detrac-db.rit.albany.edu/(交通监控视频,含车辆标注)
  • BDD100K:https://www.bdd100k.com/(自动驾驶数据集)
  • 自制数据:用 CVAT 或 LabelImg 标注 carbustruck 等类别
标注格式:

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:车辆类型、位置、车牌号、置信度

📚 参考资料

  1. RT-DETR: https://github.com/PaddlePaddle/PaddleDetection
  2. TrOCR: https://huggingface.co/docs/transformers/model_doc/trocr
  3. UA-DETRAC Dataset: http://detrac-db.rit.albany.edu/
  4. 中文车牌合成:https://github.com/zeusees/HyperLPR

🎯 总结
通过 RT-DETR + TrOCR 的 Transformer 双模型组合,你可以构建一个高精度、可扩展、语义丰富的车辆与车牌识别系统。相比传统 YOLO+CRNN 方案,它在小目标、遮挡、光照变化等场景下表现更鲁棒。

如果你希望我提供:

  • 完整的 Jupyter Notebook
  • Flask Web API 接口
  • Docker 部署脚本
  • 视频实时处理版本

网站公告

今日签到

点亮在社区的每一天
去签到