【智慧交通项目实战】 OCR车牌检测与识别项目实战(一):项目总览

【智慧交通项目实战】 《 OCR车牌检测与识别》(二):基于YOLO的车牌检测

【智慧交通项目实战】 OCR车牌检测与识别项目实战(一):项目总览

作者简介: CSDN、阿里云人工智能领域博客专家,新星方案计算机视觉导师,百度飞桨PPDE,专注大数据与AI知识共享。✨大众号:GoAI的学习小屋 ,免费共享书本、简历、导图等,更有交流群共享瑰宝材料,重视大众号回复“加群”或➡️点击链接 加群。

专栏推荐: 点击拜访➡️ 《计算机视觉》 总结目标检测、图像分类、分割OCR、等方向材料。 点击拜访➡️ 《深入浅出OCR》: 对标全网最全OCR教程,含理论与实战总结。

【才智交通项目实战】 OCR车牌检测与辨认项目实战(一):项目总览

导读:本项目为新系列【才智交通项目实战】《OCR车牌检测和辨认》(一),该系列将分为多篇文章打开分别对项目流程、数据集、检测、辨认算法、可视化进行详细介绍,本篇为该系列第一篇,将侧重介绍本次项目开源的CCPD车牌数据集,,用于本次车牌检测和辨认模型算法开发,后续系列文章将陆续更新。

【智慧交通项目实战】 OCR车牌检测与识别项目实战(一):项目总览

本系列项目目录,后续将更新对应文章:

1.才智交通预测体系(PaddleOCR版别)

参阅:blog.csdn.net/qq_36816848…

2.OCR车牌检测+辨认

本篇项目, 代码暂未公开,需求代码和辅导可加群联系。

3.车辆检测

后续更新

【智慧交通项目实战】 OCR车牌检测与识别项目实战(一):项目总览


1.项目背景:

车牌辨认技术是智能交通的重要环节,现在已广泛使用于例如停车场、收费站等等交通设施中,供给高效便捷的车辆认证的服务,其间较为典型的使用场景为卡口体系。车牌辨认即辨认车牌上的文字信息,属于光学字符辨认(OCR)的一项子使命。 ![请添加图片描绘](img-blog.csdnimg.cn/c00c0fd0a41… =500×350)

【智慧交通项目实战】 OCR车牌检测与识别项目实战(一):项目总览

项目流程:

1.基于YOLOv5的车牌检测

YOLOv5练习代码和测验代码(Pytorch)

  1. 整套YOLOv5项目工程,含练习代码train.py和测验代码demo.py
  2. 支撑高精度版别yolov5s练习和测验
  3. 支撑轻量化版别yolov5练习和测验
  4. 根据本篇博文阐明,简单装备即可开端练习:train.py
  5. 源码包含了练习好的yolov5及其他模型,装备好环境,可直接运行demo.py
  6. 测验代码demo.py支撑图片,视频和摄像头测验

2.基于CRNN和LPRNet的车牌辨认

支撑如下:

  • 1.单行蓝牌
  • 2.单行黄牌
  • 3.新能源车牌
  • 4.白色警用车牌
  • 5.教练车牌
  • 6.武警车牌
  • 7.双层黄牌
  • 8.双层白牌
  • 9.使馆车牌
  • 10.港澳粤Z牌
  • 11.双层绿牌
  • 12.民航车牌

2.车牌号码阐明

绿牌和蓝牌区别如下:

色彩区别: 小型新能源车牌采用“渐变绿”的配色,大型新能源车牌采用“黄绿双拼色”,绿牌的字体色彩为黑色;而传统燃油车蓝牌则采用“纯蓝色”规划,字体色彩为白色; 号码编排:普通蓝牌共有7位字符;新能源车牌有8位字符;新能源绿牌的号码共有6位数,其间小型新能源轿车车牌的字母规划在第一位,大型新能源轿车车牌的字母规划在最终一位。其间车牌首字母为“D/A/B/C/E”的,代表“纯电动车”;首字母为“F/G/H/J/K”的,代表“非纯电动轿车”。而普通燃油车蓝牌的号码只要5位数,首字母或数字一般不代表任何意义,只要部分地区会给营运类车型划分特定字母。

【智慧交通项目实战】 OCR车牌检测与识别项目实战(一):项目总览

以下为计算后本次车牌辨认用到的字典文件:

省份:[“皖”, “沪”, “津”, “渝”, “冀”, “晋”, “蒙”, “辽”, “吉”, “黑”, “苏”, “浙”, “京”, “闽”, “赣”, “鲁”, “豫”, “鄂”, “湘”, “粤”, “桂”, “琼”, “川”, “贵”, “云”, “藏”, “陕”, “甘”, “青”, “宁”, “新”] 地市:[‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘P’, ‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’,‘X’, ‘Y’, ‘Z’] 车牌字典:[‘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’]


3.车牌数据集CCPD

(1)车牌数据集CCPD阐明

![CCPD2020](img-blog.csdnimg.cn/82c2cee483c… =400×380)

【智慧交通项目实战】 OCR车牌检测与识别项目实战(一):项目总览

CCPD (Chinese City Parking Dataset, ECCV)是我国城市车牌数据集,共有两个: CCPD2019 : 主要是蓝牌数据,约34W,巨细为12G左右; CCPD2020 : 主要是新能源绿牌数据,约1万. 巨细为800M左右;

CCPD官方原始数据集下载地址:github.com/detectRecog…

CCPD2019数据集包含将近30万张图片、图片尺寸为720x1160x3,共包含8种类型图片,每种类型、数量及类型阐明如下表:

类型 图片数 阐明
ccpd_base 199998 正常车牌
ccpd_challenge 10006 比较有挑战的车牌
ccpd_db 20001 光线较暗或较亮车牌
ccpd_fn 19999 间隔摄像头较远或较近
ccpd_np 3036 没上牌的新车
ccpd_rotate 9998 水平歪斜20-50度,笔直歪斜-10-10度
ccpd_tilt 10000 水平歪斜15-45度,笔直歪斜-15-45度
ccpd_weather 9999 雨天、雪天或大雾的车牌
一共283037张车牌图像

![在这里刺进图片描绘](img-blog.csdnimg.cn/df9d095abf0… =500×310)

【智慧交通项目实战】 OCR车牌检测与识别项目实战(一):项目总览
CCPD2019车牌数据集拍摄的车车牌片的环境复杂多变,包含了歪斜、含糊、雨天、雪天等多个场景的数据,并且大部分图片有且仅含有一个车牌;因为收集人员主要在安徽省城市的停车场进行收集,*导致大部分数据都是含【皖】的车牌图片*,而其他省份的车牌比较少,而一些特别车牌的数据就几乎没有,比如【挂使领民航危险品】这些车牌几乎没有。下表给出CCPD数据各个省份的车牌数据计算:

【智慧交通项目实战】 OCR车牌检测与识别项目实战(一):项目总览

(2)车牌数据集CCPD标示格局

CCPD数据集没有专门的标示文件,每张图像的文件名便是对应的数据标示(label)。CCPD车牌数据集图片文件名包含车牌四个角点,车牌水平缓笔直视点以及车牌号码等信息。

详细字段解释参阅:

如图片【025-95_113-154&383_386&473-386&473_177&454_154&383_363&402-0_0_22_27_27_33_16-37-15.jpg】,其文件名的意义如下:

  1. 025:车牌区域占整个画面的比例;
  2. 95_113: 车牌水平缓笔直视点, 水平95, 竖直113
  3. 154&383_386&473:标示框左上、右下坐标,左上(154, 383), 右下(386, 473)
  4. 86&473_177&454_154&383_363&402:标示框四个角点坐标,次序为右下、左下、左上、右上
  5. 0_0_22_27_27_33_16:车牌号码映射关系如下: 第一个0为省份 对应省份字典provinces中的’皖’,;第二个0是该车所在地的地市一级代码,对应地市一级代码字典alphabets的’A’;后5位为字母和文字, 检查车牌号ads字典,如22为Y,27为3,33为9,16为S,最终车牌号码为皖AY339S

