目標檢測算法YOLO算法介紹


YOLO算法(You Only Look Once)

         比如你輸入圖像是100x100,然后在圖像上放一個網絡,為了方便講述,此處使用3x3網格,實際實現時會用更精細的網格(如19x19)。基本思想是,使用圖像分類和定位算法,然后將算法應用到9個格子上。更具體一點,你需要這樣定義訓練標簽,對於9個格子中的每一個都指定一個標簽y,其中y是一個8維向量(與前面講述的一樣,分別為Pc,bx,by,bh,bw,c1,c2,c3,其中Pc=1表示含有目標,Pc=0表示為背景;c1,c2,c3表示要分類的3個目標,如行人、汽車、摩托車,不包括背景)。9個格子,每個格子都有這樣一個8維的向量,對於不包含目標的格子,標簽y=[0, ? , ? , ? , ? , ? , ? , ? , ?],?表示任意值。對於包含目標的格子,YOLO算法是這樣處理的,取每個對象的中心點,然后將這個對象分配給包含這個對象中心點的格子,所以下圖中左邊的汽車就分配到第4個格子(從左往右,從上往下數,圖中綠色方框的格子),因此中間第5個格子不包含目標。對於第4個格子的目標標簽是這樣的:y=[1, bx, by, bh, bw, 0, 1, 0]。因此,對於任意一個格子,你都會得到一個8維輸出向量,由於這里是3x3的網格,所以有9個格子,故總的輸出尺寸是3x3x8。

         如果你現在要訓練一個輸入為100x100x3的神經網絡,最后會映射到一個3x3x8的輸出尺寸。所以你要做的就是,有一個輸入x,有對應的3x3x8的目標標簽。當你使用反向傳播訓練神經網絡時,將任意的輸入x映射到這類輸出向量y。

         這個算法的優點是,網絡可以輸出精確地邊界框。所以測試的時候,你做的是提供輸入圖像x,然后跑正向傳播,直到你得到這個輸出y,然后對於這里3x3位置對應的9個輸出,我們就可以讀出1或0。只要每個格子中目標的數量沒有超過一個,這個算法應該是沒有問題的;對於一個格子中存在多個對象的問題,以后再討論。實踐中,我們可能會使用更精細的19x19網格,所以就是19x19x8,這樣的網格精細的多,那么多個對象被分配到同一個格子的概率就很小。另外再提一句,把對象分配到一個格子的過程是,你觀察對象的中心點,然后將這個對象分配到其中心點所在的格子,所以即使對象可以橫跨多個格子,也只會被分配到9個格子其中之一。

 

1)  神經網絡輸出邊界框可以具有任意寬高比,並且能輸出更精確的坐標,不會受到滑動窗口分類器的步長大小限制

2)  這是一個卷積實現,你並沒有在3x3網格上跑9次算法,不需要讓同一個算法跑9次,相反,這是單次卷積實現,但你使用了一個卷積網絡,有很多共享的計算步驟,所以這個算法效率很高

 

事實上,YOLO算法有一個好處,因為這是一個卷積實現,它的運行速度非常快,可以達到實時識別。

  另外一個小細節,如何編碼這些邊界框(bx, by, bh, bw)?

  上面的圖中有兩輛車,我們有3x3網格,以右邊的車為例,第6個格子有汽車,所以目標標簽y中Pc=1,后面的c1,c2,c3分別為0,1,0(假設代表行人、汽車、摩托車三個類)。

         在YOLO算法中,對於這個邊界框,我們約定每個格子的左上角是(0, 0),右下角坐標是(1, 1),要指定汽車中心點(圖中橙色點)的位置,bx大概是0.4,by大概是0.3,然后是邊界框的高度,用格子總體寬度的比例表示,因此這個紅框的寬度可能是格子寬度的90%,因此bh=0.9;它的高度大概是格子高度的一半,因此bw=0.5。.換句話說,bx,by,bh,bw單位是相對格子尺度的比例,因此bx和by必須在0和1之間,而bh,bw可能大於1。當然也有其他的約定方式。

 

如何判斷目標檢測算法運作良好?

  ----交並比(IoU,intersection over union),可以用來評價目標檢測算法

 

  IoU,計算兩個邊界框交集(圖中橙色陰影部分)和並集(圖中綠色陰影部分)之比,即計算交集的大小

 

  一般情況下,在計算機視覺任務中約定,如果IoU大於或等於0.5,就說明檢測正確;如果預測器和實際邊界框完美重疊,那么IoU就是1。具體情況下,IoU閾值可以隨具體任務進行設置。

 

