1. 程式人生 > >py-faster-rcnn + cpu安裝及訓練自己的資料集

py-faster-rcnn + cpu安裝及訓練自己的資料集

下面分兩部分來講解,第一部分為py-faster-rcnn及caffe框架安裝。第二部分講解如何修改相關檔案,訓練自己的資料集。

第一部分 安裝

把專案程式碼clone下來, 注意是遞迴下載,裡面包含專案自帶的caffe,跟原版的caffe略有不同,一定要注意:

git clone --recursive  https://github.com/rbgirshick/py-faster-rcnn.git

安裝python包cython, 使用pip安裝:

sudo pip install cython

編譯cython

cd /py-faster-rcnn/lib
修改setup.py檔案,註釋掉GPU相關程式碼,如下:
#CUDA = locate_cuda()
#self.set_executable('compiler_so', CUDA['nvcc']) # Extension('nms.gpu_nms', ['nms/nms_kernel.cu', 'nms/gpu_nms.pyx'], library_dirs=[CUDA['lib64']], libraries=['cudart'], language='c++', runtime_library_dirs=[CUDA['lib64']], # this syntax is specific to this build system
# we're only going to use certain compiler args with nvcc and not with # gcc the implementation of this trick is in customize_compiler() below extra_compile_args={'gcc': ["-Wno-unused-function"], 'nvcc': ['-arch=sm_35','--ptxas-options=-v','-c','--compiler-options',"'-fPIC'"
]}, include_dirs = [numpy_include, CUDA['include']] ), setup.py修改完成後,執行make

到這裡, 我們就完成了所得的安裝。

第二部分 訓練自己的資料集

首先,我們先執行一下專案自身的demo
下載論文中提到的pascal voc 2007 資料集,pascal voc 2012資料集類似可下載:

wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCdevkit_08-Jun-2007.tar

下載完成後,解壓縮:

tar xvf VOCtrainval_06-Nov-2007.tar
tar xvf VOCtest_06-Nov-2007.tar
tar xvf VOCdevkit_08-Jun-2007.tar

解壓縮完成後,會形成如下的目錄結構:

$VOCdevkit/
$VOCdevkit/VOCcode/
$VOCdevkit/VOC2007

我們對pascal voc2007 資料集做一個連結:

cd py-faster-rcnn/data
ln -s /path/to/VOCdevkit VOCdevkit2007

現在,在data目錄下會出現VOCdevkit2007資料夾, 結構與VOCdevkit相同。

訓練資料集, 論文提供幾種訓練方式, 具體引數可看程式碼做相應設定:

cd py-fatser-rcnn
./experiments/scripts/faster_rcnn_alt_opt.sh [NET] [--set ...]
or
./experiments/scripts/faster_rcnn_end2end.sh [NET] [--set ...]

或者我們也可以執行下面命令進行訓練:

./tools/train_net.py --cpu --solver path/to/solver.prototxt --weights path/to/pretrain_model --imdb voc_2007_trainval --iters 100000 --cfgs experiments/cfgs/faster_rcnn_end2end.yml

測試可使用如下命令列:

./tools/test_net.py --cpu --def path/to/test.prototxt --net path/to/your/final.model --imdb voc_2007_test --cfgs experiments/cfgs/faster_rcnn_end2end.yml

論文作者已經預訓練好幾種模型, 我們下載即可:

cd py-faster-rcnn
./data/scripts/fetch_faster_rcnn_models.sh
./data/scripts/fetch_imagenet_models.sh
./data/scripts/fetch_selective_search_data.sh

下載完成後, 解壓縮模型,然後執行:

./tools/demo.py

會看到影象識別結果。

ok, 下面我們試著修改檔案,換成自己的資料集,進行訓練和測試。替換過程中,我們依然保持資料夾名稱不變,只置換裡面的資料。

我們下載解壓後的資料集儲存在:

/data/VOCdevkit2007/VOC2007
VOC2007下有三個資料夾:
VOC2007/Annotations
VOC2007/ImageSets
VOC2007/JPEGImages

Annotations: 儲存與圖片對應的xml檔案,每個xml檔案包含object的bbox,name等
ImageSets: 儲存切分好的資料集,包括train,val,test等檔案;
JPEGImages: 儲存所有的圖片;

我們把自己的訓練集替換掉原始的檔案,放到相應的上述三個目錄下即可。

另外, 在標註資料的過程中, 發現一個非常方便的標註軟體labelImg, 在圖片上畫出框之後,會自動生成訓練所需格式的xml檔案。
github專案主頁地址:https://github.com/tzutalin/labelImg
感興趣的可以自行下載安裝使用。

資料集替換問題解決了,接下來,我們一步步的修改檔案:

cd /lib/datasets

首先,修改pascal_voc.py,
self.CLASS = (
background‘, #保留這個類別
。。。
)
改成你自己要識別的object 類別,比如我要識別people,只需把people類別加進去即可。

然後修改模型引數, 以訓練faster_rcnn_end2end模型為例:

cd /models/pascal_voc/VGG16/faster_rcnn_end2end

包括三個prototxt檔案,分別修改如下:
對於solver.prototxt, 模型引數初始化,一般不需要修改;
對於train.prototxt, 修改如下幾個地方:
①num_classes : 設定為你的識別類別數, 比如說我只識別people這一類, 則為2(1 + 背景類)
②cls_score 層, inner_product_param引數, num_output :也設定為2(1 + 背景類)
③bbox_pred層, inner_product_param引數, num_output:設定為(1 + 背景類) ×4
對於test.prototxt檔案, 修改如下:
①cls_score層, inner_product_param引數, num_output: 設定為2(1 + 背景類)

到這裡,我們針對自己的資料集,要修改的都已經改完了。訓練的命令列再上面已經給出,這裡不在寫出。接下來就是耐心的等待訓練結果啦。

訓練完成後, 可以執行demo.py 來檢視識別結果。注意,別忘了修改 CLASS的類別。另外,demo.py每次識別一張圖片,若包含多個不同的類別,識別結果不能顯示在同一張圖片上, 可略做修改即可。
例如可以把demo.py裡的demo函式和vis_detections函式寫成一個函式:

def vis_detections(im, net, image_name, thresh=0.5):
    """Draw detected bounding boxes."""

    scores, boxes = im_detect(net, im)

    print ('Detection took {:.3f}s for '
           '{:d} object proposals').format(timer.total_time, boxes.shape[0])

    NMS_THRESH = 0.3
    for cls_ind, cls in enumerate(CLASSES[1:]):
        cls_ind += 1 # because we skipped background
        cls_boxes = boxes[:, 4*cls_ind:4*(cls_ind + 1)]
        cls_scores = scores[:, cls_ind]
        dets = np.hstack((cls_boxes,
                          cls_scores[:, np.newaxis])).astype(np.float32)
        keep = nms(dets, NMS_THRESH)
        dets = dets[keep, :]

        inds = np.where(dets[:, -1] >= thresh)[0]
        # print inds
        if len(inds) > 0:
            for i in inds:
                bbox = dets[i, :4]
                score = dets[i, -1]

                cv2.rectangle(im, (bbox[0], bbox[1]),(bbox[2], bbox[3]),(0,255,0),3)
                font = cv2.FONT_HERSHEY_SIMPLEX
                cv2.putText(im, '{:s} {:.3f}'.format(cls, score), (bbox[0], bbox[1]), font, 0.5, (0,0,255),1)

    # detection result path
    cv2.imwrite(result_dir + '/' + image_name + '.jpg', im)