參考代碼:
- TF實作版本:R3Det_Tensorflow
- Pytorch實作版本:r3det-on-mmdetection
- 旋轉檢測算法總結:RotationDetection
1. 概述
導讀:這篇文章提出了一種級聯優化的旋轉目标檢測算法。這篇文章的檢測算法可以看作是單階段的(類似RefineDet)檢測算法。算法的第一級回歸用于生成帶旋轉角度的roi proposal(也可以稱之為帶旋轉角度的anchor),在之後的優化級中去疊代優化上一級生成的roi proposal。需要注意的是文章的算法在檢測目标的優化階段對特征圖進行了優化(也就是文章提到的特征對齊操作,feature alignment operator),進而幫助擷取更加精确的目标位置定位。對于損失函數部分,文章引入傾斜矩形的交疊面積作為目标邊界框損失的權重項,進而與Smooth L1損失進行互補,兼顧不同IoU情況下的回歸損失。注意:需要去讀論文源碼的同學請閱讀TF版本的代碼實作,Pytorch版本的代碼存在較多遺漏。
需要注意的是,文章中使用的級聯優化的方式對旋轉目标框進行回歸,不過其在anchor機制上做了一些取巧的工作,文章比較了常用的anchor機制:水準anchor和帶旋轉角度的anchor,它們分别具有如下的特性:
- 1)水準anchor:在anchor數量少的情況下能擷取更高的召回;
- 2)帶角度的anchor:在密集場景下能獲得更加的性能表現;
正是基于上述兩種anchor的特性,文章在第一級直接采用水準anchor進行回歸(沒有針對角度設定anchor,角度直接進行回歸),并在後面的優化級中對帶旋轉角度的roi proposal進行進一步優化,這樣就很好兼顧了兩種不同類型anchor的性質。
2. 方法設計
2.1 方法pipline
文章的算法pipeline總體上是一階段的結構,網絡在FPN輸出結果上進行邊界框預測,其結構見下圖所示:

注意上圖中繪制的網絡結構,在第一階段輸出的分類和回歸通道都是 5 A 5A 5A的,但是在後面的優化階段中通道都變成了 5 5 5,也就正如前文提到的一緻,第一階段主要就是用水準的anchor去生成帶角度的roi proposal,之後再級聯幾個優化子產品進行精細化回歸。
上面的方法預測的是帶有旋轉角度的目标框,對此會對的目标可以描述為 ( x , y , w , h , θ ) (x,y,w,h,\theta) (x,y,w,h,θ),它們分别代表旋轉矩形框的中心點坐标、寬高和角度資訊。對于需要回歸的變量描述為:
t x = ( x − x a ) w a , t y = ( y − y a ) h a t_x=\frac{(x-x_a)}{w_a},t_y=\frac{(y-y_a)}{h_a} tx=wa(x−xa),ty=ha(y−ya)
t w = l o g ( w w a ) , t h = l o g ( h h a ) , t θ = θ − θ a t_w=log(\frac{w}{w_a}),t_h=log(\frac{h}{h_a}),t_{\theta}=\theta-\theta_a tw=log(waw),th=log(hah),tθ=θ−θa
2.2 Feature Refinement Module(FRM)
在進行邊界框位置确定的時候,使用的是浮點數,但是實際上目标的位置一般都為定點的,這就導緻了在級聯優化和定位過程中沒有對齊的情況。在兩階段的檢測算法中,是使用如RoI Pooling這樣的操作實作對齊。那麼一個在一階段的檢測網絡中怎麼去實作特征的對齊呢?文章使用的方式——雙線性插值。也就是下圖中展示的:
那麼對于插值的算子,可以描述為:
F = F l t ∗ A r b + F r t ∗ A l b + F r b ∗ A l t + F l b ∗ A r t F=F_{lt}*A_{rb}+F_{rt}*A_{lb}+F_{rb}*A_{lt}+F_{lb}*A_{rt} F=Flt∗Arb+Frt∗Alb+Frb∗Alt+Flb∗Art
不同的插值方法對性能也是有不同的影響的,可參考下表:
上面插值計算過程中使用到的點是由上一階段的預測網絡提供的roi proposal,那麼FRM子產品的特征優化過程可以描述為:
F i + 1 = F R M ( B i , S i , { P 2 , … , P 7 } ) F_{i+1}=FRM(B_i,S_i,\{P_2,\dots,P_7\}) Fi+1=FRM(Bi,Si,{P2,…,P7})
具體來講就是使用上一級生成roi proposal的邊界框位置和置信度去優化特征圖,僞代碼描述為:
對于這個子產品如何嵌入到網絡中的,可以參考下圖:
對于該FRM子產品的實作可以參考下面的代碼實作:
def refine_feature_op(self, points, feature_map, name)
那麼同樣是特征對齊,文章的方法與RoI Pooling有着什麼樣的差別呢?對此,文章中将其歸納為如下2點:
- 1)計算效率不一樣:RoI Pooling操作的是一個特征塊,而文章提出的對齊方法操作的是5個點(4個頂點+1個中心點),自然計算的效率就高了很多了;
- 2)處理資訊的範圍不一樣:RoI Pooling處理的是一個instance的特征,而文章的方法是在原特征圖上進行對齊,因而可以看作是image層級的,同時還可以避免Faster RCNN中全連接配接的引入,減少計算量;
2.3 損失函數
文章的損失函數跟傳統的檢測損失函數是類似的,也是包含分類損失和邊界框回歸損失。隻不過在回歸損失的過程中相容考慮了Smooth L1和傾斜舉行的交疊面積(Skew IoU)。這裡需要進行這樣的考慮是因為Smooth L1損失函數和實際的Skew IoU度量并不是同步的,可以參考下面的情況:
從上圖可以看到Smooth L1損失函數一緻,但是Skew IoU差别比較大。對此進行統計分析,得到這兩者之間的關系:
從上面的右圖可以看到兩者并不統一,對此文章提出将Skew IoU融入到邊界框的回歸過程中去,不過這裡不是直接通過可導的形式添加,而是通過權重的形式添加,因而文章的損失函數可以描述為:
L = λ 1 N ∑ n = 1 N o b j n L r e g ( v n ′ , v n ) ∣ L r e g ( v n ′ , v n ) ∣ ∣ f ( S k e w I o U ) ∣ + λ 2 N ∑ n = 1 N L c l s ( p n , t n ) L=\frac{\lambda_1}{N}\sum_{n=1}^Nobj_n\frac{L_{reg}(v_n^{'},v_n)}{|L_{reg}(v_n^{'},v_n)|}|f(SkewIoU)|+\frac{\lambda_2}{N}\sum_{n=1}^NL_{cls}(p_n,t_n) L=Nλ1n=1∑Nobjn∣Lreg(vn′,vn)∣Lreg(vn′,vn)∣f(SkewIoU)∣+Nλ2n=1∑NLcls(pn,tn)
其中,回歸部分的損失函數描述為(角度L1+邊界框IoU損失):
L r e g ( v ′ , v ) = L s m o o t h − l 1 ( v θ ′ , v θ ) − I o U ( v { x , y , w , h } ′ , v { x , y , w , h } ) L_{reg}(v^{'},v)=L_{smooth-l1}(v_{\theta}^{'},v_{\theta})-IoU(v_{\{x,y,w,h\}}^{'},v_{\{x,y,w,h\}}) Lreg(v′,v)=Lsmooth−l1(vθ′,vθ)−IoU(v{x,y,w,h}′,v{x,y,w,h})
那麼對于這部分損失函數的實作可以參考:
def iou_smooth_l1_loss_(targets, preds, anchor_state, target_boxes, anchors, sigma=3.0, alpha=1.0, beta=1.0, is_refine=False)
其中的Skew IoU的計算描述為:
def iou_rotate_calculate2(boxes1, boxes2)
文章使用的是級聯優化,那麼多個層級(不同層級進行篩選的時候會使用不同的IoU門檻值)的損失函數組織形式為:
L t o t a l = ∑ i = 1 N α i L i L_{total}=\sum_{i=1}^N\alpha_iL_i Ltotal=i=1∑NαiLi
文章裡面涉及的變量的消融實驗:
refine stage數量的影響:
3. 實驗結果
DOTA資料集:
ICDAR 2015資料集: