1. 程式人生 > >利用faster rcnn 訓練自己的資料集——kitti資料集

利用faster rcnn 訓練自己的資料集——kitti資料集

前言:

非常感謝https://blog.csdn.net/flztiii/article/details/73881954,這篇部落格,本文主要參考這篇文章

kitti資料集是一個車輛檢測的資料集

資料集的準備

Kitti資料集的下載只需要第一個圖片集(12G)和標註檔案即可【第一個檔案,以及標註檔案】。由於faster-rcnn使用的是VOC格式的資料集,所以我們要將kitti資料集的格式改成VOC的格式。這裡我先簡單說明一下VOC資料集的格式,便於大家對於轉換程式的理解。
以VOC2007為例,其中包含了3個資料夾:1.JPEGImages是用來存放所有的訓練圖片的2.ImageSets中有多個子資料夾(Main,Layout,Segmentation),由於我只關心detection的任務(VOC資料集還可以用來做其他任務),所以我只需要考慮其中的Main資料夾,Main資料夾中的內容是一些txt檔案,是用來標明訓練的時候的train資料集和val資料集。3.Annotation是用來存放xml檔案的,其中xml檔案中包含了相對應的bounding box的位置資訊,以及種類。xml檔案的內容如下:
  1. <?
    xmlversion="1.0"?>
  2. <annotation>
  3.     <folder>VOC2007</folder>                    //資料夾  
  4.     <filename>000012.jpg</filename>                 //xml檔案對應的圖片的名稱  
  5.     <source>
  6.         <database>The VOC2007 Database</database>
  7.         <annotation>PASCAL VOC2007</annotation
    >
  8.     </source>
  9.     <size>                                //圖片大小資訊1242x375  
  10.         <width>1242</width>
  11.         <height>375</height>
  12.         <depth>3</depth>
  13.     </size>
  14.     <object>                          //圖片中標註的物體  
  15.         <name>car</name>
                        //標註的物體類別  
  16.         <difficult>0</difficult>
  17.         <bndbox>                      //標註物體的bounding box  
  18.         <xmin>662</xmin>
  19.         <ymin>185</ymin>
  20.         <xmax>690</xmax>
  21.         <ymax>205</ymax>
  22.         </bndbox>
  23.         </object>
  24.     <object>
  25.         <name>car</name>
  26.         <difficult>0</difficult>
  27.         <bndbox>
  28.         <xmin>448</xmin>
  29.         <ymin>177</ymin>
  30.         <xmax>481</xmax>
  31.         <ymax>206</ymax>
  32.         </bndbox>
  33.     </object>
  34. </annotation>
現在我們來看一下kitti資料集的格式,我們下載的kitti資料集分為兩個壓縮檔案,其中一個是image裡面全是交通場景圖,另一個是label裡面是關於標註資訊的txt檔案。txt檔案內容如下:
  1. car 0.00 0 -1.57 599.41 156.40 629.75 189.25 2.85 2.63 12.34 0.47 1.49 69.44 -1.56  
  2. car 0.00 0 1.85 387.63 181.54 423.81 203.12 1.67 1.87 3.69 -16.53 2.39 58.49 1.57  
  3. pedestrian 0.00 3 -1.65 676.60 163.95 688.98 193.93 1.86 0.60 2.02 4.59 1.32 45.84 -1.55  
每一行就是一個object,最前方是類別資訊,後面是bounding box資訊。


瞭解了兩類資料集的格式之後,讓我們來看看如何將kitti資料集轉化為VOC資料集吧:首先由於kitti使用的是png圖片,而VOC使用的是jpg檔案,我們使用格式工廠將png圖片轉化為jpg格式,之後將jpg圖片放入JPEGImages資料夾(自己建立)。===================================================================下一步,由於我只需要汽車類car和行人類pedesreian,於是我將kitti中的卡車等其他類別進行了合併程式碼如下modify_annotations_txt.py
#!/usr/bin/env python  
# -*- coding: UTF-8 -*-  

# modify_annotations_txt.py  
import glob  
import string  
"""
將本程式和kitti的Labels放在同一目錄下執行,可以將Labels中的類別合併為只剩下car類和pedestrian類(這裡我使用小寫是防止faster-rcnn訓練報錯)。之後要把txt檔案轉化為xml檔案,在相同目錄下建立資料夾Annotations
"""

txt_list = glob.glob('./label_2/*.txt') # 儲存Labels資料夾所有txt檔案路徑  
def show_category(txt_list):  
	category_list= []  
	for item in txt_list:  
	    try:  
		with open(item) as tdf:  
		    for each_line in tdf:  
		        labeldata = each_line.strip().split(' ') # 去掉前後多餘的字元並把其分開  
		        category_list.append(labeldata[0]) # 只要第一個欄位,即類別  
	    except IOError as ioerr:  
		print('File error:'+str(ioerr))  
	print(set(category_list)) # 輸出集合  

def merge(line):  
	each_line=''  
	for i in range(len(line)):  
	    if i!= (len(line)-1):  
		each_line=each_line+line[i]+' '  
	    else:  
		each_line=each_line+line[i] # 最後一條欄位後面不加空格  
	each_line=each_line+'\n'  
	return (each_line)  

