使用Faster-Rcnn进行目标检测(实践篇)
原理
上一篇文章,已經(jīng)說過了,大家可以參考一下,Faster-Rcnn進(jìn)行目標(biāo)檢測(原理篇)
實(shí)驗(yàn)
我使用的代碼是python版本的Faster Rcnn,官方也有Matlab版本的,鏈接如下:
py-faster-rcnn(python)
faster-rcnn(matlab)
環(huán)境配置
按照官方的README進(jìn)行配置就好,不過在這之前大家還是看下硬件要求吧
-
For training smaller networks (ZF, VGG_CNN_M_1024) a good GPU (e.g., Titan, K20, K40, …) with at least 3G of memory suffices
-
For training Fast R-CNN with VGG16, you’ll need a K40 (~11G of memory)
-
For training the end-to-end version of Faster R-CNN with VGG16, 3G of GPU memory is sufficient (using CUDNN)
我的是環(huán)境是Ubuntu 14.04 + Titan X(12GB) + cuda 7.0 + cudnn V3
1 Caffe環(huán)境配置
Caffe環(huán)境需要python layer的支持,在你的Caffe的Makefile.config中去掉以下的注釋
- WITH_PYTHON_LAYER := 1
- USE_CUDNN := 1
2 安裝python庫依賴
cython,python-opencv和easydict
pip install cython pip install python-opencv pip install easydict- 1
- 2
- 3
3 克隆py-faster-rcnn源代碼
git clone --recursive https://github.com/rbgirshick/py-faster-rcnn.git- 1
4 編譯cython模塊
cd $FRCN_ROOT/lib make- 1
- 2
5 編譯Caffe和pycaffe
cd $FRCN_ROOT/caffe-fast-rcnn make -j8 && make pycaffe- 1
- 2
-j8的選項(xiàng)是進(jìn)行多核編譯,可以加速編譯過程,推薦使用
數(shù)據(jù)集
參考VOC2007的數(shù)據(jù)集格式,主要包括三個部分:
-
JPEGImages
-
Annotations
-
ImageSets/Main
JPEGImages —> 存放你用來訓(xùn)練的原始圖像
Annotations —> 存放原始圖像中的Object的坐標(biāo)信息,XML格式
ImageSets/Main —> 指定用來train,trainval,val和test的圖片的編號
這部分非常重要,數(shù)據(jù)集做不好直接導(dǎo)致代碼出現(xiàn)異常,無法運(yùn)行,或者出現(xiàn)奇怪的錯誤,我也是掉進(jìn)了很多坑,爬上來之后才寫的這篇博客,希望大家不要趟我趟過的渾水!每一個部分我都會細(xì)說的!
JPEGImages
這個沒什么,直接把你的圖片放入就可以了,但是有三點(diǎn)注意:
-
編號要以6為數(shù)字命名,例如000034.jpg
-
圖片要是JPEG/JPG格式的,PNG之類的需要自己轉(zhuǎn)換下
-
圖片的長寬比(width/height)要在0.462-6.828之間,就是太過瘦長的圖片不要
0.462-6.828是我自己實(shí)驗(yàn)得出來的,就我的數(shù)據(jù)集而言是這個比例,總之長寬比太大或者太小的,你要注意將其剔除,否則可能會出現(xiàn)下面我實(shí)驗(yàn)時候出的錯:
Traceback (most recent call last):
File “/usr/lib/python2.7/multiprocessing/process.py”, line 258, in _bootstrap
self.run()
File “/usr/lib/python2.7/multiprocessing/process.py”, line 114, in run
self._target(*self._args, **self._kwargs)
File “./tools/train_faster_rcnn_alt_opt.py”, line 130, in train_rpn
max_iters=max_iters)
File “/home/work-station/zx/py-faster-rcnn/tools/../lib/fast_rcnn/train.py”, line 160, in train_net
model_paths = sw.train_model(max_iters)
File “/home/work-station/zx/py-faster-rcnn/tools/../lib/fast_rcnn/train.py”, line 101, in train_model
self.solver.step(1)
File “/home/work-station/zx/py-faster-rcnn/tools/../lib/rpn/anchor_target_layer.py”, line 137, in forward
gt_argmax_overlaps = overlaps.argmax(axis=0)
ValueError: attempt to get argmax of an empty sequence
Google給出的原因是 Because the ratio of images width and heights is too small or large,這個非常重要
Annotations
faster rcnn訓(xùn)練需要圖像的bounding box信息作為監(jiān)督(ground truth),所以你需要將你的所有可能的object使用框標(biāo)注,并寫上坐標(biāo),最終是一個XML格式的文件,一個訓(xùn)練圖片對應(yīng)Annotations下的一個同名的XML文件
參考官方VOC的Annotations的格式:
<annotation><folder>VOC2007</folder> #數(shù)據(jù)集文件夾<filename>000105.jpg</filename> #圖片的name<source> #注釋信息,無所謂有無<database>The VOC2007 Database</database><annotation>PASCAL VOC2007</annotation><image>flickr</image><flickrid>321862192</flickrid></source><owner> #注釋信息,無所謂有無<flickrid>Eric T. Johnson</flickrid><name>?</name></owner><size> #圖片大小<width>500</width><height>333</height><depth>3</depth></size><segmented>0</segmented><object> #多少個框就有多少個object標(biāo)簽<name>boat</name> #bounding box中的object的class name<pose>Frontal</pose><truncated>1</truncated><difficult>0</difficult><bndbox><xmin>22</xmin> #框的坐標(biāo)<ymin>1</ymin><xmax>320</xmax><ymax>314</ymax></bndbox></object><object><name>person</name><pose>Frontal</pose><truncated>1</truncated><difficult>0</difficult><bndbox><xmin>202</xmin><ymin>71</ymin><xmax>295</xmax><ymax>215</ymax></bndbox></object><object><name>person</name><pose>Frontal</pose><truncated>1</truncated><difficult>0</difficult><bndbox><xmin>170</xmin><ymin>107</ymin><xmax>239</xmax><ymax>206</ymax></bndbox></object> </annotation>- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
這里有一個非常好用的工具VOC框圖工具,可以自動幫你生成需要的XML格式,實(shí)際中發(fā)現(xiàn)格式基本無誤,只有小的地方需要改動下,大家對比下就知道怎么改了,我是在linux下借助sed修改的,這個不難
Imagesets/Main
因?yàn)閂OC的數(shù)據(jù)集可以做很多的CV任務(wù),比如Object detection, Semantic segementation, Edge detection等,所以Imageset下有幾個子文件夾(Layout, Main, Segementation),我們只要修改下Main下的文件就可以了(train.txt, trainval.txt, val.txt, test.txt),里面寫上你想要進(jìn)行任務(wù)的圖片的編號
將上述你的數(shù)據(jù)集放在py-faster-rcnn/data/VOCdevkit2007/VOC2007下面,替換原始VOC2007的JPEGIMages,Imagesets,Annotations
原始VOC2007下載地址: VOC20007數(shù)據(jù)集
代碼修改
工程目錄介紹
-
caffe-fast-rcnn —> caffe框架
-
data —> 存放數(shù)據(jù),以及讀取文件的cache
-
experiments —>存放配置文件以及運(yùn)行的log文件,配置文件
-
lib —> python接口
-
models —> 三種模型, ZF(S)/VGG1024(M)/VGG16(L)
-
output —> 輸出的model存放的位置,不訓(xùn)練此文件夾沒有
-
tools —> 訓(xùn)練和測試的python文件
修改源文件
faster rcnn有兩種各種訓(xùn)練方式:
-
Alternative training(alt-opt)
-
Approximate joint training(end-to-end)
推薦使用第二種,因?yàn)榈诙N使用的顯存更小,而且訓(xùn)練會更快,同時準(zhǔn)確率差不多,兩種方式需要修改的代碼是不一樣的,同時faster rcnn提供了三種訓(xùn)練模型,小型的ZFmodel,中型的VGG_CNN_M_1024和大型的VGG16,論文中說VGG16效果比其他兩個好,但是同時占用更大的GPU顯存(~11GB)
我使用的是VGG model + alternative training,需要檢測的類別只有一類,加上背景所以總共是兩類(background + captcha)
1 py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage1_fast_rcnn_train.pt
layer { name: 'data' type: 'Python' top: 'data' top: 'rois' top: 'labels' top: 'bbox_targets' top: 'bbox_inside_weights' top: 'bbox_outside_weights' python_param { module: 'roi_data_layer.layer' layer: 'RoIDataLayer' param_str: "'num_classes': 2" #按訓(xùn)練集類別改,該值為類別數(shù)+1 } }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
2 py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage1_rpn_train.pt
layer { name: 'input-data' type: 'Python' top: 'data' top: 'im_info' top: 'gt_boxes' python_param { module: 'roi_data_layer.layer' layer: 'RoIDataLayer' param_str: "'num_classes': 2" #按訓(xùn)練集類別改,該值為類別數(shù)+1 } }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
3 py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage2_fast_rcnn_train.pt
layer { name: 'data' type: 'Python' top: 'data' top: 'rois' top: 'labels' top: 'bbox_targets' top: 'bbox_inside_weights' top: 'bbox_outside_weights' python_param { module: 'roi_data_layer.layer' layer: 'RoIDataLayer' param_str: "'num_classes': 2" #按訓(xùn)練集類別改,該值為類別數(shù)+1 } }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
4 py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage2_rpn_train.pt
layer { name: 'input-data' type: 'Python' top: 'data' top: 'im_info' top: 'gt_boxes' python_param { module: 'roi_data_layer.layer' layer: 'RoIDataLayer' param_str: "'num_classes': 2" #按訓(xùn)練集類別改,該值為類別數(shù)+1 } }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
5 py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/faster_rcnn_test.pt
layer { name: "cls_score" type: "InnerProduct" bottom: "fc7" top: "cls_score" inner_product_param { num_output: 2 #按訓(xùn)練集類別改,該值為類別數(shù)+1 } }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
6 py-faster-rcnn/lib/datasets/pascal_voc.py
class pascal_voc(imdb): def __init__(self, image_set, year, devkit_path=None): imdb.__init__(self, 'voc_' + year + '_' + image_set) self._year = year self._image_set = image_set self._devkit_path = self._get_default_path() if devkit_path is None \ else devkit_path self._data_path = os.path.join(self._devkit_path, 'VOC' + self._year) self._classes = ('__background__', # always index 0 captcha' # 有幾個類別此處就寫幾個,我是兩個)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
line 212
cls = self._class_to_ind[obj.find('name').text.lower().strip()]- 1
如果你的標(biāo)簽含有大寫字母,可能會出現(xiàn)KeyError的錯誤,所以建議全部使用小寫字母
7 py-faster-rcnn/lib/datasets/imdb.py
將append_flipped_images函數(shù)改為如下形式:
def append_flipped_images(self): num_images = self.num_images widths = [PIL.Image.open(self.image_path_at(i)).size[0] for i in xrange(num_images)] for i in xrange(num_images): boxes = self.roidb[i]['boxes'].copy() oldx1 = boxes[:, 0].copy() oldx2 = boxes[:, 2].copy() boxes[:, 0] = widths[i] - oldx2 - 1 print boxes[:, 0] boxes[:, 2] = widths[i] - oldx1 - 1 print boxes[:, 0] assert (boxes[:, 2] >= boxes[:, 0]).all() entry = {'boxes' : boxes, 'gt_overlaps' : self.roidb[i]['gt_overlaps'], 'gt_classes' : self.roidb[i]['gt_classes'], 'flipped' : True} self.roidb.append(entry) self._image_index = self._image_index * 2- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
到此代碼修改就搞定了
訓(xùn)練
訓(xùn)練前還需要注意幾個地方
1 cache問題
假如你之前訓(xùn)練了官方的VOC2007的數(shù)據(jù)集或其他的數(shù)據(jù)集,是會產(chǎn)生cache的問題的,建議在重新訓(xùn)練新的數(shù)據(jù)之前將其刪除
(1) py-faster-rcnn/output
(2) py-faster-rcnn/data/cache
2 訓(xùn)練參數(shù)
py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage_fast_rcnn_solver*.pt
base_lr: 0.001 lr_policy: 'step' step_size: 30000 display: 20 ....- 1
- 2
- 3
- 4
- 5
迭代次數(shù)在文件py-faster-rcnn/tools/train_faster_rcnn_alt_opt.py中進(jìn)行修改
line 80
max_iters = [80000, 40000, 80000, 40000]- 1
分別對應(yīng)rpn第1階段,fast rcnn第1階段,rpn第2階段,fast rcnn第2階段的迭代次數(shù),自己修改即可,不過注意這里的值不要小于上面的solver里面的step_size的大小,大家自己修改吧
開始訓(xùn)練:
cd py-faster-rcnn ./experiments/scripts/faster_rcnn_alt_opt.sh 0 VGG16 pascal_voc- 1
- 2
指明使用第一塊GPU(0),模型是VGG16,訓(xùn)練數(shù)據(jù)是pascal_voc(voc2007),沒問題的話應(yīng)該可以迭代訓(xùn)練了
結(jié)果
訓(xùn)練完畢,得到我們的訓(xùn)練模型,我們就可以使用它來進(jìn)行我們的object detection了,具體是:
1 將py-faster-rcnn/output/faster_rcnn_alt_opt/voc_2007_trainval/VGG16_faster_rcnn_final.caffemodel,拷貝到py-faster-rcnn/data/faster_rcnn_models下
2 將你需要進(jìn)行test的images放在py-faster-rcnn/data/demo下
3 修改py-faster-rcnn/tools/demo.py文件
CLASSES = ('_background_', 'captcha') #參考你自己的類別寫
NETS = {'vgg16': ('VGG16',
'VGG16_faster_rcnn_final.caffemodel'), #改成你訓(xùn)練得到的model的name
'zf': ('ZF',
'ZF_faster_rcnn_final.caffemodel')
}
- 1
上幾張我的檢測結(jié)果吧
參考
1 faster rcnn 做自己的數(shù)據(jù)集
2 faster rcnn 教程
3 使用ZF訓(xùn)練自己的faster rcnn model
4 一些錯誤的解決方法
總結(jié)
以上是生活随笔為你收集整理的使用Faster-Rcnn进行目标检测(实践篇)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: faster rcnn 数据格式
- 下一篇: LUNA再次夺冠,科大讯飞向世界宣告自己