SiameseRPN++分析

SiamRPN++

  • 論文來源
  • 論文背景
    • 什么是目標跟蹤
    • 什么是孿生網絡結構
    • Siamese的局限
    • 解決的問題
  • 論文分析
    • 創新點一:空間感知策略
    • 創新點二:ResNet-50深層網絡
    • 創新點三:多層特征融合
    • 創新點四:深層互相關
  • 代碼分析
    • 整體代碼簡述
    • (1)特征提取網絡
    • (2)逐層的特征融合(Layerwise Aggregation)
    • (3)深層互相關Depthwise Cross Correlation
    • 總結
  • 論文翻譯
    • Abstract
    • 1. Introduction
    • 2. Related Work
    • 3. Siamese Tracking with Very Deep Networks
    • 3.1. Analysis on Siamese Networks for Tracking
    • 3.2. ResNet-driven Siamese Tracking
    • 3.3. Layer-wise Aggregation
    • 3.4. Depthwise Cross Correlation
    • 4. Experimental Results
    • 4.1. Training Dataset and Evaluation
    • 4.2. Implementation Details
    • 4.3. Ablation Experiments
    • 4.4. Comparison with the state-of-the-art
    • 5. Conclusions

論文來源

論文鏈接
代碼鏈接

本文參考:
如何理解SiamRPN++?
SiamRPN++理解
SiamRPN++: 基于深度網絡的孿生視覺跟蹤的進化
【SOT】Siamese RPN++ 論文和代碼解析
SiamRPN++算法詳解

論文背景

什么是目標跟蹤

使用視頻序列第一幀的圖像(包括bounding box的位置),來找出目標出現在后序幀位置的一種方法。

什么是孿生網絡結構

在進入到正式理解SiamRPN++之前,為了更好的理解這篇論文,我們需要先了解一下孿生網絡的結構。
孿生網絡是一種度量學習的方法,而度量學習又被稱為相似度學習。
在這里插入圖片描述
孿生網絡結構被較早地利用在人臉識別的領域(《Learning a Similarity Metric Discriminatively, with Application to Face Verification》)。其思想是將一個訓練樣本(已知類別)和一個測試樣本(未知類別)輸入到兩個CNN(這兩個CNN往往是權值共享的)中,從而獲得兩個特征向量,然后通過計算這兩個特征向量的的相似度,相似度越高表明其越可能是同一個類別。在上面這篇論文中,衡量這種相似度的方法是L1距離。
在這里插入圖片描述
在目標領域中,最早利用這種思想的是SiamFC,其網絡結構如上圖。輸入的z 是第一幀ROI(也就是在手動在第一幀選擇的bounding box),x則是后一幀的圖片。兩者分別通過兩個CNN,得到兩張特征圖。再通過一次卷積操作(L=(22-6)/1+1=17),獲得最后形狀為17×17×1的特征圖。在特征圖上響應值越高的位置,代表其越可能有目標存在。其想法就類似于對上面的人臉識別孿生網絡添加了一次卷積操作。獲得特征圖后,可以獲得相應的損失函數。y={-1,+1}為真實標簽,v是特征圖相應位置的值。下列第一個式子是特征圖上每一個點的loss,第二個式子是對第一個式子作一個平均,第三個式子就是優化目標。
在這里插入圖片描述

However, both Siamese-FC and CFNet are lack of boundingbox regression and need to do multi-scale test which makesit less elegant. The main drawback of these real-time track-ers is their unsatisfying accuracy and robustness comparedto state-of-the-art correlation filter approaches.但是,Siamese-FC和CFNet都沒有邊界框回歸,因此需要進行多尺度測試,這使得它不太美觀。這些實時跟蹤器的主要缺點是,與最新的相關濾波器方法相比,它們的精度和魯棒性不令人滿意。

為了解決SiamFC的這兩個問題,就有了SiamRPN。可以看到前半部分Siamese Network部分和SiamFC一模一樣(通道數有變化)。區別就在于后面的RPN網絡部分。特征圖會通過一個卷積層進入到兩個分支中,在Classification Branch中的4×4×(2k×256)特征圖等價于有2k個4×4×256形狀的卷積核,對20×20×256作卷積操作,于是可以獲得17×17×2k的特征圖,Regression Branch操作同理。而RPN網絡進行的是多任務的學習。17×17×2k做的是區分目標和背景,其會被分為k個groups,每個group會有一層正例,一層負例。最后會用softmax + cross-entropy loss進行損失計算。17×17×4k同樣會被分為k groups,每個group有四層,分別預測dx,dy,dw,dh。而k的值即為生成的anchors的數目。而關于anchor box的運行機制,可以看下方第二張圖(來自SSD)。
在這里插入圖片描述
在這里插入圖片描述
correlation操作詳解(涉及到后續改進):以分類分支為例,在RPN中,分類分支需要輸出一個通道數為 2k 的特征圖( k 為anchor個數),SiamFC中使用的correlation只能提供通道數為1的響應圖,無法滿足要求。所以我們換了一個想法,把correlation層當成一個卷積層,template分支提取的特征作為卷積核,detection分支提取的特征作為卷積層的input,這樣只需要改變卷積核的形狀就可以達到輸出2k通道數的目的。具體做法為使用了兩個不同的卷積層,template分支的卷積層負責升維,把通道數提升到 256*2k ,為了保持對齊,detection分支也增加了一個卷積層,不過保持通道數不變。之后進行correlation操作(卷積),得到最終的分類結果。

Siamese的局限

作者的實驗發現,較深的網絡,如 ResNet, 無法帶來跟蹤精度提升的原因在于:

  1. 更深的網絡的填充會破壞嚴格的平移不變性(Strict translation invariance)
    padding會破壞這種性質
    現代化網絡:隨著何鎧明等提出殘差網絡以后,網絡的深度得到了巨大的釋放,通常物體檢測和語義分割的baseline backbone都采用ResNet50的結構。為了保證網絡具有適當/整齊的分辨率,幾乎所有的現代網絡backbone都需要執行padding操作。而ResNet網絡中具有padding操作,即該網絡肯定不具備嚴格的平移不變性,padding的引入會使得網絡輸出的響應對不同位置有了不同的認知。而我們進行進一步的訓練是希望網絡學習到如何通過物體的表觀特征來分辨回歸物體,這就限制了深網絡在tracking領域的應用。

  2. RPN要求分類和回歸具有不對稱特征
    即如果將搜索區域圖像和模板區域圖像進行互換,輸出的結果應該保持不變。(因為是相似度,所以應該有對稱性)。
    由于SiamRPN不再是進行相似度計算,而是通過計算回歸的偏移量和分類的分數來選擇最終的目標,這將使得該網絡不再具有對稱性。因而在SiamRPN的改進中需要引入非對稱的部件,如果完全Siamese的話沒法達到目的,這一點主要會引導后面的correlation設計。

文中作者引入空間感知策略來克服第一個困難,并對第二個問題進行討論。

針對第一個問題作者認為Strict translation invariance只存在沒有padding的網絡中例如Alexnet,并且假設違反了這種限制將導致空間的傾斜(spatial bias)。
作者發現如下的幾個參數,對跟蹤結果的影響,非常巨大:the receptive field size of neurons; network stride; feature padding。

具體來說,感受野決定了用于計算 feature 的圖像區域。較大的感受野,提供了更好的 image context 信息,而一個較小的感受野可能無法捕獲目標的結構信息;

網絡的步長,影響了定位準確性的程度,特別是對小目標而言;與此同時,它也控制了輸出 feature map 的大小,從而影響了 feature 的判別性和檢測精度。

此外,對于一個全卷積的結構來說,feature padding 對卷積來說,會在模型訓練中,引入潛在的位置偏移,從而使得當一個目標移動到接近搜索范圍邊界的時候,很難做出準確的預測。這三個因素,同時造成了 Siamese Tracker 無法很好的從更頂尖的模型中收益。

解決的問題

該論文主要解決的問題是將深層基準網絡ResNet、Inception等網絡應用到基于孿生網絡的跟蹤網絡中。在SiameseFC算法之后,盡管已經有很多的基于孿生網絡的跟蹤算法,但是大家可能會注意到一個問題是,這些網絡都使用淺層的類AlexNet做為基準特征提取器。其實在這之前,也有學者們嘗試著使用深層的網絡,但是發現直接使用預訓練好的深層網絡反而會導致跟蹤算法精度的下降,因此,這成為了一個基于孿生網絡的跟蹤器需要解決的一個關鍵問題!

論文分析

創新點一:空間感知策略

1.平移不變性的問題
作者認為Strict translation invariance只存在沒有padding的網絡中例如Alexnet,并且假設違反了這種限制將導致空間的傾斜(spatial bias)。作者發現如下的幾個參數,對跟蹤結果的影響,非常巨大:the receptive field size of neurons; network stride; feature padding。具體來說,感受野決定了用于計算 feature 的圖像區域。較大的感受野,提供了更好的 image context 信息,而一個較小的感受野可能無法捕獲目標的結構信息;網絡的步長,影響了定位準確性的程度,特別是對小目標而言;與此同時,它也控制了輸出 feature map 的大小,從而影響了 feature 的判別性和檢測精度。此外,對于一個全卷積的結構來說,feature padding 對卷積來說,會在模型訓練中,引入潛在的位置偏移,從而使得當一個目標移動到接近搜索范圍邊界的時候,很難做出準確的預測。這三個因素,同時造成了 Siamese Tracker 無法很好的從更頂尖的模型中收益。

2.如果破壞了網絡的平移不變性,具體會帶來什么問題呢?
如果現代化網絡的平移不變性被破壞以后,帶來的弊端就是會學習到位置偏見:按照SiamFC的訓練方法,正樣本都在正中心,網絡逐漸會學習到這種統計特性,學到樣本中正樣本分布的情況。即簡而言之,網絡會給圖像的中心位置分配更大的權重。

3.空間感知策略
要想使用更深的特征提取網絡,就要避免對目標產生強烈的中心偏移,我們采用空間感知采樣策略訓練了具有ResNet-50骨干網的SiamRPN。在訓練過程中,我們不再把正樣本塊放在圖像正中心,而是按照均勻分布的采樣方式讓目標在中心點附近進行偏移。隨著偏移的范圍增大,深度網絡可以由剛開始的完全沒有效果逐漸變好。
具體的效果如下圖所示:當我們將shift設置為0時,網絡只會關注圖像中心的位置,對應到圖中就是只有中心位置具有較大的響應值;而當我們將shift設置為16時,網絡開始關注更多的圖像范圍,對應到圖中就是響應的范圍會擴大,顏色由深變淺;而當我們將shift設置為32時,網絡會關注更大額圖像范圍,對應到圖中就是響應的范圍變得更大,顏色也更加多樣化。
在這里插入圖片描述
所以說,通過均勻分布的采樣方式讓目標在中心點附近進行偏移,可以緩解網絡因為破壞了嚴格平移不變性帶來的影響,即消除了位置偏見,讓現代化網絡可以應用于跟蹤算法中。

4.為什么該問題在檢測任務和語義分割任務中并不存在?
因為對于物體檢測和語義分割而言,訓練過程中,物體本身就是在全圖的每個位置較為均勻的分布。我們可以很容易的驗證,如果在物體檢測網絡只訓練標注在圖像中心的樣本,而邊緣的樣本都不進行訓練,那么顯然,這樣訓練的網絡只會對圖像的中心位置產生高響應,邊緣位置就隨緣了,不難想象這種時候邊緣位置的性能顯然會大幅衰減。而更為致命的是,按照SiamFC的訓練方式,中心位置為正樣本,邊緣位置為負樣本。那么網絡只會記錄下邊緣永遠為負,不管表觀是什么樣子了。這完全背離了我們訓練的初衷。

創新點二:ResNet-50深層網絡

我們主要的實驗實在ResNet-50上做的。現代化網絡一般都是stride32,但跟蹤為了定位的準確性,一般stride都比較小(Siamese系列一般都為8),所以我們把ResNet最后兩個block的stride去掉了,同時增加了dilated convolution,一是為了增加感受野,二是為了能利用上預訓練參數。論文中提到的MobileNet等現代化網絡也是進行了這樣的改動。如上圖所示,改過之后,后面三個block的分辨率就一致了。

在訓練過程中采用了新的采樣策略后,我們可以訓練ResNet網絡了,并且能夠正常跟蹤一些視頻了。(之前跟蹤過程中一直聚集在中心,根本無法正常跟蹤目標)。對backbone進行finetune以后,又能夠進一步得到一些性能提升。
在這里插入圖片描述
由于所有層的填充都保持不變,模板特征的空間大小增加到15,這給相關模塊帶來了沉重的計算負擔。因此,作者裁剪中心7×7區域作為模板特征,其中每個特征單元仍然可以捕獲整個目標區域。

創新點三:多層特征融合

在以前的工作中,僅使用像AlexNet這樣的淺層網絡,多層特性不能提供非常不同的作用。然而,考慮到感受野的變化,ResNet中的不同層更有意義。淺層的特征主要集中在低層次的信息上,如顏色、形狀等,對于定位是必不可少的,而缺乏語義信息;深層的特征具有豐富的語義信息,在某些挑戰場景(如運動模糊、形變等)中是有益的。使用這種豐富的層次信息有助于跟蹤。
在這里插入圖片描述
在這里插入圖片描述
在多層使用siamrpn的好處
如創新點2中的圖所示,我們會觀察到作者分別在conv3_3、conv4_6和conv5_3的分支上使用siamrpn網絡,并將前面siamrpn的結果輸入到后面的siamrpn網絡中,該思路類似于cvpr2019值的C-RPN算法,通過多級級聯具有兩個優點:

  1. 可以通過多個siamrpn來選擇出多樣化的樣本或者具有判別性的樣本塊,第一個siamrpn可以去除掉一些特別簡單的樣本塊,而后面的網絡進一步進行濾除,最終剩余一些hard negative sample,這樣其實有利于提升網絡的判別能力。
  2. 由于使用了多級回歸操作,因此可以獲得一個更加準確的BB。

創新點四:深層互相關

互相關模塊是嵌入兩個分支信息的核心操作。SiamFC利用互相關層獲得用于目標定位的單信道響應圖。在SiamRPN中,通過添加一個巨大的卷積層來縮放信道,擴展了互相關以嵌入更高級別的信息,例如anchors。重上行信道模塊使得參數分布嚴重不平衡,使得SiamRPN訓練優化困難。
??作者提出了一個輕量級的互相關層,稱為深度互相關,以實現有效的信息關聯。深度互相關層包含的參數比SiamRPN中使用的互相關層少10倍,性能與之相當。
??為了達到這個目標,作者采用一個 conv-bn block 來調整特征,來適應跟蹤任務。Bounding box prediction 和 基于 anchor 的分類都是非對稱的 (asymmetrical)。為了編碼這種不同,the template branch 和 search branch 傳輸兩個 non-shared convolutional layers。然后,這兩個 feature maps 是有相同個數的 channels,然后一個 channel 一個 channel 的進行 correlation operation。另一個 conv-bn-relu block,用于融合不同 channel 的輸出。最終,最后一個卷積層,用于輸出 classification 和 regression 的結果。

