基于點(diǎn)檢測的物體檢測方法(一):CornerNet
點(diǎn)擊上方“小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)
方法來自于文章:
代碼:

文章思路和實(shí)現(xiàn)比較新奇,摒棄了常用的檢測方法中通過檢測物體bounding box進(jìn)行目標(biāo)檢測的方法,通過檢測點(diǎn)的方式進(jìn)行目標(biāo)檢測。具體的,檢測物體bounding box的左上角和右下角兩個(gè)點(diǎn),根據(jù)這兩個(gè)點(diǎn)直接得到物體的bounding box。作者這個(gè)方法也是從人體pose estimation方法中的bottom-to-up的方法中得到的啟發(fā),如果做過pose estimation會(huì)更加容易理解作者意圖和實(shí)現(xiàn)。
在看到上述描述,自然而然的就會(huì)想到以下幾個(gè)問題:
1、怎么檢測這個(gè)兩個(gè)點(diǎn)?
2、怎么知道這兩個(gè)點(diǎn)所組成的框包含物體的類別?
3、當(dāng)圖像中有多個(gè)物體時(shí),怎么知道哪些點(diǎn)可以組成框?(哪些左上角的點(diǎn)和哪些右下角的點(diǎn)能夠組成有效的框)
4、Loss是什么形式?
5、網(wǎng)絡(luò)結(jié)構(gòu)是怎么樣的?
6、有沒有什么比較新奇的東西?
帶著上述的這些問題,我們先來看看整個(gè)算法的pipeline:


上面兩幅圖分別是算法的網(wǎng)絡(luò)結(jié)構(gòu)圖和算法inference階段的示意圖。根據(jù)上面兩幅圖,可以大致梳理出算法的pipeline:
1、輸入一張圖像,經(jīng)過backbone網(wǎng)絡(luò)(Hourglass network)后,得到feature map。
2、將feature map同時(shí)輸入到兩個(gè)branch,分別用于預(yù)測Top-Left Corners和Bottom-right Corners。
3、兩個(gè)branch都會(huì)先經(jīng)過一個(gè)叫Corner Pooling的網(wǎng)絡(luò),最后輸出三個(gè)結(jié)果,分別是Heatmaps、Embeddings、Offsets。
4、根據(jù)Heatmaps能夠得到物體的左上角點(diǎn)和右下角點(diǎn),根據(jù)Offsets對左上角和右下角點(diǎn)位置進(jìn)行更加精細(xì)的微調(diào),根據(jù)Embeddings可以將同一個(gè)物體的左上角和右下角點(diǎn)進(jìn)行匹配。得到到最終的目標(biāo)框。
下面就看看具體的實(shí)現(xiàn)細(xì)節(jié):

Hourglass是人體pose estimation領(lǐng)域非常經(jīng)典常用的一個(gè)網(wǎng)絡(luò)結(jié)構(gòu),其網(wǎng)絡(luò)結(jié)構(gòu)首先將feature的resolution逐步降低,再逐步的升高。在降低和升高的中間,通過shortcut進(jìn)行連接。這樣提取出的特征不僅能夠包含有high-level的語義信息,也能夠盡可能的保留空間信息。對于關(guān)鍵點(diǎn)回歸的這類任務(wù),對空間信息和高分辨率的feature map都有比較高的需求。
本文作者使用的Hourglass相對于最原始的Hourglass做了細(xì)微的改變,例如改變了使用Hourglass階數(shù)、用stride=2的卷積代替max pooling等等。具體的改變可以看代碼實(shí)現(xiàn)。

