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

news2024/11/25 1:03:15

在这里插入图片描述

👨‍💻作者简介: CSDN、阿里云人工智能领域博客专家,新星计划计算机视觉导师,百度飞桨PPDE,专注大数据与AI知识分享。✨公众号:GoAI的学习小屋 ,免费分享书籍、简历、导图等,更有交流群分享宝藏资料,关注公众号回复“加群”或➡️点击链接 加群。
🎉专栏推荐: 点击访问➡️ 《计算机视觉》 总结目标检测、图像分类、分割OCR、等方向资料。 点击访问➡️ 《深入浅出OCR》: 对标全网最全OCR教程,含理论与实战总结。以上专栏内容丰富、价格便宜且长期更新,欢迎订阅,可加入上述交流群长期学习。
🎉学习者福利: 强烈推荐优秀AI学习网站,包括机器学习、深度学习等理论与实战教程,非常适合AI学习者。➡️网站链接
🎉技术控福利: 程序员兼职社区招募!技术范围广,CV、NLP均可,要求有一定基础,最好是研究生及以上或有工作经验,也欢迎有能力本科大佬加入!群内Python、c++、Matlab等各类编程单应有尽有, 资源靠谱、费用自谈,有意向者直接访问➡️链接

在这里插入图片描述

💚 专栏地址:深入浅出OCR
🍀 专栏导读:恭喜你发现宝藏!本专栏系列主要介绍计算机视觉OCR文字识别领域,每章将分别从OCR技术发展、方向、概念、算法、论文、数据集、对现有平台及未来发展方向等各种角度展开详细介绍,综合基础与实战知识。以下是本系列目录,分为前置篇、基础篇与进阶篇,进阶篇在基础篇基础上进行全面总结,会针对最经典论文及最新算法展开讲解,内容目前包括不限于文字检测、识别、表格分析等方向。 未来看情况更新NLP方向知识,本专栏目前主要面向深度学习及CV同学学习,希望大家能够多多交流,欢迎订阅本专栏,如有错误请大家评论区指正,如有侵权联系删除。


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

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

在这里插入图片描述

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

1.智慧交通预测系统(PaddleOCR版本)

参考:https://blog.csdn.net/qq_36816848/article/details/128686227

2.OCR车牌检测+识别

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

3.车辆检测

后续更新
img


1.项目背景:

车牌识别技术是智能交通的重要环节,目前已广泛应用于例如停车场、收费站等等交通设施中,提供高效便捷的车辆认证的服务,其中较为典型的应用场景为卡口系统。车牌识别即识别车牌上的文字信息,属于光学字符识别(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位数,首字母或数字一般不代表任何含义,只有部分地区会给营运类车型划分特定字母。

在这里插入图片描述

以下为统计后本次车牌识别用到的字典文件:

省份:[“皖”, “沪”, “津”, “渝”, “冀”, “晋”, “蒙”, “辽”, “吉”, “黑”, “苏”, “浙”, “京”, “闽”, “赣”, “鲁”, “豫”, “鄂”, “湘”, “粤”, “桂”, “琼”, “川”, “贵”, “云”, “藏”, “陕”, “甘”, “青”, “宁”, “新”]
地市:[‘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

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

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

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

类型图片数说明
ccpd_base199998正常车牌
ccpd_challenge10006比较有挑战的车牌
ccpd_db20001光线较暗或较亮车牌
ccpd_fn19999距离摄像头较远或较近
ccpd_np3036没上牌的新车
ccpd_rotate9998水平倾斜20-50度,垂直倾斜-10-10度
ccpd_tilt10000水平倾斜15-45度,垂直倾斜-15-45度
ccpd_weather9999雨天、雪天或大雾的车牌
总共283037张车牌图像

在这里插入图片描述

CCPD2019车牌数据集拍摄的车牌照片的环境复杂多变,包括了倾斜、模糊、雨天、雪天等多个场景的数据,并且大部分图片有且仅含有一个车牌;由于采集人员主要在安徽省城市的停车场进行采集,*导致大部分数据都是含【皖】的车牌图片*,而其他省份的车牌比较少,而一些特殊车牌的数据就几乎没有,比如【挂使领民航危险品】这些车牌几乎没有。下表给出CCPD数据各个省份的车牌数据统计:

img

(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)

文章参考 :

https://aistudio.baidu.com/aistudio/projectdetail/4542547
https://blog.csdn.net/guyuealian/article/details/128704181

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/588975.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

西南财经大学李玉周:数智化技术广泛使用推动管理会计加快落地

近日,由用友主办的「智能会计 价值财务」2023企业数智化财务创新峰会收官站圆满举办。来自知名院校的专家学者、央国企等大型企业财务领路人相约成都,一同见证“智能会计”新时代的到来,并肩探讨“价值财务”新主张。 为更好传递智能会计对企…

UnityVR--插件1--新版InputSystem

目录 新版的InputSystem 安装新版InputSystem插件 配置新的InputSystem 在项目中配置新版输入方式实现移动和开火 添加并绑定移动事件 添加并绑定开火事件 总结(啰嗦几句) 新版的InputSystem 在最初的Unity系统中,只有键盘、鼠标、操作…

html实现好看的浪漫爱情回忆录(附源码)

文章目录 1.设计来源1.1 主界面1.2 主题描述1.3 照片墙详细界面1.4 相关跳转界面 2.效果和源码2.1 效果演示2.2 源代码 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/130946811 html实现好看的浪漫爱情回忆录…

Unity发布WebGL报错il2cpp.exe did not run properly

解决:路径中不能有任何中文,包括用户名都不能是中文 win10修改用户名为英文: 1、开启administrator账户。 1)、右键我的电脑,选择管理。 2)、本地用户和组—用户—Administrator 3)、右键—属性…

C++11新特性:decltype类型推导

上一节所讲的 auto,用于通过一个表达式在编译时确定待定义的变量类型,auto 所修饰的变量必须被初始化,编译器需要通过初始化来确定 auto 所代表的类型,即必须要定义变量。若仅希望得到类型,而不需要(或不能)定义变量的…

yum安装最新版的PHP、MySQL

本地环境:AlmaLinux9.2 在阿里的镜像源站点有一个叫remi的源,这个源专门提供了php的各种版本,目前这个源只针对Redhat、Centos和Fedora系统 Remi镜像简介 Remi镜像主页 配置Remi镜像源 这里以Enterprise Linux 9 为例 配置向导 根据配置向…

关于机器人状态估计(15)-VIO与VSLAM精度答疑、融合前端、主流深度相机说明与近期工程汇总

VIOBOT种子用户有了一定的数量,日常大家也会进行交流,整理总结一下近期的交流与答疑。 VIO-SLAM(作为三维SLAM,相对于Lidar-SLAM和LIO-SLAM)在工程上落地的长期障碍,不仅在算法精度本身,还有相对严重的鲁棒性问题&…

【Linux】iptables防火墙

文章目录 一、Linux防火墙基础1.Linux防火墙概术2.netfilter/iptables3.四表五链4.规则链之间的匹配顺序 二、iptables 安装1.常用的控制类型2.常用的管理选项 三、示例演示1.添加新的规则2.查看规则列表3.删除规则4.清空规则 四、规则的匹配1.通用匹配2.隐含匹配3.显式匹配 一…

浅谈安科瑞无线测温技术在大功率整流器上的应用

安科瑞 徐浩竣 江苏安科瑞电器制造有限公司 zx acrelxhj 摘要:随着整流器运行电流的增加 ,运行温度成为影响整 流器安全运行的主要因素 。针对目前大功率整流器运行温度通过出口水温表和纽扣继电器来监测 ,运行人员不能及时、准确地掌握整…

【测试开发】第四节.测试开发(测试分类)

作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:Java测试开发 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!! 文章目录 前…

程序员有哪些绝对不能踩的坑?

本文概要 程序员编写高质量、可维护、安全且高效的代码,通常需要大量研究和经验。但也需要避免许多技术陷阱。一起来聊聊程序员有哪些绝对不能踩的坑吧! 🌟🌟🌟个人简介🌟🌟🌟 ☀️…

Spring Boot拦截器与过滤器的区别

Spring Boot拦截器与过滤器的区别 在使用Spring Boot开发Web应用程序时,您可能需要在处理请求之前或之后执行某些操作。这些操作可以包括身份验证、日志记录、性能监测等。在这种情况下,您可以使用两种不同的机制:拦截器和过滤器。本文将介绍…

Spring Boot如何实现缓存的自动刷新

Spring Boot如何实现缓存的自动刷新 在Web应用程序中,缓存是提高性能的重要手段之一。在Spring Boot应用程序中,我们可以使用Spring Cache来实现缓存功能。然而,当缓存的数据发生变化时,我们可能需要手动刷新缓存,这可…

C语言---分支和循环语句

1、什么是语句 C语言语句可以分为五类: 表达式语句函数调用语句控制语句复合语句空语句 C语言有九种控制语句 可以分成一下三类: 条件判断语句也叫分支语句:if语句,switch语句;循环执行语句:do while语…

基于html+css的图展示100

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

安卓手机使用Termux搭建Hexo个人博客网站【内网穿透公网访问】

文章目录 1. 安装 Hexo2. 安装cpolar内网穿透3. 公网远程访问4. 固定公网地址 转载自cpolar极点云的文章:安卓手机使用Termux搭建Hexo个人博客网站【内网穿透公网访问】 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#…

Ansible基础1——介绍安装、清单文件、配置文件、临时命令参数、常用功能模块

文章目录 一、发展起源1.1 自动化工具对比1.2 Ansible介绍 二、安装流程2.1 安装清单2.2 系统初始化2.3 安装验证 三、清单文件3.1 默认静态清单3.2 自定义静态清单 四、配置文件4.1 优先级4.2 配置参数4.2.1 [defaults]配置4.2.2 [privilege_escalation]配置4.2.3 其他配置 4.…

C++ new delete

可执行程序(进程) 的虚拟地址空间: 内核: 操作系统 栈区:函数的形参,非静态的局部变量,函数现场保护数据等等,栈是向下增长的。 共享库的内存映射区域:用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存,做进程间通…

四足机器人A1目标跟踪

四足机器人A1目标跟踪 前期准备工作1.安装TeamViewer2.将四足机器人所有线连接好3.将四足机器人调至运动模式 运行流程1.开机阶段2.运行阶段 效果展示代码配置 前期准备工作 1.安装TeamViewer 由于外接屏幕损坏,故四足机器人内部配置了TeamViewer,因此…

VM——编写脚本,TCP发送16进制字符串

1、参考: (1)​​​(246条消息) TCP中发送接收16进制数(16进制字符串与字节数组之间的转换)_tcp发送16进制字符串_start_continue的博客-CSDN博客 (2)(246条消息) C#byte String转换_c# byte转…