通過用 Depthwise correlation 替換掉 cross-correlation,我們可以很大程度上降低計算代價和內存使用。通過這種方式,template 和 search branch 的參數數量就會趨于平衡,導致訓練過程更加穩定。
在這里插入圖片描述
如上圖所示,圖中(a)互相關層預測方法是取自SiamFC中目標模板和搜索圖像之間的單通道相似性映射。模板圖像和搜索圖像在經過網絡后輸出通道數相同的featuremap,兩者逐通道相互卷積,最后取平均值。
圖中(b)上行信道互相關層,取自SiamRPN,模板圖像和搜索圖像經過特征提取網絡生成feature map后,輸入RPN網絡,分類分支和回歸分支分別經過非權值共享的卷積層后在相互卷積,參數量十分巨大。
圖中(c)深度互相關層預測模板和搜索圖像之間的多通道相關性特征,取自SiamRPN++,模板圖像經過卷積層后并不像SiamRPN那樣將通道數增加2k倍(每個grid生成k個anchors),而是保持不變,同時搜索圖像也與模板圖像保持一致,兩者逐通道相互卷積,之后接一個1×1的卷積層,再改變通道數,這樣在保持精度的同時減少了參數量。如下第一張圖,輸入兩個從ResNet獲得的特征層(channel數目是一致的),先同樣分別通過一個卷積層(由于需要學的任務不同,所以卷積層參數不共享),再分別進行DW卷積操作,然后兩分支再分別通過一層不同的卷積層改變通道數以獲得想要的分類和回歸結果。這樣一來,就可以減少計算量,且使得兩個分支更加平衡。
在這里插入圖片描述
通道數的研究:
下圖說明了一個有趣的現象。同一類別的對象在同一信道(148信道的car、222信道的person和226信道的face)上具有高響應,而其余信道的響應被抑制。這一特性可以理解為,由深度互相關產生的信道方向特征幾乎是正交的,每個信道代表一些語義信息。我們還分析了當使用上通道互相關時的熱圖,而響應圖的解釋性較差。
在這里插入圖片描述
上圖為conv4中的深度相關輸出通道。conv4共有256個通道,但只有少數信道在跟蹤過程中有較高的響應。因此,選擇第148、222、226個通道作為演示,它們是圖中的第2、3、4行。第一行包含來自OTB數據集的六個相應的搜索區域。不同的通道表示不同的語義,第148通道對汽車的響應較高,而對人和臉的響應較低。第222頻道和第226頻道分別對人和臉有很高的響應。

代碼分析

整體代碼簡述

整體代碼主要分成兩個部分,第一個是初始幀標記的目標box為temple,第二個部分為追蹤過程中的track目標。

代碼首先將初始幀進行處理成127×127的形式然后進入主體網絡(包括resnet50(經過resnet50后輸出三個feature_map大小分別是[1, 512, 15, 15]、[1, 1024, 15, 15]、[1, 2048, 15, 15])和adjustnect)框架中,并將輸出的3個feature_map,其大小分別是[1, 128, 7, 7]、[1, 256, 7, 7]、[1, 512, 7, 7]進行保存。
追蹤過程(始終保持上一幀目標位置的中心),根據上一幀目標位置的得分判斷是否進行長期追蹤(長期追蹤圍繞中心位置搜索的面積較大寫,短期追蹤圍繞中心面積搜索的范圍較小,是否進行長期追蹤主要是根據上上衣目標幀的得分決定),按照追蹤形式將上一幀范圍內的像素進行剪裁填充以及resize成255×255,將剪裁過后的圖片輸入到網絡框架中(包括resnet50經過resnet50后輸出三個feature_map大小分別是[1, 512, 31, 31]、[1, 1024, 31, 31]、[1, 2048, 31, 31])和adjustnect),并輸出三個feature_map大小分別為[1, 128, 31, 31]、[1, 256, 31, 31]、[1, 512, 31, 31]
最后temple和track中分別輸出的feature_map進入rpn網絡中,按照索引一一對應進行卷積操,之后將templw中的feature展開成[temple.size[0]*temple.size[1], 1,temple.size[2],temple. zise[3]]的形式作為kernel,track同樣改變通道數作輸入層進行卷積操作,之后將三次卷積操作的結果按照一定權重(網絡中訓練出來的權重參數)相加最后輸出。rpn中有兩個分支一個用來預測是否是目標類別cls輸出的tensor大小[1, 10, 25,25](選擇的anchor數為5,預測為2分類因此第二個維度上的通道數為10),另一個分支預測位置的偏移量loc,輸出的tensor大小為[1, 20, 25, 25](選擇的anchor為5,預測四個位置上的偏移[x, y, w, h])。
根據cls何loc的輸出預測是否是目標以及目標位置,將cls何loc分別展開成[3125, 2], [3125, 4]的形式,cls經過softmax分類器,并取最后一列最為目標位置的預測概率。anchor box結合回歸結果得出bounding box。最后使用余弦窗和尺度變化懲罰來對cls中經過softmax處理過后的最后一列進行排序,選最好的。余弦窗是為了抑制距離過大的,尺度懲罰是為了抑制尺度大的變化

特征提取網絡: 改進的殘差網絡ResNet-50
逐層特征融合(Layerwise Aggregation)
Depthwise Cross Correlation
接下來按照分成的三部分進行詳細說明。

(1)特征提取網絡

論文中提到

The original ResNet has a large stride of 32 pixels, which is not suitable for dense Siamese network prediction. As shown in Fig.3, we reduce the effective strides at the last two block from 16 pixels and 32 pixels to 8 pixels by modifying the conv4 and conv5 block to have unit spatial stride, and also increase its receptive field by dilated convolutions. An extra 1 x 1 convolution layer is appended to each of block outputs to reduce the channel to 256.

作者的意思就是嫌棄原來ResNet的stride過大,從而在conv4和conv5中將stride=2改動為stride=1。但是同時為了保持之前的感受野,采用了空洞卷積。其代碼定義如下:

class ResNetPP(nn.Module):def __init__(self, block, layers, used_layers):self.inplanes = 64super(ResNetPP, self).__init__()self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=0,  # 3bias=False)self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)self.layer1 = self._make_layer(block, 64, layers[0])self.layer2 = self._make_layer(block, 128, layers[1], stride=2)self.feature_size = 128 * block.expansionself.used_layers = used_layerslayer3 = True if 3 in used_layers else Falselayer4 = True if 4 in used_layers else Falseif layer3:self.layer3 = self._make_layer(block, 256, layers[2],stride=1, dilation=2)  # 15x15, 7x7self.feature_size = (256 + 128) * block.expansionelse:self.layer3 = lambda x: x  # identityif layer4:self.layer4 = self._make_layer(block, 512, layers[3],stride=1, dilation=4)  # 7x7, 3x3self.feature_size = 512 * block.expansionelse:self.layer4 = lambda x: x  # identityfor m in self.modules():if isinstance(m, nn.Conv2d):n = m.kernel_size[0] * m.kernel_size[1] * m.out_channelsm.weight.data.normal_(0, math.sqrt(2. / n))elif isinstance(m, nn.BatchNorm2d):m.weight.data.fill_(1)m.bias.data.zero_()def _make_layer(self, block, planes, blocks, stride=1, dilation=1):downsample = Nonedd = dilationif stride != 1 or self.inplanes != planes * block.expansion:if stride == 1 and dilation == 1:downsample = nn.Sequential(nn.Conv2d(self.inplanes, planes * block.expansion,kernel_size=1, stride=stride, bias=False),nn.BatchNorm2d(planes * block.expansion),)else:if dilation > 1:dd = dilation // 2padding = ddelse:dd = 1padding = 0downsample = nn.Sequential(nn.Conv2d(self.inplanes, planes * block.expansion,kernel_size=3, stride=stride, bias=False,padding=padding, dilation=dd),nn.BatchNorm2d(planes * block.expansion),)layers = []layers.append(block(self.inplanes, planes, stride,downsample, dilation=dilation))self.inplanes = planes * block.expansionfor i in range(1, blocks):layers.append(block(self.inplanes, planes, dilation=dilation))return nn.Sequential(*layers)def forward(self, x):x = self.conv1(x)x = self.bn1(x)x_ = self.relu(x)x = self.maxpool(x_)p1 = self.layer1(x)p2 = self.layer2(p1)p3 = self.layer3(p2)p4 = self.layer4(p3)out = [x_, p1, p2, p3, p4]out = [out[i] for i in self.used_layers]if len(out) == 1:return out[0]else:return out

從上述代碼中的這段代碼可以看出

if layer3:self.layer3 = self._make_layer(block, 256, layers[2],stride=1, dilation=2)  # 15x15, 7x7self.feature_size = (256 + 128) * block.expansionelse:self.layer3 = lambda x: x  # identityif layer4:self.layer4 = self._make_layer(block, 512, layers[3],stride=1, dilation=4)  # 7x7, 3x3self.feature_size = 512 * block.expansion

作者在原來的ResNet-50的基礎上進行了一些修改,包括stride=1與空洞卷積的使用。

(2)逐層的特征融合(Layerwise Aggregation)

熟悉目標檢測的FPN網絡的小伙伴們一定不會對Layerwise Aggregation陌生。一般而言,淺層的網絡包含的信息更多有關于物體的顏色、條紋等,深層的網絡包含的信息更多包含物體的語義特征。正如作者文中提到的那樣:

Features from earlier layers will mainly focus on low level information such as color, shape, are essential for localization, while lacking of semantic information
使用特征融合可以彌補淺層信息和深層信息的不足,更有助于單目標追蹤。

本文中的Siamese RPN++利用了ResNet-50在conv3、conv4、conv5的輸出作為輸入。如下圖所示。
在這里插入圖片描述
也就是這三個輸出分別都有各自的RPN網絡,并不是通過堆疊或者相加進行融合。這在代碼中是這樣體現的

self.features = resnet50(**{'used_layers': [2, 3, 4]})

先使用改進后的resnet50作為特征提取網絡,返回輸出的層 id 為[2,3,4],其實就是conv3、conv4、conv5的輸出。

然后分別對template圖像和需要detection的圖像分別進行特征提取。

        zf = self.features(template)xf = self.features(detection)

事實上,zf 和 xf 并不是單一的特征圖,而是一個列表,每個列表中包含了三個特征圖。

接著,在特征提取結束后,需要對提取的特征進行調整,代碼中是這樣實現的:

		zf = self.neck(zf)xf = self.neck(xf)

那么這個neck的定義如下:

AdjustAllLayer(**{'in_channels': [512, 1024, 2048], 'out_channels': [256, 256, 256]})

AdjustAllLayer定義如下:

class AdjustLayer(nn.Module):def __init__(self, in_channels, out_channels):super(AdjustLayer, self).__init__()self.downsample = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False),nn.BatchNorm2d(out_channels),)def forward(self, x):x = self.downsample(x)if x.size(3) < 20:l = 4r = l + 7x = x[:, :, l:r, l:r]return xclass AdjustAllLayer(nn.Module):def __init__(self, in_channels, out_channels):super(AdjustAllLayer, self).__init__()self.num = len(out_channels)if self.num == 1:self.downsample = AdjustLayer(in_channels[0], out_channels[0])else:for i in range(self.num):self.add_module('downsample'+str(i+2),AdjustLayer(in_channels[i], out_channels[i]))def forward(self, features):if self.num == 1:return self.downsample(features)else:out = []for i in range(self.num):adj_layer = getattr(self, 'downsample'+str(i+2))out.append(adj_layer(features[i]))return out

可見上面的AdjustAllLayer的作用就是對特征提取網絡輸出的三個特征圖分別做1x1卷積,調整所有特征圖的通道數為256。論文中也有提及:

An extra 1 x 1 convolution layer is appended to each of block outputs to reduce the channel to 256

上述代碼中有個很有趣的forward,即

 def forward(self, x):x = self.downsample(x)if x.size(3) < 20:l = 4r = l + 7x = x[:, :, l:r, l:r]return x

這么做是為了什么呢?我們發現原文中提到:

Since the paddings of all layers are kept, the spatial size of the template feature increases to 15, which imposes a heavy computational burden on the correlation module. Thus we crop the center 7 x 7 regions as the template feature where each feature cell can still capture the entire target region.

原來是因為降低運算量所以對template的特征圖進行了裁剪,恍然大悟呀!原來原文中的細節都在代碼中有所描述,所以我十分推薦大家結合代碼看論文,這是非常容易進行理解的。

特征提取以及所有通道都壓縮至256后,緊接著代碼實現如下:

  cls, loc = self.head(zf, xf)

其中head定義如下:

 self.head = MultiRPN(**{'anchor_num': 5, 'in_channels': [256, 256, 256], 'weighted': True})

其中MultiRPN定義如下:

class MultiRPN(RPN):def __init__(self, anchor_num, in_channels, weighted=False):super(MultiRPN, self).__init__()self.weighted = weightedfor i in range(len(in_channels)):self.add_module('rpn'+str(i+2),DepthwiseRPN(anchor_num, in_channels[i], in_channels[i]))if self.weighted:self.cls_weight = nn.Parameter(torch.ones(len(in_channels)))self.loc_weight = nn.Parameter(torch.ones(len(in_channels)))def forward(self, z_fs, x_fs):cls = []loc = []for idx, (z_f, x_f) in enumerate(zip(z_fs, x_fs), start=2):rpn = getattr(self, 'rpn'+str(idx))c, l = rpn(z_f, x_f)cls.append(c)loc.append(l)if self.weighted:cls_weight = F.softmax(self.cls_weight, 0)loc_weight = F.softmax(self.loc_weight, 0)def avg(lst):return sum(lst) / len(lst)def weighted_avg(lst, weight):s = 0for i in range(len(weight)):s += lst[i] * weight[i]return sif self.weighted:return weighted_avg(cls, cls_weight), weighted_avg(loc, loc_weight)else:return avg(cls), avg(loc)

(3)深層互相關Depthwise Cross Correlation

Siamese RPN++中選用了Depth-wise Cross Correlation Layer對Template和Search Region進行卷積運算。這么做是為了降低計算量。具體實現過程如下

class DepthwiseXCorr(nn.Module):def __init__(self, in_channels, hidden, out_channels, kernel_size=3, hidden_kernel_size=5):super(DepthwiseXCorr, self).__init__()self.conv_kernel = nn.Sequential(nn.Conv2d(in_channels, hidden, kernel_size=kernel_size, bias=False),nn.BatchNorm2d(hidden),nn.ReLU(inplace=True),)self.conv_search = nn.Sequential(nn.Conv2d(in_channels, hidden, kernel_size=kernel_size, bias=False),nn.BatchNorm2d(hidden),nn.ReLU(inplace=True),)self.head = nn.Sequential(nn.Conv2d(hidden, hidden, kernel_size=1, bias=False),nn.BatchNorm2d(hidden),nn.ReLU(inplace=True),nn.Conv2d(hidden, out_channels, kernel_size=1))def forward(self, kernel, search):kernel = self.conv_kernel(kernel)search = self.conv_search(search)feature = xcorr_depthwise(search, kernel)out = self.head(feature) #維度提升return outclass DepthwiseRPN(RPN):def __init__(self, anchor_num=5, in_channels=256, out_channels=256):super(DepthwiseRPN, self).__init__()self.cls = DepthwiseXCorr(in_channels, out_channels, 2 * anchor_num)self.loc = DepthwiseXCorr(in_channels, out_channels, 4 * anchor_num)def forward(self, z_f, x_f):cls = self.cls(z_f, x_f)loc = self.loc(z_f, x_f)return cls, loc

其中xcorr_depthwise定義如下

def xcorr_depthwise(x, kernel):"""depthwise cross correlation"""batch = kernel.size(0)channel = kernel.size(1)x = x.view(1, batch*channel, x.size(2), x.size(3))kernel = kernel.view(batch*channel, 1, kernel.size(2), kernel.size(3))out = F.conv2d(x, kernel, groups=batch*channel)out = out.view(batch, channel, out.size(2), out.size(3))return out

實質上Depthwise Cross Correlation采用的就是分組卷積的思想,分組卷積可以帶來運算量的大幅度降低,被廣泛用于MobileNet系列網絡中。

通過上述代碼可以看出,與Siamese RPN網絡不同,Siamese RPN++提升網絡通道數為2k或者4k的操作是在卷積操作( Cross Correlation)之后,而Siamese RPN網絡是在卷積操作之前,這樣就減少了大量的計算量了。這在DepthwiseXCorr類中的forward中定義出來了,如下:

    def forward(self, kernel, search):kernel = self.conv_kernel(kernel)search = self.conv_search(search)feature = xcorr_depthwise(search, kernel)out = self.head(feature) #維度提升return out

上面的self.head運算就是升維運算(到2k或者4k),可以看出,其發生在xcorr_depthwise之后。

最后的最后,網絡最后輸出的3個cls和loc分支進行了按權重融合。這在MultiRPN的forward定義了,如下:

 def forward(self, z_fs, x_fs):cls = []loc = []for idx, (z_f, x_f) in enumerate(zip(z_fs, x_fs), start=2):rpn = getattr(self, 'rpn'+str(idx))c, l = rpn(z_f, x_f)cls.append(c)loc.append(l)if self.weighted:cls_weight = F.softmax(self.cls_weight, 0)loc_weight = F.softmax(self.loc_weight, 0)def avg(lst):return sum(lst) / len(lst)def weighted_avg(lst, weight):s = 0for i in range(len(weight)):s += lst[i] * weight[i]return sif self.weighted:return weighted_avg(cls, cls_weight), weighted_avg(loc, loc_weight)else:return avg(cls), avg(loc)

總結

至此,Siamese RPN++的網絡結構就講解結束了,代碼總結如下:

 def forward(self, template, detection):zf = self.features(template) #ResNet-50特征提取xf = self.features(detection)zf = self.neck(zf) #降低維度為256xf = self.neck(xf)cls, loc = self.head(zf, xf) #RPNreturn cls, loc

總體的結構圖如下:
在這里插入圖片描述

圖中右側的支路中

  1. adj系列就是降維為256的1x1卷積
  2. DW_Conv就是Depthwise Cross Correlation操作
  3. Box_Head就是提升維度為4k的1x1卷積
  4. Cls_Head就是提升維度為2k的1x1卷積

至此,Siamese RPN++的結構解析也結束了。

論文翻譯

Abstract

在這里插入圖片描述

1. Introduction

在這里插入圖片描述

2. Related Work

在這里插入圖片描述

3. Siamese Tracking with Very Deep Networks

在這里插入圖片描述

3.1. Analysis on Siamese Networks for Tracking

在這里插入圖片描述

3.2. ResNet-driven Siamese Tracking

在這里插入圖片描述

3.3. Layer-wise Aggregation

在這里插入圖片描述

3.4. Depthwise Cross Correlation

在這里插入圖片描述

4. Experimental Results

4.1. Training Dataset and Evaluation

在這里插入圖片描述

4.2. Implementation Details

在這里插入圖片描述

4.3. Ablation Experiments

在這里插入圖片描述

4.4. Comparison with the state-of-the-art

在這里插入圖片描述

5. Conclusions

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/389241.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/389241.shtml
英文地址,請注明出處:http://en.pswp.cn/news/389241.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL:Innodb page clean 線程 (二) :解析

一、數據結構和入口函數 1、數據結構 ● page_cleaner_t&#xff1a;整個Innodb只有一個&#xff0c;包含整個page clean線程相關信息。其中包含了一個page_cleaner_slot_t的指針。變量名含義mutex用于保護整個page_cleaner_t結構體和page_cleaner_slot_t結構體&#xff0c;當…

Lockdown Wheelie項目

“It’s Strava for wheelies,” my lockdown project, combining hyper-local exercise with data analytics to track and guide improvement. Practising wheelies is a great way to stay positive; after all, it’s looking up, moving forward.我的鎖定項目“將Strava運…

api地理編碼_通過地理編碼API使您的數據更有意義

api地理編碼Motivation動機 In my second semester of my Master’s degree, I was working on a dataset which had all the records of the road accident in Victoria, Australia (2013-19). I was very curious to know, which national highways are the most dangerous …

js進階 12-5 jquery中表單事件如何使用

js進階 12-5 jquery中表單事件如何使用 一、總結 一句話總結&#xff1a;表單事件如何使用&#xff1a;可元素添加事件監聽&#xff0c;然后監聽元素&#xff0c;和javase里面一樣。 1、表單獲取焦點和失去焦點事件有哪兩組&#xff1f; 注意是blur/focus和focus in/out&#x…

SiamBAN論文學習

SiameseBAN論文來源論文背景主要貢獻論文分析網絡框架創新點一&#xff1a;Box Adaptive Head創新點二&#xff1a;Ground-truth創新點三&#xff1a;Anchor Free論文流程訓練部分&#xff1a;跟蹤部分論文翻譯Abstract1. Introduction2. Related Works2.1. Siamese Network Ba…

