N formas de reconocimiento de matrículas: desde OCR hasta aprendizaje profundo

1. Introducción al reconocimiento de matrículas

Con el desarrollo de la ciencia y la tecnología, la tecnología de inteligencia artificial se usa cada vez más en nuestras vidas. Se han aplicado muchos escenarios, como el reconocimiento facial, el reconocimiento de matrículas y el reconocimiento de objetivos, lo que ha mejorado enormemente nuestra calidad de vida. La eficiencia se mejora mucho y también se ahorra una gran cantidad de mano de obra.

Hoy hablaremos sobre la tarea del reconocimiento de matrículas. Después de años de desarrollo, la tecnología de reconocimiento de matrículas ha diversificado las rutas técnicas. Permítanos presentarle dos de ellas:

El primer reconocimiento de un solo carácter.

En primer lugar, hay un área de detección del sensor en el suelo. Cuando pasa un vehículo, automáticamente tomará una foto y luego preprocesará la foto para convertirla en una imagen en escala de grises, eliminar el ruido, etc., eliminar algunos factores de interferencia. y reducir el tamaño de la imagen.Es conveniente para la extracción de bordes en la etapa posterior;

En segundo lugar, utilice técnicas de extracción de bordes, como canny operator y sobel operator, para extraer el contorno de la imagen y elimine la mayoría de los insospechados de acuerdo con la relación de aspecto de la matrícula, que es de aproximadamente 1:2,5; luego, utilice el valor de gris de la imagen en la La proyección en la dirección horizontal y la dirección vertical recorta los caracteres;

Finalmente, use la coincidencia de plantillas o un modelo de aprendizaje profundo entrenado para el reconocimiento, reconozca cada carácter individualmente y concatene para obtener el número de placa completo.

El cuello de botella de este método es cómo cortar con precisión cada carácter, lo que involucra muchas técnicas de procesamiento de imágenes, como el desenfoque gaussiano, la nitidez de la imagen, la expansión de la imagen, el cambio gamma, la transformación afín, etc. Actualmente, para los caracteres ingleses La precisión de reconocimiento de números y números es de alrededor del 96%, y la precisión del reconocimiento de caracteres chinos es de alrededor del 95%.

inserte la descripción de la imagen aquí
El segundo método, todo el reconocimiento de matrículas.

En primer lugar, al igual que el primer tipo de reconocimiento de matrículas, el sensor se utiliza para la detección de vehículos y se fotografía todo el vehículo;

En segundo lugar, utilice el algoritmo de detección de matrículas entrenado, como el algoritmo YOLO u otros algoritmos de detección de objetivos para detectar la matrícula. Para mejorar la precisión del reconocimiento de matrículas, se puede utilizar la tecnología de preprocesamiento de imágenes para procesar la imagen y reducir los elementos de interferencia;

Por último, utilice el modelo de aprendizaje profundo entrenado para reconocer toda la matrícula. Como LPRNet, Darknet, etc.

2. Realización de la tecnología de reconocimiento de matrículas.

## El primer método: use pytesseract para la identificación

pytesseract es una herramienta de reconocimiento de OCR. La instalación específica de pytesseract se puede instalar en Baidu. La precisión del reconocimiento obtenido mediante el uso directo de esta herramienta aún es un poco baja y no se puede lograr el efecto deseado. Es necesario entrenarlo con los datos de la matrícula. antes de que pueda ser utilizado.

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

## El segundo método de identificación - PaddleOCR

PaddleOCR es un módulo OCR bajo Baidu paddlepaddle. Puede usarlo para reconocer matrículas. Puede descargar directamente el modelo pre-entrenado para reconocimiento. Tiene una buena tasa de precisión para números y suegra, pero el efecto para chino el reconocimiento no es lo ideal Necesita su propio conjunto de datos Realice un nuevo entrenamiento.

Para usar este modelo para entrenar el reconocimiento de matrículas, se requiere una gran cantidad de datos de matrículas, la recopilación manual no solo lleva mucho tiempo, sino que también requiere un costo relativamente alto para involucrar las matrículas de cada provincia.