非極大值抑制抑制NMS

 

  目前為止,目標檢測中的一個問題是,你的算法可能對同一個對象作出多次檢測,非極大值抑制這個方法可以確保你的算法對每個對象只檢測一次。

 

         舉個例子,假如你需要在這張圖片里檢測行人和汽車,你可能會在上面放19x19網格,理論上這輛車只有一個中點,所以它應該只被分配到一個格子里,而實踐中當你跑目標分類和定位算法時,對每個格子都跑一次,可能會有多個格子認為對象的中心點在其自己的格子內。

 

         因為你要在361格子上都跑一次,圖像檢測和定位算法,那么可能很多格子都會說我這個格子里有車的概率很高,所以當你跑算法的時候,最后可能會對同一個對象做出多次檢測,如下圖所示。因此非極大值抑制做的就是清理這些檢測結果,這樣一輛車只檢測一次,而不是每輛車都出發多次檢測。

 

         所以具體上,這個算法是這樣做的,首先看看每次報告,每個檢測結果相關的概率為Pc。首先看概率最大的那個,在這個例子中是0.9,然后就說這是最可靠的檢測,之后,非極大值抑制就會逐一審視剩下的矩形,所有和這個最大的邊界框有很高交並比,高度重疊的其他邊界框,那么這些輸出就被被抑制,所以這兩個矩形Pc分別為0.6和0.7,它們和0.9的矩形有很高的重疊度,因此這兩個矩形就會被抑制。接下來逐一審視剩下的矩形,找出概率最高的那個,是左邊0.8概率的那個矩形,然后非極大值抑制算法就會去掉其他IoU值很高的矩形。最后剩下的矩形框就是最終結果。

         非極大值抑制意味着,你只輸出概率最大的分類結果,但是會抑制那些很接近但不是最大的預測結果。

算法細節

         首先在這個19x19網格上跑一下算法,你會得到19x19x8的輸出尺寸,不過對於這個例子,我們簡化一下,我們只做汽車檢測,因此每個格子(總共19x19=361個格子)輸出的預測值就是[Pc, bx, by, bh, bw],Pc表示有對象的概率。

 

  現在要實現非極大值抑制,你可以做的第一件事就是去掉所有的Pc值小於等於某一閾值(如0.6)的邊界框,即拋棄所有概率低的邊界框;接下來處理剩下的邊界框,我們重復的選擇概率Pc最高的邊界框,然后把它輸出成預測結果;接下來去掉所有剩下的邊界框,所有任何沒有達到輸出標准的邊界框,把這些和輸出邊界框有很高重疊面積和上一步輸出的邊界框有很高交並比的邊界框全部拋棄,所有while循環的第二步是(上一張幻燈片變暗的那些邊界框和高亮標記的邊界框重疊面積很高的那些邊界框拋棄掉),不停的循環,直到每個邊界框都判斷過了,它們有的作為輸出結果,另外的就被拋棄。

         上述算法是針對單個目標的情況,如果你嘗試同時檢測三個對象,比如說行人、汽車、摩托車,那么輸出向量就會有三個額外的分量;那么正確的做法就是獨立進行三次非極大值抑制,對每個類別都做一次。

 

 

 

Anchor Boxes

 

         目前為止,每個格子只能檢測出一個對象,如果你想讓一個格子檢測出多個對象,你可以使用anchor box。

         假設你有這樣一張圖,對於這個例子,我們繼續使用3x3的網格,注意行人的中心點和汽車的中心點,幾乎在同一個地方,兩者都落到同一個格子中,所有對於那個格子,如果y輸出這個向量,你可以檢測3個類,行人、汽車和摩托,它將無法輸出檢測結果,所以我必須從兩個檢測結果中選擇一個。

 

  而anchor box的思路是這樣的,預先定義兩個不同形狀的anchor box,你要做的就是把預測結果和這兩個anchor box關聯起來,一般來說,你可能會用更多的anchor box,可能要5個或者更多,但是此處為了講解方便,就用兩個anchor box。你要做的就是定義類別標簽,用的向量不是上面那個,而是重復兩次。即為每個anchor box賦予一個與上面一樣的標簽y=[Pc, bx, by, bh, bw, c1, c2, c3]。因為行人的形狀更類似於anchor box1的形狀,而不是anchor box2的形狀,所以你可以用前8個數值來預測行人。

 

  總結一下,不用anchor box的時候,你需要做這些:對於訓練圖像中的每一個對象,都根據那個對象的中心點位置,分配到對應的格子中,所以輸出就是3x3x8。因為是3x3網格,對於每個網格位置,我們有輸出向量y=[Pc, bx, by, bh, bw, c1, c2, c3]。

現在用到anchor box的時候,現在每個對象都和之前一樣分配到對象中心點所在的格子中,但它還分配到一個anchor box,和對象形狀交並比(IoU)最高的anchor box。所以現在的輸出y就是3x3x16(因為有2個anchor box,每個anchor box占8個數值),或者你也可以看成是3x3x2x8,因為現在這里有兩個anchor box,而y是8維的。

 

 

 