(3)车牌数据集CCPD可视化作用(Python

经过解析图片的python脚本,调用parser_annotations(image_file)函数,即可回来标示信息,并可视化车牌标示的结果

代码需求用到pybaseutils工具,请使用pip装置即可:pip install pybaseutils

# -*-coding: utf-8 -*-
import os
import cv2
import numpy as np
from tqdm import tqdm
from pybaseutils import file_utils, image_utils
def get_plate_licenses(plate):
    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']
    result = [provinces[int(plate[0])], alphabets[int(plate[1])]]
    result += [ads[int(p)] for p in plate[2:]]
    result = "".join(result)
    # 新能源车牌的要求,如果不是新能源车牌能够删掉这个if
    # if result[2] != 'D' and result[2] != 'F' \
    #         and result[-1] != 'D' and result[-1] != 'F':
    #     print(plate)
    #     print("Error label, Please check!")
    print(plate, result)
    return result
def parser_annotations(image_file):
    """
    :param image_file: 图片路径
    :return: 回来标示信息info
    """
    filename = os.path.basename(image_file)
    try:
        annotations = filename.split("-")
        rate = annotations[0]  # 车牌区域占整个画面的比例;
        angle = annotations[1].split("_")  # 车牌水平缓笔直视点, 水平95, 竖直113
        box = annotations[2].replace("&", "_").split("_")  # 标示框左上、右下坐标,左上(154, 383), 右下(386, 473)
        point = annotations[3].replace("&", "_").split("_")  # 标示框四个角点坐标,次序为右下、左下、左上、右上
        plate = annotations[4].split("_")  # licenses 标示框四个角点坐标,次序为右下、左下、左上、右上
        plate = get_plate_licenses(plate)
        box = [int(b) for b in box]
        point = [int(b) for b in point]
        point = np.asarray(point).reshape(-1, 2)
        bboxes = [box]
        angles = [angle]
        points = [point]
        plates = [plate]
        labels = ["plate"] * len(bboxes)
    except Exception as e:
        bboxes = []
        points = []
        labels = []
        plates = []
        angles = []
    info = {"filename": filename, "bboxes": bboxes, "points": points,
            "labels": labels, "plates": plates, "angles": angles}
    return info
def save_plate_licenses(image, bboxes, plates, out_dir, name=""):
    crops = image_utils.get_bboxes_crop(image, bboxes)
    for i in range(len(crops)):
        label = plates[i]
        # image_id = file_utils.get_time(format="p")
        file = os.path.join(out_dir, "{}_{}_{:0=3d}.jpg".format(label, name, i))
        file_utils.create_file_path(file)
        cv2.imwrite(file, crops[i])
def converter_CCPD2voc(image_dir, vis=True):
    """
    将CCPD数据集转换为VOC数据格局(xmin,ymin,xmax,ymax)
    :param image_dir: BITVehicle数据集图片(*.jpg)根目录
    :param annot_file: BITVehicle数据集标示文件VehicleInfo.mat
    :param out_voc: 输出VOC格局数据集目录
    :param vis: 是否可视化作用
    """
    print("image_dir :{}".format(image_dir))
    class_set = []
    image_list = file_utils.get_images_list(image_dir)
    for i, image_file in enumerate(tqdm(image_list)):
        info = parser_annotations(image_file)
        labels = info["labels"]
        bboxes = info["bboxes"]
        points = info["points"]
        plates = info["plates"]
        angles = info["angles"]
        image_name = info["filename"]
        print("i={},plates:{},angles(水平,笔直视点):{}".format(os.path.basename(image_file), plates, angles))
        if len(labels) == 0:
            continue
        image_name = os.path.basename(image_name)
        img_postfix = image_name.split(".")[-1]
        image_id = image_name[:-len(img_postfix) - 1]
        class_set = labels + class_set
        class_set = list(set(class_set))
        if not os.path.exists(image_file):
            print("not exist:{}".format(image_file))
            continue
        image = cv2.imread(image_file)
        if vis:
            image = image_utils.draw_image_bboxes_text(image, bboxes, plates, color=(255, 0, 0), thickness=3,
                                                       fontScale=1.2, drawType="chinese")
            # image = image_utils.draw_image_points_lines(image, points=points[0], line_color=(0, 0, 255))
            image_utils.cv_show_image("det", image, use_rgb=False, delay=0)
    print("class_set:{}".format(class_set))
if __name__ == "__main__":
    image_dir = "./dataset/CCPD2020/ccpd_green/train"
    converter_CCPD2voc(image_dir, vis=True)

文章参阅 :

aistudio.baidu.com/aistudio/pr… blog.csdn.net/guyuealian/…