轉 Yolov3轉化Caffe框架詳解


轉自https://blog.csdn.net/watermelon1123/article/details/82083522
前些日子因工程需求,需要將yolov3從基於darknet轉化為基於Caffe框架,過程中踩了一些坑,特在此記錄一下。

1.Yolov3的網絡結構

想要轉化為Caffe框架,就要先了解yolov3的網絡結構,如下圖。

    如果有運行過darknet應該會很熟悉,這是darknet運行成功后打印log信息,這里面包含了yolo網絡結構的一些信息。yolov3與v2相比,網絡結構中加入了殘差(shortcut層),並且引入了上采樣(upsample層),並為了將采樣后的特征圖進行融合引入了拼接(route層),最后融合的特征圖以三個不同的大小13*13*75,26*26*75,52*52*75輸入給yolo層最后得到目標的位置及分類信息,加上卷積層convolution,這些便是yolov3的網絡基本構造。因此只要我們如果在Caffe中找到對應的層按照相應的進行構造就能夠使用Caffe實現yolov3了。

    卷積層不說,yolov3中的shortcut層可以用eltwise替代,route層可以用concat替代,而upsample層和yolo層則需要自己實現,並添加到Caffe中即可。upsample層主要完成了上采樣的工作,這里不細說。本文主要講一下yolo層如何實現,上圖中的YOLO Detection即為yolo層的所在位置,接收三種不同大小的特征圖,並完成對特征圖的解析,得到物體的位置和類別信息。所以其實yolo層主要起到了解析特征並輸出檢測結果的作用,這一過程我們完全可以在外部實現而無需加入到網絡結構當中,也就是說我們無需將實現的yolo層加入到Caffe當中去。

 

 

    通過上圖(我自己花的靈魂解析圖,湊活看吧),可以解釋yolo層如何得到檢測目標的位置和分類。Yolo層的input是一個13*13*N的特征圖,其中13*13如果有看過yolov1的論文作者有給出過解釋,其實就是圖像被分成了13*13個grid cell,而每個grid中是一個長度為N的張量,其中的數據是這樣分布的,前4個位置分別為x,y,w,h,用於計算目標框的位置;第5個位置為置信度值Pr(object)*IOU,表明了該位置的目標框包含目標的置信度;第5個位置往后則為該box包含物體類別的條件概率Pr(class|object),從class1~class n,n為你所需檢測類別數。這樣(x,y,w,h)+ Pr(object)*IOU + n*Pr(class|object)構成了box1的所有信息,而一個grid cell中含有3個這樣的boxes,這就是輸入到yolo層的特征圖的直觀解釋。在yolo層進行檢測的時候,首先判定每個box的包含物體的置信度值即p的值是否大於設定閾值thresh,如果大於該閾值則認為這個box中含有物體,讀取位置信息(x,y,w,h)與對應的anchor box的信息計算得到物體框的實際位置。之后針對於每個含有物體的box,根據其類別概率判定其類別所屬,再對同一類別的目標框進行非極大值抑制NMS,即得到最終結果。

    以上即為yolo層所實現的檢測過程簡要介紹,具體的過程如何計算還需要看官們仔細看一下代碼和論文,當然此過程不包括訓練的前向和反向過程,僅包含推理。因此我們轉換到Caffe框架下的yolov3也僅能實現推理過程,具體的訓練還需要通過darknet來完成。

2.如何實現

    下面這部分將着重講一下如何實現從darknet向yolov3的轉換,首先這一過程要感謝chenyingpeng提供的代碼,博客在這里

1.加入upsample層並編譯Caffe

upsample層的代碼在這里,密碼bwrd。

其中的upsample_layer.hpp放入include/caffe/layers下面;upsample_layer.cpp與upsample_layer.cu放在src/caffe/layers下面。

修改相應的caffe.proto文件,src/caffe/proto/caffe.proto中的LayerParameter的最后一行加入加入:

message LayerParameter {
    .....
    optional UpsampleParameter upsample_param = 149;
}

注意149為新層的ID號,該ID號請根據個人的caffe.proto文件指定即可。

然后再caffe.proto中添加upsample層的參數:

message UpsampleParameter{
  optional int32 scale = 1 [default = 1];
}

緊接着重新編譯Caffe,這樣就完成了在Caffe中添加upsample層。更多信息請參考caffe中添加新層教程

上面說過轉換到Caffe后只包含推理過程,因此我們需要將訓練好的模型(.cfg)和權重文件(.weights)轉換到對應Caffe下的.proto和.caffemodel,代碼可以借鑒github上的模型轉換工具。注意該工具需要pytorch支持請自行安裝。且該工具應用於Yolov2,因為我們在Caffe中加入了相應的upsample層並且yolov3和v2的網絡結構有變化,因此需要替換相應的darknet2caffe.py,代碼在這里,密碼:i6y2。

至此我們的准備工作就結束了,這樣通過Caffe我們就能得到相應的blobs,這些blobs里包含的信息和darknet輸入給yolo層的信息是一樣的。我們只需要通過yolo layer將blobs的信息進行解析就能夠得到目標的位置和類別信息。因為私人原因,這部分代碼不能開放,但是可以參考chenyingpeng的代碼,在這里。經測試是同樣可用的,只需要注意因為我們的yolo layer的檢測過程是在Caffe外部實現的,因此yolo layer層的相應信息作者以硬編碼的形式加入到代碼中,使用的時候需要根據個人yolo layer的參數進行修改(比如我測試的時候yolo_layer.cpp中的函數get_detections中的類別數目沒有修改就發生了難以言表的結果...)。

   yolov3從darknet轉Caffe的整個過程就結束了,其中關於yolov3的原理並沒有詳細解釋特別多,本文主要着重於和轉到Caffe框架相關的內容,具體yolov3的原理性文章推薦大家看這篇,里面關於yolov1~v3講解的很詳細(來自一群還在上大一的學生的論文解讀,不禁讓人感嘆長江后浪推前浪,前浪我已GG)。關於yolov3的訓練代碼,推薦大家去看darknet的源碼,尤其是關於Yolo layer的代碼,里面有許多作者文章里沒有講清楚的內容,感興趣的可以仔細鑽研一下。

   本人才疏學淺,本文僅是最近工程實踐中的一點成果,如有錯誤還望指正。

   

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM