★★★ 本文源自AlStudio社区精品项目,【点击此处】查看更多精品内容 >>>

背景介绍

车牌识别技术是一种利用计算机视觉技术对车辆车牌进行自动检测、识别的技术。它可以通过摄像头实时捕获车辆车牌信息,并经过算法处理后得到车牌号码信息,实现对车辆的自动识别、管理和监控。车牌识别技术被广泛应用于城市交通管理、安防监控行业、停车场管理等领域,可以提高交通管理效率,降低人工劳动成本,保障公共安全。

随着自动驾驶技术的快速发展,车辆自主性越来越高,丰富的实时数据也为车牌识别技术的运用提供了更多可能性。未来,车牌识别技术将会更加智能化、精准化,成为城市交通管理、智慧安防等领域的重要组成部分。

本项目主要基于PaddleOCR套件中的PP-OCR进行车牌的检测与识别,PP-OCR是PaddleOCR自研的实用的超轻量OCR系统。在实现前沿算法的基础上,考虑精度与速度的平衡,进行模型瘦身和深度优化,使其尽可能满足产业落地需求。该系统包含文本检测和文本识别两个阶段,其中文本检测算法选用DB,文本识别算法选用CRNN,并在检测和识别模块之间添加文本方向分类器,以应对不同方向的文本识别。我们这次使用的模块为PP-OCRv3,在PP-OCRv2的基础上,针对检测模型和识别模型,进行了共计9个方面的升级,进一步提升了模型效果。

一、PaddleOCR介绍

📑1.1 简介

PaddleOCR是一套丰富、领先、且实用的OCR工具库,旨在助力开发者训练出更好的模型,并应用落地。

部分应用场景如下:

🌟1.2 特性

PaddleOCR支持多种OCR相关前沿算法,在此基础上打造产业级特色模型PP-OCRPP-Structure,并打通数据生产、模型训练、压缩、预测部署全流程。

⚡1.3 快速开始

更多关于PaddleOCR套件的详细信息请访问此地址

二、 数据集简介和预处理

2.1 数据集简介

所使用的数据集为 CCPD2020 新能源车牌数据集,该数据集为

该数据集分布如下:

数据集类型数量
训练集5769
验证集1001
测试集5006

数据集图片示例如下:

2.2 数据集处理

# 解压数据集
!tar -xvf /home/aistudio/data/data148343/CCPD2020.tar
import cv2
import os
import json
from tqdm import tqdm
import numpy as np

provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'O']
ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O']

def make_label(img_dir, save_gt_folder, phase):
    crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs')
    os.makedirs(crop_img_save_dir, exist_ok=True)

    f_det = open(os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8')
    f_rec = open(os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8')

    i = 0
    for filename in tqdm(os.listdir(os.path.join(img_dir, phase))):
        str_list = filename.split('-')
        if len(str_list) < 5:
            continue
        coord_list = str_list[3].split('_')
        txt_list = str_list[4].split('_')
        boxes = []
        for coord in coord_list:
            boxes.append([int(x) for x in coord.split("&")])
        boxes = [boxes[2], boxes[3], boxes[0], boxes[1]]
        lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[1])] + ''.join([ads[int(x)] for x in txt_list[2:]])

        # det
        det_info = [{'points':boxes, 'transcription':lp_number}]
        f_det.write('{}\t{}\n'.format(os.path.join(phase, filename), json.dumps(det_info, ensure_ascii=False)))

        # rec
        boxes = np.float32(boxes)
        img = cv2.imread(os.path.join(img_dir, phase, filename))
        # crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())]
        crop_img = get_rotate_crop_image(img, boxes)
        crop_img_save_filename = '{}_{}.jpg'.format(i,'_'.join(txt_list))
        crop_img_save_path = os.path.join(crop_img_save_dir, crop_img_save_filename)
        cv2.imwrite(crop_img_save_path, crop_img)
        f_rec.write('{}/crop_imgs/{}\t{}\n'.format(phase, crop_img_save_filename, lp_number))
        i+=1
    f_det.close()
    f_rec.close()

