1. 程式人生 > >目標檢測|YOLOv2原理與實現(附YOLOv3)

目標檢測|YOLOv2原理與實現(附YOLOv3)

作者:葉虎     

編輯:李雪冬   

前  言


在前面的一篇文章中,我們詳細介紹了YOLOv1的原理以及實現過程。這篇文章接著介紹YOLOv2的原理以及實現,YOLOv2的論文全名為YOLO9000: Better, Faster, Stronger,它斬獲了CVPR 2017 Best Paper Honorable Mention。在這篇文章中,作者首先在YOLOv1的基礎上提出了改進的YOLOv2,然後提出了一種檢測與分類聯合訓練方法,使用這種聯合訓練方法在COCO檢測資料集和ImageNet分類資料集上訓練出了YOLO9000模型,其可以檢測超過9000多類物體。所以,這篇文章其實包含兩個模型:YOLOv2和YOLO9000,不過後者是在前者基礎上提出的,兩者模型主體結構是一致的。YOLOv2相比YOLOv1做了很多方面的改進,這也使得YOLOv2的mAP有顯著的提升,並且YOLOv2的速度依然很快,保持著自己作為one-stage方法的優勢,YOLOv2和Faster R-CNN, SSD等模型的對比如圖1所示。這裡將首先介紹YOLOv2的改進策略,並給出YOLOv2的TensorFlow實現過程,然後介紹YOLO9000的訓練方法。近期,YOLOv3也放出來了,YOLOv3也在YOLOv2的基礎上做了一部分改進,我們在最後也會簡單談談YOLOv3所做的改進工作。

640?wx_fmt=png&wxfrom=5&wx_lazy=1

圖1:YOLOv2與其它模型在VOC 2007資料集上的效果對比

1

YOLOv2的改進策略

YOLOv1雖然檢測速度很快,但是在檢測精度上卻不如R-CNN系檢測方法,YOLOv1在物體定位方面(localization)不夠準確,並且召回率(recall)較低。YOLOv2共提出了幾種改進策略來提升YOLO模型的定位準確度和召回率,從而提高mAP,YOLOv2在改進中遵循一個原則:保持檢測速度,這也是YOLO模型的一大優勢。YOLOv2的改進策略如圖2所示,可以看出,大部分的改進方法都可以比較顯著提升模型的mAP。下面詳細介紹各個改進策略。

640?wx_fmt=png

圖2:YOLOv2相比YOLOv1的改進策略

(1)Batch Normalization

Batch Normalization可以提升模型收斂速度,而且可以起到一定正則化效果,降低模型的過擬合。在YOLOv2中,每個卷積層後面都添加了Batch Normalization層,並且不再使用droput。使用Batch Normalization後,YOLOv2的mAP提升了2.4%。

(2)High Resolution Classifier

目前大部分的檢測模型都會在先在ImageNet分類資料集上預訓練模型的主體部分(CNN特徵提取器),由於歷史原因,ImageNet分類模型基本採用大小為

640?wx_fmt=png的圖片作為輸入,解析度相對較低,不利於檢測模型。所以YOLOv1在採用640?wx_fmt=png分類模型預訓練後,將解析度增加至

640?wx_fmt=png,並使用這個高解析度在檢測資料集上finetune。但是直接切換解析度,檢測模型可能難以快速適應高解析度。所以YOLOv2增加了在ImageNet資料集上使用640?wx_fmt=png來finetune分類網路這一中間過程(10 epochs),這可以使得模型在檢測資料集上finetune之前已經適用高解析度輸入。使用高解析度分類器後,YOLOv2的mAP提升了約4%。

(3)Convolutionlal With Anchor Boxes

