faster-rcnn學(xué)習(xí)筆記

環(huán)境配置

Microsoft/caffe-master + windows

我的電腦比較渣,獨(dú)立顯卡計(jì)算能力低于要求迹淌,所以并沒有使用GPU+Cudnn加速。首先岔擂,依照README.md中的指示在Makefile.config依次配置python赛不,matlab環(huán)境惩嘉。其中,在配置Miniconda2環(huán)境時(shí)踢故,需要將E:\ProgramData\Miniconda2 & E:\ProgramData\Miniconda2\Scripts寫入系統(tǒng)路徑文黎,然后才可以使用pip命令安裝numpy和protobuf,安裝指令為

pip install numpy
conda install --yes numpy scipy matplotlib scikit-image pip
pip install protobuf

環(huán)境配置完成后殿较,修改windows下的CommonSettings.props文件耸峭,然后編譯caffe for windows源碼,記得將roi_pooling_layer和smooth_l1_loss_layer加到解決方案中來斜脂,這兩個(gè)層默認(rèn)是沒有加進(jìn)來的抓艳。如果只用CPU的話,在運(yùn)行faster-rcnn代碼時(shí)帚戳,將和GPU有關(guān)的代碼屏蔽掉即可玷或。

BVLC/caffe + ubuntu

首先下載caffe源碼: git clone git://github.com/BVLC/caffe.git
配置第三方庫的過程請參考博客:www.cnblogs.com/yaoyaoliu/p/5850993.html

安裝Cudnn

下載地址:developer.nvidia.com/cudnn,需要先注冊賬號片任,下載的時(shí)候需要注意cuda和cudnn版本的兼容性偏友,我的是cuda7.5 & cudnn-7.5-linux-x64-v5.1。解壓之后对供,需要將相應(yīng)的頭文件和庫文件拷貝到cuda的路徑下以便調(diào)用位他,指令如下:

sudo tar xvf cudnn-7.5-linux-x64-v5.1.tgz
cd cuda
sudo cp include/*.h /usr/local/cuda/include/
sudo cp lib64/lib* /usr/local/cuda/lib64
cd /usr/local/lib
sudo chmod +r libcudnn.so.5.1.10
sudo ln -sf licd bcudnn.so.5.1.10 libcudnn.so.5
sudo ln -sf libcudnn.so.5 libcudnn.so
sudo ldconfig

修改配置文件

# cuDNN acceleration switch (uncomment to build with cuDNN).
USE_CUDNN := 1
# CPU-only switch (uncomment to build without GPU support).
# CPU_ONLY := 1
USE_OPENCV := 1
USE_LEVELDB := 1
USE_LMDB := 1
OPENCV_VERSION := 3
CUDA_DIR := /usr/local/cuda
CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \
-gencode arch=compute_20,code=sm_21 \
-gencode arch=compute_30,code=sm_30 \
-gencode arch=compute_35,code=sm_35 \
-gencode arch=compute_50,code=sm_50 \
-gencode arch=compute_52,code=sm_52 \
-gencode arch=compute_52,code=compute_52
BLAS := atlas
MATLAB_DIR := /usr/local/MATLAB/R2014a
PYTHON_INCLUDE := /usr/include/python2.7 \
/usr/lib/python2.7/dist-packages/numpy/core/include
PYTHON_LIB := /usr/lib
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include
LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib
BUILD_DIR := build
DISTRIBUTE_DIR := distribute
TEST_GPUID := 0
Q ?= @

開始編譯

在caffe路徑下執(zhí)行make all -j8編譯源碼氛濒。在編譯matcaffe時(shí)可能會(huì)出現(xiàn)問題,如果是g++版本的問題鹅髓,可以這樣解決:在Makefile文件中加上一句話

CXXFLAGS += -MMD -MP
CXXFLAGS += -std=c++11

如果報(bào)出缺少caffe.pb.h的錯(cuò)誤舞竿,那么可以用 protoc caffe.proto --cpp_out=./ 指令生成caffe.pb.h文件,然后拷貝到 caffe/include/caffe/proto/路徑下窿冯。這樣編譯之后的caffe在faster-rcnn中仍然會(huì)報(bào)錯(cuò)骗奖,原因是缺少roi_pooling和smooth_l1_loss層,所以要在源碼中加入這兩個(gè)層醒串,之后還要修改caffe.proto文件执桌,要分別在LayerParameter和V1layerParameter中添加:

optional ROIPoolingParameter roi_pooling_param = 150 
optional SmoothL1LossParameter smooth_l1_loss_param = 151;

另外,需要用如下方法來聲明這兩個(gè)層:

message ROIPoolingParameter {
optional uint32 pooled_h = 1 [default = 0]; // The pooled output height
optional uint32 pooled_w = 2 [default = 0]; // The pooled output width
optional float spatial_scale = 3 [default = 1];
}
message SmoothL1LossParameter {
optional float sigma = 1 [default = 1];
}

如此配置之后的caffe在faster-rcnn中仍會(huì)報(bào)錯(cuò)芜赌,這其中包括dropout train scale沒有聲明以及caffe缺少成員函數(shù)reshape_as_input等錯(cuò)誤仰挣。說明faster-rcnn的caffe在BVLC版caffe的基礎(chǔ)上有了較大改動(dòng),所以我決定使用shaoqingren提供的caffe代碼重新編譯缠沈。

shaoqingren/caffe + ubuntu

作者提供的caffe由于是基于cuda6.5實(shí)現(xiàn)的膘壶,所以可能和自己裝的cuda版本不一致,和cudnn相關(guān)的所有代碼將出現(xiàn)不兼容的問題博烂,并不想重裝cuda香椎,所有我嘗試用caffe-master的代碼重新編譯。

Microsoft/caffe-master + ubuntu

這個(gè)過程還算順利禽篱,只需要去掉box_annotator_ohem_layer.cpp 這個(gè)文件畜伐,然后使用之前修改好的Makefile.config就可以了,大功告成躺率!但是高興太早玛界,這個(gè)版本的caffe只能跑跑demo,訓(xùn)練時(shí)候仍然會(huì)報(bào)錯(cuò)悼吱,所以想要訓(xùn)練自己的數(shù)據(jù)還是要編譯shaoqingren提供的caffe源碼慎框。

代碼解讀

整體框架

  1. faster-rcnn 把整張圖片輸入CNN, 進(jìn)行特征提取
  2. RPN網(wǎng)絡(luò)生成建議窗口(Proposals)后添,每張圖片大概300個(gè)
  3. fast-rcnn網(wǎng)絡(luò)把建議窗口映射到CNN的最后一層卷積feature map上
  4. ROI pooling層使每個(gè)ROI生成固定尺寸的feature map
  5. fast-rcnn網(wǎng)絡(luò)利用softmax loss和smooth L1 loss對分類概率和邊框回歸聯(lián)合訓(xùn)練

網(wǎng)絡(luò)結(jié)構(gòu)

RPN網(wǎng)絡(luò):

layer input size_kernal pad stride output
conv1 3@800×600 7 × 7 3 2 96@401 × 301
pool1 96@401 × 301 3 × 3 1 2 96@201 × 152
conv2 96@201 × 152 5 × 5 2 2 256@101 × 77
pool2 256@101 × 77 3 × 3 1 2 256@51 × 39
conv3 256@51 × 39 3 × 3 1 1 384@51 × 39
conv4 384@51 × 39 3 × 3 1 1 384@51 × 39
conv5 384@51 × 39 3 × 3 1 1 256@51 × 39
conv_prososal1 256@51 × 39 3 × 3 1 1 256@51 × 39
proposal_bbox_pred 256@51 × 39 1 × 1 0 1 36@51 × 39
proposal_cls_score 256@51 × 39 1 × 1 0 1 18@51 × 39
proposal_cls_score_reshape 18@51 × 39 - - - 2 ×@51 × 351

fast-rcnn網(wǎng)絡(luò):

fast-rcnn網(wǎng)絡(luò)結(jié)構(gòu)

訓(xùn)練代碼

  • 參數(shù)配置

需要配置的參數(shù)包括model笨枯,dataset,conf_proposal遇西,conf_fast_rcnn馅精。model包含了圖像均 值、預(yù)訓(xùn)練網(wǎng)絡(luò)粱檀、stage1_rpn洲敢、stage1_fast_rcnn、stage2_rpn茄蚯、stage2_fast_rcnn压彭、pre_trainde_net_file睦优。dataset經(jīng)訓(xùn)練數(shù)據(jù)組織成imdb和roidb的形式,imdb文件是一個(gè)matlab的表結(jié)構(gòu)壮不,表的每一行是一幅圖像汗盘,分別包含如下信息:圖像的路徑,編號忆畅,大小衡未,groundtruth等。conf_proposal以及conf_fast_rcnn配置了RPN和fast-rcnn網(wǎng)絡(luò)的基本參數(shù)家凯。

model = Model.ZF_for_Faster_RCNN_VOC0712;
dataset = Dataset.voc0712_trainval(dataset, 'train', use_flipped);
dataset = Dataset.voc2007_test(dataset, 'test', false);
conf_proposal = proposal_config('image_means', model.mean_image, 'feat_stride', model.feat_stride);
conf_fast_rcnn = fast_rcnn_config('image_means', model.mean_image);
  • 產(chǎn)生anchor

首先產(chǎn)生輸入圖像大小和conv5_3大小的對應(yīng)關(guān)系map;然后產(chǎn)生9個(gè)基本anchors如失。

[conf_proposal.anchors, conf_proposal.output_width_map, conf_proposal.output_height_map]
= proposal_prepare_anchors(conf_proposal, model.stage1_rpn.cache_name, model.stage1_rpn.test_net_def_file);
anchors
  • 開始訓(xùn)練

訓(xùn)練采取分步訓(xùn)練的方式绊诲,共分為4個(gè)階段:訓(xùn)練RPN網(wǎng)絡(luò);RPN網(wǎng)絡(luò)提取的Proposal作為輸入訓(xùn)練fast-rcnn網(wǎng)絡(luò)褪贵;用前一階段訓(xùn)練得到的網(wǎng)絡(luò)作為初始網(wǎng)絡(luò)掂之,繼續(xù)訓(xùn)練RPN網(wǎng)絡(luò);用第二階段訓(xùn)練的網(wǎng)絡(luò)作為初始網(wǎng)絡(luò)脆丁,前一階段訓(xùn)練的RPN網(wǎng)絡(luò)提取的Propsol作為輸入訓(xùn)練fast-RCNN網(wǎng)絡(luò)世舰。

%%  stage one proposal
% train
model.stage1_rpn            = Faster_RCNN_Train.do_proposal_train(conf_proposal, dataset, model.stage1_rpn, opts.do_val);
% test
dataset.roidb_train         = cellfun(@(x, y) Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage1_rpn, x, y), dataset.imdb_train, dataset.roidb_train, 'UniformOutput', false);
dataset.roidb_test          = Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage1_rpn, dataset.imdb_test, dataset.roidb_test);

%%  stage one fast rcnn
% train
model.stage1_fast_rcnn      = Faster_RCNN_Train.do_fast_rcnn_train(conf_fast_rcnn, dataset, model.stage1_fast_rcnn, opts.do_val);
% test
opts.mAP                    = Faster_RCNN_Train.do_fast_rcnn_test(conf_fast_rcnn, model.stage1_fast_rcnn, dataset.imdb_test, dataset.roidb_test);

%%  stage two proposal
% net proposal
% train
model.stage2_rpn.init_net_file = model.stage1_fast_rcnn.output_model_file;
model.stage2_rpn            = Faster_RCNN_Train.do_proposal_train(conf_proposal, dataset, model.stage2_rpn, opts.do_val);
% test
dataset.roidb_train         = cellfun(@(x, y) Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage2_rpn, x, y), dataset.imdb_train, dataset.roidb_train, 'UniformOutput', false);
dataset.roidb_test          = Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage2_rpn, dataset.imdb_test, dataset.roidb_test);

%%  stage two fast rcnn
% train
model.stage2_fast_rcnn.init_net_file = model.stage1_fast_rcnn.output_model_file;
model.stage2_fast_rcnn      = Faster_RCNN_Train.do_fast_rcnn_train(conf_fast_rcnn, dataset, model.stage2_fast_rcnn, opts.do_val);

do_proposal_train代碼如下,采樣時(shí)并不是整張圖像的每個(gè)位置都參與梯度反傳槽卫,而是通過隨機(jī)采樣的方式?jīng)Q定哪些前景或背景的rois參與訓(xùn)練跟压,參與訓(xùn)練權(quán)重為1,否則置為0歼培。這樣可以保證背景和前景的數(shù)量不至于懸殊太大震蒋。

    % Preparing training data
    [image_roidb_train, bbox_means, bbox_stds]...
                            = proposal_prepare_image_roidb(conf, opts.imdb_train, opts.roidb_train);

    while (iter_ < max_iter)
        caffe_solver.net.set_phase('train');

        % generate minibatch training data
        [shuffled_inds, sub_db_inds] = generate_random_minibatch(shuffled_inds, image_roidb_train, conf.ims_per_batch);        
        [net_inputs, scale_inds] = proposal_generate_minibatch_fun(conf, image_roidb_train(sub_db_inds));
        
        caffe_solver.net.reshape_as_input(net_inputs);

        % one iter SGD update
        caffe_solver.net.set_input_data(net_inputs);
        caffe_solver.step(1);
        iter_ = caffe_solver.iter();
    end

檢測代碼

  • 初始化模型
model_dir = fullfile(pwd, 'output', 'faster_rcnn_final', 'faster_rcnn_VOC0712_ZF'); 
proposal_detection_model    = load_proposal_detection_model(model_dir);
proposal_detection_model.conf_proposal.test_scales = opts.test_scales;
proposal_detection_model.conf_detection.test_scales = opts.test_scales;
rpn_net = caffe.Net(proposal_detection_model.proposal_net_def, 'test');
rpn_net.copy_from(proposal_detection_model.proposal_net);
fast_rcnn_net = caffe.Net(proposal_detection_model.detection_net_def, 'test');
fast_rcnn_net.copy_from(proposal_detection_model.detection_net);
  • 提取proposal
    首先將輸入圖像縮放到目標(biāo)尺度,然后調(diào)整圖像的維度順序躲庄,輸入送進(jìn)網(wǎng)絡(luò)得到輸出查剖,通過bbox的損失預(yù)測bbox的位置,最后對每個(gè)bbox的分?jǐn)?shù)排序噪窘,取高分bbox作為proposal笋庄。
    [im_blob, im_scales] = get_image_blob(conf, im);
    im_size = size(im);
    scaled_im_size = round(im_size * im_scales);
    
    im_blob = im_blob(:, :, [3, 2, 1], :); % from rgb to brg
    im_blob = permute(im_blob, [2, 1, 3, 4]);
    im_blob = single(im_blob);

    net_inputs = {im_blob};

    caffe_net.reshape_as_input(net_inputs);
    output_blobs = caffe_net.forward(net_inputs);

    box_deltas = output_blobs{1};
    featuremap_size = [size(box_deltas, 2), size(box_deltas, 1)];
    box_deltas = permute(box_deltas, [3, 2, 1]);
    box_deltas = reshape(box_deltas, 4, [])';
    
    anchors = proposal_locate_anchors(conf, size(im), conf.test_scales, featuremap_size);
    pred_boxes = fast_rcnn_bbox_transform_inv(anchors, box_deltas);
    
    scores = output_blobs{2}(:, :, end);
    scores = reshape(scores, size(output_blobs{1}, 1), size(output_blobs{1}, 2), []);
    scores = permute(scores, [3, 2, 1]);
    scores = scores(:);

    [scores, scores_ind] = sort(scores, 'descend');
    pred_boxes = pred_boxes(scores_ind, :);
  • 開始檢測
    檢測階段,將rpn網(wǎng)絡(luò)的最后一個(gè)卷積層和rois作為輸入送入fast-rcnn網(wǎng)絡(luò)倔监,輸出結(jié)果為類標(biāo)簽和回歸之后的bbox直砂。
    caffe_net.blobs('data').copy_data_from(conv_feat_blob);
    net_inputs = {[], sub_rois_blob};

    % Reshape net's input blobs
    caffe_net.reshape_as_input(net_inputs);
    output_blobs = caffe_net.forward(net_inputs);
    
    pred_boxes = fast_rcnn_bbox_transform_inv(boxes, box_deltas);
    pred_boxes = clip_boxes(pred_boxes, size(im, 2), size(im, 1));

【參考文獻(xiàn)】
http://blog.csdn.net/Seven_year_Promise/article/details/60954553
http://blog.csdn.net/mllearnertj/article/details/53709766

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市丐枉,隨后出現(xiàn)的幾起案子哆键,更是在濱河造成了極大的恐慌,老刑警劉巖瘦锹,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件籍嘹,死亡現(xiàn)場離奇詭異闪盔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)辱士,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進(jìn)店門泪掀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人颂碘,你說我怎么就攤上這事异赫。” “怎么了头岔?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵塔拳,是天一觀的道長。 經(jīng)常有香客問我峡竣,道長靠抑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任适掰,我火速辦了婚禮颂碧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘类浪。我一直安慰自己载城,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布费就。 她就那樣靜靜地躺著诉瓦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪受楼。 梳的紋絲不亂的頭發(fā)上垦搬,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天,我揣著相機(jī)與錄音艳汽,去河邊找鬼猴贰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛河狐,可吹牛的內(nèi)容都是我干的米绕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼馋艺,長吁一口氣:“原來是場噩夢啊……” “哼栅干!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捐祠,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤碱鳞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后踱蛀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窿给,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贵白,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了崩泡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片禁荒。...
    茶點(diǎn)故事閱讀 40,021評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖角撞,靈堂內(nèi)的尸體忽然破棺而出呛伴,到底是詐尸還是另有隱情,我是刑警寧澤谒所,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布热康,位于F島的核電站,受9級特大地震影響劣领,放射性物質(zhì)發(fā)生泄漏褐隆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一剖踊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衫贬,春花似錦德澈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至葬毫,卻和暖如春镇辉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贴捡。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工忽肛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烂斋。 一個(gè)月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓屹逛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親汛骂。 傳聞我的和親對象是個(gè)殘疾皇子罕模,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容