车牌识别的N种办法——从OCR到深度学习

本文详细介绍了车牌识别技术,包括两种主要方法:单个字符识别和整张车牌识别。首先,通过图像预处理、边缘检测和模板匹配等技术实现单个字符切割与识别,对于英文和数字的准确率可达96%,汉字则为95%。其次,利用YOLO等目标检测算法检测整张车牌,再通过深度学习模型进行识别。此外,还介绍了PaddleOCR和LPRNet算法,以及如何生成模拟车牌数据集。最后,讨论了车牌数据集的平衡、模型训练和测试等步骤,全面涵盖了车牌识别系统的构建流程。

一、车牌识别简介

随着科学技术的发展,人工智能技术在我们的生活中的应用越来越广泛,人脸识别、车牌识别、目标识别等众多场景已经落地应用,给我们的生活品质得到很大的提升,办事效率大大提高,同时也节约了大量的劳动力。

今天我们来讲一讲车牌识别这个任务,车牌识别技术经过多年的发展,技术路线也呈现多样化,我们来介绍一下其中的两种:

第一种,单个字符识别

首先,在地面上有传感器感应区域,当有车辆经过时自动进行拍照,然后对拍的照片进行预处理,变成灰度图像,去除噪声等,把一些干扰因素去掉,同时降低图像的大小,便于后期进行边缘提取;

其次,利用边缘提取技术,比如canny算子、sobel算子,把图像轮廓提取出来,根据车牌长宽比大概为1:2.5左右把大部分不疑似的去掉;然后,再利用图像灰度值在水平方向和竖直方向上的投影,将字符切割出来;

最后,利用模板匹配或者是已经训练好的深度学习模型进行识别,单独把每个字符识别后进行串联得到整张车牌号码。

这种方法的瓶颈在于怎么样把每一个字符准确地切割出来,这涉及到很多图像处理技术,比如高斯模糊、图像锐化、图像膨胀、伽马变化、仿射变换等等,目前对于英文字符和数字的识别准确度在96%左右,汉字识别的准确度在95%左右。

在这里插入图片描述
第二种办法,整张车牌识别

首先,与第一种车牌识别一样,利用传感器进行车辆感应,把整辆车进行拍照;

其次,利用训练好的车牌检测算法,比如YOLO算法或者其他的目标检测算法把车牌检测出来。为了提升车牌识别的准确度,可以利用图像预处理技术对图像进行处理,降低干扰项;

最后,利用已经训练好的深度学习模型对整张车牌进行识别。比如LPRNet、Darknet等

二、车牌识别技术实现

## 第一种方法 ——利用 pytesseract 进行识别

pytesseract是一个OCR识别工具,具体的 pytesseract 安装可百度安装,直接使用这个工具进行识别得到的准确度还有点低,达不到理想的效果,需要利用车牌数据进行训练才可以使用。

import cv2 as cv
from PIL import Image
import pytesseract as tess
 
def recoginse_text(image):
    """
    步骤:
    1、灰度,二值化处理
    2、形态学操作去噪
    3、识别
    :param image:
    :return:
    """
 
    # 灰度 二值化
    gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    # 如果是白底黑字 建议 _INV
    ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV| cv.THRESH_OTSU)
 
 
    # 形态学操作 (根据需要设置参数(1,2))
    kernel = cv.getStructuringElement(cv.MORPH_RECT,(1,2))  #去除横向细线
    morph1 = cv.morphologyEx(binary,cv.MORPH_OPEN,kernel)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (2, 1)) #去除纵向细线
    morph2 = cv.morphologyEx(morph1,cv.MORPH_OPEN,kernel)
    cv.imshow("Morph",morph2)
 
    # 黑底白字取非,变为白底黑字(便于pytesseract 识别)
    cv.bitwise_not(morph2,morph2)
    textImage = Image.fromarray(morph2)
 
    # 图片转文字
    text=tess.image_to_string(textImage)
    print("识别结果:%s"%text)
 
 
def main():
 
    # 读取需要识别的数字字母图片,并显示读到的原图
    src = cv.imread(r'C:\Users\lenovo\Desktop\00A8CX87_5.jpg')
    cv.imshow("src",src)
 
    # 识别
    recoginse_text(src)
 
    cv.waitKey(0)
    cv.destroyAllWindows()

if __name__=="__main__":
    main()

## 第二种识别办法——PaddleOCR