def get_rotate_crop_image(img, points):
    '''
    img_height, img_width = img.shape[0:2]
    left = int(np.min(points[:, 0]))
    right = int(np.max(points[:, 0]))
    top = int(np.min(points[:, 1]))
    bottom = int(np.max(points[:, 1]))
    img_crop = img[top:bottom, left:right, :].copy()
    points[:, 0] = points[:, 0] - left
    points[:, 1] = points[:, 1] - top
    '''
    assert len(points) == 4, "shape of points must be 4*2"
    img_crop_width = int(
        max(
            np.linalg.norm(points[0] - points[1]),
            np.linalg.norm(points[2] - points[3])))
    img_crop_height = int(
        max(
            np.linalg.norm(points[0] - points[3]),
            np.linalg.norm(points[1] - points[2])))
    pts_std = np.float32([[0, 0], [img_crop_width, 0],
                          [img_crop_width, img_crop_height],
                          [0, img_crop_height]])
    M = cv2.getPerspectiveTransform(points, pts_std)
    dst_img = cv2.warpPerspective(
        img,
        M, (img_crop_width, img_crop_height),
        borderMode=cv2.BORDER_REPLICATE,
        flags=cv2.INTER_CUBIC)
    dst_img_height, dst_img_width = dst_img.shape[0:2]
    if dst_img_height * 1.0 / dst_img_width >= 1.5:
        dst_img = np.rot90(dst_img)
    return dst_img

img_dir = '/home/aistudio/data/CCPD2020/ccpd_green'
save_gt_folder = '/home/aistudio/data/CCPD2020/PPOCR'
# phase = 'train' # change to val and test to make val dataset and test dataset
for phase in ['train','val','test']:
    make_label(img_dir, save_gt_folder, phase)

以上是官网对该数据集的处理,本项目由于数据集已经处理好了,所以不再进行处理,这里仅分享。

数据集格式如下:

|- CCPD2020
    |-ccpd_green
        |-small
               |-img1.jpg
               |-img2.jpg
               |-...
        |-test
               |-img1.jpg
               |-img2.jpg
               |-...
        |-train
               |-img1.jpg
               |-img2.jpg
               |-...
        |-val
               |-img1.jpg
               |-img2.jpg
               |-...
    |-PPOCR
        |-test
            |-crop_imgs
            |-det.txt
            |-rec.txt
        |-train
            |-crop_imgs
            |-det.txt
            |-rec.txt
        |-val
            |-crop_imgs
            |-det.txt
            |-rec.txt

三、环境配置

在左边的套件里面下载PaddleOCR套件。

# 安装相关依赖
!pip install -r /home/aistudio/requirements.txt

四、训练

4.1 检测模型训练

4.1.1 预训练模型直接预测
# 下载预训练模型
import os
!mkdir models
os.chdir('/home/aistudio/models')
!wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar
!tar -xf ch_PP-OCRv3_det_distill_train.tar
os.chdir('/home/aistudio/PaddleOCR-2.6.0')
!python tools/eval.py -c /home/aistudio/ch_PP-OCRv3_det_student.yml -o \
    Global.pretrained_model=/home/aistudio/models/ch_PP-OCRv3_det_distill_train/student.pdparams \
    Eval.dataset.data_dir=/home/aistudio/CCPD2020/ccpd_green \
    Eval.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/test/det.txt]

通过上述评估结果我们可以发现,直接使用预训练检测模型的hmean为0.76。

hmean是一个综合指标,从下面的表达式可以看出其值介于精度和回调之间,其表达式为:
$
hmean=\frac{2\times precision\times recall}{precision+recall}
$

4.1.2 CCPD车牌数据集fine-tune训练
# 训练
!python tools/train.py -c /home/aistudio/ch_PP-OCRv3_det_student.yml -o \
    Global.pretrained_model=/home/aistudio/models/ch_PP-OCRv3_det_distill_train/student.pdparams \
    Global.save_model_dir=/home/aistudio/output/CCPD/det \
    Global.eval_batch_step="[0, 772]" \
    Optimizer.lr.name=Const \
    Optimizer.lr.learning_rate=0.0005 \
    Optimizer.lr.warmup_epoch=0 \
    Train.dataset.data_dir=//home/aistudio/CCPD2020/ccpd_green \
    Train.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/train/det.txt] \
    Eval.dataset.data_dir=/home/aistudio/CCPD2020/ccpd_green \
    Eval.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/test/det.txt]
!python tools/eval.py -c /home/aistudio/ch_PP-OCRv3_det_student.yml -o \
    Global.pretrained_model=/home/aistudio/output/CCPD/det/best_accuracy.pdparams \
    Eval.dataset.data_dir=/home/aistudio/CCPD2020/ccpd_green \
    Eval.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/test/det.txt]

我训练了100轮左右,发现训练46轮后效果最好,这时候hmean达到了99.2%。

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99.00%
4.1.3 CCPD车牌数据集fine-tune+量化训练
!python3.7 deploy/slim/quantization/quant.py -c /home/aistudio/ch_PP-OCRv3_det_student.yml -o \
    Global.pretrained_model=/home/aistudio/output/CCPD/det/best_accuracy.pdparams \
    Global.save_model_dir=/home/aistudio/output/CCPD/det_quant \
    Global.eval_batch_step="[0, 772]" \
    Optimizer.lr.name=Const \
    Optimizer.lr.learning_rate=0.0005 \
    Optimizer.lr.warmup_epoch=0 \
    Train.dataset.data_dir=/home/aistudio/CCPD2020/ccpd_green \
    Train.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/train/det.txt] \
    Eval.dataset.data_dir=/home/aistudio/CCPD2020/ccpd_green \
    Eval.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/test/det.txt]

4.2 识别模型训练

4.2.1 预训练模型直接预测
import os
os.chdir('/home/aistudio/models')
!wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar
!tar -xf ch_PP-OCRv3_rec_train.tar

PaddleOCR提供的PP-OCRv3识别模型采用蒸馏训练策略,因此提供的预训练模型中会包含Teacher和Student模型的参数,详细信息可参考knowledge_distillation.md。 因此,模型下载完成后需要使用如下代码提取Student模型的参数:

import paddle
# 加载预训练模型
all_params = paddle.load("../models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams")
# 查看权重参数的keys
print(all_params.keys())
# 学生模型的权重提取
s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key}
# 查看学生模型权重参数的keys
print(s_params.keys())
# 保存
paddle.save(s_params, "../models/ch_PP-OCRv3_rec_train/student.pdparams")
import os
os.chdir('/home/aistudio/PaddleOCR-2.6.0')
!python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
    Global.pretrained_model=/home/aistudio/models/ch_PP-OCRv3_rec_train/student.pdparams \
    Eval.dataset.data_dir=/home/aistudio/CCPD2020/PPOCR \
    Eval.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/test/rec.txt]

如果出现了acc精度为0的情况,那么我们需要到/home/aistudio/PaddleOCR-2.6.0/ppocr/postprocess/rec_postprocess.py文件里,在第98行加入text = text.replace('·','')代码,这是因为我们识别出的结果里面将车牌号字母和数字之间的点·也给识别出来了,所以要将其替换掉进行评估。

具体操作如下:

我们可以先识别一张图片,比如:

import os
os.chdir('/home/aistudio/PaddleOCR-2.6.0')
!python tools/infer_rec.py -c /home/aistudio/ch_PP-OCRv3_rec.yml -o \
    Global.pretrained_model=/home/aistudio/models/ch_PP-OCRv3_rec_train/student.pdparams \
    Global.infer_img=/home/aistudio/car1.jpg

4.2.2 CCPD车牌数据集fine-tune训练
import os
os.chdir('/home/aistudio/PaddleOCR-2.6.0')
!python tools/train.py -c /home/aistudio/ch_PP-OCRv3_rec.yml -o \
    Global.pretrained_model=/home/aistudio/models/ch_PP-OCRv3_rec_train/student.pdparams \
    Global.save_model_dir=/home/aistudio/output/CCPD/rec/ \
    Global.eval_batch_step="[0, 90]" \
    Optimizer.lr.name=Const \
    Optimizer.lr.learning_rate=0.0005 \
    Optimizer.lr.warmup_epoch=0 \
    Train.dataset.data_dir=/home/aistudio/CCPD2020/PPOCR \
    Train.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/train/rec.txt] \
    Eval.dataset.data_dir=/home/aistudio/CCPD2020/PPOCR \
    Eval.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/test/rec.txt]
!python tools/eval.py -c /home/aistudio/ch_PP-OCRv3_rec.yml -o \
    Global.pretrained_model=/home/aistudio/output/CCPD/rec/best_accuracy.pdparams \
    Eval.dataset.data_dir=/home/aistudio/CCPD2020/PPOCR \
    Eval.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/test/rec.txt]

4.2.3 CCPD车牌数据集fine-tune+量化训练
!python3.7 deploy/slim/quantization/quant.py -c /home/aistudio/ch_PP-OCRv3_rec.yml -o \
    Global.pretrained_model=/home/aistudio/output/CCPD/rec/best_accuracy.pdparams \
    Global.save_model_dir=/home/aistudio/output/CCPD/rec_quant/ \
    Global.eval_batch_step="[0, 90]" \
    Optimizer.lr.name=Const \
    Optimizer.lr.learning_rate=0.0005 \
    Optimizer.lr.warmup_epoch=0 \
    Train.dataset.data_dir=/home/aistudio/CCPD2020/PPOCR \
    Train.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/train/rec.txt] \
    Eval.dataset.data_dir=/home/aistudio/CCPD2020/PPOCR \
    Eval.dataset.label_file_list=[/home/aistudio/CCPD2020/PPOCR/test/rec.txt]