Otra forma es usar la tecnología de procesamiento de imágenes para la generación de datos, además de la tecnología de mejora de imágenes para hacer conjuntos de datos, que se mencionarán en nuestro tercer capítulo de métodos de reconocimiento.

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

Exportar los resultados a una carpeta de Excel

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

## El tercer método: algoritmo LPRNet
Dado que se necesita mucho tiempo para recopilar datos que satisfagan el aprendizaje profundo, una forma es generar una gran cantidad de conjuntos de datos simulados a través de la generación de datos.

A continuación, podemos usar el algoritmo LPRNet para el reconocimiento de matrículas Hay dos versiones de tensorflow y torch descargadas de GitHub.

El primer paso es generar el conjunto de datos de matrícula azul
. El segundo paso es modificar el nombre de la imagen de acuerdo con los requisitos del modelo de algoritmo y colocarlo en la carpeta designada.
El tercer paso es entrenar y probar el modelo.

## (1) Generación de matrículas azules

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 - noise.min()) / (noise.max() - noise.min())
    noise *= diff
    # noise= noise.astype(np.uint8)
    dst = single + noise
    return dst


def addNoise(img):    # sdev = 0.5,avg=10
    img[:, :, 0] = AddNoiseSingleChannel(img[:, :, 0])
    img[:, :, 1] = AddNoiseSingleChannel(img[:, :, 1])
    img[:, :, 2] = AddNoiseSingleChannel(img[:, :, 2])
    return img
 
class GenPlate:
    def __init__(self, fontCh, fontEng, NoPlates):
        self.fontC = ImageFont.truetype(fontCh, 43, 0)
        self.fontE = ImageFont.truetype(fontEng, 60, 0)
        self.img = np.array(Image.new("RGB", (226, 70),(255, 255, 255)))
#         self.img = np.array(Image.new("RGB", (226, 70),(0, 0, 0)))
        self.bg  = cv.resize(cv.imread(r"C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\generate_picture\images\blue.bmp"), (226, 70)) 
        # template.bmp:车牌背景图
        self.smu = cv.imread(r"E:\AI_projects\vehicle license plate recognition\car_recognition\data\images\\smu2.jpg")  
        # smu2.jpg:模糊图像
        self.noplates_path = []
        for parent, parent_folder, filenames in os.walk(NoPlates):
            for filename in filenames:
                path = parent + "\\" + filename
                self.noplates_path.append(path)
 
    def draw(self, val):
        offset = 2
        self.img[0:70, offset+8:offset+8+23] = GenCh(self.fontC, val[0])
        self.img[0:70, offset+8+23+6:offset+8+23+6+23] = GenCh1(self.fontE, val[1])
        for i in range(5):
            base = offset + 8 + 23 + 6 + 23 + 17 + i * 23 + i * 6
            self.img[0:70, base:base+23] = GenCh1(self.fontE, val[i+2])
        return self.img
    
    def generate(self, text):
        if len(text) == 7:
            fg = self.draw(text)    # decode(encoding="utf-8")
            fg = cv.bitwise_not(fg)
            com = cv.bitwise_or(fg, self.bg)
            com = rot(com, r(30)-10, com.shape,30)
            com = rotRandrom(com, 5, (com.shape[1], com.shape[0]))
            com = tfactor(com)
            com = random_envirment(com, self.noplates_path)
            com = AddGauss(com, 1+r(4))
            com = addNoise(com)
            return com

    @staticmethod
    def genPlateString(pos, val):
        """
        生成车牌string,存为图片
        生成车牌list,存为label
        """
        plateStr = ""
        plateList=[]
        box = [0, 0, 0, 0, 0, 0, 0]
        if pos != -1:
            box[pos] = 1
        for unit, cpos in zip(box, range(len(box))):
            if unit == 1:
                plateStr += val
                plateList.append(val)
            else:
                if cpos == 0:
                    plateStr += chars[r(31)]
                    plateList.append(plateStr)
                elif cpos == 1:
                    plateStr += chars[41 + r(24)]
                    plateList.append(plateStr)
                else:
                    plateStr += chars[31 + r(34)]
                    plateList.append(plateStr)
        plate = [plateList[0]]
        b = [plateList[i][-1] for i in range(len(plateList))]
        plate.extend(b[1:7])
        return plateStr, plate

    @staticmethod
    def genBatch(batchsize, outputPath, size):
        """
        将生成的车牌图片写入文件夹,对应的label写入label.txt
        :param batchsize:  批次大小
        :param outputPath: 输出图像的保存路径
        :param size: 输出图像的尺寸
        :return: None
        """
        if not os.path.exists(outputPath):
            os.mkdir(outputPath)
        outfile = open(r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\label_blue.txt',
                       'w', encoding='utf-8')
        for i in range(batchsize):
            plateStr, plate = G.genPlateString(-1, -1)
            img = G.generate(plateStr)
            img = cv.resize(img, size)
            content = "".join(plate)
            cv.imwrite(outputPath + "\\" + str(i).zfill(2) + ".jpg", img)
            outfile.write("./train/"+str(i).zfill(2)+".jpg"+'\t'+content +"\n")


G = GenPlate(r"E:\AI_projects\vehicle license plate recognition\car_recognition\data\font\platech.ttf", 
             r'E:\AI_projects\vehicle license plate recognition\car_recognition\data\font\platechar.ttf', 
             r"E:\AI_projects\vehicle license plate recognition\car_recognition\data\NoPlates")
G.genBatch(1000, r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\test_in_blue', (272, 72))

Se puede cambiar la cantidad de datos de matrícula que se deben generar modificando el número de la última línea de código

## (2) Producir matrículas amarillas

El paso de generar la placa es escribir los caracteres en la imagen de fondo pura. La placa azul es escribir los caracteres blancos en la placa azul. Puede escribir directamente los caracteres en la placa base, pero la placa amarilla no se puede escribir simplemente Escriba caracteres negros, y el resultado de la escritura es que los caracteres están ocultos y necesitan un tratamiento especial.

El enfoque correcto es:
Paso 1, construya una placa negra pura del tamaño de una placa y escriba caracteres blancos en ella
Paso 2, invierta el blanco y negro, invierta los caracteres y el fondo de la
tarjeta Una tarjeta amarilla sin caracteres se combina con la matrícula invertida, y luego se utilizan varias combinaciones aleatorias, como el desenfoque gaussiano, el cambio de luz y el ángulo de rotación, para simular las imágenes tomadas y procesadas en la vida real.

#黄色车牌生成
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,0,0), 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 - noise.min()) / (noise.max() - noise.min())
    noise *= diff
    # noise= noise.astype(np.uint8)
    dst = single + noise
    return dst


def addNoise(img):    # sdev = 0.5,avg=10
    img[:, :, 0] = AddNoiseSingleChannel(img[:, :, 0])
    img[:, :, 1] = AddNoiseSingleChannel(img[:, :, 1])
    img[:, :, 2] = AddNoiseSingleChannel(img[:, :, 2])
    return img
 
class GenPlate:
    def __init__(self, fontCh, fontEng, NoPlates):
        self.fontC = ImageFont.truetype(fontCh, 43, 0)
        self.fontE = ImageFont.truetype(fontEng, 60, 0)
        self.img = np.array(Image.new("RGB", (226, 70),(255, 255, 255)))
#         self.img = np.array(Image.new("RGB", (226, 70),(0, 0, 0)))
        self.bg  = cv.resize(cv.imread(r"C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\generate_picture\images\black.jpg"), (226, 70)) 
        # template.bmp:车牌背景图
        self.smu = cv.imread(r"E:\AI_projects\vehicle license plate recognition\car_recognition\data\images\\smu2.jpg")  
        # smu2.jpg:模糊图像
        self.noplates_path = []
        for parent, parent_folder, filenames in os.walk(NoPlates):
            for filename in filenames:
                path = parent + "\\" + filename
                self.noplates_path.append(path)
 
    def draw(self, val):
        offset = 2
        self.img[0:70, offset+8:offset+8+23] = GenCh(self.fontC, val[0])
        self.img[0:70, offset+8+23+6:offset+8+23+6+23] = GenCh1(self.fontE, val[1])
        for i in range(5):
            base = offset + 8 + 23 + 6 + 23 + 17 + i * 23 + i * 6
            self.img[0:70, base:base+23] = GenCh1(self.fontE, val[i+2])
        return self.img
    
    def generate(self, text):
        if len(text) == 7:
            fg = self.draw(text)    # decode(encoding="utf-8")
            fg = cv.bitwise_not(fg)
            com = cv.bitwise_or(fg, self.bg)
