当前位置: 首页 > news >正文

基于YoloV11+PaddleOCR的车牌检测系统

文章目录

  • 一、CCPD数据集进行处理
    • 1.1 从文件夹构建txt格式数据集
    • 1.2 运行脚本按照8:2划分训练集,测试集
  • 二 、YOLOV11训练模型
    • 2.1 编写car_plate.yaml文件
    • 2.2 编写train脚本:
    • 2.3 训练过程
  • 三、PaddleOCR识别车牌号
    • 3.1 安装paddleocr,以及paddlepadddle-cpu还是gpu往下看,先勿操作
      • 3.1.1 安装paddlepadddle-gpu(CPU和GPU选一个就行)
      • 3.1.2 安装cpu版本的(CPU和GPU选一个就行)
      • 3.1.3 安装paddleocr
    • 3.2 安装过程
      • 3.2.1 paddleocr安装过程如下
      • 3.2.2 PaddlePaddle安装过程如下
    • **3.2 代码示例**

实现思路:yolov11提取车牌坐标,进行分割,然后使用PaddleOCR进行识别!

图片:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

完整源码获取方式关注底部wx公号,私信获得(有偿)

一、CCPD数据集进行处理

下载链接:https://github.com/detectRecog/CCPD

在这里插入图片描述

在这里插入图片描述

打开readme文件,查找百度网盘链接,在此不再赘述!

在这里插入图片描述

数据集比较大,

数据集说明:

CCPD2019车牌数据集是采集人员在合肥停车场采集、手工标注得来,采集时间在早7:30到晚10:00之间。且拍摄车牌照片的环境复杂多变,包括雨天、雪天、倾斜、模糊等。CCPD数据集包含将近30万张图片、图片尺寸为720x1160x3,共包含8种类型图片,每种类型、数量及类型说明如下表:

类型图片数说明
ccpd_base199996正常车牌
ccpd_challenge50003比较有挑战的车牌
ccpd_db10132光线较暗或较亮车牌
ccpd_fn20967距离摄像头较远或较近
ccpd_np3036没上牌的新车
ccpd_rotate10053水平倾斜20-50度,垂直倾斜-10-10度
ccpd_tilt30216水平倾斜15-45度,垂直倾斜-15-45度
ccpd_weather9999雨天、雪天或大雾的车牌
ccpd_blur20611模糊的车牌
cppd_newenergy11776新能源车牌

总共283037张车牌图像
图片命名:“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”

解释:

025:车牌区域占整个画面的比例;
95_113: 车牌水平和垂直角度, 水平95°, 竖直113°
154&383_386&473:标注框左上、右下坐标,左上(154, 383), 右下(386, 473)
86&473_177&454_154&383_363&402:标注框四个角点坐标,顺序为右下、左下、左上、右上
0_0_22_27_27_33_16:车牌号码映射关系如下: 第一个0为省份 对应省份字典provinces中的’皖’,;第二个0是该车所在地的地市一级代码,对应地市一级代码字典alphabets的’A’;后5位为字母和文字, 查看车牌号ads字典,如22为Y,27为3,33为9,16为S,最终车牌号码为皖AY339S
省份:[“皖”, “沪”, “津”, “渝”, “冀”, “晋”, “蒙”, “辽”, “吉”, “黑”, “苏”, “浙”, “京”, “闽”, “赣”, “鲁”, “豫”, “鄂”, “湘”, “粤”, “桂”, “琼”, “川”, “贵”, “云”, “藏”, “陕”, “甘”, “青”, “宁”, “新”]

地市:[‘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’]

最新的CCPD2020又补充了1万多张新能源汽车数据,都在下面的官网,感兴趣的可以去下载。

由于数据量过大,我从各个类型里面随机抽取10%,最终重构以后得到最终的数据集!

最终的数据集数据量如下:

类型图片数说明
ccpd_base19999正常车牌
ccpd_challenge5000比较有挑战的车牌
ccpd_db1013光线较暗或较亮车牌
ccpd_fn2096距离摄像头较远或较近
ccpd_np303没上牌的新车 没有坐标信息,忽略
ccpd_rotate1005水平倾斜20-50度,垂直倾斜-10-10度
ccpd_tilt3021水平倾斜15-45度,垂直倾斜-15-45度
ccpd_weather999雨天、雪天或大雾的车牌
ccpd_blur2061模糊的车牌
cppd_newenergy1177新能源车牌

1.1 从文件夹构建txt格式数据集

去除重复图片+未上牌新车,将所有图片放在一个datasets文件夹里面,共35885张图片,然后运行下述代码:

import os
import cv2