五、模型导出

5.1 检测非量化模型的导出

!python tools/export_model.py -c /home/aistudio/ch_PP-OCRv3_det_student.yml -o \
    Global.pretrained_model=/home/aistudio/output/CCPD/det/best_accuracy.pdparams \
    Global.save_inference_dir=/home/aistudio/output/det/infer
W0510 15:08:10.075659 21722 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.2, Runtime API Version: 11.2
W0510 15:08:10.080330 21722 gpu_resources.cc:91] device: 0, cuDNN Version: 8.2.
[2023/05/10 15:08:11] ppocr INFO: load pretrain successful from /home/aistudio/output/CCPD/det/best_accuracy
[2023/05/10 15:08:15] ppocr INFO: inference model is saved to /home/aistudio/output/det/infer/inference

5.2 识别非量化模型的导出

!python tools/export_model.py -c /home/aistudio/ch_PP-OCRv3_rec.yml -o \
    Global.pretrained_model=/home/aistudio/output/CCPD/rec/best_accuracy.pdparams \
    Global.save_inference_dir=/home/aistudio/output/rec/infer
W0510 15:12:13.691772 22522 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.2, Runtime API Version: 11.2
W0510 15:12:13.696485 22522 gpu_resources.cc:91] device: 0, cuDNN Version: 8.2.
[2023/05/10 15:12:16] ppocr INFO: load pretrain successful from /home/aistudio/output/CCPD/rec/best_accuracy
[2023/05/10 15:12:18] ppocr INFO: inference model is saved to /home/aistudio/output/rec/infer/inference

六、模型部署

!python tools/infer/predict_system.py \
    --det_model_dir=/home/aistudio/output/det/infer/ \
    --rec_model_dir=/home/aistudio/output/rec/infer/ \
    --image_dir="/home/aistudio/CCPD2020/ccpd_green/test/04421336206896552-88_265-177&509_550&618-546&600_187&618_177&527_550&509-0_0_3_32_31_32_31_32-87-37.jpg" \
    --rec_image_shape=3,48,320
[2023/05/10 15:16:44] ppocr INFO: In PP-OCRv3, rec_image_shape parameter defaults to '3, 48, 320', if you are using recognition model with PP-OCRv2 or an older version, please set --rec_image_shape='3,32,320
[2023/05/10 15:16:45] ppocr DEBUG: dt_boxes num : 1, elapse : 1.3750038146972656
[2023/05/10 15:16:46] ppocr DEBUG: rec_res num  : 1, elapse : 0.5280847549438477
[2023/05/10 15:16:46] ppocr DEBUG: 0  Predict time of /home/aistudio/CCPD2020/ccpd_green/test/04421336206896552-88_265-177&509_550&618-546&600_187&618_177&527_550&509-0_0_3_32_31_32_31_32-87-37.jpg: 1.908s
[2023/05/10 15:16:46] ppocr DEBUG: 皖AD87878, 0.981
[2023/05/10 15:16:46] ppocr DEBUG: The visualized image saved in ./inference_results/04421336206896552-88_265-177&509_550&618-546&600_187&618_177&527_550&509-0_0_3_32_31_32_31_32-87-37.jpg
[2023/05/10 15:16:46] ppocr INFO: The predict total time is 1.998774766921997

98774766921997

推理结果保存在/home/aistudio/PaddleOCR-2.6.0/inference_results路径下。

推理结果如下:

总结

  • 本次车牌识别项目旨在设计和实现一个高效、准确的车牌检测与识别系统,能够在各种复杂的场景下自动完成车牌的识别和记录,并提高城市交通管理的效率。PadlleOCR套件里的PP-OCR在精度和速度上都已经达到了很不错的效果。
  • 在该项目中,我们采用了PaddleOCR套件提供的车牌识别模型并进行了相关的优化和调整。同时,我们还采用了大量的车牌图像数据进行训练和测试,以确保系统的准确性和稳定性。
  • 通过对算法的优化和实验验证,我们成功地实现了车牌号识别的自动化,取得了较高的识别率和较低的误识别率。接下来,我们将设计了一个友好的用户界面,可以方便地进行数据管理和查询,以提升车牌管理的智能化和便捷性。
  • 总体而言,基于PaddleOCR套件的车牌号识别项目在技术和实用性方面取得了很好的成果,为城市交通管理和智慧安防等领域的相关应用提供了可靠的技术支持。未来,我们将继续优化和升级该系统,以满足不断变化的实际需求和挑战。

此文章为搬运
原项目链接

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