print('before modify categories are:\n')  
show_category(txt_list)  

for item in txt_list:  
	new_txt=[]  
	try:  
	    with open(item, 'r') as r_tdf:  
		for each_line in r_tdf:  
		    labeldata = each_line.strip().split(' ')  
		    if labeldata[0] in ['Truck','Van','Tram','Car']: # 合併汽車類  
		        labeldata[0] = labeldata[0].replace(labeldata[0],'car')  
		    if labeldata[0] in ['Person_sitting','Cyclist','Pedestrian']: # 合併行人類  
		        labeldata[0] = labeldata[0].replace(labeldata[0],'pedestrian')  
		    if labeldata[0] == 'DontCare': # 忽略Dontcare類  
		        continue  
		    if labeldata[0] == 'Misc': # 忽略Misc類  
		        continue  
		    new_txt.append(merge(labeldata)) # 重新寫入新的txt檔案  
	    with open(item,'w+') as w_tdf: # w+是開啟原檔案將內容刪除,另寫新內容進去  
		for temp in new_txt:  
		    w_tdf.write(temp)  
	except IOError as ioerr:  
	    print('File error:'+str(ioerr))  

print('\nafter modify categories are:\n')  
show_category(txt_list)  

將本程式和kitti的Labels放在同一目錄下執行,可以將Labels中的類別合併為只剩下car類和pedestrian類(這裡我使用小寫是防止faster-rcnn訓練報錯)。

===================================================================

之後要把txt檔案轉化為xml檔案,在相同目錄下建立資料夾Annotations。執行檔案程式碼如下:

txt_to_xml.py

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# txt_to_xml.py
# 根據一個給定的XML Schema,使用DOM樹的形式從空白檔案生成一個XML
from xml.dom.minidom import Document
import cv2
import os


def generate_xml(name, split_lines, img_size, class_ind):
    doc = Document()  # 建立DOM文件物件

    annotation = doc.createElement('annotation')
    doc.appendChild(annotation)

    title = doc.createElement('folder')
    title_text = doc.createTextNode('VOC2007')  # 這裡修改了資料夾名
    title.appendChild(title_text)
    annotation.appendChild(title)

    img_name = name + '.jpg'  # 要用jpg格式

    title = doc.createElement('filename')
    title_text = doc.createTextNode(img_name)
    title.appendChild(title_text)
    annotation.appendChild(title)

    source = doc.createElement('source')
    annotation.appendChild(source)

    title = doc.createElement('database')
    title_text = doc.createTextNode('The VOC2007 Database')  # 修改為VOC
    title.appendChild(title_text)
    source.appendChild(title)

    title = doc.createElement('annotation')
    title_text = doc.createTextNode('PASCAL VOC2007')  # 修改為VOC
    title.appendChild(title_text)
    source.appendChild(title)

    size = doc.createElement('size')
    annotation.appendChild(size)

    title = doc.createElement('width')
    title_text = doc.createTextNode(str(img_size[1]))
    title.appendChild(title_text)
    size.appendChild(title)

    title = doc.createElement('height')
    title_text = doc.createTextNode(str(img_size[0]))
    title.appendChild(title_text)
    size.appendChild(title)

    title = doc.createElement('depth')
    title_text = doc.createTextNode(str(img_size[2]))
    title.appendChild(title_text)
    size.appendChild(title)

    for split_line in split_lines:
        line = split_line.strip().split()
        if line[0] in class_ind:
            object = doc.createElement('object')
            annotation.appendChild(object)

            title = doc.createElement('name')
            title_text = doc.createTextNode(line[0])
            title.appendChild(title_text)
            object.appendChild(title)

        title = doc.createElement('difficult')
        title_text = doc.createTextNode('0')
        title.appendChild(title_text)
        object.appendChild(title)

        bndbox = doc.createElement('bndbox')
        object.appendChild(bndbox)
        title = doc.createElement('xmin')
        title_text = doc.createTextNode(str(int(float(line[4]))))
        title.appendChild(title_text)
        bndbox.appendChild(title)
        title = doc.createElement('ymin')
        title_text = doc.createTextNode(str(int(float(line[5]))))
        title.appendChild(title_text)
        bndbox.appendChild(title)
        title = doc.createElement('xmax')
        title_text = doc.createTextNode(str(int(float(line[6]))))
        title.appendChild(title_text)
        bndbox.appendChild(title)
        title = doc.createElement('ymax')
        title_text = doc.createTextNode(str(int(float(line[7]))))
        title.appendChild(title_text)
        bndbox.appendChild(title)

        # 將DOM物件doc寫入檔案


        f = open('Annotations/' + name + '.xml', 'w')
        f.write(doc.toprettyxml(indent=''))
        f.close()

if __name__ == '__main__':
    class_ind = ('pedestrian', 'car')  # 修改為了兩類
    cur_dir = os.getcwd()
    labels_dir = os.path.join(cur_dir, 'label_2')
    for parent, dirnames, filenames in os.walk(labels_dir):  # 分別得到根目錄,子目錄和根目錄下檔案
        for file_name in filenames:
            full_path = os.path.join(parent, file_name)  # 獲取檔案全路徑
            # print full_path
            f = open(full_path)
            split_lines = f.readlines()
            name = file_name[:-4]  # 後四位是副檔名.txt,只取前面的檔名
            # print name
            img_name = name + '.jpg'
            img_path = os.path.join('/home/xuy/桌面/training/JPEGImages',
                                    img_name)  # 路徑需要自行修改
            # print img_path
            img_size = cv2.imread(img_path).shape
            generate_xml(name, split_lines, img_size, class_ind)