def parse_filename(filename):
    """解析CCPD文件名,提取车牌边界框坐标"""
    try:

    except Exception as e:
        print(f"解析文件名失败: {filename}, 错误: {e}")
        return None

def convert_to_yolo_format():
    """将边界框转换为YOLO格式(归一化)"""


def process_ccpd_dataset(image_dir, label_dir):
    """处理CCPD数据集,生成YOLO格式的标签文件"""
   

    print("CCPD 数据集处理完成,标签已生成。")

# 使用示例
image_dir = "datasets-car"  # 替换为CCPD图片目录
label_dir = "datasets-car_labels"  # 生成的YOLO标签目录
process_ccpd_dataset(image_dir, label_dir)

1.2 运行脚本按照8:2划分训练集,测试集

import os
import random
import shutil

# 设置文件夹路径
source_images_dir = "car_plate/Image_Files"  # 原始图片目录
source_labels_dir = "car_plate/XML_Files"  # 原始标签目录
datasets_dir = "datasets-carplate"  # 输出数据集目录

# 输出目录

# 创建 datasets 文件夹路径


# 设置划分比例
train_ratio = 0.8  # 80% 训练集
val_ratio = 0.2    # 20% 验证集

# 获取所有图片文件和标签文件

# 检查一致性
assert len(image_files) == len(label_files), "图片文件与标签文件数量不一致!"
for img_file, lbl_file in zip(image_files, label_files):
    assert os.path.splitext(img_file)[0] == os.path.splitext(lbl_file)[0], f"文件名不匹配:{img_file}{lbl_file}"

# 随机打乱文件
combined = list(zip(image_files, label_files))
random.shuffle(combined)
image_files, label_files = zip(*combined)

# 划分数据集


# 复制文件
def copy_files(file_list, source_dir, target_dir):
    for file in file_list:
        shutil.copy(os.path.join(source_dir, file), os.path.join(target_dir, file))

# 复制训练集
copy_files(train_images, source_images_dir, train_images_dir)
copy_files(train_labels, source_labels_dir, train_labels_dir)

# 复制验证集
copy_files(val_images, source_images_dir, val_images_dir)
copy_files(val_labels, source_labels_dir, val_labels_dir)

# 检查分割后的文件数量和一致性
def validate_dataset(images_dir, labels_dir):
    print(f"验证通过:{images_dir}{labels_dir} 完全匹配!")

# 验证所有子集
print("Dataset splitting complete and validation passed!")

最终得到处理后的数据集!

二 、YOLOV11训练模型

2.1 编写car_plate.yaml文件

train: D:\Users\15204\Desktop\yolov11_car_plate_detection\datasets\images\train
val: D:\Users\15204\Desktop\yolov11_car_plate_detection\datasets\images\val
 
nc: 1
 
# Classes
names: ['car_plate']

2.2 编写train脚本:

基于yolov11n.pt预训练权重


开始训练!!在这里插入图片描述

拿一个训练了20轮的模型看了看,的确不错可以,

在这里插入图片描述

可以看出来模型结果挺不错的!!!

2.3 训练过程

  Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
  40/50      2.39G      0.808     0.3246     0.9742          5        640: 100%|██████████| 1795/1795 [05:45<00:00,  5.19it/s]
             Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100%|██████████| 225/225 [00:37<00:00,  6.04it/s]
               all       7177       7177      0.998      0.998      0.994      0.836



  Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
  45/50      2.38G     0.7623     0.2749     0.9641          4        640: 100%|██████████| 1795/1795 [05:39<00:00,  5.28it/s]
             Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100%|██████████| 225/225 [00:38<00:00,  5.85it/s]
               all       7177       7177      0.998      0.998      0.994      0.837

  Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
  46/50      2.41G     0.7575     0.2714     0.9656          4        640: 100%|██████████| 1795/1795 [05:43<00:00,  5.22it/s]
             Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100%|██████████| 225/225 [00:37<00:00,  6.00it/s]
               all       7177       7177      0.998      0.998      0.994      0.837

  Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
  47/50      2.38G     0.7532     0.2661     0.9609          4        640: 100%|██████████| 1795/1795 [05:43<00:00,  5.23it/s]
             Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100%|██████████| 225/225 [00:39<00:00,  5.75it/s]
               all       7177       7177      0.998      0.998      0.994      0.838

  Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
  48/50      2.39G     0.7472     0.2633     0.9582          4        640: 100%|██████████| 1795/1795 [05:40<00:00,  5.27it/s]
             Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100%|██████████| 225/225 [00:38<00:00,  5.89it/s]
               all       7177       7177      0.998      0.998      0.994      0.838



  Epoch    GPU_mem   box_loss   cls_loss   dfl_loss  Instances       Size
  50/50      2.41G     0.7383     0.2556     0.9533          4        640: 100%|██████████| 1795/1795 [05:41<00:00,  5.26it/s]
             Class     Images  Instances      Box(P          R      mAP50  mAP50-95): 100%|██████████| 225/225 [00:37<00:00,  6.06it/s]
               all       7177       7177      0.998      0.998      0.994      0.838

