百度 AI Studio 车牌识别
生活随笔
收集整理的這篇文章主要介紹了
百度 AI Studio 车牌识别
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
任務(wù)描述:
本次實(shí)踐是一個(gè)多分類任務(wù),需要將照片中的每個(gè)字符分別進(jìn)行識(shí)別,完成車牌識(shí)別
實(shí)踐平臺(tái):百度AI實(shí)訓(xùn)平臺(tái)-AI Studio、PaddlePaddle1.8.0 動(dòng)態(tài)圖
深度神經(jīng)網(wǎng)絡(luò)(DNN)
深度神經(jīng)網(wǎng)絡(luò)(Deep Neural Networks,簡(jiǎn)稱DNN)是深度學(xué)習(xí)的基礎(chǔ),其結(jié)構(gòu)為input、hidden(可有多層)、output,每層均為全連接。
數(shù)據(jù)集介紹
-
數(shù)據(jù)集文件名為characterData.zip,其中有65個(gè)文件夾
-
包含0-9,A-Z,以及各省簡(jiǎn)稱
-
圖片為12020的灰度圖像
-
本次實(shí)驗(yàn)中,取其中的10%作為測(cè)試集,90%作為訓(xùn)練集
1、數(shù)據(jù)準(zhǔn)備
''' 參數(shù)配置 ''' train_parameters = {"input_size": [1, 20, 20], #輸入圖片的shape"class_dim": -1, #分類數(shù)"src_path":"data/data47142/characterData.zip", #原始數(shù)據(jù)集路徑"target_path":"/home/aistudio/data/dataset", #要解壓的路徑 "train_list_path": "./train_data.txt", #train_data.txt路徑"eval_list_path": "./val_data.txt", #eval_data.txt路徑"label_dict":{}, #標(biāo)簽字典"readme_path": "/home/aistudio/data/readme.json", #readme.json路徑"num_epochs": 20, #訓(xùn)練輪數(shù)"train_batch_size": 32, #批次的大小"learning_strategy": { #優(yōu)化函數(shù)相關(guān)的配置"lr": 0.001 #超參數(shù)學(xué)習(xí)率} } def unzip_data(src_path,target_path):'''解壓原始數(shù)據(jù)集,將src_path路徑下的zip包解壓至data/dataset目錄下'''if(not os.path.isdir(target_path)): z = zipfile.ZipFile(src_path, 'r')z.extractall(path=target_path)z.close()else:print("文件已解壓") def get_data_list(target_path,train_list_path,eval_list_path):'''生成數(shù)據(jù)列表'''#存放所有類別的信息class_detail = []#獲取所有類別保存的文件夾名稱data_list_path=target_pathclass_dirs = os.listdir(data_list_path)if '__MACOSX' in class_dirs:class_dirs.remove('__MACOSX')# #總的圖像數(shù)量all_class_images = 0# #存放類別標(biāo)簽class_label=0# #存放類別數(shù)目class_dim = 0# #存儲(chǔ)要寫(xiě)進(jìn)eval.txt和train.txt中的內(nèi)容trainer_list=[]eval_list=[]#讀取每個(gè)類別for class_dir in class_dirs:if class_dir != ".DS_Store":class_dim += 1#每個(gè)類別的信息class_detail_list = {}eval_sum = 0trainer_sum = 0#統(tǒng)計(jì)每個(gè)類別有多少?gòu)垐D片class_sum = 0#獲取類別路徑 path = os.path.join(data_list_path,class_dir)# print(path)# 獲取所有圖片img_paths = os.listdir(path)for img_path in img_paths: # 遍歷文件夾下的每個(gè)圖片if img_path =='.DS_Store':continuename_path = os.path.join(path,img_path) # 每張圖片的路徑if class_sum % 10 == 0: # 每10張圖片取一個(gè)做驗(yàn)證數(shù)據(jù)eval_sum += 1 # eval_sum為測(cè)試數(shù)據(jù)的數(shù)目eval_list.append(name_path + "\t%d" % class_label + "\n")else:trainer_sum += 1 trainer_list.append(name_path + "\t%d" % class_label + "\n")#trainer_sum測(cè)試數(shù)據(jù)的數(shù)目class_sum += 1 #每類圖片的數(shù)目all_class_images += 1 #所有類圖片的數(shù)目# 說(shuō)明的json文件的class_detail數(shù)據(jù)class_detail_list['class_name'] = class_dir #類別名稱class_detail_list['class_label'] = class_label #類別標(biāo)簽class_detail_list['class_eval_images'] = eval_sum #該類數(shù)據(jù)的測(cè)試集數(shù)目class_detail_list['class_trainer_images'] = trainer_sum #該類數(shù)據(jù)的訓(xùn)練集數(shù)目class_detail.append(class_detail_list) #初始化標(biāo)簽列表train_parameters['label_dict'][str(class_label)] = class_dirclass_label += 1#初始化分類數(shù)train_parameters['class_dim'] = class_dimprint(train_parameters)#亂序 random.shuffle(eval_list)with open(eval_list_path, 'a') as f:for eval_image in eval_list:f.write(eval_image) #亂序 random.shuffle(trainer_list) with open(train_list_path, 'a') as f2:for train_image in trainer_list:f2.write(train_image) # 說(shuō)明的json文件信息readjson = {}readjson['all_class_name'] = data_list_path #文件父目錄readjson['all_class_images'] = all_class_imagesreadjson['class_detail'] = class_detailjsons = json.dumps(readjson, sort_keys=True, indent=4, separators=(',', ': '))with open(train_parameters['readme_path'],'w') as f:f.write(jsons)print ('生成數(shù)據(jù)列表完成!') def data_reader(file_list):'''自定義data_reader'''def reader():with open(file_list, 'r') as f:lines = [line.strip() for line in f]for line in lines:img_path, lab = line.strip().split('\t')img = cv2.imread(img_path)img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img = np.array(img).astype('float32')img = img/255.0yield img, int(lab) return reader ''' 參數(shù)初始化 ''' src_path=train_parameters['src_path'] target_path=train_parameters['target_path'] train_list_path=train_parameters['train_list_path'] eval_list_path=train_parameters['eval_list_path'] batch_size=train_parameters['train_batch_size'] ''' 解壓原始數(shù)據(jù)到指定路徑 ''' unzip_data(src_path,target_path)#每次生成數(shù)據(jù)列表前,首先清空train.txt和eval.txt with open(train_list_path, 'w') as f: f.seek(0)f.truncate() with open(eval_list_path, 'w') as f: f.seek(0)f.truncate() #生成數(shù)據(jù)列表 get_data_list(target_path,train_list_path,eval_list_path)''' 構(gòu)造數(shù)據(jù)提供器 ''' train_reader = paddle.batch(data_reader(train_list_path),batch_size=batch_size,drop_last=True) eval_reader = paddle.batch(data_reader(eval_list_path),batch_size=batch_size,drop_last=True) 文件已解壓 {'input_size': [1, 20, 20], 'class_dim': 65, 'src_path': 'data/data47142/characterData.zip', 'target_path': '/home/aistudio/data/dataset', 'train_list_path': './train_data.txt', 'eval_list_path': './val_data.txt', 'label_dict': {'0': 'e1', '1': 'X', '2': 'hu', '3': 'C', '4': 'P', '5': 'shan', '6': 'su', '7': '1', '8': 'M', '9': 'zang', '10': 'ji', '11': 'wan', '12': 'gui1', '13': 'yue', '14': 'Q', '15': 'ning', '16': 'B', '17': 'jin', '18': 'liao', '19': 'min', '20': 'H', '21': 'gan1', '22': '3', '23': 'S', '24': 'K', '25': 'meng', '26': '6', '27': '7', '28': '9', '29': 'gan', '30': 'A', '31': 'V', '32': 'D', '33': 'Y', '34': 'N', '35': 'F', '36': 'lu', '37': 'xin', '38': 'E', '39': 'G', '40': 'cuan', '41': 'yun', '42': 'jing', '43': 'T', '44': '4', '45': 'L', '46': 'sx', '47': '8', '48': 'qing', '49': 'hei', '50': '2', '51': 'yu', '52': 'R', '53': 'zhe', '54': 'qiong', '55': 'gui', '56': '0', '57': 'Z', '58': 'U', '59': 'jl', '60': 'xiang', '61': 'W', '62': 'J', '63': '5', '64': 'yu1'}, 'readme_path': '/home/aistudio/data/readme.json', 'num_epochs': 20, 'train_batch_size': 32, 'learning_strategy': {'lr': 0.001}} 生成數(shù)據(jù)列表完成! Batch=0 Batchs=[] all_train_accs=[] def draw_train_acc(Batchs, train_accs):title="training accs"plt.title(title, fontsize=24)plt.xlabel("batch", fontsize=14)plt.ylabel("acc", fontsize=14)plt.plot(Batchs, train_accs, color='green', label='training accs')plt.legend()plt.grid()plt.show()all_train_loss=[] def draw_train_loss(Batchs, train_loss):title="training loss"plt.title(title, fontsize=24)plt.xlabel("batch", fontsize=14)plt.ylabel("loss", fontsize=14)plt.plot(Batchs, train_loss, color='red', label='training loss')plt.legend()plt.grid()plt.show()2、定義模型
###在以下cell中完成DNN網(wǎng)絡(luò)的定義###
#定義DNN網(wǎng)絡(luò) class MyDNN(fluid.dygraph.Layer):'''DNN網(wǎng)絡(luò)'''def __init__(self):super(MyDNN,self).__init__()self.hidden1_1 = Conv2D(1,28,5,1) #通道數(shù)、卷積核個(gè)數(shù)、卷積核大小self.hidden1_2 = Pool2D(pool_size=2,pool_type='max',pool_stride=1)self.hidden2_1 = Conv2D(28,32,3,1)self.hidden2_2 = Pool2D(pool_size=2,pool_type='max',pool_stride=1)self.hidden3 = Conv2D(32,32,3,1)self.hidden4 = Linear(32*10*10,65,act='softmax')def forward(self,input): # forward 定義執(zhí)行實(shí)際運(yùn)行時(shí)網(wǎng)絡(luò)的執(zhí)行邏輯'''前向計(jì)算'''#print(input.shape)x = self.hidden1_1(input)#print(x.shape)x = self.hidden1_2(x)#print(x.shape)x = self.hidden2_1(x)#print(x.shape)x = self.hidden2_2(x)#print(x.shape)x = self.hidden3(x)#print(x.shape)x = fluid.layers.reshape(x, shape=[-1, 32*10*10])y = self.hidden4(x)return y3、訓(xùn)練模型
with fluid.dygraph.guard():model=MyDNN() #模型實(shí)例化model.train() #訓(xùn)練模式opt=fluid.optimizer.SGDOptimizer(learning_rate=train_parameters['learning_strategy']['lr'], parameter_list=model.parameters())#優(yōu)化器選用SGD隨機(jī)梯度下降,學(xué)習(xí)率為0.001.epochs_num=train_parameters['num_epochs'] #迭代次數(shù)for pass_num in range(epochs_num):for batch_id,data in enumerate(train_reader()):images=np.array([x[0].reshape(1,20,20) for x in data],np.float32)labels = np.array([x[1] for x in data]).astype('int64')labels = labels[:, np.newaxis]image=fluid.dygraph.to_variable(images)label=fluid.dygraph.to_variable(labels)predict=model(image) #數(shù)據(jù)傳入modelloss=fluid.layers.cross_entropy(predict,label)avg_loss=fluid.layers.mean(loss)#獲取loss值acc=fluid.layers.accuracy(predict,label)#計(jì)算精度if batch_id!=0 and batch_id%50==0:Batch = Batch+50 Batchs.append(Batch)all_train_loss.append(avg_loss.numpy()[0])all_train_accs.append(acc.numpy()[0])print("train_pass:{},batch_id:{},train_loss:{},train_acc:{}".format(pass_num,batch_id,avg_loss.numpy(),acc.numpy()))avg_loss.backward() opt.minimize(avg_loss) #優(yōu)化器對(duì)象的minimize方法對(duì)參數(shù)進(jìn)行更新 model.clear_gradients() #model.clear_gradients()來(lái)重置梯度fluid.save_dygraph(model.state_dict(),'MyDNN')#保存模型draw_train_acc(Batchs,all_train_accs) draw_train_loss(Batchs,all_train_loss) train_pass:0,batch_id:50,train_loss:[2.5459664],train_acc:[0.375] train_pass:0,batch_id:100,train_loss:[2.475458],train_acc:[0.46875] train_pass:0,batch_id:150,train_loss:[1.2719567],train_acc:[0.6875] train_pass:0,batch_id:200,train_loss:[1.4321089],train_acc:[0.6875] train_pass:0,batch_id:250,train_loss:[0.69725776],train_acc:[0.875] train_pass:0,batch_id:300,train_loss:[1.1576208],train_acc:[0.75] train_pass:0,batch_id:350,train_loss:[1.207567],train_acc:[0.75] train_pass:0,batch_id:400,train_loss:[0.6369293],train_acc:[0.84375] train_pass:0,batch_id:450,train_loss:[0.99959254],train_acc:[0.78125]4、模型評(píng)估
#模型評(píng)估 with fluid.dygraph.guard():accs = []model_dict, _ = fluid.load_dygraph('MyDNN')model = MyDNN()model.load_dict(model_dict) #加載模型參數(shù)model.eval() #訓(xùn)練模式for batch_id,data in enumerate(eval_reader()):#測(cè)試集images=np.array([x[0].reshape(1,20,20) for x in data],np.float32)labels = np.array([x[1] for x in data]).astype('int64')labels = labels[:, np.newaxis]image=fluid.dygraph.to_variable(images)label=fluid.dygraph.to_variable(labels) predict=model(image) acc=fluid.layers.accuracy(predict,label)accs.append(acc.numpy()[0])avg_acc = np.mean(accs)print(avg_acc) 0.965686265、使用模型
5.1對(duì)車牌圖像進(jìn)行預(yù)處理
# 對(duì)車牌圖片進(jìn)行處理,分割出車牌中的每一個(gè)字符并保存 license_plate = cv2.imread('work/車牌.png') gray_plate = cv2.cvtColor(license_plate, cv2.COLOR_RGB2GRAY) ret, binary_plate = cv2.threshold(gray_plate, 175, 255, cv2.THRESH_BINARY) #ret:閾值,binary_plate:根據(jù)閾值處理后的圖像數(shù)據(jù) # 按列統(tǒng)計(jì)像素分布 result = [] for col in range(binary_plate.shape[1]):result.append(0)for row in range(binary_plate.shape[0]):result[col] = result[col] + binary_plate[row][col]/255 # print(result) #記錄車牌中字符的位置 character_dict = {} num = 0 i = 0 while i < len(result):if result[i] == 0:i += 1else:index = i + 1while result[index] != 0:index += 1character_dict[num] = [i, index-1]num += 1i = index # print(character_dict) #將每個(gè)字符填充,并存儲(chǔ) characters = [] for i in range(8):if i==2:continuepadding = (170 - (character_dict[i][1] - character_dict[i][0])) / 2#將單個(gè)字符圖像填充為170*170ndarray = np.pad(binary_plate[:,character_dict[i][0]:character_dict[i][1]], ((0,0), (int(padding), int(padding))), 'constant', constant_values=(0,0))ndarray = cv2.resize(ndarray, (20,20))cv2.imwrite('work/' + str(i) + '.png', ndarray)characters.append(ndarray)def load_image(path):img = paddle.dataset.image.load_image(file=path, is_color=False)img = img.astype('float32')img = img[np.newaxis, ] / 255.0return img5.2 對(duì)標(biāo)簽進(jìn)行轉(zhuǎn)換
#將標(biāo)簽進(jìn)行轉(zhuǎn)換 print('Label:',train_parameters['label_dict']) match = {'A':'A','B':'B','C':'C','D':'D','E':'E','F':'F','G':'G','H':'H','I':'I','J':'J','K':'K','L':'L','M':'M','N':'N','O':'O','P':'P','Q':'Q','R':'R','S':'S','T':'T','U':'U','V':'V','W':'W','X':'X','Y':'Y','Z':'Z','yun':'云','cuan':'川','hei':'黑','zhe':'浙','ning':'寧','jin':'津','gan':'贛','hu':'滬','liao':'遼','jl':'吉','qing':'青','zang':'藏','e1':'鄂','meng':'蒙','gan1':'甘','qiong':'瓊','shan':'陜','min':'閩','su':'蘇','xin':'新','wan':'皖','jing':'京','xiang':'湘','gui':'貴','yu1':'渝','yu':'豫','ji':'冀','yue':'粵','gui1':'桂','sx':'晉','lu':'魯','0':'0','1':'1','2':'2','3':'3','4':'4','5':'5','6':'6','7':'7','8':'8','9':'9'} L = 0 LABEL ={} for V in train_parameters['label_dict'].values():LABEL[str(L)] = match[V]L += 1 print(LABEL) Label: {'0': 'Y', '1': 'hu', '2': '2', '3': 'cuan', '4': 'ji', '5': 'T', '6': '5', '7': '9', '8': 'yue', '9': 'yun', '10': 'hei', '11': 'H', '12': 'G', '13': 'L', '14': 'gan1', '15': '1', '16': '6', '17': 'qing', '18': 'K', '19': 'gui', '20': 'C', '21': 'gan', '22': 'yu', '23': 'X', '24': '8', '25': 'sx', '26': 'xiang', '27': 'S', '28': 'ning', '29': 'jin', '30': 'xin', '31': 'jl', '32': 'min', '33': 'B', '34': 'J', '35': 'yu1', '36': 'N', '37': 'gui1', '38': 'M', '39': '4', '40': 'D', '41': 'R', '42': 'shan', '43': '7', '44': 'E', '45': 'Q', '46': 'A', '47': 'U', '48': '3', '49': 'F', '50': 'W', '51': 'meng', '52': 'liao', '53': 'jing', '54': 'zang', '55': 'lu', '56': 'V', '57': 'Z', '58': '0', '59': 'su', '60': 'wan', '61': 'P', '62': 'zhe', '63': 'e1', '64': 'qiong'} {'0': 'Y', '1': '滬', '2': '2', '3': '川', '4': '冀', '5': 'T', '6': '5', '7': '9', '8': '粵', '9': '云', '10': '黑', '11': 'H', '12': 'G', '13': 'L', '14': '甘', '15': '1', '16': '6', '17': '青', '18': 'K', '19': '貴', '20': 'C', '21': '贛', '22': '豫', '23': 'X', '24': '8', '25': '晉', '26': '湘', '27': 'S', '28': '寧', '29': '津', '30': '新', '31': '吉', '32': '閩', '33': 'B', '34': 'J', '35': '渝', '36': 'N', '37': '桂', '38': 'M', '39': '4', '40': 'D', '41': 'R', '42': '陜', '43': '7', '44': 'E', '45': 'Q', '46': 'A', '47': 'U', '48': '3', '49': 'F', '50': 'W', '51': '蒙', '52': '遼', '53': '京', '54': '藏', '55': '魯', '56': 'V', '57': 'Z', '58': '0', '59': '蘇', '60': '皖', '61': 'P', '62': '浙', '63': '鄂', '64': '瓊'}5.3 使用模型進(jìn)行預(yù)測(cè)
#構(gòu)建預(yù)測(cè)動(dòng)態(tài)圖過(guò)程 with fluid.dygraph.guard():model=MyDNN()#模型實(shí)例化model_dict,_=fluid.load_dygraph('MyDNN')model.load_dict(model_dict)#加載模型參數(shù)model.eval()#評(píng)估模式lab=[]for i in range(8):if i==2:continueinfer_imgs = []infer_imgs.append(load_image('work/' + str(i) + '.png'))infer_imgs = np.array(infer_imgs)infer_imgs = fluid.dygraph.to_variable(infer_imgs)result=model(infer_imgs)lab.append(np.argmax(result.numpy())) print(lab) display(Image.open('work/車牌.png')) for i in range(len(lab)):print(LABEL[str(lab[i])],end='') [55, 46, 16, 24, 16, 44, 34] 魯A686EJ總結(jié)
以上是生活随笔為你收集整理的百度 AI Studio 车牌识别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 企业使用RTX腾讯通2013
- 下一篇: JAVA HD japan_小米小爱AI