print('all txts has converted into xmls')
print('all txts has converted into xmls')

將程式放在Labels同一級目錄下執行,則可以在Annotations資料夾下生成xml檔案

=================================================================

之後在同級目錄下建立Imagesets資料夾,在資料夾中建立Main,Layout,Segmentation子資料夾。執行檔案程式碼如下(用python3執行。t執行程式過程中,如遇到pdb提示,可按c鍵,再按enter鍵)

from __future__ import print_function
# -*- coding:utf-8 -*-
__author__ = 'xuy'
"""
在python3的環境下執行
"""

import pdb
import glob
import os
import random
import math


def get_sample_value(txt_name, category_name):
    label_path = './label_2/'
    txt_path = label_path + txt_name+'.txt'
    try:
        with open(txt_path) as r_tdf:
            if category_name in r_tdf.read():
                return ' 1'
            else:
                return '-1'
    except IOError as ioerr:
        print('File error:'+str(ioerr))

txt_list_path = glob.glob('./label_2/*.txt')
txt_list = []

for item in txt_list_path:
	#temp1返回檔名,temp2返回字尾名
    temp1,temp2 = os.path.splitext(os.path.basename(item))
    txt_list.append(temp1)
txt_list.sort()
print(txt_list, end = '\n\n')

# 有部落格建議train:val:test=8:1:1,先嚐試用一下
num_trainval = random.sample(txt_list, math.floor(len(txt_list)*9/10.0)) # 可修改百分比
num_trainval.sort()
print(num_trainval, end = '\n\n')

num_train = random.sample(num_trainval,math.floor(len(num_trainval)*8/9.0)) # 可修改百分比
num_train.sort()
print(num_train, end = '\n\n')

num_val = list(set(num_trainval).difference(set(num_train)))
num_val.sort()
print(num_val, end = '\n\n')

num_test = list(set(txt_list).difference(set(num_trainval)))
num_test.sort()
print(num_test, end = '\n\n')

pdb.set_trace()

Main_path = './ImageSets/Main/'
train_test_name = ['trainval','train','val','test']
category_name = ['Car','Pedestrian']#修改類別

# 迴圈寫trainvl train val test
for item_train_test_name in train_test_name:
    list_name = 'num_'
    list_name += item_train_test_name
    train_test_txt_name = Main_path + item_train_test_name + '.txt'
    try:
        # 寫單個檔案,train.txt,trainval.txt,val.txt,test.txt這四個檔案
        with open(train_test_txt_name, 'w') as w_tdf:
            # 一行一行寫
            for item in eval(list_name):
                w_tdf.write(item+'\n')
        # 迴圈寫Car Pedestrian Cyclist
        for item_category_name in category_name:
            category_txt_name = Main_path + item_category_name + '_' + item_train_test_name + '.txt'
            with open(category_txt_name, 'w') as w_tdf:
                # 一行一行寫
                for item in eval(list_name):
                    w_tdf.write(item+' '+ get_sample_value(item, item_category_name)+'\n')
    except IOError as ioerr:
        print('File error:'+str(ioerr))

產生檔案如下圖所示:


在Labels同級目錄下執行檔案,生成Main中的txt檔案。至此,資料集的準備結束,我們將準備好的Annotations,JPEGImages,ImageSets資料夾放到如下目錄下

python-faster-rcnn/data/VOCdevkit2007/VOC2007

檔案結構如下圖所示:


Faster-rcnn訓練

先簡要介紹一下faster-rcnn的工程目錄吧:caffe-fast-rcnn —> caffe框架
data —> 存放資料,以及讀取檔案的cache
experiments —>存放配置檔案以及執行的log檔案,配置檔案
lib —> python介面
models —> 三種模型, ZF(S)/VGG1024(M)/VGG16(L)
output —> 輸出的model存放的位置,不訓練此資料夾沒有
tools —> 訓練和測試的python檔案
faster-rcnn有兩種訓練方法: Alternative training(alt-opt)和Approximate joint training(end-to-end),這裡我使用的是apt-opt的訓練方法,使用到的是tools/train_faster_rcnn_alt_opt.py,感興趣的可以看一下其的程式碼,這裡我就不多說了。我使用的網路是VGG16,相比於ZF,VGG16可以達到更高的準確性。當然,直接進行訓練是不可能的,我們要修改faster-rcnn的網路結構以適應我們car和pedestrian兩類的情況,要修改的網路部分如下:1./py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage1_fast_rcnn_train.pt檔案第14行
  1. name: "VGG_ILSVRC_16_layers"  
  2. layer {  
  3.   name: 'data'  
  4.   type: 'Python'  
  5.   top: 'data'  
  6.   top: 'rois'  
  7.   top: 'labels'  
  8.   top: 'bbox_targets'  
  9.   top: 'bbox_inside_weights'  
  10.   top: 'bbox_outside_weights'  
  11.   python_param {  
  12.     module: 'roi_data_layer.layer'  
  13.     layer: 'RoIDataLayer'  
  14.     param_str: "'num_classes': 3" #此處修改類別  
  15.   }  
  16. }  