本文的算法模型,在backbone之后接上了兩個(gè)prediction module branch,分別用于得到物體的左上角點(diǎn)和右下角點(diǎn)。
上圖是左上角點(diǎn)的prediction module。主要有兩部分組成,一部分是Corner Pooling,這部分后面會(huì)介紹,另一部分就是網(wǎng)絡(luò)最后的輸出部分了。網(wǎng)絡(luò)輸出三種feature map,heatmaps、embeddings、offsets。這些都會(huì)在后文進(jìn)行詳細(xì)介紹
在網(wǎng)絡(luò)的輸出部分,一共生成了2個(gè)heatmaps set,一個(gè)是用于左上角的檢測,另一個(gè)是用于右下角的檢測。每個(gè)heatmaps集合的形式都是
,其中
代表的是檢測目標(biāo)的類別數(shù),
和
則代表heatmap的分辨率。
簡而言之,我們可以根據(jù)這個(gè)heatmap set最大的響應(yīng)值,得到當(dāng)前Corner點(diǎn)的位置和所屬類別。例如,在左上角的heatmap set中,響應(yīng)值最高的值出現(xiàn)在第c個(gè)channel的第(w,h)的位置,那么我們可以認(rèn)為這個(gè)左上角點(diǎn)的位置就在(w,h),且這個(gè)Corner的類別就是第c個(gè)channel所對應(yīng)的類別。
知道了heatmap set,就開始構(gòu)造其Loss形式,作者使用了Focal loss,并對Focal loss做了一定的改變,具體形式如下:

其中,
是圖像中物體的數(shù)量,
和
是一組超參(作者的設(shè)定
,
),用來控制圖像中每個(gè)點(diǎn)對loss的貢獻(xiàn)程度。另外,標(biāo)簽
是一個(gè)由高斯函數(shù)生成的值:
,
和
表示的是以(
,
)為坐標(biāo)原點(diǎn),其他位置的相對坐標(biāo)。此標(biāo)簽可以這么理解,真值位置的標(biāo)簽為1,真值附近一定范圍內(nèi)的標(biāo)簽不為0,是一個(gè)隨著到真值位置距離的增大,而逐漸衰減的值。
在Hourglass模型之前,為了減少計(jì)算量,往往會(huì)將特征的分辨率縮小一定倍數(shù)。例如,輸入圖像為368*368,而輸出的feature map 只有46*46,原圖像的坐標(biāo)(
,
)映射到feature map上坐標(biāo)就變成了(
,
),這樣就產(chǎn)生了一定的誤差:

為了減少這種誤差對于最終預(yù)測結(jié)果的影響,作者加入了一個(gè)offset map,map上的值就當(dāng)前Corner點(diǎn)的偏移量。其loss計(jì)算采用了Smooth1 Loss:

在一幅圖中會(huì)出現(xiàn)多個(gè)物體,因此也會(huì)出現(xiàn)多個(gè)左上角點(diǎn)和右下角點(diǎn)。在這些檢測出的點(diǎn)中,我們需要對其進(jìn)行配對,即判斷哪些點(diǎn)可以組成一對角點(diǎn),能夠檢測出目標(biāo)。作者這里使用的group方法也是效仿pose estimation(引文2)中的方法。其中主要思想是,在生成角點(diǎn)heatmap時(shí),同時(shí)生成一個(gè)embedding vector,如果一個(gè)左上角角點(diǎn)和右下角角點(diǎn)屬于同一個(gè)物體,那么他們的embeddng vector之間的距離就應(yīng)該非常小。我們可以根據(jù)這些距離來對Corner點(diǎn)進(jìn)行匹配。
但是這里又會(huì)有一個(gè)問題,embeding該怎么打標(biāo)簽?zāi)兀繄D像中的Corner數(shù)量不一定,我該怎么給他們,對于每個(gè)位置的Corner我該賦什么樣的值呢?賦值有應(yīng)該遵循什么樣的規(guī)則賦呢?這些都是棘手的問題。
這里作者采用了非常巧妙的loss計(jì)算方法,避免了對embeding進(jìn)行打標(biāo)的過程。我們不需要管embeding中對應(yīng)Corner位置的值具體是多少,我們關(guān)心的是應(yīng)該配對的那兩個(gè)角點(diǎn)的embedding向量的距離是不是很小,理想情況下成對的角點(diǎn)的embedding向距離應(yīng)該為0 ,而不成對距離應(yīng)該非常的大。
這里就可以引申出這個(gè)loss應(yīng)該具有兩部分,一部分可以pull成對的Corner點(diǎn),讓成對的Corner點(diǎn)的embedding向量差別較小,另一部分可以push不成對的Corner,讓他們的embedding向量差異較大。