三、PaddleOCR识别车牌号

选择百度的paddleocr进行识别,理由如下:
在这里插入图片描述

3.1 安装paddleocr,以及paddlepadddle-cpu还是gpu往下看,先勿操作

3.1.1 安装paddlepadddle-gpu(CPU和GPU选一个就行)

我的电脑支持gpu就安装了gpu版本的,

如果你使用的是 GPU,需要安装 PaddlePaddle 的 GPU 版本:

使用下述代码:

python
import torch #导入pytorch库
print(torch.cuda.is_available()) #查看是否有cuda
print(torch.backends.cudnn.is_available()) #查看是否有cudnn
print(torch.version.cuda) #打印cuda的版本
print(torch.backends.cudnn.version()) #打印cudnn的版本

输出结果如下:

在这里插入图片描述

可以直到CUDA版本为12.1

需要查看对应的关系如下:

CUDA 11.2paddlepaddle-gpu==2.4.2
CUDA 11.6paddlepaddle-gpu==2.5.0
CUDA 11.7paddlepaddle-gpu==2.6.0
CUDA 12.xpaddlepaddle-gpu==2.6.0
pip install paddlepaddle-gpu==2.6.0 -i https://pypi.tuna.tsinghua.edu.cn/simple

3.1.2 安装cpu版本的(CPU和GPU选一个就行)

pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple  # 安装 PaddlePaddle

3.1.3 安装paddleocr

pip install paddleocr

3.2 安装过程

3.2.1 paddleocr安装过程如下

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.2.2 PaddlePaddle安装过程如下

在这里插入图片描述
在这里插入图片描述

3.2 代码示例

测试了一个demo.py程序,将前面的图片传过去看看效果:

from paddleocr import PaddleOCR, draw_ocr
import cv2
import matplotlib.pyplot as plt

# 初始化 PaddleOCR(lang="ch" 表示支持中文)
ocr = PaddleOCR(use_angle_cls=True, lang="ch")  

# 读取车牌图片
image_path = "license_plate.jpg"  # 替换成你的车牌图片路径
image = cv2.imread(image_path)

# 进行 OCR 识别
results = ocr.ocr(image, cls=True)

# 解析识别结果
for line in results:
    for word_info in line:
        text, confidence = word_info[1][0], word_info[1][1]
        print(f"识别结果: {text}, 置信度: {confidence:.4f}")

# 可视化结果
boxes = [word[0] for line in results for word in line]  # 文字框
txts = [word[1][0] for line in results for word in line]  # 文字内容
scores = [word[1][1] for line in results for word in line]  # 置信度

# 绘制检测结果
image_with_boxes = draw_ocr(image, boxes, txts, scores, font_path="path/to/chinese.ttf")  # 需要指定中文字体路径
plt.imshow(image_with_boxes)
plt.axis("off")
plt.show()

相关文章:

  • STM32硬件SPI函数解析与示例
  • 蓝桥杯之KMP算法
  • 【Linux】环境变量
  • 【Python】从爬虫小白到大佬(一)
  • 玩转适配器模式
  • VMware Workstate 的 Ubuntu18 安装 vmware tools(不安装没法共享)
  • 【DeepSeek】DeepSeek R1 本地windows部署(Ollama+Docker+OpenWebUI)
  • 【数据结构-红黑树】
  • UE5.2后 Bake Out Materials失效
  • ong API Key 认证插件详解
  • 防火墙过滤漏洞问题
  • 【Java集合一】集合概述
  • vue3 关于插槽的使用
  • 给本地模型“投喂“数据
  • 我的新书《青少年Python趣学编程(微课视频版)》出版了!
  • [免费]Springboot+Vue医疗(医院)挂号管理系统【论文+源码+SQL脚本】
  • 单调队列及其相关题解
  • png、jpg、gif、webp的区别
  • 华为交换机堆叠配置
  • OpenAI发布新模型及会员订阅计划:o3-mini、GPT-4.5与GPT-5的全新体验
  • 中央两学一做网站/seo关键词优化最多可以添加几个词
  • 请人建网站应注意什么/河南省人民政府
  • 福田瑞沃轻卡/开源seo软件
  • 简单好看个人主页网站模板/地推放单平台
  • 如何给自己的公司网站做优化/百度快速收录
  • wordpress如何做淘宝客/台州百度推广优化