车牌数据及训练脚本汇总

本文提供了批量修改文件名、数据集json转txt、车牌检测数据集制作、车牌识别数据集制作及识别数据集标签的Python代码,涉及图像处理和数据标注相关技术。
摘要由CSDN通过智能技术生成

目录

一、数据集相关

批量修改文件名

数据集格式转换json转txt

制作车牌检测数据集

制作车牌识别数据集

识别数据集标签crnn

统计训练数据集中各省份数量分布


一、数据集相关

  • 批量修改文件名

"""
    批量修改文件名,给文件名加-加序号
    将路径下的文件以序号命名
"""
import os

def rename_number():
    count = 1
    path = 'D:/rec_datasets/shan'
    filename = os.listdir(path)  # 获取当前路径下的文件的文件名
    for files in filename:
        Olddir = os.path.join(path, files)  # 获取当前文件的绝对路径和名称生成绝对路径名
        if os.path.isdir(Olddir):
            continue
        filename = os.path.splitext(files)[0]  # 获取当前文件的名称
        filetype = os.path.splitext(files)[1]  # 获取当前文件的后缀名
        if filetype == '.py':
            continue  # 忽略.py结尾的文件
        Newdir = os.path.join(path, filename + "_" + str(count) + filetype)  # 根据count编号给文件新命名
        os.rename(Olddir, Newdir)  # 用新的名称替换之前的名称
        count += 1  # 计数加1

rename_number()
  • 数据集格式转换json转txt

'''
    labelme标注车牌四个点,转换成label x y w h x1 y1 x2 y2 x3 y3 x4 y4
'''
import json
import os
import numpy as np
from copy import deepcopy
import cv2

def allFilePath(rootPath,allFIleList):
    fileList = os.listdir(rootPath)
    for temp in fileList:
        if os.path.isfile(os.path.join(rootPath,temp)):
            allFIleList.append(os.path.join(rootPath,temp))
        else:
            allFilePath(os.path.join(rootPath,temp),allFIleList)

def xywh2yolo(rect,landmarks_sort,img):
    h,w,c =img.shape
    rect[0] = max(0, rect[0])
    rect[1] = max(0, rect[1])
    rect[2] = min(w - 1, rect[2]-rect[0])
    rect[3] = min(h - 1, rect[3]-rect[1])
    annotation = np.zeros((1, 12))
    annotation[0, 0] = (rect[0] + rect[2] / 2) / w  # cx
    annotation[0, 1] = (rect[1] + rect[3] / 2) / h  # cy
    annotation[0, 2] = rect[2] / w  # w
    annotation[0, 3] = rect[3] / h  # h

    annotation[0, 4] = landmarks_sort[0][0] / w  # l0_x
    annotation[0, 5] = landmarks_sort[0][1] / h  # l0_y
    annotation[0, 6] = landmarks_sort[1][0] / w  # l1_x
    annotation[0, 7] = landmarks_sort[1][1] / h  # l1_y
    annotation[0, 8] = landmarks_sort[2][0] / w  # l2_x
    annotation[0, 9] = landmarks_sort[2][1] / h # l2_y
    annotation[0, 10] = landmarks_sort[3][0] / w  # l3_x
    annotation[0, 11] = landmarks_sort[3][1] / h  # l3_y
    # annotation[0, 12] = (landmarks_sort[0][0]+landmarks_sort[1][0])/2 / w  # l4_x
    # annotation[0, 13] = (landmarks_sort[0][1]+landmarks_sort[1][1])/2 / h  # l4_y
    return annotation            
            
def order_points(pts):
    rect = np.zeros((4, 2), dtype = "float32")
    s = pts.sum(axis = 1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    diff = np.diff(pts, axis = 1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
 
    # return the ordered coordinates
    return rect

def four_point_transform(image, pts):
    rect = order_points(pts)
    (tl, tr, br, bl) = rect
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype = "float32")
    M = cv2.getPerspectiveTransform(rect, dst)
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
 
    # return the warped image
    return warped
            
if __name__ == "__main__":
    pic_file_list = []
    pic_file = r"E:/License_Plate_Recognition/datasets/own_datasets/pic"
    save_small_path = "small"
    #label_file = ['single','double']
    label_file = ['carplate']
    allFilePath(pic_file,pic_file_list)
    count=0
    index = 0
    for pic_ in pic_file_list:
        if not pic_.endswith(".jpg"):
            continue
        count+=1
        img = cv2.imread(pic_)
        img_name = os.path.basename(pic_)
        txt_name = img_name.replace(".jpg",".txt")
        txt_path = os.path.join(pic_file,txt_name)
        json_file_ = pic_.replace(".jpg",".json")
        if not os.path.exists(json_file_):
            continue
        with open(json_file_, 'r',encoding='utf-8') as a:
            data_dict = json.load(a)
            # print(data_dict['shapes'])
            with open(txt_path,"w") as f:
                for  data_message in data_dict['shapes']:
                    index+=1
                    label=data_message['label']
                    points = data_message['points']
                    pts = np.array(points)
                    pts=order_points(pts)
                    new_img = four_point_transform(img,pts)
                    roi_img_name = label+"_"+str(index)+".jpg"
                    save_path=os.path.join(save_small_path,roi_img_name)
                    # cv2.imwrite(save_path,new_img)
                    x_max,y_max = np.max(pts,axis=0)
                    x_min,y_min = np.min(pts,axis=0)
                    rect = [x_min,y_min,x_max,y_max]
                    rect1=deepcopy(rect)
                    annotation=xywh2yolo(rect1,pts,img)
                    print(data_message)
                    label = data_message['label']
                    str_label = label_file.index(label)
                    # str_label = "0 "
                    str_label = str(str_label)+" "
                    for i in range(len(annotation[0])):
                            str_label = str_label + " " + str(annotation[0][i])
                    str_label = str_label.replace('[', '').replace(']', '')
                    str_label = str_label.replace(',', '') + '\n'

                    f.write(str_label)
            print(count,img_name)
                # point=data_message[points]
  • 制作车牌检测数据集

import os
import glob
import cv2
from pathlib import Path
import numpy as np

root_dir=""   #图片文件
txt_dir=""     #标签文件
# 文件名命名和CCPD相同
use_landmarks=True #用于车牌定位,如MTCNN、YOLO5Face,cls,x,y,w,h,four points
use_xywh=False #用于车牌检测,如YOLO等 cls,x,y,w,h
use_ocr=False #用于识别  车牌号
os.makedirs(txt_dir,exist_ok=True)

#返回中心点坐标、宽、高以及四个顶点的位置信息共12个信息,可用于mtcnn或yolo5Face检测定位车牌
def ccpd_landmarks(points_list,imgw,imgh):
    '''
    Args:
        points_list: 车牌四个顶点的位置信息
        imgw: 图片宽度
        imgh: 图片高度
    Returns:
    '''
    annotation=np.zeros((1,12))
    points_list_=[]
    #得到四个端点
    for points in points_list.split("_"):
        points_=list(map(int,points.split("&")))
        points_list_.append(points_)
    points_list_=np.array(points_list_)

    #获的box的坐标
    xmin=min(points_list_[:,0])
    xmax=max(points_list_[:,0])
    ymin=min(points_list_[:,1])
    ymax=max(points_list_[:,1])
    dw=1./imgw
    dh=1./imgh
    w,h=xmax-xmin,ymax-ymin
    #生成对应的信息列表
    annotation[0,0]=((xmin+xmax)/2.-1)*dw #cx
    annotation[0,1]=((ymin+ymax)/2.-1)*dh #cy
    annotation[0,2]=w*dw #w
    annotation[0,3]=h*dh #h
    annotation[0,4]=points_list_[2][0]/imgw #左上x
    annotation[0,5]=points_list_[2][1]/imgh #左上y
    annotation[0,6]=points_list_[3][0]/imgw #右上x
    annotation[0,7]=points_list_[3][1]/imgh #右上y
    annotation[0,8]=points_list_[0][0]/imgw #右下x
    annotation[0,9]=points_list_[0][1]/imgh #右上y
    annotation[0,10]=points_list_[1][0]/imgw #左下x
    annotation[0,11]=points_list_[1][1]/imgh #左下y
    return annotation


#仅返回图片的中心点坐标以及宽高信息,可用于YOLO系列检测车牌
def ccpd_xywh(points_list,imgw,imgh):
    '''
        Args:
            points_list: 车牌四个顶点的位置信息
            imgw: 图片宽度
            imgh: 图片高度
        Returns:
        '''
    annotation = np.zeros((1, 4))
    points_list_ = []
    # 得到四个端点
    for points in points_list.split("_"):
        points_ = list(map(int, points.split("&")))
        points_list_.append(points_)
    points_list_ = np.array(points_list_)

    #获的box的坐标
    xmin=min(points_list_[:,0])
    xmax=max(points_list_[:,0])
    ymin=min(points_list_[:,1])
    ymax=max(points_list_[:,1])
    dw=1./imgw
    dh=1./imgh
    w,h=xmax-xmin,ymax-ymin
    # 生成对应的信息列表
    annotation[0, 0] = ((xmin + xmax) / 2. - 1) * dw  # cx
    annotation[0, 1] = ((ymin + ymax) / 2. - 1) * dh  # cy
    annotation[0, 2] = w * dw  # w
    annotation[0, 3] = h * dh  # h
    return annotation

#返回对应的文本信息,可用于ocr识别车牌
def ccpd_ocr(plate):
    '''
    Args:
        plate: 文件名中的数字
    Returns:
    '''
    #车牌字典
    #省
    provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤",
                 "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
    #具体信息
    word_lists = ['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', '1', '2', '3', '4', '5', '6', '7', '8', '9','0']


    label_list=plate.split("_")
    print(len(label_list))
    result=""
    result+=provinces[int(label_list[0])]
    result+=word_lists[int(label_list[1])]
    result+=word_lists[int(label_list[2])]+word_lists[int(label_list[3])]+word_lists[int(label_list[4])]+\
            word_lists[int(label_list[5])]+word_lists[int(label_list[6])]
    return result


def ccpd2label(all_list):
    for imgpath in all_list:
        img=cv2.imread(imgpath)
        h,w=img.shape[:2]

        imgname=Path(imgpath).name
        points_list,plate_list=imgname.split("-")[3],imgname.split("-")[4]#四个关键点的坐标[右下、左下、左上、右上],车牌号映射表
        if use_landmarks:
            annotation=ccpd_landmarks(points_list,w,h) #获得要写入txt的信息
            txtname = imgname.replace(".jpg", ".txt")
            txt_path = os.path.join(txt_dir, txtname)
            str_label = "0"  # 类别默认为0
            with open(txt_path, "a+") as fw:
                for i in range(len(annotation[0])):
                    str_label = str_label + " " + str(annotation[0][i])
                fw.write(str_label)
        elif use_xywh:
            annotation=ccpd_xywh(points_list,w,h) #获得要写入txt的信息
            txtname = imgname.replace(".jpg", ".txt")
            txt_path = os.path.join(txt_dir, txtname)
            str_label = "0"  # 类别默认为0
            with open(txt_path, "a+") as fw:
                for i in range(len(annotation[0])):
                    str_label = str_label + " " + str(annotation[0][i])
                fw.write(str_label)
        elif use_ocr:
            ocr_label=ccpd_ocr(plate_list)
            txtname=imgname.replace(".jpg",".txt")
            txt_path=os.path.join(txt_dir,txtname)
            with open(txt_path,"a+") as fw:
                fw.write(ocr_label)

if __name__ == '__main__':
    image_list=glob.glob(root_dir+os.sep+"*.jpg")
    ccpd2label(image_list)
  • 制作车牌识别数据集

'''
透射并裁剪车牌区域
'''
import numpy as np
import cv2
import os

words_list = [
    "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"
]

con_list = [
    "皖", "沪", "津", "渝", "冀",
    "晋", "蒙", "辽", "吉", "黑",
    "苏", "浙", "京", "闽", "赣",
    "鲁", "豫", "鄂", "湘", "粤",
    "桂", "琼", "川", "贵", "云",
    "西", "陕", "甘", "青", "宁",
    "新"
]


def order_points(pts):
    # 初始化坐标点
    rect = np.zeros((4, 2), dtype='float32')

    # 获取左上角和右下角坐标点
    s = pts.sum(axis=1)  # 每行像素值进行相加;若axis=0,每列像素值相加
    rect[0] = pts[np.argmin(s)]  # top_left,返回s首个最小值索引,eg.[1,0,2,0],返回值为1
    rect[2] = pts[np.argmax(s)]  # bottom_left,返回s首个最大值索引,eg.[1,0,2,0],返回值为2
    # 分别计算左上角和右下角的离散差值
    diff = np.diff(pts, axis=1)  # 第i+1列减第i列
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect


def four_point_transform(image, pts):
    # 获取坐标点,并将它们分离开来
    rect = order_points(pts)
    (tl, tr, br, bl) = rect
    # 计算新图片的宽度值,选取水平差值的最大值
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))
    # 计算新图片的高度值,选取垂直差值的最大值
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))
    # 构建新图片的4个坐标点,左上角为原点
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype="float32")
    # 获取透视变换矩阵并应用它
    M = cv2.getPerspectiveTransform(rect, dst)
    # 进行透视变换
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
    # 返回变换后的结果
    return warped


if __name__ == "__main__":
    global points
    total = []
    for filename in os.listdir(os.path.join('E:/License_Plate_Recognition/datasets/CCPD2019/ccpd_rotate/')):
        img = cv2.imread('E:/License_Plate_Recognition/datasets/CCPD2019/ccpd_rotate/' + filename)
        _, _, bbox, points, label, _, _ = filename.split('-')

        # 提取四个点坐标
        points = points.split('_')
        tmp = points
        points = []
        for _ in tmp:
            points.append([int(_.split('&')[0]), int(_.split('&')[1])])
        # print(points)

        # 提取车牌号
        label = label.split('_')
        con = con_list[int(label[0])]
        words = [words_list[int(_)] for _ in label[1:]]
        label = con + ''.join(words)
        line = filename + '\t' + label
        line = line[:] + '\n'
        total.append(line)

        # 还原像素位置
        points = np.array(points, dtype=np.float32)
        warped = four_point_transform(img, points)
        # save_path = os.path.join('E:/License_Plate_Recognition/datasets/own_datasets/images_roi', filename)
        # cv2.imwrite(save_path, warped)

        cv2.imencode('.jpg', warped)[1].tofile(
            r"E:/License_Plate_Recognition/datasets/CCPD2019/ccpd_tilt_roi/{}.jpg".format(label))

    with open('E:/License_Plate_Recognition/datasets/CCPD2019/' + 'ccpd_rotate.txt', 'w', encoding='UTF-8') as f:
        for line in total:
            f.write(line)
  • 识别数据集标签crnn

import cv2
import imageio
import numpy as np
import os
import shutil
import argparse
# from alphabets import plate_chr
def allFileList(rootfile,allFile):
    folder =os.listdir(rootfile)
    for temp in folder:
        fileName = os.path.join(rootfile,temp)
        if os.path.isfile(fileName):
            allFile.append(fileName)
        else:
            allFileList(fileName,allFile)
def is_str_right(plate_name):
    for str_ in plate_name:
        if str_ not in palteStr:
            return False
    return True
if __name__=="__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--image_path', type=str, default="E:\License_Plate_Recognition\datasets\own_datasets/rec", help='source')
    parser.add_argument('--label_file', type=str, default='E:\License_Plate_Recognition\datasets\own_datasets/rec/labels.txt', help='model.pt path(s)')
    
    opt = parser.parse_args()
    rootPath = opt.image_path
    labelFile = opt.label_file
    # palteStr=r"#京沪津渝冀晋蒙辽吉黑苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云藏陕甘青宁新学警港澳挂使领民深危险品0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"
    plate_chr="#京沪津渝冀晋蒙辽吉黑苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云藏陕甘青宁新学警港澳挂使领民航危0123456789ABCDEFGHJKLMNPQRSTUVWXYZ险品"
    palteStr=plate_chr
    print(len(palteStr))
    plateDict ={}
    for i in range(len(list(palteStr))):
        plateDict[palteStr[i]]=i
    fp = open(labelFile,"w",encoding="utf-8")
    file =[]
    allFileList(rootPath,file)
    picNum = 0
    for jpgFile in file:
        print(jpgFile)
        jpgName = os.path.basename(jpgFile)
        name =jpgName.split("_")[0]
        if " " in name:
            continue
        labelStr=" "
        if not is_str_right(name):
            continue
        strList = list(name)
        for  i in range(len(strList)):
            labelStr+=str(plateDict[strList[i]])+" "
        # while i<7:
        #     labelStr+=str(0)+" "
        #     i+=1
        picNum+=1
        # print(jpgFile+labelStr)
        fp.write(jpgFile+labelStr+"\n")
    fp.close()
  • 统计训练数据集中各省份数量分布

import os
import shutil

def allFilePath(rootPath,allFIleList):
    fileList = os.listdir(rootPath)
    for temp in fileList:
        if os.path.isfile(os.path.join(rootPath,temp)):
            allFIleList.append(os.path.join(rootPath,temp))
        else:
            allFilePath(os.path.join(rootPath,temp),allFIleList)


if __name__=="__main__":
    # palteStr=r"京沪津渝冀晋蒙辽吉黑苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云藏陕甘青宁新学警港澳挂使领民"
    palteStr = r"京沪津渝冀晋蒙辽吉黑苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云藏陕甘青宁新"   #31省
    file_path =r"D:/rec_datasets/train_new_balance"
    file_list=[]
    pro_dict={}
    for province in palteStr:
        pro_dict[province]=0
    # print(pro_dict)
    save_folder="save_train"
    allFilePath(file_path,file_list)
    index=0
    error=0
    for file in file_list:
        index+=1
        try:
            plate_name=os.path.basename(file).split("_")[0]
            pro_dict.get(plate_name[-1],0)
            if plate_name[-1] in ["警","港","澳","学","挂","领"]:
                pro_dict[plate_name[-1]]+=1
            else:
                pro_dict[plate_name[0]]+=1
            
        except:
            error+=1
            # print(plate_name,"error")
    a = sorted(pro_dict.items(), key=lambda x: x[1],reverse=True)
    # print(a)
    for key in a:
        print(key)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值