首先要安裝 caffe 和 pycaffe,安裝過程可參考我的上一篇博文
在安裝並運行 Faster R-CNN demo,訓練和測試自己的 VOC 數據集中也出現了各種各樣的問題,但大多數問題都是因為 Faster R-CNN 本身和其他各種依賴項之間的兼容問題,大概是因為我安裝的 CUDA,cuDNN 等其他一些依賴項的版本比較高造成的。
Faster R-CNN 安裝並運行 demo
其 Github 上也有比較詳細的安裝過程可供參考,傳送門:
1. 下載 Faster R-CNN,編譯 Cython 模塊
git clone --recursive https://github.com/rbgirshick/py-faster-rcnn.git cd py-faster-rcnn/lib make
2. 創建 Makefile.config 文件,打開並修改,修改方式和 Caffe 中的修改方式一樣,可參考我的上一篇博文
cd py-faster-rcnn/caffe-fast-rcnn cp Makefile.config.example Makefile.config
替換 py-faster-rcnn/caffe-fast-rcnn/include/caffe/util 里的 cudnn.hpp 為最新版 caffe 里的 cudnn.hpp
替換 py-faster-rcnn/caffe-fast-rcnn/include/caffe/layers 里以 cudnn 開頭的文件為最新版 caffe 里以 cudnn 開頭的文件
否則會報 cudnn 版本不兼容的問題
3. 編譯 Caffe 和 pycaffe
cd py-faster-rcnn/caffe-fast-rcnn
make -j8 && make pycaffe
4. 下載預計算的 Faster-RCNN 檢測器模型,有它才可以實現 demo 中的檢測
cd $FRCN_ROOT ./data/scripts/fetch_faster_rcnn_models.sh
5. 運行 demo
cd py-faster-rcnn
./tools/demo.py
如果成功運行會彈出幾張圖片,上面會框出被識別的區域並標明其類別。
訓練和測試 VOC 格式數據集
首先需要准備好 VOC 格式的數據集,不管是網上下載的還是自己准備,這里只針對 VOC 格式數據集的訓練和測試。
訓練和測試步驟參考了 Github 上關於 Faster-RCNN 的另一篇 tutorial,傳送門。
1. 建立數據集的軟鏈接
假設 Py-Faster-RCNN 的根目錄為 $PY_FASTER_RCNN,在 PY_FASTER_RCNN/data 文件夾中建立鏈接到數據集的軟鏈接,例如我創建了 example_devkit 文件夾,在example_devkit 文件夾中創建 data 文件夾,並建立其到數據集的軟鏈接,假設數據集文件夾名為 example,命令如下:
ln -s <數據集的文件路徑>/example $PY_FASTER_RCNN/data/example_devkit/data
2. 添加 lib/datasets/yourdatabase.py 文件
在 $PY_FASTER_RCNN 下,添加 lib/datasets/yourdatabase.py 文件,因為數據集是 VOC 的格式,所以我結合了原 Faster-RCNN repository 中 lib/datasets/pascal_voc.py 文件和那個 tutorial repository 中 lib/datasets/inria.py 文件,來修改了我添加的文件 example.py。以下是幾處主要修改的地方,我先對 inria.py 進行了修改:
1) self._classes 處添加數據集的類別,是背景加上其他類別的總數量
2) 指向數據集中圖片和 ImageSets 文件夾的路徑 image_path 和 image_set_file 的修改
3) 引用 pascal_voc.py 中的 _load_pascal_annotation 函數替代原 _load_inria_annotation 函數
4) 一些細節上的修改,函數名,import 包等
3. 更新 lib/datasets/factory.py 文件
添加如下代碼
from datasets.example import example example_devkit_path = '$PY_FASTER_RCNN/data/example_devkit' for split in ['train', 'test']: name = '{}_{}'.format('example', split) __sets[name] = (lambda split=split: example(split, eample_devkit_path))
4. 修改網絡模型
以 ZF 模型的 alternated optimizations 為例,復制原模型文件到新的 example 文件夾中並修改
cd $PY_FASTER_RCNN/models/ mkdir example cp -r pascal_voc/ZF/faster_rcnn_alt_opt/ example/
主要是對模型的類別進行修改,比如我的數據集有8類,修改 faster_rcnn_test.pt,stage1_fast_rcnn_train.pt,stage2_fast_rcnn_train.pt,stage2_rpn_train.pt 每個文件中原21處為8(總共要修改7處)
修改 faster_rcnn_test.pt,stage1_fast_rcnn_train.pt,stage2_fast_rcnn_train.pt 每個文件中原 84 處為32(4*8,總共要修改3處)
此外,還需修改 stage1_fast_rcnn_solver30k40k.pt,stage2_fast_rcnn_solver30k40k.pt,stage2_rpn_solver60k80k.pt 每個文件中 train_net 的路徑為新的路徑,例如 models/example/faster_rcnn_alt_opt/stage1_fast_rcnn_train.pt
5. 在 $PY_FASTER_RCNN 下創建模型的 config.yml 文件
echo 'MODELS_DIR: "$PY_FASTER_RCNN/models"' >> config.yml
6. 開始訓練
在 $PY_FASTER_RCNN 目錄下輸入以下命令進行訓練:
./tools/train_faster_rcnn_alt_opt.py --gpu 0 --net_name example --weights data/imagenet_models/ZF.v2.caffemodel --imdb example_train --cfg config.yml
其中 data/imagenet_models/ZF.v2.caffemodel 為需要下載的預訓練的 ImageNet 模型,可運行如下命令下載,可能會因為網速下不下來,那就要另找途徑了。。。
cd $PY_FASTER_RCNN ./data/scripts/fetch_imagenet_models.sh
可以先用小的迭代次數測試訓練是否順利,將 py-faster-rcnn/tools/train_faster_rcnn_alt_opt.py 中的迭代次數(第81行)改變為被注釋的 max_iters = [100, 100, 100, 100],先讓試着訓練一次。如果一切順利,那就可以直接放大的迭代次數就可以了,這樣會比較節省時間一點。訓練中可能會出現一些問題,解決方式參考文章末節的 ‘訓練過程中的問題和解決方式’。
7. 測試
訓練結束之后將 $PY_FASTER_RCNN/output/default/train 中的最終模型 example_faster_rcnn_final.caffemodel 拷貝到 data/faster_rcnn_models 中,在 tools/ 文件夾下新建 demo_example.py 文件,添加修改后的 demo.py 文件的內容, 主要修改包括
1) 修改類別
CLASSES = ('__background__', 'class1','class2', ...,'classn')
2) 修改NET名稱
NETS = {'vgg16': ('VGG16', 'VGG16_faster_rcnn_final.caffemodel'),
'zf': ('ZF', 'example_faster_rcnn_final.caffemodel')}
3) 修改 prototxt 文件的路徑
prototxt = '$PY_FASTER_RCNN/models/example/faster_rcnn_alt_opt/faster_rcnn_test.pt'
4) 添加要測試的圖片的文件名
im_names = ['example1.jpg','example2.jpg', ..., 'examplen.jpg']
在 $PY_FASTER_RCNN 下,運行 example.py
./tools/example.py --net zf
訓練過程中的問題和解決方式
1. 'module' object has no attribute 'text_format'
在文件 /lib/fast_rcnn/train.py 增加一行 import google.protobuf.text_format
2. 'numpy.float64' object cannot be interpreted as an index
1) /home/xxx/py-faster-rcnn/lib/roi_data_layer/minibatch.py
將第26行:fg_rois_per_image = np.round(cfg.TRAIN.FG_FRACTION * rois_per_image)
改為:fg_rois_per_image = np.round(cfg.TRAIN.FG_FRACTION * rois_per_image).astype(np.int)
2) /home/xxx/py-faster-rcnn/lib/datasets/ds_utils.py
將第12行:hashes = np.round(boxes * scale).dot(v)
改為:hashes = np.round(boxes * scale).dot(v).astype(np.int)
3) /home/xxx/py-faster-rcnn/lib/fast_rcnn/test.py
將第129行: hashes = np.round(blobs['rois'] * cfg.DEDUP_BOXES).dot(v)
改為: hashes = np.round(blobs['rois'] * cfg.DEDUP_BOXES).dot(v).astype(np.int)
4) /home/xxx/py-faster-rcnn/lib/rpn/proposal_target_layer.py
將第60行:fg_rois_per_image = np.round(cfg.TRAIN.FG_FRACTION * rois_per_image)
改為:fg_rois_per_image = np.round(cfg.TRAIN.FG_FRACTION * rois_per_image).astype(np.int)
3. slice indices must be integers or None or have an __index__ method
修改 /home/XXX/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 類型,這種類型的數據不能作為索引,所以必須對其進行強制類型轉換,轉化結果如下:
for ind in inds: ind = int(ind) cls = clss[ind] start = int(4 * cos) 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 return bbox_targets, bbox_inside_weight