PaddleOCR 是百度paddlepaddle下的OCR模块,可以用它来识别车牌,直接下载预训练模型进行识别,对于数字和子母都得到不错的准确率,但是针对中文识别的效果并不理想,需要自己的数据集进行再训练。

要想利用这个模型进行训练车牌识别,需要大量的车牌数据,人工收集不仅耗费时间长,要涉及每个省份的车牌需要比较大的成本。

另外的办法是利用图像处理技术进行数据生成,加上图像增强技术来制作数据集,这将在我们的第三章识别方法中讲到。

from paddleocr import PaddleOCR
import os

# ocr = PaddleOCR(use_gpu=False, use_angle_cls=True, lang="ch")
ocr = PaddleOCR(use_gpu=True, use_angle_cls=True, lang="ch")
path=r'E:\车牌数据'
results=[]
for file in os.listdir(path):
    img_path =os.path.join(path,file)
    result = ocr.ocr(img_path, cls=True)
    if len(result)>0: 
        results.append([img_path,result[0][1][0]])
    else:
        results.append([img_path])

将结果导出到Excel文件夹

import pandas as pd
resultss=pd.DataFrame(results)
resultss.to_excel(r'C:\Users\lenovo\Desktop\11.xlsx')

## 第三种办法 ——LPRNet算法
由于要收集满足深度学习的数据需要花费大量的时间,有一种办法是通过数据生成的办法生成大量的模拟数据集。

紧接着,我们可以利用LPRNet算法进行车牌识别,从GitHub上下载有tensorflow、torch两个版本。

第一步,生成蓝色车牌数据集
第二步,根据算法模型要求将图像名称修改并放到指定的文件夹中
第三步,模型训练和测试

## (1) 蓝色车牌生成

import os
import cv2 as cv
import numpy as np
from math import *
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw


index = {"京": 0, "沪": 1, "津": 2, "渝": 3, "冀": 4, "晋": 5, "蒙": 6, "辽": 7, "吉": 8, "黑": 9,
              "苏": 10, "浙": 11, "皖": 12, "闽": 13, "赣": 14, "鲁": 15, "豫": 16, "鄂": 17, "湘": 18, "粤": 19,
              "桂": 20, "琼": 21, "川": 22, "贵": 23, "云": 24, "藏": 25, "陕": 26, "甘": 27, "青": 28, "宁": 29,
              "新": 30, "0": 31, "1": 32, "2": 33, "3": 34, "4": 35, "5": 36, "6": 37, "7": 38, "8": 39,
              "9": 40, "A": 41, "B": 42, "C": 43, "D": 44, "E": 45, "F": 46, "G": 47, "H": 48, "J": 49,
              "K": 50, "L": 51, "M": 52, "N": 53, "P": 54, "Q": 55, "R": 56, "S": 57, "T": 58, "U": 59,
              "V": 60, "W": 61, "X": 62, "Y": 63, "Z": 64}

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


def AddSmudginess(img, Smu):
    """
    模糊处理
    :param img: 输入图像
    :param Smu: 模糊图像
    :return: 添加模糊后的图像
    """
    rows = r(Smu.shape[0] - 50)
    cols = r(Smu.shape[1] - 50)
    adder = Smu[rows:rows + 50, cols:cols + 50]
    adder = cv.resize(adder, (50, 50))
    img = cv.resize(img,(50,50))
    img = cv.bitwise_not(img)
    img = cv.bitwise_and(adder, img)
    img = cv.bitwise_not(img)
    return img


def rot(img, angel, shape, max_angel):
    """
    添加透视畸变
    """
    size_o = [shape[1], shape[0]]
    size = (shape[1]+ int(shape[0] * cos((float(max_angel ) / 180) * 3.14)), shape[0])
    interval = abs(int(sin((float(angel) / 180) * 3.14) * shape[0]))
    pts1 = np.float32([[0, 0], [0, size_o[1]], [size_o[0], 0], [size_o[0], size_o[1]]])
    if angel > 0:
        pts2 = np.float32([[interval, 0], [0, size[1]], [size[0], 0], [size[0] - interval, size_o[1]]])
    else:
        pts2 = np.float32([[0, 0], [interval, size[1]], [size[0] - interval, 0], [size[0], size_o[1]]])
    M = cv.getPerspectiveTransform(pts1, pts2)
    dst = cv.warpPerspective(img, M, size)
    return dst


