1. 程式人生 > >基於KITTI資料集的KERAS-YOLOV3實踐

基於KITTI資料集的KERAS-YOLOV3實踐

資料整理

One row for one image;
Row format: image_file_path box1 box2 … boxN;
Box format: x_min,y_min,x_max,y_max,class_id (no space).
For VOC dataset, try python voc_annotation.py
Here is an example:

path/to/img1.jpg 50,100,150,200,0 30,50,200,120,3
path/to/img2.jpg 120,300,250,600,2

LABEL格式:

Car 0.00 0 -1.67 642.24 178.50 680.14 208.68 1.38 1.49 3.32 2.41 1.66 34.98 -1.60 

關於資料定義,參考了這篇博文:
https://blog.csdn.net/jesse_mx/article/details/65634482
這裡寫圖片描述
該資料集的標註一共分為8個類別:’Car’, ’Van’, ’Truck’, ’Pedestrian’, ’Person (sit- ting)’, ’Cyclist’, ’DontCare’ 和’Misc’
在程式碼中合併’Car’, ’Van’, ’Truck’為’Car’,合併 ’Pedestrian’, ’Person (sit- ting)’為’Pedestrian’。
最後實際執行還有三個分類:’Pedestrian’、 ’Person (sit- ting)’、’Pedestrian’。
這裡主要使用:TYPE和BBOX兩個引數
處理程式碼如下:

import glob
### 獲取標註資料
lable_list = glob.glob('data_object_label_2/training/label_2/*')
label_result=[]
type_list=[]
for label in label_list:
    ### box合併資料
    bbox=[]
    with open(label) as r_label:
        for each_line in r_label:
            labeldata = each_line.strip().split(' ')
            if
labeldata[0] in ['Truck','Van','Tram']: # 合併汽車類 labeldata[0] = labeldata[0].replace(labeldata[0],'Car') if labeldata[0] == 'Person_sitting': # 合併行人類 labeldata[0] = labeldata[0].replace(labeldata[0],'Pedestrian') if labeldata[0] == 'DontCare': # 忽略Dontcare類 continue if labeldata[0] == 'Misc': # 忽略Misc類 continue if labeldata[0] not in type_list: type_list.append(labeldata[0]) ### 提取分類標籤和BOX座標,YOLOV3的座標是整數,需要資料轉型。 bbox_item=[type_list.index(labeldata[0]),int(float(labeldata[4])),int(float(labeldata[5])),int(float(labeldata[6])), int(float(labeldata[7]))] bbox.append(bbox_item) ### 目標圖片路徑 imgfilename="data_object_image_2/testing/image_2/"+label[37:44]+"png" strline=imgfilename for box in bbox: ### 將BOX按照約定格式記入檔案中。 strbox=" "+str(box[1])+","+str(box[2])+","+str(box[3])+","+str(box[4])+","+str(box[0]) strline=strline+strbox label_result.append(strline) try: ### 專案預設資料名為train.txt outputfilename="train.txt" with open(outputfilename,'w+') as w_output: # w+是開啟原檔案將內容刪除,另寫新內容進去 for line in label_result: w_output.write(line+"\n") except IOError as ioerr: print('File error:'+str(ioerr))

訓練相關程式碼修改

annotation_path = 'train.txt'
log_dir = 'logs/000/'
classes_path = 'model_data/voc_classes.txt'
anchors_path = 'model_data/yolo_anchors.txt'

需要修改voc_classes.txt,保證分類與我們的模型一致。

按照GITHUB上的流程進行操作。

Make sure you have run python convert.py -w yolov3.cfg yolov3.weights model_data/yolo_weights.h5
The file model_data/yolo_weights.h5 is used to load pretrained weights.

Modify train.py and start training.
python train.py
Use your trained weights or checkpoint weights in yolo.py.
Remember to modify class path or anchor path.

最後得到訓練後的模型。

定製修改

本來以為簡單到爆表的操作,實際過程中發現有些地方需要修改。必須改的:

    # train.py
    # 訓練資料標註
    annotation_path = 'train.txt'
    log_dir = 'logs/000/'
    # 訓練分類
    classes_path = 'model_data/voc_classes.txt'
    anchors_path = 'model_data/yolo_anchors.txt'
    #yolo.py
    # 訓練後的模型
    self.model_path = 'model_data/trained_weights_final.h5' # model path or trained weights path
    # 訓練分類
    self.anchors_path = 'model_data/yolo_anchors.txt'
    self.classes_path = 'model_data/voc_classes.txt'

預訓練模型修改

這裡寫圖片描述
看一下網路框架,主要區別在於最右下角的CONVS層,YOLOV3官網提供的預訓練模型是基於COCO 80分類的,而本文的框架只有3個分類,那麼在預載入模型的時候就需要進行修改。
(ps:你也可以不改,這三層就直接重新訓練。不過使用修改後預訓練模型收斂更快)
注意:如果你修改最後三層filters,而convert.py不對應修改,整個預訓練模型載入都會是錯誤的

本開源框架是使用了CONVERT.PY檔案進行weights轉化。
通過讀取yolov3.cfg檔案,按位元組順序讀取。有需要的可以瞭解一下configparser,我個人只是大概看了一下。
讀取預載入模型的需要按照80分類來讀取預載入模型,但是寫入模型的時候需要按照3分類的方式寫入。
硬編碼了一下,filters等於255的時候,進行強制轉化。。。
有需要的可以參考我提交的GITHUB:
https://github.com/yangchengtest/keras-yolov3-kitti.git

剩下的就和原來一樣了,可以直接訓練了。
LR使用了
reduce_lr = ReduceLROnPlateau(monitor=’val_loss’, factor=0.1, patience=3, verbose=1)
可以關注一下。

最後修改YOLO.PY的配置檔案,就可以看到結果了。

圖片批量處理

原來的介面,圖片一張一張看,我嫌煩。
改了一下,支援多圖片批量處理。
python yolo.py -s test_images -d output_images

視訊寫入有問題

需要在CV讀取完成後釋放資源:
return_value, frame = vid.read()
if not return_value:
break