深度神经网络实践:车牌识别
生活随笔
收集整理的這篇文章主要介紹了
深度神经网络实践:车牌识别
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
深度神經網絡實踐:車牌識別
- 任務描述:
- 深度神經網絡(DNN)
- 數據集介紹
- 1、數據準備
- 2、定義模型
- 3、訓練模型
- 4、模型評估
- 5、使用模型
- 5.1對車牌圖像進行預處理
- 5.2 對標簽進行轉換
- 5.3 使用模型進行預測
注意只有需要訓練和更新權重參數的算子才能作為單獨的一層,比如全連接層(FC)、卷積層(CONV),而激活函數(ReLU、Sigmoid等)、池化(MAX POOL、AVAGE POOL等)則不能算做一層。
任務描述:
本次實踐是一個多分類任務,需要將照片中的每個字符分別進行識別,完成車牌的識別
實踐平臺:百度AI實訓平臺-AI Studio、PaddlePaddle1.8.0 動態圖
深度神經網絡(DNN)
深度神經網絡(Deep Neural Networks,簡稱DNN)是深度學習的基礎,其結構為input、hidden(可有多層)、output,每層均為全連接。
數據集介紹
-
數據集文件名為characterData.zip,其中有65個文件夾
-
包含0-9,A-Z,以及各省簡稱
-
圖片為12020的灰度圖像
-
本次實驗中,取其中的10%作為測試集,90%作為訓練集
1、數據準備
''' 參數配置 ''' train_parameters = {"input_size": [1, 20, 20], #輸入圖片的shape"class_dim": -1, #分類數"src_path":"data/data23617/characterData.zip", #原始數據集路徑"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":{}, #標簽字典"readme_path": "/home/aistudio/data/readme.json", #readme.json路徑"num_epochs": 1, #訓練輪數"train_batch_size": 32, #批次的大小"learning_strategy": { #優化函數相關的配置"lr": 0.001 #超參數學習率} } def unzip_data(src_path,target_path):'''解壓原始數據集,將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):'''生成數據列表'''#存放所有類別的信息class_detail = []#獲取所有類別保存的文件夾名稱data_list_path=target_pathclass_dirs = os.listdir(data_list_path)if '__MACOSX' in class_dirs:class_dirs.remove('__MACOSX')# #總的圖像數量all_class_images = 0# #存放類別標簽class_label=0# #存放類別數目class_dim = 0# #存儲要寫進eval.txt和train.txt中的內容trainer_list=[]eval_list=[]#讀取每個類別for class_dir in class_dirs:if class_dir != ".DS_Store":class_dim += 1#每個類別的信息class_detail_list = {}eval_sum = 0trainer_sum = 0#統計每個類別有多少張圖片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: # 遍歷文件夾下的每個圖片if img_path =='.DS_Store':continuename_path = os.path.join(path,img_path) # 每張圖片的路徑if class_sum % 10 == 0: # 每10張圖片取一個做驗證數據eval_sum += 1 # eval_sum為測試數據的數目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測試數據的數目class_sum += 1 #每類圖片的數目all_class_images += 1 #所有類圖片的數目# 說明的json文件的class_detail數據class_detail_list['class_name'] = class_dir #類別名稱class_detail_list['class_label'] = class_label #類別標簽class_detail_list['class_eval_images'] = eval_sum #該類數據的測試集數目class_detail_list['class_trainer_images'] = trainer_sum #該類數據的訓練集數目class_detail.append(class_detail_list) #初始化標簽列表train_parameters['label_dict'][str(class_label)] = class_dirclass_label += 1#初始化分類數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) # 說明的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 ('生成數據列表完成!') 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 ''' 參數初始化 ''' 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'] ''' 解壓原始數據到指定路徑 ''' unzip_data(src_path,target_path)#每次生成數據列表前,首先清空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() #生成數據列表 get_data_list(target_path,train_list_path,eval_list_path)''' 構造數據提供器 ''' 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) 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、定義模型
#定義DNN網絡 class MyDNN(fluid.dygraph.Layer):def __init__(self):super(MyDNN,self).__init__()self.hidden1 = Linear(20*20,200,act='relu')self.hidden2 = Linear(200,100,act='relu')self.hidden3 = Linear(100,100,act='relu')self.out = Linear(100,65,act='softmax')def forward(self,input): # forward 定義執行實際運行時網絡的執行邏輯x = fluid.layers.reshape(input, shape=[-1,20*20]) #-1 表示這個維度的值是從x的元素總數和剩余維度推斷出來的,有且只能有一個維度設置為-1# print(x.shape)x = self.hidden1(x)# print('1', x.shape)x = self.hidden2(x)# print('2',x.shape)x = self.hidden3(x)# print('3',x.shape)y = self.out(x)# print('4',y.shape)return y3、訓練模型
with fluid.dygraph.guard():model=MyDNN() #模型實例化model.train() #訓練模式opt=fluid.optimizer.SGDOptimizer(learning_rate=train_parameters['learning_strategy']['lr'], parameter_list=model.parameters())#優化器選用SGD隨機梯度下降,學習率為0.001.epochs_num=train_parameters['num_epochs'] #迭代次數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) #數據傳入modelloss=fluid.layers.cross_entropy(predict,label)avg_loss=fluid.layers.mean(loss)#獲取loss值acc=fluid.layers.accuracy(predict,label)#計算精度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) #優化器對象的minimize方法對參數進行更新 model.clear_gradients() #model.clear_gradients()來重置梯度fluid.save_dygraph(model.state_dict(),'MyDNN')#保存模型draw_train_acc(Batchs,all_train_accs) draw_train_loss(Batchs,all_train_loss)
4、模型評估
#模型評估 with fluid.dygraph.guard():accs = []model_dict, _ = fluid.load_dygraph('MyDNN')model = MyDNN()model.load_dict(model_dict) #加載模型參數model.eval() #訓練模式for batch_id,data in enumerate(eval_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) acc=fluid.layers.accuracy(predict,label)accs.append(acc.numpy()[0])avg_acc = np.mean(accs)print(avg_acc) 0.0827205855、使用模型
5.1對車牌圖像進行預處理
# 對車牌圖片進行處理,分割出車牌中的每一個字符并保存 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:根據閾值處理后的圖像數據 # 按列統計像素分布 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) #將每個字符填充,并存儲 characters = [] for i in range(8):if i==2:continuepadding = (170 - (character_dict[i][1] - character_dict[i][0])) / 2#將單個字符圖像填充為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 對標簽進行轉換
#將標簽進行轉換 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)5.3 使用模型進行預測
#構建預測動態圖過程 with fluid.dygraph.guard():model=MyDNN()#模型實例化model_dict,_=fluid.load_dygraph('MyDNN')model.load_dict(model_dict)#加載模型參數model.eval()#評估模式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='')總結
以上是生活随笔為你收集整理的深度神经网络实践:车牌识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python Matplotlib基本用
- 下一篇: 【百度飞浆】目标检测综述