def rotRandrom(img, factor, size):
    """
    添加放射畸变
    :param img: 输入图像
    :param factor: 畸变的参数
    :param size: 图片目标尺寸
    :return: 放射畸变后的图像
    """
    shape = size
    pts1 = np.float32([[0, 0], [0, shape[0]], [shape[1], 0], [shape[1], shape[0]]])
    pts2 = np.float32([[r(factor), r(factor)], [r(factor), shape[0] - r(factor)], [shape[1] - r(factor), r(factor)],
                       [shape[1] - r(factor), shape[0] - r(factor)]])
    M = cv.getPerspectiveTransform(pts1, pts2)
    dst = cv.warpPerspective(img, M, size)
    return dst


def tfactor(img):
    """
    添加饱和度光照的噪声
    """
    hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
    hsv[:, :, 0] = hsv[:, :, 0] * (0.8 + np.random.random() * 0.2)
    hsv[:, :, 1] = hsv[:, :, 1] * (0.3 + np.random.random() * 0.7)
    hsv[:, :, 2] = hsv[:, :, 2] * (0.2 + np.random.random() * 0.8)
    img = cv.cvtColor(hsv, cv.COLOR_HSV2BGR)
    return img


def random_envirment(img, noplate_bg):
    """
    添加自然环境的噪声, noplate_bg为不含车牌的背景图
    """
    bg_index = r(len(noplate_bg))
    env = cv.imread(noplate_bg[bg_index])
    env = cv.resize(env, (img.shape[1], img.shape[0]))
    bak = (img == 0)
    bak = bak.astype(np.uint8) * 255
    inv = cv.bitwise_and(bak, env)
    img = cv.bitwise_or(inv, img)
    return img

 
def GenCh(f, val):
    """
    生成中文字符
    """
    img = Image.new("RGB", (45, 70), (255, 255, 255))  #白色
#     img = Image.new("RGB", (45, 70), (0, 0, 0))  #黑色
    draw = ImageDraw.Draw(img)
#     draw.text((0, 3), val, (0, 0, 0), font=f)
    draw.text((0, 3), val, (0, 0, 0), font=f)
    img =  img.resize((23, 70))
    A = np.array(img)
    return A


def GenCh1(f, val):
    """
    生成英文字符
    """
    img =Image.new("RGB", (23, 70), (255,255,255))#白色
#     img =Image.new("RGB", (23, 70), (0, 0, 0))#黑色
    draw = ImageDraw.Draw(img)
    draw.text((0, 2), val, (0,125,125), font=f)    # val.decode('utf-8')
    A = np.array(img)
    return A

 
def AddGauss(img, level):
    """
    添加高斯模糊
    """ 
    return cv.blur(img, (level * 2 + 1, level * 2 + 1))


def r(val):
    return int(np.random.random() * val)


def AddNoiseSingleChannel(single):
    """
    添加高斯噪声
    """
    diff = 255 - single.max()
    noise = np.random.normal(0, 1 + r(6), single.shape)
    noise = (noise -
目标识别计算机视觉一个重要的研究领域,由此延伸出的车辆型号识别具有重 要的实际应用价值,特别是在当今交通状况复杂的大城市,智能交通系统成为发展趋 势,这离不开对车辆型号进行识别和分类的工作,本文围绕如何利用计算机视觉的方 法进行车辆型号的识别和分类展开了一系列研究: 本文对当前的目标识别和分类的特征和算法做了总结和归纳。分析比较了作为图 像特征描述常见的特征算子,总结归纳了他们的提取方法、特征性能以及相互之间的 关联。另外,介绍了在目标识别工作中常用的分类方法,阐述了他们各自的原理和工作 方法。研究了深度神经网络的理论依据,分析比较了深度神经网络不同的特征学习方 法,以及卷积神经网络的训练方法。分析比较不同特征学习方法的特点选取 k-means 作为本文使用的特征学习方法,利用卷积神经网络结构搭建深度学习模型,进行车辆 车型识别工作。 本文为了测试基于深度学习的车辆型号分类算法的性能在 30 个不同型号共 7158 张图片上进行实验;并在相同数据上利用改进了的 SIFT 特征匹配的算法进行对比实验; 进过实验测试,深度学习方法在进行车型分类的实验中取得 94%的正确率,并在与 SIFT 匹配实验结果对比后进一步证实:深度学习的方法能够应用在车辆型号识别领域
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值