#             com = rot(com, r(60)-30, com.shape,30)
#             com = rotRandrom(com, 10, (com.shape[1], com.shape[0]))
#             com = tfactor(com)
#             com = random_envirment(com, self.noplates_path)
#             com = AddGauss(com, 1+r(4))
#             com = addNoise(com)
            return com

    @staticmethod
    def genPlateString(pos, val):
        """
        生成车牌string,存为图片
        生成车牌list,存为label
        """
        plateStr = ""
        plateList=[]
        box = [0, 0, 0, 0, 0, 0, 0]
        if pos != -1:
            box[pos] = 1
        for unit, cpos in zip(box, range(len(box))):
            if unit == 1:
                plateStr += val
                plateList.append(val)
            else:
                if cpos == 0:
                    plateStr += chars[r(31)]
                    plateList.append(plateStr)
                elif cpos == 1:
                    plateStr += chars[41 + r(24)]
                    plateList.append(plateStr)
                else:
                    plateStr += chars[31 + r(34)]
                    plateList.append(plateStr)
        plate = [plateList[0]]
        b = [plateList[i][-1] for i in range(len(plateList))]
        plate.extend(b[1:7])
        return plateStr, plate

    @staticmethod
    def genBatch(batchsize, outputPath, size):
        """
        将生成的车牌图片写入文件夹,对应的label写入label.txt
        :param batchsize:  批次大小
        :param outputPath: 输出图像的保存路径
        :param size: 输出图像的尺寸
        :return: None
        """
        if not os.path.exists(outputPath):
            os.mkdir(outputPath)
        outfile = open(r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\label_yellow.txt',
                       'w', encoding='utf-8')
        for i in range(batchsize):
            plateStr, plate = G.genPlateString(-1, -1)
            img = G.generate(plateStr)
            img = cv.resize(img, size)            
            content = "".join(plate)
            cv.imwrite(outputPath + "\\" + str(i).zfill(2) + ".jpg", img)
            outfile.write("./train/"+str(i).zfill(2)+".jpg"+'\t'+content +"\n")


G = GenPlate(r"E:\AI_projects\vehicle license plate recognition\car_recognition\data\font\platech.ttf", 
             r'E:\AI_projects\vehicle license plate recognition\car_recognition\data\font\platechar.ttf', 
             r"E:\AI_projects\vehicle license plate recognition\car_recognition\data\NoPlates")