其中
和
圖像中第k個(gè)目標(biāo)的top-left點(diǎn)和bottom-right點(diǎn)的embedding向量,
表示兩個(gè)embedding向量的均值。
上面講的detecting corner 和grouping corner其實(shí)沒有什么創(chuàng)新的地方,作者只不過是把他們從pose estimation領(lǐng)域引入到了object detection領(lǐng)域。作者自己本身提出的比較有創(chuàng)新的地方就是Corner Pooling。

上圖是top-left corner的 Corner Pooling過程。在水平方向,從最右端開始往最左端遍歷,每個(gè)位置的值都變成從最右到當(dāng)前位置為止,出現(xiàn)的最大的值。同理,bottom-right corner的Corner Pooling則是最左端開始往最右端遍歷。同樣的,在垂直方向上,也是這樣同樣的Pooling的方式。
Insight:以左上角點(diǎn)為例,當(dāng)我們決定此點(diǎn)是否個(gè)corner點(diǎn)的時(shí)候,往往會(huì)沿著水平的方向向右看,看看是否與物體有相切,還會(huì)沿著垂直方向向下看,看看是否與物體相切。簡而言之,其實(shí)corner點(diǎn)是物體上邊緣點(diǎn)和坐邊緣點(diǎn)的集合,因此在pooling的時(shí)候通過Corner Pooling的方式能夠一定程度上體現(xiàn)出當(dāng)前點(diǎn)出發(fā)的射線是否與物體向交。
在訓(xùn)練階段,網(wǎng)絡(luò)的輸入分辨率為511*511, 輸出的分辨率為128*128
訓(xùn)練階段總的loss:
,且
, 
inference階段的時(shí)間:244ms/per image,速度比較慢,這里我理解輸出慢的原因有兩個(gè):1)網(wǎng)絡(luò)比較大,尤其是輸出的feature map比較多,因?yàn)檩敵龅膄eature map的channel數(shù)是與物體類別數(shù)相關(guān)的。2)后處理階段,需要對所有可能的Corner組合都進(jìn)行一次embedding向量的距離計(jì)算。
現(xiàn)在再回頭看文章一開頭提的那幾個(gè)問題,都可以一一解答了:
1、怎么檢測這個(gè)兩個(gè)點(diǎn)?
生成keypoint的heatmap,heatmap中響應(yīng)值最大的位置就是點(diǎn)的位置。
2、怎么知道這兩個(gè)點(diǎn)所組成的框包含物體的類別?
Corner響應(yīng)值最大所在的channel即對應(yīng)了物體的類別。
3、當(dāng)圖像中有多個(gè)物體時(shí),怎么知道哪些點(diǎn)可以組成框?(哪些左上角的點(diǎn)和哪些右下角的點(diǎn)能夠組成有效的框)
生成embedding向量,用向量的距離衡量兩個(gè)Corner是否可以組成對。
4、Loss是什么形式?
loss總共分了三個(gè)部分,一部分是用于定位keypoint點(diǎn)的detecting loss,一個(gè)是用于精確定位的offset loss,一個(gè)是用于對Corner點(diǎn)進(jìn)行配對的grouping loss
5、網(wǎng)絡(luò)結(jié)構(gòu)是怎么樣的?
使用Hourglass作為backbone,使用Corner Pooling構(gòu)造了prediction module,用來得到最終的結(jié)果。
6、有沒有什么比較新奇的東西?
提出的Corner Pooling。
第一次使用檢測點(diǎn)的方法檢測物體。
交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN、算法競賽等微信群(以后會(huì)逐漸細(xì)分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會(huì)根據(jù)研究方向邀請進(jìn)入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會(huì)請出群,謝謝理解~