第428和第451行
  1. layer {  
  2.   name: "cls_score"  
  3.   type: "InnerProduct"  
  4.   bottom: "fc7"  
  5.   top: "cls_score"  
  6.   param {  
  7.     lr_mult: 1  
  8.   }  
  9.   param {  
  10.     lr_mult: 2  
  11.   }  
  12.   inner_product_param {  
  13.     num_output: 3 #此處修改類別  
  14.     weight_filler {  
  15.       type: "gaussian"  
  16.       std: 0.01  
  17.     }  
  18.     bias_filler {  
  19.       type: "constant"  
  20.       value: 0  
  21.     }  
  22.   }  
  23. }  
  24. layer {  
  25.   name: "bbox_pred"  
  26.   type: "InnerProduct"  
  27.   bottom: "fc7"  
  28.   top: "bbox_pred"  
  29.   param {  
  30.     lr_mult: 1  
  31.   }  
  32.   param {  
  33.     lr_mult: 2  
  34.   }  
  35.   inner_product_param {  
  36.     num_output: 12 #此處修改類別  
  37.     weight_filler {  
  38.       type: "gaussian"  
  39.       std: 0.001  
  40.     }  
  41.     bias_filler {  
  42.       type: "constant"  
  43.       value: 0  
  44.     }  
  45.   }  
  46. }  

2./py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage1_rpn_train.pt檔案
第11行
  1. name: "VGG_ILSVRC_16_layers"  
  2. layer {  
  3.   name: 'input-data'  
  4.   type: 'Python'  
  5.   top: 'data'  
  6.   top: 'im_info'  
  7.   top: 'gt_boxes'  
  8.   python_param {  
  9.     module: 'roi_data_layer.layer'  
  10.     layer: 'RoIDataLayer'  
  11.     param_str: "'num_classes': 3" #此處修改類別  
  12.   }  
  13. }  
3./py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage2_fast_rcnn_train.pt檔案
第14行
  1. name: "VGG_ILSVRC_16_layers"  
  2. layer {  
  3.   name: 'data'  
  4.   type: 'Python'  
  5.   top: 'data'  
  6.   top: 'rois'  
  7.   top: 'labels'  
  8.   top: 'bbox_targets'  
  9.   top: 'bbox_inside_weights'  
  10.   top: 'bbox_outside_weights'  
  11.   python_param {  
  12.     module: 'roi_data_layer.layer'  
  13.     layer: 'RoIDataLayer'  
  14.     param_str: "'num_classes': 3" #此處修改類別  
  15.   }  
  16. }  
第380和第399行
  1. layer {  
  2.   name: "cls_score"  
  3.   type: "InnerProduct"  
  4.   bottom: "fc7"  
  5.   top: "cls_score"  
  6.   param { lr_mult: 1 }  
  7.   param { lr_mult: 2 }  
  8.   inner_product_param {  
  9.     num_output: 3 #此處修改類別  
  10.     weight_filler {  
  11.       type: "gaussian"  
  12.       std: 0.01  
  13.     }  
  14.     bias_filler {  
  15.       type: "constant"  
  16.       value: 0  
  17.     }  
  18.   }  
  19. }  
  20. layer {  
  21.   name: "bbox_pred"  
  22.   type: "InnerProduct"  
  23.   bottom: "fc7"  
  24.   top: "bbox_pred"  
  25.   param { lr_mult: 1 }  
  26.   param { lr_mult: 2 }  
  27.   inner_product_param {  
  28.     num_output: 12 #此處修改類別  
  29.     weight_filler {  
  30.       type: "gaussian"  
  31.       std: 0.001  
  32.     }  
  33.     bias_filler {  
  34.       type: "constant"  
  35.       value: 0  
  36.     }  
  37.   }  
  38. }  
4./py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage2_rpn_train.pt檔案
第11行
  1. name: "VGG_ILSVRC_16_layers"  
  2. layer {  
  3.   name: 'input-data'  
  4.   type: 'Python'  
  5.   top: 'data'  
  6.   top: 'im_info'  
  7.   top: 'gt_boxes'  
  8.   python_param {  
  9.     module: 'roi_data_layer.layer'  
  10.     layer: 'RoIDataLayer'  
  11.     param_str: "'num_classes': 3"    
  12.   }  
  13. }  
自此網路結構修改結束。但是為了防止訓練結果不收斂(其實是由於後面進行訓練的時候卡在階段一),我們要將訓練的學習率調小,調整到0.0001。(試驗後得到的引數值)需要調整的檔案是/py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt目錄下的所有的solver檔案的
  1. base_lr: 0.0001  

之後執行/py-fater-rcnn/data/scripts/fetch_imagenet_model.sh,得到imagenet的caffemodel檔案,因為rpn網路的訓練是以imagenet為初始值進行訓練的。再之後修改py-faster-rcnn/lib/datasets/pascal_voc.py檔案的31行,修改為自己的類別,如下:
  1. self._classes = ('__background__'# always index 0
  2.                  'car''pedestrian')  

修改py-faster-rcnn/lib/dataset/imdb.py檔案,修改102行的append_flipped_images函式為:
  1. def append_flipped_images(self):  
  2.     num_images = self.num_images  
  3.     widths = [PIL.Image.open(self.image_path_at(i)).size[0]    
  4.               for i in xrange(num_images)]   
  5.     for i in xrange(num_images):  
  6.         boxes = self.roidb[i]['boxes'].copy()  
  7.         oldx1 = boxes[:, 0].copy()  
  8.         oldx2 = boxes[:, 2].copy()  
  9.         boxes[:, 0] = widths[i] - oldx2 - 1
  10.         boxes[:, 2] = widths[i] - oldx1 - 1
  11.         assert (boxes[:, 2] >= boxes[:, 0]).all()  
  12.         entry = {'boxes' : boxes,  
  13.                  'gt_overlaps' : self.roidb[i]['gt_overlaps'],  
  14.                  'gt_classes' : self.roidb[i]['gt_classes'],  
  15.                  'flipped' : True}  
  16.         self.roidb.append(entry)  
  17.     self._image_index = self._image_index * 2


自此程式碼修改結束,不過如果不想排錯的話,建議先再看本文的排錯部分,修改其他程式碼再進行訓練。
接來下先介紹一下如何修改訓練超引數(學習率已經在前面改過了,就不再說了),大多數超引數都是在/py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt目錄下的所有的solver檔案中進行改動的。只有訓練次數不同,訓練次數是在/py-faster-rcnn/tools/train_faster_rcnn_alt_opt.py中進行修改的:第80行
  1. max_iters = [1200008000012000080000]  
分別對應rpn第1階段,fast rcnn第1階段,rpn第2階段,fast rcnn第2階段的迭代次數,不過注意這裡的值不能小於上面的solver裡面的step_size的大小。在這裡我建議大家先把訓練次數調小兩個數量集,這樣排除錯誤的時候就不會等太長時間了。
接下來就是在py-faster-rcnn目錄下開啟終端,執行下列命令:
  1. ./experiments/scripts/faster_rcnn_alt_opt.sh 0 VGG16 pascal_voc   
開始訓練,如果在py-faster-rcnn資料夾下出現output資料夾,output資料夾下有final caffemodel則表明訓練成功。

訓練中遇到了錯誤及問題

下面是我在訓練的過程中所遇到的一些問題以及解決的方法,希望對大家有所幫助。問題一:rpn階段一訓練結束後不開始fast-rcnn階段一的訓練這個問題是因為學習率過大的原因,調小學習率可以解決問題二:pb2.text_format.Merge(f.read(), self.solver_param) AttributeError: 'module' object has no attribute 'text_format'這個問題是因為protobuf的版本不對,解決方法是pip install protobuf==2.6.0問題三:訓練faster rcnn時出現如下報錯:
File "/py-faster-rcnn/tools/../lib/datasets/imdb.py", line 108, in append_flipped_images
    assert (boxes[:, 2] >= boxes[:, 0]).all()
AssertionError

這個問題是由於faster rcnn會對Xmin,Ymin,Xmax,Ymax進行減一操作如果Xmin為0,減一後變為65535

解決方法如下

改/py-faster-rcnn/lib/fast_rcnn/config.py的61行,不使圖片實現翻轉,如下改為:
# Use horizontally-flipped images during training?
__C.TRAIN.USE_FLIPPED = False

問題四:

TypeError: ‘numpy.float64’ object cannot be interpreted as an index

這個錯誤是/py-faster-rcnn/lib/roi_data_layer下的minibatch.py中的npr.choice引起的(98行到116行),所以需要改成如下所示

  1. if fg_inds.size > 0:  
  2.     for i in range(0,len(fg_inds)):  
  3.         fg_inds[i] = int(fg_inds[i])  
  4.     fg_inds = npr.choice(fg_inds, size=int(fg_rois_per_this_image), replace=False)  
  5. # Select background RoIs as those within [BG_THRESH_LO, BG_THRESH_HI)
  6. bg_inds = np.where((overlaps < cfg.TRAIN.BG_THRESH_HI) &  
  7.                    (overlaps >= cfg.TRAIN.BG_THRESH_LO))[0]  
  8. # Compute number of background RoIs to take from this image (guarding
  9. # against there being fewer than desired)
  10. bg_rois_per_this_image = rois_per_image - fg_rois_per_this_image  
  11. bg_rois_per_this_image = np.minimum(bg_rois_per_this_image,  
  12.                                     bg_inds.size)  
  13. # Sample foreground regions without replacement
  14. if bg_inds.size > 0:  
  15.     for i in range(0,len(bg_inds)):  
  16.         bg_inds[i] = int(bg_inds[i])  
  17.     bg_inds = npr.choice(bg_inds, size=int(bg_rois_per_this_image), replace=False)  
注意有兩個npr.choice,所以兩個地方都按照如上來改。

問題五:

labels[fg_rois_per_this_image:] = 0
TypeError: slice indices must be integers or None or have an index method

這個錯誤是由numpy的版本引起的,只要將fg_rois_per_this_image強制轉換為int型就可以了
labels[int(fg_rois_per_this_image):] = 0

問題六:bbox_targets[ind, start:end] = bbox_target_data[ind, 1:]
TypeError: slice indices must be integers or None or have an __index__ method

解決方法:修改/py-faster-rcnn/lib/rpn/proposal_target_layer.py,轉到123行

for ind in inds:
        cls = clss[ind]
        start = 4 * cls
        end = start + 4
        bbox_targets[ind, start:end] = bbox_target_data[ind, 1:]
        bbox_inside_weights[ind, start:end] = cfg.TRAIN.BBOX_INSIDE_WEIGHTS
    return bbox_targets, bbox_inside_weights
這裡的ind,start,end都是 numpy.int 型別,這種型別的資料不能作為索引,所以必須對其進行強制型別轉換,轉化結果如下:

  1. for ind in inds:  
  2.     ind = int(ind)  
  3.     cls = clss[ind]  
  4.     start = int(4 * cls)  
  5.     end = int(start + 4)  
  6.     bbox_targets[ind, start:end] = bbox_target_data[ind, 1:]  
  7.     bbox_inside_weights[ind, start:end] = cfg.TRAIN.BBOX_INSIDE_WEIGHTS  
  8. return bbox_targets, bbox_inside_weights  

問題七:

/home/iair339-04/py-faster-rcnn/tools/../lib/rpn/proposal_layer.py:175: RuntimeWarning: invalid value encountered in greater_equal
  keep = np.where((ws >= min_size) & (hs >= min_size))[0]

解決方法

修改/py-faster-rcnn/lib/datasets/pascal_voc.py第204-207行,修改結果如下:

  1. x1 = float(bbox.find('xmin').text)  
  2. y1 = float(bbox.find('ymin').text)  
  3. x2 = float(bbox.find('xmax').text)   
  4. y2 = float(bbox.find('ymax').text) 

問題八:

mini_batch.py檔案當中

仍然是numpy的版本問題,1.11.0以上的版本不支援非整數索引,需要修改為如下程式碼:

    for ind in inds:
        ind=int(ind)
        cls = clss[ind]
        start = int(4 * cls)
        end = int(start + 4)
        bbox_targets[ind, start:end] = bbox_target_data[ind, 1:]
        bbox_inside_weights[ind, start:end] = cfg.TRAIN.BBOX_INSIDE_WEIGHTS

問題九:

由於製作的xml檔案沒有pose,以及truncated屬性,因此在測試階段會報錯,顯示pose和truncated為空置

因此,在voc_eval.py檔案當中註釋掉這兩個屬性

def parse_rec(filename):
    """ Parse a PASCAL VOC xml file """
    tree = ET.parse(filename)
    objects = []
    for obj in tree.findall('object'):
        obj_struct = {}
        obj_struct['name'] = obj.find('name').text
        # obj_struct['pose'] = obj.find('pose').text
        # obj_struct['truncated'] = int(obj.find('truncated').text)
        obj_struct['difficult'] = int(obj.find('difficult').text)
        bbox = obj.find('bndbox')
        obj_struct['bbox'] = [int(bbox.find('xmin').text),
                              int(bbox.find('ymin').text),
                              int(bbox.find('xmax').text),
                              int(bbox.find('ymax').text)]
        objects.append(obj_struct)

    return objects

Faster rcnn測試

接下來是測試部分的程式碼修改,我使用的tools裡的demo.py進行修改來實現模型的測試。首先我們要修改測試的模型檔案

/py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/faster_rcnn_test.pt檔案

第392和第401行

  1. layer {  
  2.   name: "cls_score"  
  3.   type: "InnerProduct"  
  4.   bottom: "fc7"  
  5.   top: "cls_score"  
  6.   inner_product_param {  
  7.     num_output: 3 #修改類別數  
  8.   }  
  9. }  
  10. layer {  
  11.   name: "bbox_pred"  
  12.   type: "InnerProduct"  
  13.   bottom: "fc7"  
  14.   top: "bbox_pred"  
  15.   inner_product_param {  
  16.     num_output: 12 #修改類別數  
  17.   }  
  18. }  
接下來將訓練好的final caffemodel放到/py-faster-rcnn/data/faster_rcnn_models目錄下,並且把待測試圖片放到/py-faster-rcnn/data/demo目錄下。修改/py-faster-rcnn/tools/demo.py檔案,修改如下:

第27行修改類別

  1. CLASSES = ('__background__',  
  2.            'car''pedestrian'#此處修改類別

第31行修改模型名稱為final caffemodel名稱
  1. NETS = {'vgg16': ('VGG16',  
  2.                   'kitti4.caffemodel'),#修改model名字
  3.         'zf': ('ZF',  
  4.                   'ZF_faster_rcnn_final.caffemodel')}  

第141行修改測試圖片名稱
  1.   im_names = ['1348.png','1562.png','4714.png','5509.png','5512.png','5861.png','12576.png','12924.png',  
  2. '22622.png','23873.png','2726.png','3173.png','8125.png','8853.png','9283.png','11714.png','24424.png',  
  3. '25201.png','25853.png','27651.png']  

之後執行demo.py便可以進行測試,在此我並沒有把行人檢測和車輛檢測合併到同一個圖片上,感興趣的可以自己去網上搜索相關資料。

後記:

1.利用中間階段生成的pkl輸出多個框

參考https://blog.csdn.net/majinlei121/article/details/78903537

在訓練和測試模型的時候,會產生pkl檔案,用來記錄訓練的中間過程

pkl檔案包含了多個框,也就是在nms之前的結果,nms將這些框進行非極大值抑制,最終獲取了一個框

以車輛檢測的pkl為例,py-faster-rcnn/output/faster_rcnn_alt_opt/voc_2007_test/VGG16_faster_rcnn_final/car_pr.pkl

在該路徑下新建一個pkl資料夾/results資料夾

# -*- coding:utf-8 -*-

import os
import os.path
import numpy as np
import xml.etree.ElementTree as xmlET
from PIL import Image, ImageDraw
import cPickle as pickle 

f = open('car_pr.pkl')  
ship_pr = pickle.load(f) 

test_file='/home/xuy/py-faster-rcnn/data/VOCdevkit2007/VOC2007/ImageSets/Main/test.txt'
file_path_img = '/home/xuy/py-faster-rcnn/data/VOCdevkit2007/VOC2007/JPEGImages'
save_file_path = 'pkl/results'

with open(test_file) as f:
    image_index = [x.strip() for x in f.readlines()]


f = open('detections.pkl')  
info = pickle.load(f)
dets = info[1]


num = 0
for idx in xrange(len(dets)):
    if len(dets[idx]) == 0:
        continue
    img = Image.open(os.path.join(file_path_img, image_index[idx] + '.jpg')) 
    draw = ImageDraw.Draw(img)
    for i in xrange(len(dets[idx])):
        box = dets[idx][i]
        draw.rectangle([int(np.round(float(box[0]))), int(np.round(float(box[1]))), 
                    int(np.round(float(box[2]))), int(np.round(float(box[3])))], outline=(255, 0, 0))
    img.save(os.path.join(save_file_path, image_index[idx] + '.jpg'))  

結果生成了所有測試集的候選框矩形框

2.基於攝像頭的實時監測

參考連結:https://blog.csdn.net/weixin_36441117/article/details/77127014?locationNum=5&fps=1

撰寫Python測試程式
  1. # -*- coding:utf-8 -*-
  2. # 用於模型的單張影象分類操作
  3. import os  
  4. os.environ['GLOG_minloglevel'] = '2'# 將caffe的輸出log資訊不顯示,必須放到import caffe前
  5. import caffe # caffe 模組
  6. from caffe.proto import caffe_pb2  
  7. from google.protobuf import text_format  
  8. import numpy as np  
  9. import cv2  
  10. import matplotlib.pyplot as plt  
  11. import time  
  12. import skimage.io  
  13. global num  
  14. num = 0
  15. def detect(image1,net):  
  16.     # 傳進來的image1的dtype為uint8
  17.     # print image1.shape
  18.     # print image1.dtype
  19.     # print image1.size
  20.     # image = np.array(image1, dtype=np.float32)
  21.     # image = caffe.io.resize_image(image1, (480, 640))
  22.     image = skimage.img_as_float(image1).astype(np.float32)  
  23.     # image = caffe.io.resize_image(image2, (300, 300))
  24. 相關推薦

    利用faster rcnn 訓練自己資料——kitti資料

    前言:非常感謝https://blog.csdn.net/flztiii/article/details/73881954,這篇部落格,本文主要參考這篇文章kitti資料集是一個車輛檢測的資料集資料集的準備Kitti資料集的下載只需要第一個圖片集(12G)和標註檔案即可【第一

    使用pytorch版faster-rcnn訓練自己資料

    使用pytorch版faster-rcnn訓練自己資料集 引言 faster-rcnn pytorch程式碼下載 訓練自己資料集 接下來工作 參考文獻 引言 最近在復現目標檢測程式碼(師兄強烈推薦F

    Faster RCNN訓練自己資料

    Faster RCNN(py caffe)工程各個目錄的作用: caffe-fast-rcnn:caffe框架目錄; data:用來存放pretrained(預訓練)模型以及讀取檔案的cache快取,還有一些下載模型的指令碼; experiments:存放配置

    Caffe學習系列——Faster-RCNN訓練自己資料

    由於要實現服裝的目標檢測,所以一直在研究Faster-RCNN 。講到目標檢測,不得不提到rbg大神的深度神經網路檢測算法系列RCNN、Fast-RCNN、Faster-RCNN,其還在github上開源了自己的程式碼,造福廣大碼農。這是rbg大神的主頁 https://people.eecs.berk

    Faster RCNN 訓練自己資料遇到的一些問題

    1. xml標籤格式問題 原本的標籤是yaml格式的,需要轉換成xml格式。 在製作xml標籤時,有些資訊是比較重要的不能省略 <?xml version="1.0" encoding="utf-8"?> <annotation> <folder>

    不能再詳細!!!手把手教你用Faster-RCNN訓練自己資料

    一、環境安裝準備 python2.7以及相關的包cython, python-opencv, easydict 本文假設你已經按照上面的教程完成了安裝,並可以執行demo.py 並且可以訓練 二、準備自己的資料集 在實際的應用中,這個資料集肯定是自己專案裡面拍攝的。

    深度學習Caffe實戰筆記(20)Windows平臺 Faster-RCNN 訓練自己資料

    1、把自己的資料集放到Faster-master中 我覺得這個過程是最重要的一個過程吧,博主在這裡跳了很多的坑,最後找到了一個非常簡單高效的方法。不用修改任何檔案,就可以輕鬆實現載入自己的資料集。 在faster_rcnn-master資料夾下,有一個d

    Faster-RCNN 訓練自己資料的坑記錄

    主要照這篇部落格進行訓練配置,因為沒有GPU所以好多坑,CPU訓練可以參見這篇部落格 正所謂,跑通了的都一樣,錯誤千萬樣。按照教程來也是坑多 訓練: python train_faster_rcnn_alt_opt.py --net_name ZF --weights

    py-faster-rcnn訓練自己資料需要修改的引數

    faster rcnn預設有三種網路模型ZF(小)、VGG_CNN_M_1024(中)、VGG16 (大) 訓練圖片大小為500*500,類別數1。 修改VGG_CNN_M_1024模型配置

    win10 tensorflow faster rcnn訓練自己資料(一、製作VOC2007資料

    參考部落格:http://blog.csdn.net/gaohuazhao/article/details/60871886 一、關於VOC資料集: 1)JPEGImages資料夾 資料夾裡包含了訓練圖片和測試圖片,混放在一起 2)Annatations資料夾 資

    使用faster rcnn訓練自己資料(py-faster-rcnn

    出於在csdn上面學到很多東西這裡也幫自己的一些收穫和大家分享一下     直奔主題~~ 前提是已經安裝好caffe的環境 本文是在Ubuntu 15.04下做的測試 $Faster_rcnn表示py-faster-rcnn根目錄 1. 修改資料介面 ($Faster_rc

    faster-rcnn訓練自己資料時報錯too many indices

    利用faster-rcnn 好不容易四個階段訓練完了,在測試的時候出現這個錯誤。 原因:在data/VOCdevkit2007/results/VOC2007/Main/  這個檔案下有n個txt檔案。n是你的類別數            每個txt儲存了test.txt

    深度學習Caffe實戰筆記(21)Windows平臺 Faster-RCNN 訓練好的模型測試資料

    前一篇部落格介紹瞭如何利用Faster-RCNN訓練自己的資料集,訓練好會得到一個模型,這篇部落格介紹如何利用訓練好的模型進行測試資料。 1、訓練好的模型存放位置 訓練好的模型存放在faster_rcnn-master\output\faster_rcnn_

    使用faster-rcnn訓練自己的模型

    參考 faster-rcnn 原始碼連結 論文連結 一個不錯的參考 faster rcnn簡介 各檔案目錄介紹  caffe-fast-rcnn —> caffe框架  data —> 存放資料,以及讀取檔案的ca

    使用faster rcnn訓練自己的模型

    安裝caffe 資料預處理 我這裡主要是使用python對xml進行處理。 生產xml的程式碼: # -*- coding:utf-8 -*- __author__ = "Yu Chen" import xml.dom

    製作自己的目標檢測資料利用tf-faster-rcnn訓練

    1.製作資料集的工具 我利用資料集標註工具是精靈標註助手,我認為很好用。奉勸一句標註資料集時不要隨便找人給你標,如果他沒有用心給你標註,你在後面訓練會出現很多問題。在一開始標註資料集的時候不要一下子給他標註完,先標註幾十張圖片,然後用在你的網路裡,看看有沒有錯誤,如果沒有問

    Mxnet(2)---faster-rcnn製作自己資料進行訓練

    Mxnet自帶有faster-rcnn的例子,但是如果要用自己的資料進行訓練可能需要作一些更改,一個是類別的數目,一個數據的標籤。其實它的修改方式和py-faster-rcnn差不多。 **

    tf-faster-rcnn執行自己資料記錄

    我只從遇到問題到地方開始記錄,沒有問題到地方按照作者的read me做下去即可。 1、執行到第3步,準備測試demo 時候出現問題 解決辦法:自己下載三個訓練資料集,然後解壓到tf-faster-rcnn根目錄下,並改名為VOCdevkit2007,然後放置到da

    Fast RCNN 訓練自己資料 (1編譯配置)

    FastRCNN 訓練自己資料集 (1編譯配置) FastRCNN是Ross Girshick在RCNN的基礎上增加了Multi task training整個的訓練過程和測試過程比RCNN快了許多。別的一些細節不展開,過幾天會上傳Fast RCNN的論文筆記。FastRCNN mAP效能上略有上升。Fa

    Fast RCNN 訓練自己資料(3訓練和檢測)

    1.預訓練模型介紹 首先在data目錄下,有兩個目錄就是之前在1中解壓好 fast_rcnn_models/ imagenet_models/ fast_rcnn_model資料夾下面是作者用fast rcnn訓練好的三個網路,分別對應著小、中、大型網路,大家可以試用一下這幾個網路,看一些檢測效果,