G.genBatch(1000, r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\test_in_yellow', (272, 72))

inversión de personajes y fondos

#将车牌黑色反转
import cv2
import random

def addNoise(img):    # sdev = 0.5,avg=10
    img[:, :, 0] = AddNoiseSingleChannel(img[:, :, 0])
    img[:, :, 1] = AddNoiseSingleChannel(img[:, :, 1])
    img[:, :, 2] = AddNoiseSingleChannel(img[:, :, 2])
    return img
sample_cp=cv.resize(cv2.imread(r"C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\generate_picture\images\yellow.bmp"), (272, 72))
path=r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\test_in_yellow'
for file in os.listdir(path):
    if file.endswith('.jpg'):
        image=os.path.join(path,file)
        img=cv2.imread(image)
        
        for i in range(72):
            for j in range(272):
                if img[i][j][0]>50:
                    img[i][j][0]=0    #黑色
                    img[i][j][1]=0
                    img[i][j][2]=0
                else:
                    img[i][j][0]=255  #白色
                    img[i][j][1]=255
                    img[i][j][2]=255
                    
        for i in range(72):
            for j in range(272):
                if img[i][j][0]<50 and img[i][j][1]<50 and  img[i][j][2]<50:
                    img[i][j][0]=img[i][j][0]
                    img[i][j][1]=img[i][j][1]
                    img[i][j][2]=img[i][j][2]
                else:
                    img[i][j][0]=sample_cp[i][j][0] #+random.randint(0,9)
                    img[i][j][1]=sample_cp[i][j][1] #+random.randint(0,5)
                    img[i][j][2]=sample_cp[i][j][2]  #+random.randint(0,10)
        addNoise(img)
                    
        images=os.path.join(path,file)
        cv2.imwrite(images,img)

Combinando caracteres y placas inferiores, y aplicando varios métodos, como distorsión, desenfoque y rotación, se construye una variedad de imágenes de placas de matrícula.

import cv2
import numpy as np
from math import cos,sin
import os


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 = cv2.getPerspectiveTransform(pts1, pts2)
    dst = cv2.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 = cv2.getPerspectiveTransform(pts1, pts2)
    dst = cv2.warpPerspective(img, M, size)
    return dst

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

def tfactor(img):
    """
    添加饱和度光照的噪声
    """
    hsv = cv2.cvtColor(img,cv2.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 = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
    return img


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

def AddGauss(img, level):
    return cv2.blur(img, (level * 2 + 1, level * 2 + 1))


def AddNoiseSingleChannel(single):
    """
    添加高斯噪声
    """
    diff = 255 - single.max()
    noise = np.random.normal(0, 1 + r(6), single.shape)
    noise = (noise - noise.min()) / (noise.max() - noise.min())
    noise *= diff
    # noise= noise.astype(np.uint8)
    dst = single + noise
    return dst

def addNoise(img):    # sdev = 0.5,avg=10
    img[:, :, 0] = AddNoiseSingleChannel(img[:, :, 0])
    img[:, :, 1] = AddNoiseSingleChannel(img[:, :, 1])
    img[:, :, 2] = AddNoiseSingleChannel(img[:, :, 2])
    return img
  
path0=r"C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\generate_picture\NoPlates"
noplates_path=[]
for file in os.listdir(path0):
    noplates_path.append(os.path.join(path0,file))

# bg=cv2.resize(cv2.imread(r"C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\generate_picture\images\new.jpg"), (272, 72))
# fg=cv2.imread(r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\picture_new\00.jpg')

# com=fg
# com = rot(com, r(30)-10, com.shape,30)
# com = rotRandrom(com, 5, (com.shape[1], com.shape[0]))
# com = tfactor(com)
# # com = random_envirment(com,noplates_path)  
# # com = AddGauss(com, 1+r(4))
# com = addNoise(com)

# cv2.imshow('com',com)
# cv2.waitKey(0)
# cv2.destroyAllWindows()


# fg = cv2.bitwise_not(fg)
# com = cv2.bitwise_or(fg, bg)
path=r"C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\test_in_yellow"
path1=r"C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\test_in_yellow"
for file in os.listdir(path):
    if file.endswith('.jpg'):
        fg=cv2.imread(os.path.join(path,file))
        com=fg
        com = rot(com, r(30)-10, com.shape,30)
        com = rotRandrom(com, 5, (com.shape[1], com.shape[0]))
        com = tfactor(com)
        com = random_envirment(com,noplates_path)
        com = AddGauss(com, 1+r(4))
        com = addNoise(com)
        
        images=os.path.join(path1,file)
        cv2.imwrite(images,com)
  

## (3) Producción de nuevas placas de energía

El método de generación de la placa de nueva energía es el mismo que el de la placa amarilla, pero la longitud de la placa de nueva energía es un poco más larga que la de la placa azul y la placa amarilla, y el tercer carácter se designa como D o F, pero no lo consideramos al generarlo. Simplemente modifique el código para permitir que el programa genere placas de matrícula de la misma longitud.

#黄色车牌生成
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] - 20)  #50
    cols = r(Smu.shape[1] - 20)
    adder = Smu[rows:rows + 20, cols:cols + 20]
    adder = cv.resize(adder, (20, 20))
    img = cv.resize(img,(20,20))
    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, 2), val, (0, 0, 0), font=f)
    img =  img.resize((19, 70))
    A = np.array(img)
    return A


def GenCh1(f, val):
    """
    生成英文字符
    """
    img =Image.new("RGB", (19, 70), (255,255,255))#白色
#     img =Image.new("RGB", (23, 70), (0, 0, 0))#黑色
    draw = ImageDraw.Draw(img)
    draw.text((0, 2), val, (0,0,0), 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 - noise.min()) / (noise.max() - noise.min())
    noise *= diff
    # noise= noise.astype(np.uint8)
    dst = single + noise
    return dst


def addNoise(img):    # sdev = 0.5,avg=10
    img[:, :, 0] = AddNoiseSingleChannel(img[:, :, 0])
    img[:, :, 1] = AddNoiseSingleChannel(img[:, :, 1])
    img[:, :, 2] = AddNoiseSingleChannel(img[:, :, 2])
    return img
 
class GenPlate:
    def __init__(self, fontCh, fontEng, NoPlates):
        self.fontC = ImageFont.truetype(fontCh, 43, 0)
        self.fontE = ImageFont.truetype(fontEng, 52, 0)  #60--52
        self.img = np.array(Image.new("RGB", (226, 70),(255, 255, 255)))
#         self.img = np.array(Image.new("RGB", (226, 70),(0, 0, 0)))
        self.bg  = cv.resize(cv.imread(r"C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\generate_picture\images\black.jpg"), (226, 70)) 
        # template.bmp:车牌背景图
        self.smu = cv.imread(r"E:\AI_projects\vehicle license plate recognition\car_recognition\data\images\\smu2.jpg")  
        # smu2.jpg:模糊图像
        self.noplates_path = []
        for parent, parent_folder, filenames in os.walk(NoPlates):
            for filename in filenames:
                path = parent + "\\" + filename
                self.noplates_path.append(path)
 
    def draw(self, val):
        offset = 2
        self.img[0:70, offset+6:offset+6+19] = GenCh(self.fontC, val[0])
        self.img[0:70, offset+6+19+7:offset+6+19+7+19] = GenCh1(self.fontE, val[1])
        for i in range(6):
            base = offset + 6 + 19 + 7 + 19 + 17 + i * 19 + i * 7
            self.img[0:70, base:base+19] = GenCh1(self.fontE, val[i+2])  #23--19  6--7  8--6
        return self.img
    
    def generate(self, text):
        if len(text) == 8:
            fg = self.draw(text)    # decode(encoding="utf-8")
            fg = cv.bitwise_not(fg)
            com = cv.bitwise_or(fg, self.bg)
#             com = rot(com, r(60)-30, com.shape,30)
#             com = rotRandrom(com, 10, (com.shape[1], com.shape[0]))
#             com = tfactor(com)
#             com = random_envirment(com, self.noplates_path)
#             com = AddGauss(com, 1+r(4))
#             com = addNoise(com)
            return com

    @staticmethod
    def genPlateString(pos, val):
        """
        生成车牌string,存为图片
        生成车牌list,存为label
        """
        plateStr = ""
        plateList=[]
        box = [0, 0, 0, 0, 0, 0, 0,0]
        if pos != -1:
            box[pos] = 1
        for unit, cpos in zip(box, range(len(box))):
            if unit == 1:
                plateStr += val
                plateList.append(val)
            else:
                if cpos == 0:
                    plateStr += chars[r(31)]  #31
                    plateList.append(plateStr)
                elif cpos == 1:
                    plateStr += chars[41 + r(24)]  #41  24
                    plateList.append(plateStr)
                else:
                    plateStr += chars[31 + r(34)]  #31  34
                    plateList.append(plateStr)
        plate = [plateList[0]]
        b = [plateList[i][-1] for i in range(len(plateList))]
        plate.extend(b[1:8])
        return plateStr, plate

    @staticmethod
    def genBatch(batchsize, outputPath, size):
        """
        将生成的车牌图片写入文件夹,对应的label写入label.txt
        :param batchsize:  批次大小
        :param outputPath: 输出图像的保存路径
        :param size: 输出图像的尺寸
        :return: None
        """
        if not os.path.exists(outputPath):
            os.mkdir(outputPath)
        outfile = open(r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\label_new.txt',
                       'w', encoding='utf-8')
        for i in range(batchsize):
            plateStr, plate = G.genPlateString(-1, -1)
            img = G.generate(plateStr)
            img = cv.resize(img, size)            
            content = "".join(plate)
            cv.imwrite(outputPath + "\\" + str(i).zfill(2) + ".jpg", img)
            outfile.write("./train/"+str(i).zfill(2)+".jpg"+'\t'+content +"\n")


G = GenPlate(r"E:\AI_projects\vehicle license plate recognition\car_recognition\data\font\platech.ttf", 
             r'E:\AI_projects\vehicle license plate recognition\car_recognition\data\font\platechar.ttf', 
             r"E:\AI_projects\vehicle license plate recognition\car_recognition\data\NoPlates")
G.genBatch(1000, r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\test_in_new', (272, 72))

Lo anterior genera parte del código de la placa, y otros códigos se refieren a la parte anterior

(4) Cambiar el nombre de varios nombres de matrículas para que sea adecuado para los requisitos de generación de notas de capacitación

#将以数字命名的图片转换为省份编号+车牌命名
import os
import pandas as pd

path=r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\label_yellow.txt'

num=[]
with open(path,'rb') as f:
    lines=f.readlines()
for line in lines:
    data=line.decode('utf-8')#.encode('gb2312')
    data1=data.split('\t')[0]
    data2=data.split('\t')[1].split('\r')[0]
    num.append([data1,data2])
    
number=pd.DataFrame(num,columns=['p','j'])

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','_'
         ]
dicts = {'A01':'京','A02':'津','A03':'沪','B02':'蒙',
        'S01':'皖','S02':'闽','S03':'粤','S04':'甘',
        'S05': '贵', 'S06': '鄂', 'S07': '冀', 'S08': '黑', 'S09': '湘',
        'S10': '豫', 'S12': '吉', 'S13': '苏', 'S14': '赣', 'S15': '辽',
        'S17': '川', 'S18': '鲁', 'S22': '浙',
        'S30':'渝', 'S31':'晋', 'S32':'桂', 'S33':'琼', 'S34':'云', 'S35':'藏',
        'S36':'陕','S37':'青', 'S38':'宁', 'S39':'新'}
path_root=r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\test_in_yellow'

for k in range(len(number)): 
    for t in range(len(CHARS)):
        pp=number['p'][k].split('/train/')[1]
        if number['j'][k][0]==CHARS[t]:
            original_name=os.path.join(path_root,pp)            
            d=list(dicts.keys())[t] 
            pd=number['j'][k]
            dd=d+'_'+pd[1:]+'_0'+'.jpg'
            post_name=os.path.join(path_root,dd) 
            if os.path.exists(original_name):
                if not os.path.exists(post_name):
                    os.rename(original_name,post_name)

(5) Contar el número de matrículas en cada provincia

Principalmente para confirmar el equilibrio del número de caracteres chinos.

import os

path=r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\picture_real'

S=[]
for file in os.listdir(path):
    a=file.split('_')[0]
    S.append(a)

Set=set(S)
Dict={}
for item in Set:
    Dict.update({item:S.count(item)})
print(Dict)

(6) Mueva la matrícula a las carpetas de entrenamiento y prueba

import os
import shutil

path_from=r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\test_in_new'
path_to=r'C:\Users\lenovo\Desktop\Plate_Recognition-LPRnet-master\Plate_Recognition-LPRnet-master\test'
for file in os.listdir(path_from):
    image=os.path.join(path_from,file)
#     if not os.path.join(path_to,file):
    shutil.move(image,path_to)

(7) Modelo de entrenamiento y prueba

Luego viene el entrenamiento modelo. . . (levemente)

Resumir

Usar el tercer método LPRNet para llevar a cabo el reconocimiento de matrículas es un muy buen proyecto, que involucra varios conocimientos relacionados con la imagen, como el procesamiento de imágenes y el aprendizaje profundo. Después de completar la capacitación de este proyecto, la capacidad de ingeniería del proyecto ha mejorado mucho. es de gran ayuda en el trato con el trabajo y los problemas encontrados en el trabajo.

¡Amigos que pueden ver esto en serio, por favor den un pulgar hacia arriba!

Supongo que te gusta

Origin blog.csdn.net/quantam/article/details/123407254
Recomendado
Clasificación