Caffe(12)--實現YOLOv2目標檢測
DarkNet轉Caffe中有很多潛在的問題,在YOLOv1、v2、v3幾個網路中有一些特殊的層。要在Caffe中跑YOLO,就得在Caffe中原始碼實現這些層。這些層的Caffe原始碼實現可以在網上找到很多。
YOLO特殊層的Caffe框架實現 | ||
---|---|---|
YOLOv1 | detection層 | 原始碼實現 |
YOLOv2 | route層 | 用concat層替換 |
reorg層 | 原始碼實現 | |
region層 | 原始碼實現 | |
YOLOv3 | shortcut層 | 用eltwise層實現 |
route層 | 用concat層實現 | |
yolo層 | 原始碼實現 |
在Caffe平臺實現YOLO系列,可以分成以下兩種方式:
(1)DarkNet平臺訓練完成YOLO模型,然後將
.cfg檔案
和.weights檔案
通過指令碼轉換為Caffe框架下的.prototxt檔案
和.caffemodel檔案
,最後在Caffe下使用轉換好的.prototxt檔案
和.caffemodel
檔案進行目標檢測任務。(2)手動寫好
.prototxt模型結構檔案
,直接在Caffe下進行訓練,訓練完成後進行目標檢測任務。
以上兩種方式,都是以當前Caffe已經原始碼實現上面那幾個特殊層為前提。
具體按哪種方式看自己實際需求,比如,我現在是已經有在DarkNet下訓練好可用YOLOv2_tiny模型,所以我選擇將訓練好的模型轉換到Caffe再使用,而不是從頭訓練。個人感覺YOLO在原生框架DarkNet下訓練起來更方便一些,更重要的是,在Caffe實現YOLO後可以將中間引數以及輸出結果拿出來,再和DarkNet下的YOLO做對比分析,這點還是很關鍵的,相同的模型結構和權重引數,經過對比可以很清楚的知道轉換是否正確、Caffe新加層實現是否正確。
1、YOLOv1
YOLOv1主要是需要實現detection層,再就是YOLO系列中使用的啟用函式是Leaky,可以選擇單獨實現,也可以用ReLU實現(配置引數)。
2、YOLOv2
重點說YOLOv2的實現,YOLOv2的Caffe實現就已經很多了,網上可以找到很多個版本,都挺好的,但也都存在的不同的問題。
上面幾個都有很大的參考價值,綜合以上和其他一些實現,踩了很多坑,總算是把這條路走下來了。
具體步驟如下(以YOLOv2_tiny為例):
這裡有個問題需要注意!!!
下圖中,對於YOLOv2_tiny,416*416
的輸入,經過最後一個max pool(size=2,stride=1)
13*13
處理後還是13*13
。這就有點問題了,測試發現,Caffe中經過這一層特徵圖由
13*13
變成了12*12
,會導致在Caffe下檢測結果的box有偏差。解決方案:對這層max pool使用pad,由於Caffe和DarkNet對pool的處理邏輯有些差異,需要指定DarkNet中該層padding=2,Caffe種該層pad=1
。
去看DarkNet原始碼maxpool_layer.c
發現:
簡單說一下,在DarkNet中有pad和padding兩個東西,是不一樣的,重點體現在卷積層中,而對於池化層就沒那麼複雜了,用padding指定引數就行。
處理之後,經該max pool層處理特徵圖會由13*13變為14*14
,DarkNet和Caffe兩個框架下達成統一。
(3)模型轉換
使用指令碼將.cfg檔案和.weights檔案
轉換為.prototxt檔案和.caffemodel檔案
。
模型轉換參考:https://github.com/lwplw/darknet2caffe
(4)在Caffe框架下進行測試
1)下載caffe_yolov2原始碼:https://github.com/lwplw/caffe_yolov2
2)解壓得到資料夾caffe_yolov2-master
3)編譯安裝
make all -j8
sudo make pycaffe -j8
4)測試
進入caffe_yolov2-master/examples/yolov2
目錄下,執行命令:python detect.py
注:具體測試時使用的資料集,以及測多少張等,自行在指令碼detect.py中進行修改。