簡單入門Javascript正則表達式

我們已經會熟練使用js字符串類型了&#xff0c;例如你想知道一個變量是否等于一個字符串&#xff0c;可能可能這樣判斷 if(ahello,world){... } 復制代碼但是往往我們有時候對一些字符串判斷顯得力不從心&#xff0c;例如判斷一個文件的類型是否為js類型&#xff0c;可能有下面…

實現klib_使用klib加速數據清理和預處理

實現klibTL;DRThe klib package provides a number of very easily applicable functions with sensible default values that can be used on virtually any DataFrame to assess data quality, gain insight, perform cleaning operations and visualizations which results …

MMDetection修改代碼無效

最近在打比賽&#xff0c;使用MMDetection框架&#xff0c;但是無論是Yolo修改類別還是更改head&#xff0c;代碼運行后發現運行的是修改之前的代碼。。。也就是說修改代碼無效。。。 問題解決辦法&#xff1a; MMDetection在首次運行后會把一部分運行核心放在anaconda的環境…

docker etcd

etcd是CoreOS團隊于2013年6月發起的開源項目&#xff0c;它的目標是構建一個高可用的分布式鍵值(key-value)數據庫&#xff0c;用于配置共享和服務發現 etcd內部采用raft協議作為一致性算法&#xff0c;etcd基于Go語言實現。 etcd作為服務發現系統&#xff0c;有以下的特點&…

SpringBoot簡要

2019獨角獸企業重金招聘Python工程師標準>>> 簡化Spring應用開發的一個框架&#xff1b;      整個Spring技術棧的一個大整合&#xff1b;      J2EE開發的一站式解決方案&#xff1b;      自動配置&#xff1a;針對很多Spring應用程序常見的應用功能&…

發送郵件 的類 C# .net

/// <summary> /// 發送郵件 /// </summary> /// <param name"SendTo">發送人的地址</param> /// <param name"MyEmail">我的Email地址</param> /// <param name"SendTit…

簡明易懂的c#入門指南_統計假設檢驗的簡明指南

簡明易懂的c#入門指南介紹 (Introduction) One of the main applications of frequentist statistics is the comparison of sample means and variances between one or more groups, known as statistical hypothesis testing. A statistic is a summarized/compressed proba…

計算機科學期刊_成為數據科學家的五種科學期刊

計算機科學期刊The field of data science is advancing at an incredible pace. New scientific articles are published daily. As a student, I try to stay up-to-date with the scientific literature that is published. In this blog post, I created a list of scienti…

Torch.distributed.elastic 關于 pytorch 不穩定

錯誤日志&#xff1a; Epoch: [229] Total time: 0:17:21 Test: [ 0/49] eta: 0:05:00 loss: 1.7994 (1.7994) acc1: 78.0822 (78.0822) acc5: 95.2055 (95.2055) time: 6.1368 data: 5.9411 max mem: 10624 WARNING:torch.distributed.elastic.agent.server.api:Rec…

0x22 迭代加深

poj2248 真是個新套路。還有套路剪枝...大到小和判重 #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<bitset> using namespace std;int n,D,x[110];bool…

云原生全球最大峰會之一KubeCon首登中國 Kubernetes將如何再演進?

雷鋒網消息&#xff0c;11月14日&#xff0c;由CNCF發起的云原生領域全球最大的峰會之一KubeConCloudNativeCon首次登陸中國&#xff0c;中國已經成為云原生領域一股強大力量&#xff0c;并且還在不斷成長。 毫無疑問&#xff0c;Kubernetes已經成為容器編排事實標準&#xff…

分布分析和分組分析_如何通過群組分析對用戶進行分組并獲得可行的見解

分布分析和分組分析數據分析 (DATA ANALYSIS) Being a regular at a restaurant is great.乙 eing定期在餐廳是偉大的。 When I started university, my dad told me I should find a restaurant I really liked and eat there every month with some friends. Becoming a reg…

python 工具箱_Python交易工具箱:通過指標子圖增強圖表

python 工具箱交易工具箱 (trading-toolbox) After a several months-long hiatus, I can finally resume posting to the Trading Toolbox Series. We started this series by learning how to plot indicators (specifically: moving averages) on the top of a price chart.…

PDA端的數據庫一般采用的是sqlce數據庫

PDA端的數據庫一般采用的是sqlce數據庫,這樣與PC端的sql2000中的數據同步就變成了一個問題,如在PDA端處理,PDA端的內存,CPU等都是一個制約因素,其次他們的一個連接穩定及其間的數據傳輸也是一個難點.本例中通過在PC端的轉化后再復制到PDA上面,這樣,上面所有的問題都得到了一個有…

bzoj 1016 [JSOI2008]最小生成樹計數——matrix tree(相同權值的邊為階段縮點)(碼力)...

題目&#xff1a;https://www.lydsy.com/JudgeOnline/problem.php?id1016 就是縮點&#xff0c;每次相同權值的邊構成的聯通塊求一下matrix tree。注意gauss里的編號應該是從1到...的連續的。 學習了一個TJ。用了vector。自己曾寫過一個只能過樣例的。都放上來吧。 路徑壓縮的…