注:本文寫於早期學習摸索階段,不免有錯誤、不到位的理解,僅用做遇到相同錯誤的人參考。后續一直在使用RBG大神的py-faster-rcnn。
既然faster-rcnn原版發表時候是matlab版代碼,那就用matlab版代碼吧!不過遇到的坑挺多的,不知道python版會不會好一點。
======= update =========
總體上包括這些步驟,請注意檢查:
1 獲取數據;(標准數據集/比賽數據/自行收集數據)
2 整理圖片名和標注信息格式、指定訓練集和測試集;(轉voc格式,同時記得修改vocinit.m中類別信息;或者自己修改代碼中讀取數據的地方)
3 正確使用均值圖像:手動算一個或用默認的減去128,別用錯
4 選擇網絡與設定網絡參數(solver和net);(根據業務需求和顯存大小設定;修改網絡中目標類別數量)
5 檢查batch_size;
6 檢查anchor;
7 清空cache目錄;
8 開始訓練;
9 確保電腦供電且不會休眠睡眠;
10 執行測試;整理測試結果
======= update =========
anyway,這里記錄一下我遇到的幾個錯誤和解決辦法
這里假設你已經配置好了faster-rcnn。我是在win10下配置的,顯卡GTX 970,使用ZF網絡。
0. 准備數據集
官方訓練時用的是voc2007系列數據,那就轉換成這個系列的好了,主要包括:0.下載數據集 1.整理圖片 2.xml格式的annotation文件 3.txt格式指定訓練集、測試集、驗證集、訓練驗證集,以及每個類別各自的這四種文件
0.0 下載數據集
看具體情況,比如做某個比賽,那就下載;如果是自己收集的數據集,那就統一放到一起
0.1 整理圖片
主要是圖片格式統一,比如都是png
以及,命名規范,比如統一是6位長度的數字:000001.png,並且序號是連續的
訓練圖片和測試圖片都放在一個JPEGImages目錄里
0.2 xml格式的annotation文件
其實voc2007這種方式:為每張圖片編寫一個xml文件,記錄圖片各種元信息(作者、文件名、寬度高度深度、來源),以及bounding box坐標信息(左上、右下定點)等,很蛋疼啊,圖片多的話每次處理xml文件讀寫I/O就增大了。anyway,遵守標准的好處是省的自己造各種工具。
這里貼一個例子好了,000001.xml:
<annotation>
<folder>VOC2007</folder>
<filename>000001.png</filename>
<source>
<database>My Database</database>
<annotation>VOC2007</annotation>
<image>flickr</image>
<flickrid>NULL</flickrid>
</source>
<owner>
<flickrid>NULL</flickrid>
<name>chriszz</name>
</owner>
<size>
<width>1280</width>
<height>720</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>369</xmin>
<ymin>403</ymin>
<xmax>409</xmax>
<ymax>418</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>434</xmin>
<ymin>375</ymin>
<xmax>443</xmax>
<ymax>401</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>461</xmin>
<ymin>368</ymin>
<xmax>471</xmax>
<ymax>395</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>571</xmin>
<ymin>473</ymin>
<xmax>593</xmax>
<ymax>490</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>674</xmin>
<ymin>470</ymin>
<xmax>683</xmax>
<ymax>478</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>693</xmin>
<ymin>471</ymin>
<xmax>714</xmax>
<ymax>480</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>976</xmin>
<ymin>413</ymin>
<xmax>998</xmax>
<ymax>438</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>1004</xmin>
<ymin>396</ymin>
<xmax>1011</xmax>
<ymax>410</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>1024</xmin>
<ymin>388</ymin>
<xmax>1031</xmax>
<ymax>405</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>1046</xmin>
<ymin>388</ymin>
<xmax>1071</xmax>
<ymax>406</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>1114</xmin>
<ymin>390</ymin>
<xmax>1143</xmax>
<ymax>410</ymax>
</bndbox>
</object>
<object>
<name>sign</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>913</xmin>
<ymin>431</ymin>
<xmax>928</xmax>
<ymax>458</ymax>
</bndbox>
</object>
</annotation>
記得所有xml文件的文件名要和圖片序號一一對應:000001.xml對應000001.png
並且,所有xml文件放到Annotations目錄中
0.3 txt文件指定訓練集、測試集等
在ImageSets/Main目錄下保存這些文件。比如我的任務是檢測交通標識,只有一個類別需要檢測,或者說是二分類問題,只需要判斷一個bbox區域是否為交通標識(sign),那么我創建sign對應的4個文件;以及4個表示總體的訓練、驗證、訓練驗證、測試的txt文件:

其中,sign_train、sign_test、sign_trainval、sign_val每行格式相同
圖片id(不帶后綴,不用全路徑) +1或-1(表示這張圖片中是否包含sign類別的區域)
對於我的情況,類別標簽都是+1
然后是train、val、trainval、test文件,其中trainval是train和val的拼接。
這里我是需要
1 修改faster-rcnn的幾個代碼細節
1.0 experiments\script_faster_rcnn_VOC2007_ZF.m第30、31行
這里默認居然是用select search生成region proposal,我也是醉了。
改成:
dataset = Dataset.voc2007_trainval(dataset, 'train', use_flipped);
dataset = Dataset.voc2007_test(dataset, 'test', false);
1.1 experiments\+Dataset\voc2007_test.m第11行、第14行,test改成val
這個真的是太坑了,在這里我卡了大半天。為什么會卡在這個地方,然后程序一直運行出錯呢?以及,程序出錯大概如下:
錯誤使用 proposal_prepare_image_roidb>scale_rois (line 110) 兩個輸入數組的單一維度必須相互匹配,...

設斷點debug后發現,roidb_train里各種字段都有值(比如gt、坐標、閾值、類別等);而roidb_val里面是空的。
實際上是在experiments\+Faster_RCNN_Train\do_proposal_train.m里面,把dataset.roidb_test賦值給roidb_val了:
function model_stage = do_proposal_train(conf, dataset, model_stage, do_val)
if ~do_val
dataset.imdb_test = struct();
dataset.roidb_test = struct();
end
model_stage.output_model_file = proposal_train(conf, dataset.imdb_train, dataset.roidb_train, ...
'do_val', do_val, ...
'imdb_val', dataset.imdb_test, ...
'roidb_val', dataset.roidb_test, ... # 尼瑪,在這里賦值了
'solver_def_file', model_stage.solver_def_file, ...
'net_file', model_stage.init_net_file, ...
'cache_name', model_stage.cache_name);
end
問題就是在這里了,不多說。那么接下來就是把experiments\+Dataset\voc2007_test.m第11行、第14行,test改成val,保證以后在imdb\cache目錄下有val的mat數據存在,roidb_val也不會說里面內容都為空的了。
2 修改網絡參數
看到下面這張圖應該知道要改那幾個文件了:

具體可以參考小咸魚的faster-rcnn matlab版的配置
