1 目標定位( object localization )
目標定位既要識別,又要定位,它要做的事就是用一個框框把物體目標的位置標出來。
怎么做這個問題呢,我們考慮三目標的定位問題,假定圖中最多只出現一個目標,假定圖片的左上角為(0,0),右下角為(1,1)。
我們輸出層的標簽有這么幾個,pc, bx, by, bh, bw, c1, c2, c3,其中pc表示是否存在目標,c1,c2,c3分別代表三個類別的目標是否存在,(bx, by)表示框框中心點的坐標,bh表示框框高度,bw表示框框寬度。
考慮損失函數,y = 0 時,只考慮pc之間的邏輯回歸損失或平方損失都行,因為此時沒有目標;
y = 1時,一般對pc采用平方損失或者邏輯回歸的損失,對c1, c2, c3采用softmax的損失,對bx, by, bh, bw采用平方損失。
2 特征點檢測( landmark detection )
假如你想標記出人臉中的特征位置(比如眼睛),對於神經網絡的輸出單元,首先有個face表示是否有人臉,然后是一系列的特征點的坐標,比如l1x, l1y, l2x, l2y, l3x, l3y, l4x, l4y表示四個特征點,表示左眼的外眼角和內眼角,右眼的外眼角和內眼角。
當然要訓練這個網絡,必須有標簽好的數據,一般都是人為辛苦標注的。
這個檢測臉部特征模塊,是一個識別臉部表情的基本模塊,也是計算機圖形效果(比如實現頭戴皇冠,臉部扭曲)的一個關鍵模塊。
如果你對人體姿態檢測感興趣的話,也是使用類似上述的方法,先檢測出人體姿態的關鍵特征點。
3 目標檢測( object detection )
比如我們想做一個汽車的目標檢測,首先先構建一個數據集,輸入圖像,輸出圖像是否為汽車,注意有汽車的圖像中汽車要盡量占滿整個畫布且在正中央。
用這個數據集訓練一個卷積神經網絡,能夠預測圖像中是否為汽車。
然后可以利用滑動窗口的技術,先用小窗口,對新來的圖像用窗口截取一段用網絡判斷是否為汽車,依次滑動窗口進行判斷,對每個位置用0和1標記,直到滑過圖像的每一個角落。然后增大窗口,重復操作,再增大一點窗口,重復操作。
滑動窗口的缺點就是計算成本太高,每次滑動都要用卷積來計算一次,這樣滑動太慢了。
如果滑動stride小,則計算量大;如果stride大,可能無法准確定位到目標。
4 滑動窗口的卷積實現( Convolutional implementation of sliding windows )
事實上,我們不用像上一節中那樣,自己去滑動窗口截取圖片的一小部分然后檢測,卷積這個操作就可以實現滑動窗口。
如下圖中間一行卷積的初始圖,我們假設輸入的圖像是16*16的,而窗口大小是14*14,我們要做的是把藍色區域輸入卷積網絡,生成0或1分類,接着向右滑動2個元素,形成的區域輸入卷積網絡,生成0或1分類,然后接着滑動,重復操作。我們在16*16的圖像上卷積了4次,輸出了4個標簽,我們會發現這4次卷積里很多計算是重復的。
而實際上,直接對這個16*16的圖像進行卷積,如下圖中間一行的卷積的整個過程,這個卷積就是在計算我們剛剛提到的很多重復的計算,過程中藍色的區域就是我們初始的時候用來卷積的第一塊區域,到最后它變成了2*2的塊的左上角那一塊,我們可以看到最后輸出的2*2塊,剛好就是4個輸出,對應我們上面說的輸出4個標簽。
這兩個過程剛好可以對應的上。所以我們不需要把原圖分成四個部分,分為用卷積去檢測,而是把它們作為一張圖片輸入給卷積網絡進行計算,其中的公有區域可以共享很多計算。
我們不用依靠連續的卷積操作來識別圖片中的汽車,我們可以對整張圖片進行卷積,一次得到所有的預測值,如果足夠幸運,神經網絡便可以識別出汽車的位置。
5 邊界框預測( Bounding box prediction )
上一節的算法有一個缺點,就是邊界框(bounding box)的位置可能不夠准確,例如,可能你的框沒有完美地框中汽車,而是框中了四分之三的樣子。
其中一個能得到更精准的邊界框的算法就是YOLO算法,YOLO的意思是you only look once。
怎么做的呢?假設我們的圖像是100*100,我們在圖像上放上3*3=9的網格(用3*3是為了介紹簡單,實際實現會更精細,比如19*19)。
基本思路就是逐一在9個格子里使用目標定位。對於沒有目標的格子,它的標簽y就是pc為0,沒啥好說的;
對於某個有目標的格子,按目標定位的方法貼上標簽。需要注意的是,yolo會把目標分配到包含對象中點的那個格子里,所以如果車子的邊緣跑到別的格子去了,我們會忽視那些邊緣。
因為我們的標簽有8個分量(參見前面說過的目標定位),所以最終的標簽的shape是3*3*8。
我們要訓練的卷積神經網絡就是輸入100*100*3的圖像,輸出3*3*8的標簽。這樣我們就可以得到精准的邊界框了。
這個算法能夠得到更准確的邊界框而不用受限於滑動窗口的步長;其次這是一個卷積實現,我們並沒有在9塊區域跑9次算法,而是直接對整張圖進行卷積的訓練,因為在各個格子里的很多計算步驟是可以共享的。所以這個算法效率很高。
另外有個細節,關於bx, by, bh, bw,我們說格子左上角是(0, 0),右下角是(1, 1),那么這四個參數可以認為是在格子中占的比例大小,bx, by是(0,1)的,而bh, bw可能大於1,因為可能目標太大占了幾個格子,指定邊界框的方式有很多,這種約定是比較合理的。
6 交並比( Intersection over union)
交並比函數IoU是用來評判目標檢測是否准確的,它做的就是計算預測邊框和實際邊框的交集和並集的比。
一般IoU大於等於0.5就說明檢測正確,如果你希望嚴格點,可以定為0.6或0.7。
7 非極大值限制( Non-max suppression)
之前講的yolo算法中,有個問題就是當一輛汽車占了很多個格子的時候,很多格子都會覺得它里面有輛車,所以算法可能會對同一對象做多次檢測。
非最大值限制做的就是清理這些檢測結果,使每個對象只被檢測一次。具體怎么做,我們先假設目標只有一個,汽車,那么標簽變成5個( pc, bx, by, bh, bw )
把圖片分成19*19格子,對每一格子如果pc<=0.6,則丟棄,認為它不包含汽車。
對於剩下的格子,選擇概率pc最高的框框,然后把跟這個框框的IoU很高(比如說>=0.5)的框框抑制;
然后再找概率最高的框框,接着把IoU(重疊)很高的框框抑制;
以此類推,最后把抑制的框框都去掉,這就是非最大值抑制。如果嘗試同時檢測三個目標的話,就對三個類獨立地進行非最大值抑制。
8 Anchor Boxes
Anchor Boxes是處理一個格子出現多個目標的手段。
如下圖所示,人和車重疊在了一起,這個時候可以預先定義不同形狀的anchor box,這個例子中我們定義兩個anchor box。
然后標簽也變成原來的2倍,分別表示2個box:[ pc, bx, by, bh, bw, c1, c2, c3, pc, bx, by, bh, bw, c1, c2, c3 ]
對於第一個box,行人的形狀,用標簽的前8個表示,這里所有的參數都和檢測行人有關。
對於第二個box,汽車的形狀,用標簽的后8個表示,這里所有的參數都和檢測汽車有關。
之前,訓練的每一個目標,都分配到包含中點的格子里。
現在,訓練的每一個目標,都分配到(包含中點的格子,和目標IoU最高的anchor box)里。
如果你有2個anchor但是格子出現了3個目標,這種情況算法並沒有很好的處理辦法,但執行了默認的手段就是把兩個對象放在一個格子里且它們的anchor是一樣的,希望你的數據集不會出現這種情況。
如何選擇anchor呢,人們一般手工指定anchor的形狀,你可以選擇5-10個anchor box覆蓋多種不同的形狀,涵蓋你想要檢測的對象的各種形狀。
后期YOLO論文有更好的做法,用k-menas將兩類對象的形狀進行聚類,用它來選擇一組anchor box。
9 yolo算法( yolo algorithm )
先根據上面講述的內容,給訓練樣本貼好相應的標簽,然后訓練,預測。
最后要做非最大值抑制,步驟如下。
(1) 如果anchor box有兩個,那么對於每個格子都會得到有兩個邊界框;
(2) 拋棄概率低的框框;
(3) 假設我們要預測三個目標,那么對每一個類,單獨用非最大值抑制去得到最后的預測框框。
10 候選區域( Region proposals )
候選區域用的比較少,但是這個概念在計算機視覺領域的影響力很大,是個很有趣的想法。
我們之前講的滑動窗口,它可能會在顯然沒有任何對象的區域上運算,這很沒意義。
針對這個,有人提出了R-CNN,帶區域的卷積網絡,這個算法嘗試選出一些區域,在這些區域上運行卷積網絡分類器是有意義的。
選出候選區域的方法是運行圖像分割算法,找一些色塊,在這些色塊上做卷積得到特征,然后(SVM)分類。
R-CNN運行還是挺慢的,所以有一系列的研究工作去改進這個算法。
比如Fast R-CNN,用了卷積(實現的滑動窗口)來進行分類,提高了速度,但是它得到候選區的速度還是挺慢的。
所以又提出了Faster R-CNN,用卷積去來獲得候選區域色塊,結果比Fast快很多。