下面來看一個具體的例子。

         由於行人更類似於anchor box1的形狀,所以對於行人來說,我們將他分配到向量的上半部分,同理,汽車被分配到下半個格子。現在,其中一個格子有車,沒有行人,那么當一個格子中有三個對象的時候,這種情況下算法處理不好;或者,同一個格子中兩個對象的anchor box形狀也一樣,這樣的情況算法也處理不好。

 

         最后,如何選擇anchor box?大家一般是手工指定anchor box形狀,你可以選擇5到10個的anchor box形狀,覆蓋你想要檢測的對象的各種形狀。K-Means可以將兩類對象形狀聚類,如果我們用它來選擇一組anchor box,選擇最具有代表性的一組anchor box,可以代表你試圖檢測的十幾個對象類別,這是自動選擇anchor box的高級方法。

 

 

YOLO算法

 

         首先看看如何構造數據集。假設你要訓練一個算法,要檢測三種對象,行人,汽車和摩托,你還需要顯式指定完整的背景類別。如果你要用兩個anchor box,那么輸出y就是3x3(因為使用的是3x3的網格),然后x2(anchor box的數量),最后x8。要構造訓練集,你需要遍歷9個格子,然后構成對應的目標向量y。所以對於第一個格子,里面沒有出現要檢測的對象,所以第一個格子的目標y=[0,?,?,?,?,?,?,?,0,?,?,?,?,?,?,?],對於下圖中汽車所在的那個格子,其對應的目標向量y=[0,?,?,?,?,?,?,?,1,bx,by,bh,bw,0,1,0](汽車的形狀與第二個anchor box類似)。最終輸出尺寸是3x3x16(實際中可以使用19x19x16,如果需要用到更多的anchor box,那可能是19x19x5x8)。這是訓練集,然后你訓練一個卷積網絡,輸入是圖片,大小可能是100x100x3,然后你的卷積網絡最后輸出尺寸是3x3x16或者3x3x2x8。

 

  

  接下來,我們看看算法如何做出預測。輸入圖像,你的神經網絡的輸出尺寸是3x3x2x8,對於9個格子,每個都有對應的向量。最后要跑一下這個非極大值抑制。

 

         為了讓內容更有趣一些,我們看看一張新的測試圖片,這就是運行非極大值抑制的過程。如果你使用兩個anchor box,那么對於9個格子中任何一個都會有兩個預測的邊界框,其中一個的概率Pc很低,但9個格子中,每個都有兩個預測的邊界框,比如說我們得到的邊界框是下面這樣的,注意有些邊界框可以超出所在格子的高度和寬度。

 

  接下來,你拋棄概率低的預測,去掉那些連神經網絡都說這里很可能什么都沒有的邊界框。

 

 

  最后,如果你有三個對象檢測類別,你希望檢測行人、車子和摩托,那么你要做的就是對於每個類別,單獨運行非極大值抑制,處理預測結果就是那個類別的邊界框。

 

 

 

RPN網絡

 

         候選區域(region proposals)

 

        

  Region with CNN(R-CNN),這個算法嘗試選出一些區域,在這些區域上運行卷積網絡分類器是有意義的,所以這個不再針對每個滑動窗口跑檢測算法,而只是選擇一些窗口,在少數窗口上運行卷積網絡分類器,選出的候選區域方法是運行圖像分割算法,分割的結果是下面右邊的圖像。為了找出可能存在對象的區域,比如說,分割算法在某個區域找到一個色塊,所以你可能會選擇其對應的一個邊界框,然后在那個色塊上跑分類器。你可以做的就是先找出可能的2000多個色塊,然后在這2000多個色塊上放置邊界框,然后在這2000個色塊上跑一下分類器,這樣的處理比滑動窗口法處理的窗口少的多。

 

 

  以上就是RCNN的大體介紹,現在看來RCNN運行速度是非常慢的,所以有一系列的工作去改進這個算法。所以基本的RCNN算法是使用某種算法求出候選區域,然后對每個候選區域跑一下分類器,每個區域會輸出一個標簽和一個邊界框,另外,說明一下,RCNN算法不會直接信任輸入的邊界框,它也會輸出一個邊界框bx,by,bh,bw,這樣得到的邊界框比較精確,比單純使用圖像分割算法給出的色塊邊界要好。RCNN算法的一個缺點是太慢了,因此又有對其做出來改進。如Fast R-CNN,利用卷積實現了滑動窗口。但是其缺點是得到候選區域的聚類步驟仍然非常緩慢,因此Faster R-CNN又對其進行改進,使用的卷積神經網絡而不是傳統的分割算法來獲得候選區域色塊,結果比Fast-RCNN快很多,但是還是比YOLO算法慢。

 

 

 

內容主要來自與:

Andrew Ng的卷積神經網絡課程


免責聲明!

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



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