在YOLOv1中,輸入圖片最終被劃分為7*7網格,每個單元格預測2個邊界框。YOLOv1最後採用的是全連線層直接對邊界框進行預測,其中邊界框的寬與高是相對整張圖片大小的,而由於各個圖片中存在不同尺度和長寬比(scales and ratios)的物體,YOLOv1在訓練過程中學習適應不同物體的形狀是比較困難的,這也導致YOLOv1在精確定位方面表現較差。YOLOv2借鑑了Faster R-CNN中RPN網路的先驗框(anchor boxes,prior boxes,SSD也採用了先驗框)策略。RPN對CNN特徵提取器得到的特徵圖(feature map)進行卷積來預測每個位置的邊界框以及置信度(是否含有物體),並且各個位置設定不同尺度和比例的先驗框,所以RPN預測的是邊界框相對於先驗框的offsets值(其實是transform值,詳細見Faster R_CNN論文),採用先驗框使得模型更容易學習。所以YOLOv2移除了YOLOv1中的全連線層而採用了卷積和anchor boxes來預測邊界框。為了使檢測所用的特徵圖解析度更高,移除其中的一個pool層。在檢測模型中,YOLOv2不是採481*418圖片作為輸入,而是採用416*416大小。因為YOLOv2模型下采樣的總步長為32,對於416*416大小的圖片,最終得到的特徵圖大小為13*13,維度是奇數,這樣特徵圖恰好只有一箇中心位置。對於一些大物體,它們中心點往往落入圖片中心位置,此時使用特徵圖的一箇中心點去預測這些物體的邊界框相對容易些。所以在YOLOv2設計中要保證最終的特徵圖有奇數個位置。對於YOLOv1,每個cell都預測2個boxes,每個boxes包含5個值:640?wx_fmt=png前4個值是邊界框位置與大小,最後一個值是置信度(confidence scores,包含兩部分:含有物體的概率以及預測框與ground truth的IOU)。但是每個cell只預測一套分類概率值(class predictions,其實是置信度下的條件概率值),供2個boxes共享。YOLOv2使用了anchor boxes之後,每個位置的各個anchor box都單獨預測一套分類概率值,這和SSD比較類似(但SSD沒有預測置信度,而是把background作為一個類別來處理)。

使用anchor boxes之後,YOLOv2的mAP有稍微下降(這裡下降的原因,我猜想是YOLOv2雖然使用了anchor boxes,但是依然採用YOLOv1的訓練方法)。YOLOv1只能預測98個邊界框640?wx_fmt=png,而YOLOv2使用anchor boxes之後可以預測上千個邊界框640?wx_fmt=png。所以使用anchor boxes之後,YOLOv2的召回率大大提升,由原來的81%升至88%。

(4)Dimension Clusters

在Faster R-CNN和SSD中,先驗框的維度(長和寬)都是手動設定的,帶有一定的主觀性。如果選取的先驗框維度比較合適,那麼模型更容易學習,從而做出更好的預測。因此,YOLOv2採用k-means聚類方法對訓練集中的邊界框做了聚類分析。因為設定先驗框的主要目的是為了使得預測框與ground truth的IOU更好,所以聚類分析時選用box與聚類中心box之間的IOU值作為距離指標: 

640?wx_fmt=png

圖3為在VOC和COCO資料集上的聚類分析結果,隨著聚類中心數目的增加,平均IOU值(各個邊界框與聚類中心的IOU的平均值)是增加的,但是綜合考慮模型複雜度和召回率,作者最終選取5個聚類中心作為先驗框,其相對於圖片的大小如右邊圖所示。對於兩個資料集,5個先驗框的width和height如下所示(來源:YOLO原始碼的cfg檔案):

COCO: (0.57273, 0.677385), (1.87446, 2.06253), (3.33843, 5.47434), (7.88282, 3.52778), (9.77052, 9.16828)
VOC: (1.3221, 1.73145), (3.19275, 4.00944), (5.05587, 8.09892), (9.47112, 4.84053), (11.2364, 10.0071)

但是這裡先驗框的大小具體指什麼作者並沒有說明,但肯定不是畫素點,從程式碼實現上看,應該是相對於預測的特徵圖大小(13*13)。對比兩個資料集,也可以看到COCO資料集上的物體相對小點。這個策略作者並沒有單獨做實驗,但是作者對比了採用聚類分析得到的先驗框與手動設定的先驗框在平均IOU上的差異,發現前者的平均IOU值更高,因此模型更容易訓練學習。

640?wx_fmt=png

圖3:資料集VOC和COCO上的邊界框聚類分析結果

(5) New Network:Darknet-19

YOLOv2採用了一個新的基礎模型(特徵提取器),稱為Darknet-19,包括19個卷積層和5個maxpooling層,如圖4所示。Darknet-19與VGG16模型設計原則是一致的,主要採用3*3卷積,採用2*2的maxpooling層之後,特徵圖維度降低2倍,而同時將特徵圖的channles增加兩倍。與NIN(Network in Network)類似,Darknet-19最終採用global avgpooling做預測,並且在3*3卷積之間使用1*1卷積來壓縮特徵圖channles以降低模型計算量和引數。Darknet-19每個卷積層後面同樣使用了batch norm層以加快收斂速度,降低模型過擬合。在ImageNet分類資料集上,Darknet-19的top-1準確度為72.9%,top-5準確度為91.2%,但是模型引數相對小一些。使用Darknet-19之後,YOLOv2的mAP值沒有顯著提升,但是計算量卻可以減少約33%。

640?wx_fmt=png

圖4:Darknet-19模型結構

(6) Direct location prediction

前面講到,YOLOv2借鑑RPN網路使用anchor boxes來預測邊界框相對先驗框的offsets。邊界框的實際中心位置640?wx_fmt=png,需要根據預測的座標偏移值640?wx_fmt=png,先驗框的尺度640?wx_fmt=jpeg以及中心座標640?wx_fmt=png(特徵圖每個位置的中心點)來計算:

640?wx_fmt=png

 但是上面的公式是無約束的,預測的邊界框很容易向任何方向偏移,如當640?wx_fmt=png時邊界框將向右偏移先驗框的一個寬度大小,而當640?wx_fmt=png時邊界框將向左偏移先驗框的一個寬度大小,因此每個位置預測的邊界框可以落在圖片任何位置,這導致模型的不穩定性,在訓練時需要很長時間來預測出正確的offsets。所以,YOLOv2棄用了這種預測方式,而是沿用YOLOv1的方法,就是預測邊界框中心點相對於對應cell左上角位置的相對偏移值,為了將邊界框中心點約束在當前cell中,使用sigmoid函式處理偏移值,這樣預測的偏移值在(0,1)範圍內(每個cell的尺度看做1)。總結來看,根據邊界框預測的4個offsets640?wx_fmt=png,可以按如下公式計算出邊界框實際位置和大小: 

640?wx_fmt=png

其中640?wx_fmt=png為cell的左上角座標,如圖5所示,在計算時每個cell的尺度為1,所以當前cell的左上角座標為640?wx_fmt=png。由於sigmoid函式的處理,邊界框的中心位置會約束在當前cell內部,防止偏移過多。而640?wx_fmt=png640?wx_fmt=png是先驗框的寬度與長度,前面說過它們的值也是相對於特徵圖大小的,在特徵圖中每個cell的長和寬均為1。這裡記特徵圖的大小為640?wx_fmt=png(在文中是640?wx_fmt=png),這樣我們可以將邊界框相對於整張圖片的位置和大小計算出來(4個值均在0和1之間): 

640?wx_fmt=png

如果再將上面的4個值分別乘以圖片的寬度和長度(畫素點值)就可以得到邊界框的最終位置和大小了。這就是YOLOv2邊界框的整個解碼過程。約束了邊界框的位置預測值使得模型更容易穩定訓練,結合聚類分析得到先驗框與這種預測方法,YOLOv2的mAP值提升了約5%。

640?wx_fmt=png

圖5:邊界框位置與大小的計算示例圖

(7)Fine-Grained Features  

YOLOv2的輸入圖片大小為416*416,經過5次maxpooling之後得到13*13大小的特徵圖,並以此特徵圖採用卷積做預測。13*13大小的特徵圖對檢測大物體是足夠了,但是對於小物體還需要更精細的特徵圖(Fine-Grained Features)。因此SSD使用了多尺度的特徵圖來分別檢測不同大小的物體,前面更精細的特徵圖可以用來預測小物體。YOLOv2提出了一種passthrough層來利用更精細的特徵圖。YOLOv2所利用的Fine-Grained Features是26*26大小的特徵圖(最後一個maxpooling層的輸入),對於Darknet-19模型來說就是大小為26*26*512的特徵圖。passthrough層與ResNet網路的shortcut類似,以前面更高解析度的特徵圖為輸入,然後將其連線到後面的低解析度特徵圖上。前面的特徵圖維度是後面的特徵圖的2倍,passthrough層抽取前面層的每個2*2的區域性區域,然後將其轉化為channel維度,對於26*26*512的特徵圖,經passthrough層處理之後就變成了13*13*2048的新特徵圖(特徵圖大小降低4倍,而channles增加4倍,圖6為一個例項),這樣就可以與後面的13*13*1024特徵圖連線在一起形成13*13*3072的特徵圖,然後在此特徵圖基礎上卷積做預測。在YOLO的C原始碼中,passthrough層稱為reorg layer。在TensorFlow中,可以使用tf.extract_image_patches或者tf.space_to_depth來實現passthrough層:

out = tf.extract_image_patches(in, [1, stride, stride, 1], [1, stride, stride, 1], [1,1,1,1], padding="VALID")
// or use tf.space_to_depth
out = tf.space_to_depth(in, 2)

640?wx_fmt=jpeg

圖6:passthrough層例項

另外,作者在後期的實現中借鑑了ResNet網路,不是直接對高分辨特徵圖處理,而是增加了一箇中間卷積層,先採用64個1*1卷積核進行卷積,然後再進行passthrough處理,這樣26*26*512的特徵圖得到13*13*256的特徵圖。這算是實現上的一個小細節。使用Fine-Grained Features之後YOLOv2的效能有1%的提升。

(8)Multi-Scale Training

由於YOLOv2模型中只有卷積層和池化層,所以YOLOv2的輸入可以不限於416*416大小的圖片。為了增強模型的魯棒性,YOLOv2採用了多尺度輸入訓練策略,具體來說就是在訓練過程中每間隔一定的iterations之後改變模型的輸入圖片大小。由於YOLOv2的下采樣總步長為32,輸入圖片大小選擇一系列為32倍數的值:640?wx_fmt=png輸入圖片最小為320*320,此時對應的特徵圖大小為10*10(不是奇數了,確實有點尷尬),而輸入圖片最大為608*608,對應的特徵圖大小為19*19,在訓練過程,每隔10個iterations隨機選擇一種輸入圖片大小,然後只需要修改對最後檢測層的處理就可以重新訓練。 

640?wx_fmt=png

圖7:Multi-Scale Training

採用Multi-Scale Training策略,YOLOv2可以適應不同大小的圖片,並且預測出很好的結果。在測試時,YOLOv2可以採用不同大小的圖片作為輸入,在VOC 2007資料集上的效果如下圖所示。可以看到採用較小解析度時,YOLOv2的mAP值略低,但是速度更快,而採用高分辨輸入時,mAP值更高,但是速度略有下降,對於544*544,mAP高達78.6%。注意,這只是測試時輸入圖片大小不同,而實際上用的是同一個模型(採用Multi-Scale Training訓練)。 

640?wx_fmt=png

圖8:YOLOv2在VOC 2007資料集上的效能對比

總結來看,雖然YOLOv2做了很多改進,但是大部分都是借鑑其它論文的一些技巧,如Faster R-CNN的anchor boxes,YOLOv2採用anchor boxes和卷積做預測,這基本上與SSD模型(單尺度特徵圖的SSD)非常類似了,而且SSD也是借鑑了Faster R-CNN的RPN網路。從某種意義上來說,YOLOv2和SSD這兩個one-stage模型與RPN網路本質上無異,只不過RPN不做類別的預測,只是簡單地區分物體與背景。在two-stage方法中,RPN起到的作用是給出region proposals,其實就是作出粗糙的檢測,所以另外增加了一個stage,即採用R-CNN網路來進一步提升檢測的準確度(包括給出類別預測)。而對於one-stage方法,它們想要一步到位,直接採用“RPN”網路作出精確的預測,要因此要在網路設計上做很多的tricks。YOLOv2的一大創新是採用Multi-Scale Training策略,這樣同一個模型其實就可以適應多種大小的圖片了。

2

YOLOv2的訓練

YOLOv2的訓練主要包括三個階段。第一階段就是先在ImageNet分類資料集上預訓練Darknet-19,此時模型輸入為224*224,共訓練160個epochs。然後第二階段將網路的輸入調整為448*448,繼續在ImageNet資料集上finetune分類模型,訓練10個epochs,此時分類模型的top-1準確度為76.5%,而top-5準確度為93.3%。第三個階段就是修改Darknet-19分類模型為檢測模型,並在檢測資料集上繼續finetune網路。網路修改包括(網路結構視覺化):移除最後一個卷積層、global avgpooling層以及softmax層,並且新增了三個3*3*2014卷積層,同時增加了一個passthrough層,最後使用1*1卷積層輸出預測結果,輸出的channels數為:640?wx_fmt=png,和訓練採用的資料集有關係。由於anchors數為5,對於VOC資料集輸出的channels數就是125,而對於COCO資料集則為425。這裡以VOC資料集為例,最終的預測矩陣為T(shape為640?wx_fmt=png),可以先將其reshape為

640?wx_fmt=png其中640?wx_fmt=png為邊界框的位置和大小

640?wx_fmt=png640?wx_fmt=png為邊界框的置信度,而640?wx_fmt=png為類別預測值。

640?wx_fmt=png

圖9:YOLOv2訓練的三個階段

640?wx_fmt=png

圖10:YOLOv2結構示意圖

YOLOv2的網路結構以及訓練引數我們都知道了,但是貌似少了點東西。仔細一想,原來作者並沒有給出YOLOv2的訓練過程的兩個最重要方面,即先驗框匹配(樣本選擇)以及訓練的損失函式,難怪Ng說YOLO論文很難懂,沒有這兩方面的說明我們確實不知道YOLOv2到底是怎麼訓練起來的。不過預設按照YOLOv1的處理方式也是可以處理,我看了YOLO在TensorFlow上的實現darkflow(見yolov2/train.py),發現它就是如此處理的:和YOLOv1一樣,對於訓練圖片中的ground truth,若其中心點落在某個cell內,那麼該cell內的5個先驗框所對應的邊界框負責預測它,具體是哪個邊界框預測它,需要在訓練中確定,即由那個與ground truth的IOU最大的邊界框預測它,而剩餘的4個邊界框不與該ground truth匹配。YOLOv2同樣需要假定每個cell至多含有一個grounth truth,而在實際上基本不會出現多於1個的情況。與ground truth匹配的先驗框計算座標誤差、置信度誤差(此時target為1)以及分類誤差,而其它的邊界框只計算置信度誤差(此時target為0)。YOLOv2和YOLOv1的損失函式一樣,為均方差函式。但是我看了YOLOv2的原始碼(訓練樣本處理與loss計算都包含在檔案region_layer.c中,YOLO原始碼沒有任何註釋,反正我看了是直搖頭),並且參考國外的blog以及allanzelener/YAD2K(Ng深度學習教程所參考的那個Keras實現)上的實現,發現YOLOv2的處理比原來的v1版本更加複雜。先給出loss計算公式:

640?wx_fmt=png

我們來一點點解釋,首先W,H分別指的是特徵圖(13*13)的寬與高,而A指的是先驗框數目(這裡是5),各個640?wx_fmt=png值是各個loss部分的權重係數。第一項loss是計算background的置信度誤差,但是哪些預測框來預測背景呢,需要先計算各個預測框和所有ground truth的IOU值,並且取最大值Max_IOU,如果該值小於一定的閾值(YOLOv2使用的是0.6),那麼這個預測框就標記為background,需要計算noobj的置信度誤差。第二項是計算先驗框與預測寬的座標誤差,但是隻在前12800個iterations間計算,我覺得這項應該是在訓練前期使預測框快速學習到先驗框的形狀。第三大項計算與某個ground truth匹配的預測框各部分loss值,包括座標誤差、置信度誤差以及分類誤差。先說一下匹配原則,對於某個ground truth,首先要確定其中心點要落在哪個cell上,然後計算這個cell的5個先驗框與ground truth的IOU值(YOLOv2中bias_match=1),計算IOU值時不考慮座標,只考慮形狀,所以先將先驗框與ground truth的中心點都偏移到同一位置(原點),然後計算出對應的IOU值,IOU值最大的那個先驗框與ground truth匹配,對應的預測框用來預測這個ground truth。在計算obj置信度時,在YOLOv1中target=1,而YOLOv2增加了一個控制引數rescore,當其為1時,target取預測框與ground truth的真實IOU值。對於那些沒有與ground truth匹配的先驗框(與預測框對應),除去那些Max_IOU低於閾值的,其它的就全部忽略,不計算任何誤差。這點在YOLOv3論文中也有相關說明:YOLO中一個ground truth只會與一個先驗框匹配(IOU值最好的),對於那些IOU值超過一定閾值的先驗框,其預測結果就忽略了。這和SSD與RPN網路的處理方式有很大不同,因為它們可以將一個ground truth分配給多個先驗框。儘管YOLOv2和YOLOv1計算loss處理上有不同,但都是採用均方差來計算loss。另外需要注意的一點是,在計算boxes的誤差時,YOLOv1中採用的是平方根以降低boxes的大小對誤差的影響,而YOLOv2是直接計算,但是根據ground truth的大小對權重係數進行修正:l.coord_scale * (2 - truth.w*truth.h),這樣對於尺度較小的boxes其權重係數會更大一些,起到和YOLOv1計算平方根相似的效果(參考YOLO v2 損失函式原始碼分析)。

最終的YOLOv2模型在速度上比YOLOv1還快(採用了計算量更少的Darknet-19模型),而且模型的準確度比YOLOv1有顯著提升,詳情見paper。

3

YOLOv2在TensorFlow上實現

這裡參考YOLOv2在Keras上的復現(見yhcc/yolo2),使用TensorFlow實現YOLOv2在COCO資料集上的test過程。首先是定義YOLOv2的主體網路結構Darknet-19:

def darknet(images, n_last_channels=425):
   """Darknet19 for YOLOv2"""
   net
= conv2d(images, 32, 3, 1, name="conv1")
   net = maxpool(net, name="pool1")
   net = conv2d(net, 64, 3, 1, name="conv2")
   net = maxpool(net, name="pool2")
   net = conv2d(net, 128, 3, 1, name="conv3_1")
   net = conv2d(net, 64, 1, name="conv3_2")
   net = conv2d(net, 128, 3, 1, name="conv3_3")
   net = maxpool(net, name="pool3")
   net = conv2d(net, 256, 3, 1, name="conv4_1")
   net = conv2d(net, 128, 1, name="conv4_2")
   net = conv2d(net, 256, 3, 1, name="conv4_3")
   net = maxpool(net, name="pool4")
   net = conv2d(net, 512, 3, 1, name="conv5_1")
   net = conv2d(net, 256, 1, name="conv5_2")
   net = conv2d(net, 512, 3, 1, name="conv5_3")
   net = conv2d(net, 256, 1, name="conv5_4")
   net = conv2d(net, 512, 3, 1, name="conv5_5")
   shortcut = net
   net = maxpool(net, name="pool5")
   net = conv2d(net, 1024, 3, 1, name="conv6_1")
   net = conv2d(net, 512, 1, name="conv6_2")
   net = conv2d(net, 1024, 3, 1, name="conv6_3")
   net = conv2d(net, 512, 1, name="conv6_4")
   net = conv2d(net, 1024, 3, 1, name="conv6_5")
   # ---------
   net = conv2d(net, 1024, 3, 1, name="conv7_1")
   net = conv2d(net, 1024, 3, 1, name="conv7_2")
   # shortcut
   shortcut = conv2d(shortcut, 64, 1, name="conv_shortcut")
   shortcut = reorg(shortcut, 2)
   net = tf.concat([shortcut, net], axis=-1)
   net = conv2d(net, 1024, 3, 1, name="conv8")
   # detection layer
   net = conv2d(net, n_last_channels, 1, batch_normalize=0,
                activation=None, use_bias=True, name="conv_dec")
   return net

然後實現對Darknet-19模型輸出的解碼:

def decode(detection_feat, feat_sizes=(13, 13), num_classes=80,
          anchors=None):
   """decode from the detection feature"""
   H, W = feat_sizes
   num_anchors = len(anchors)
   detetion_results = tf.reshape(detection_feat, [-1, H * W, num_anchors,
                                       num_classes + 5])

   bbox_xy = tf.nn.sigmoid(detetion_results[:, :, :, 0:2])
   bbox_wh = tf.exp(detetion_results[:, :, :, 2:4])
   obj_probs = tf.nn.sigmoid(detetion_results[:, :, :, 4])
   class_probs = tf.nn.softmax(detetion_results[:, :, :, 5:])

   anchors = tf.constant(anchors, dtype=tf.float32)

   height_ind = tf.range(H, dtype=tf.float32)
   width_ind = tf.range(W, dtype=tf.float32)
   x_offset, y_offset = tf.meshgrid(height_ind, width_ind)
   x_offset = tf.reshape(x_offset, [1, -1, 1])
   y_offset = tf.reshape(y_offset, [1, -1, 1])

   # decode
   bbox_x = (bbox_xy[:, :, :, 0] + x_offset) / W
   bbox_y = (bbox_xy[:, :, :, 1] + y_offset) / H
   bbox_w = bbox_wh[:, :, :, 0] * anchors[:, 0] / W * 0.5
   bbox_h = bbox_wh[:, :, :, 1] * anchors[:, 1] / H * 0.5

   bboxes = tf.stack([bbox_x - bbox_w, bbox_y - bbox_h,
                      bbox_x + bbox_w, bbox_y + bbox_h], axis=3)

   return bboxes, obj_probs, class_probs

我將YOLOv2的官方訓練權重檔案轉換了TensorFlow的checkpoint檔案(下載連結),具體的測試demo都放在我的GitHub上了,感興趣的可以去下載測試一下,至於train的實現就自己折騰吧,相對會棘手點。

640?wx_fmt=png

圖11:YOLOv2在自然圖片上的測試

4

YOLO9000

YOLO9000是在YOLOv2的基礎上提出的一種可以檢測超過9000個類別的模型,其主要貢獻點在於提出了一種分類和檢測的聯合訓練策略。眾多周知,檢測資料集的標註要比分類資料集打標籤繁瑣的多,所以ImageNet分類資料集比VOC等檢測資料集高出幾個數量級。在YOLO中,邊界框的預測其實並不依賴於物體的標籤,所以YOLO可以實現在分類和檢測資料集上的聯合訓練。對於檢測資料集,可以用來學習預測物體的邊界框、置信度以及為物體分類,而對於分類資料集可以僅用來學習分類,但是其可以大大擴充模型所能檢測的物體種類。

作者選擇在COCO和ImageNet資料集上進行聯合訓練,但是遇到的第一問題是兩者的類別並不是完全互斥的,比如"Norfolk terrier"明顯屬於"dog",所以作者提出了一種層級分類方法(Hierarchical classification),主要思路是根據各個類別之間的從屬關係(根據WordNet)建立一種樹結構WordTree,結合COCO和ImageNet建立的WordTree如下圖所示:

640?wx_fmt=png

圖12:基於COCO和ImageNet資料集建立的WordTree

WordTree中的根節點為"physical object",每個節點的子節點都屬於同一子類,可以對它們進行softmax處理。在給出某個類別的預測概率時,需要找到其所在的位置,遍歷這個path,然後計算path上各個節點的概率之積。

相關推薦

目標檢測|YOLOv2原理實現(YOLOv3)

作者:葉虎     編輯:李雪冬   前  言在前面的一篇文章中,我們詳細介紹了YOLOv1的原

目標檢測|YOLO原理實現

轉載自知乎目標檢測|YOLO原理與實現 目標檢測|YOLO原理與實現 最新的YOLOv2和YOLOv3: 小白將:目標檢測|YOLOv2原理與實現(附YOLOv3)​ zhuanlan.zhihu.com 前言 當我們談起計算機視覺時,首先想到的就是影象分類,沒錯

P2P之UDP穿透NAT的原理實現(C++原始碼)[轉載]

論壇上經常有對P2P原理的討論,但是討論歸討論,很少有實質的東西產生(原始碼)。呵呵,在這裡我就用自己實現的一個原始碼來說明UDP穿越NAT的原理。 首先先介紹一些基本概念:     NAT(Network Address Translators),網路地址轉換:網路地址轉換是在IP地址日益缺乏的情況下產生

IOS 下載檔案斷點續傳原理實現(原始碼)

在網路狀況不好的情況下,對於檔案的傳輸,我們希望能夠支援可以每次傳部分資料。首先從檔案傳輸協議FTP和TFTP開始分析, FTP是基於TCP的,一般情況下建立兩個連線,一個負責指令,一個負責資料;而TFTP是基於UDP的,由於UDP傳輸是不可靠的,雖然傳輸速度很快,但對於普通的檔案像PDF這種,少了一個

目標檢測目標檢測原理實現(五)--基於Cascade分類器的目標檢測

基於Cascade分類器的目標檢測        從今天開始進入基於機器學習的目標檢測,前幾節雖然也接觸了一些機器學習的方法,但它主要是做輔助工作,機器學習的方法和非機器學習的方法結合在一起使用,說到這想起來前幾天看到一位博士師兄發的笑話,說的是百度實驗室:  

目標檢測(Object Detection)原理實現(一)

基於閾值影象處理的目標檢測           從今天起開始要寫一些關於目標檢測的文章,涵蓋從簡單的閾值影象處理檢測、霍夫變換(hough transform)檢測、模版匹配檢測(剛體匹配)、AAM+ASM+ACM(非剛體)匹配檢測到近代機器學習方法檢測,儘量貼一些程式碼,

目標檢測(Object Detection)原理實現(六)

基於形變部件模型(Deformable Part Models)的目標檢測         上節說了基於cascade的目標檢測,cascade的級聯思想可以快速拋棄沒有目標的平滑窗(sliding window),因而大大提高了檢測效率,但也不是沒缺點,缺點就是它僅僅

目標檢測(Object Detection)原理實現(五)

基於Cascade分類器的目標檢測        從今天開始進入基於機器學習的目標檢測,前幾節雖然也接觸了一些機器學習的方法,但它主要是做輔助工作,機器學習的方法和非機器學習的方法結合在一起使用,說到這想起來前幾天看到一位博士師兄發的笑話,說的是百度實驗室:     

目標檢測(Object Detection)原理實現

基於形變部件模型(Deformable Part Models)的目標檢測         上節說了基於cascade的目標檢測,cascade的級聯思想可以快速拋棄沒有目標的平滑窗(sliding window),因而大大提高了檢測效率,但也不是沒缺點,缺點就是它僅僅是

影象目標檢測(Object Detection)原理實現(三)

基於霍夫森林的目標檢測        上節說了霍夫變換(HT)和廣義霍夫變換(GHT),今天就接著廣義霍夫變換說下去,在廣義霍夫變換中,每個投票元素(比如邊緣畫素中的點)在霍夫空間中累加投票的權重是相等的,每個元素投票的權重互不影響,這其實是假設了影象空間中的每個畫

目標檢測目標檢測原理實現(一)

轉載:http://blog.csdn.net/marvin521/article/details/9058735 基於閾值影象處理的目標檢測           從今天起開始要寫一些關於目標檢測的文章,涵蓋從簡單的閾值影象處理檢測、霍夫變換(hough transf

影象目標檢測(Object Detection)原理實現(一)

基於閾值影象處理的目標檢測           從今天起開始要寫一些關於目標檢測的文章,涵蓋從簡單的閾值影象處理檢測、霍夫變換(hough transform)檢測、模版匹配檢測(剛體匹配)、AAM+ASM+ACM(非剛體)匹配檢測到近代機器學習方法檢測,儘量貼一些程式

P2P之UDP穿透NAT的原理實現原始碼)

原文連結 關於UDP穿透NAT的中文資料在網路上是很少的,僅有<<P2P之UDP穿透NAT的原理與實現(shootingstars)>>這篇文章有實際的參考價值。 本人近兩年來也一直從事P2P方面的開發工作,比較有代表性的是個人開發的BitTorr

Java 線程池的原理實現

控制 try 所在 使用 urn str waiting media .info 這幾天主要是狂看源程序,在彌補了一些曾經知識空白的同一時候,也學會了不少新的知識(比方 NIO)。或者稱為新技術吧。 線程池就是當中之中的一個,一提到線程。我們會想到曾經《操作系統》的

防盜鏈的基本原理實現

rec eal limit ole 站點 new exceptio stub text 1. 我的實現防盜鏈的做法,也是參考該位前輩的文章。基本原理就是就是一句話:通過判斷request請求頭的refer是否來源於本站。(當然請求頭是來自於客戶端的,是可偽造的,暫不在本文

最小二乘法多項式曲線擬合原理實現 zz

博客 del p s 並且 多項式 聯網 python mar 程序 概念 最小二乘法多項式曲線擬合,根據給定的m個點,並不要求這條曲線精確地經過這些點,而是曲線y=f(x)的近似曲線y= φ(x)。 原理 [原理部分由個人根據互聯網上的資料進行總結,希望對大

無限極分類原理實現(轉)

轉換 完成 外灘 獲得 意思 容易 set 導航 另一個   前言   無限極分類是我很久前學到知識,今天在做一個項目時,發現對其概念有點模糊,所以今天就來說說無限極分類。   首先來說說什麽是無限極分類。按照我的理解,就是對數據完成多次分類,如同一棵樹一樣,從根開始,

java監聽器的原理實現

來看 class copyto 圖片 http size stat 順序 方法 監聽器模型涉及以下三個對象,模型圖如下: (1)事件:用戶對組件的一個操作,稱之為一個事件 (2)事件源:發生事件的組件就是事件源 (3)事件監聽器(處理器):監聽並負責處理事件的方法 執行順序

Redis實現分布式鎖原理實現分析

數據表 防止 中一 csdn 訂單 not 產生 www 整體 一、關於分布式鎖 關於分布式鎖,可能絕大部分人都會或多或少涉及到。 我舉二個例子: 場景一:從前端界面發起一筆支付請求,如果前端沒有做防重處理,那麽可能在某一個時刻會有二筆一樣的單子同時到達系統後臺。 場

TLD視覺目標跟蹤框架原理實踐

圖像 視頻 tld comm rec 計算機 認識 實踐 計算 最近花了不少時間,仔細的做了一個有關TLD視覺目標跟蹤框架的視頻課程,希望能夠幫助一些對計算機視覺感興趣的人,通過對該課程的學習,能夠對計算機視覺技術中的一些基本問題有一定的認識和理解,進而達到技術進階的目的。