主要思路和創新點

這是一篇為單目標跟蹤任務設計的 Transformer 結構,在各大資料集上都取得了很好的精度,同時速度也大幅超越之前的方法。

其實對於整體網路來說,其中的 Transformer 只是採取了最普遍簡單的形式,甚至不是 Vision Transformer。概括起來其實創新點在於,在網路最後採用了獨特的輸出端融合經過 Transformer 編碼和解碼的序列。之後選擇使用兩階段訓練方法,分別訓練位置預測端和類別預測端。

先單說預測位置的方式,可以看一下整體結構:

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

搜尋區域和初始模版區域分別輸入共同的骨架網路,這裡使用 ResNet-50 或 ResNet-101,之後將獲得的兩個特徵圖拉長,組合起來輸入 Transformer 模組。可以看下這塊整體結構的程式碼:

def

forward_pass

self

data

run_box_head

run_cls_head

):

feat_dict_list

=

[]

# process the templates

for

i

in

range

self

settings

num_template

):

template_img_i

=

data

‘template_images’

][

i

view

-

1

*

data

‘template_images’

shape

2

:])

# (batch, 3, 128, 128)

template_att_i

=

data

‘template_att’

][

i

view

-

1

*

data

‘template_att’

shape

2

:])

# (batch, 128, 128)

feat_dict_list

append

self

net

img

=

NestedTensor

template_img_i

template_att_i

),

mode

=

‘backbone’

))

# process the search regions (t-th frame)

search_img

=

data

‘search_images’

view

-

1

*

data

‘search_images’

shape

2

:])

# (batch, 3, 320, 320)

search_att

=

data

‘search_att’

view

-

1

*

data

‘search_att’

shape

2

:])

# (batch, 320, 320)

feat_dict_list

append

self

net

img

=

NestedTensor

search_img

search_att

),

mode

=

‘backbone’

))

# run the transformer and compute losses

seq_dict

=

merge_template_search

feat_dict_list

#將兩個輸出每個模組分別聯合在一起

out_dict

_

_

=

self

net

seq_dict

=

seq_dict

mode

=

“transformer”

run_box_head

=

run_box_head

run_cls_head

=

run_cls_head

# out_dict: (B, N, C), outputs_coord: (1, B, N, C), target_query: (1, B, N, C)

return

out_dict

def

merge_template_search

inp_list

return_search

=

False

return_template

=

False

):

‘’‘NOTICE: search region related features must be in the last place’‘’

# 很簡單的操作,搜尋區域在後面因為之後會講到一個提取

seq_dict

=

{

“feat”

torch

cat

([

x

“feat”

for

x

in

inp_list

],

dim

=

0

),

“mask”

torch

cat

([

x

“mask”

for

x

in

inp_list

],

dim

=

1

),

“pos”

torch

cat

([

x

“pos”

for

x

in

inp_list

],

dim

=

0

)}

return

seq_dict

之後保留 Encoder 的輸出及最終 Decoder 輸出,這兩個輸出大小是不一樣的,Decoder 的輸出大小取決於目標序列,大小一般為 1。這兩個輸出通道數是一樣的,因此先將它們點積,再與 Encoder 的輸出做每個畫素的乘法,可以看下面的輸出端圖:

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

這張圖將輸出端的具體操作解釋的很清楚,在得到乘積後的目標序列後再將其展開為二維的特徵圖。最後將這個特徵圖輸入進兩個結構完全一樣的 FCN 網路,得到兩張熱度圖,分別預測目標物體檢測框的左上角位置和右下角位置。可以參考一下這部分輸出端的程式碼:

def

forward_box_head

self

hs

memory

):

‘’‘

hs: output embeddings (1, B, N, C) 解碼器的最終輸出

memory: encoder embeddings (H1W1+H2W2, B, C) 編碼器的中間輸出,大小為模板影象素+搜尋區域影象素

’‘’

# adjust shape 這就是為什麼上面在組合時搜尋區域一定要在後面

enc_opt

=

memory

-

self

feat_len_s

:]

transpose

0

1

# encoder output for the search region (B, H2W2, C)

dec_opt

=

hs

squeeze

0

transpose

1

2

# (B, C, N)

att

=

torch

matmul

enc_opt

dec_opt

# (B, H2W2, N)

opt

=

enc_opt

unsqueeze

-

1

*

att

unsqueeze

-

2

))

permute

((

0

3

2

1

))

contiguous

()

# (B, HW, C, N) ——> (B, N, C, HW)

bs

Nq

C

HW

=

opt

size

()

opt_feat

=

opt

view

-

1

C

self

feat_sz_s

self

feat_sz_s

# 上面就是輸入 FCN 前的操作

# run the corner head

outputs_coord

=

box_xyxy_to_cxcywh

self

box_head

opt_feat

))

#下面的程式碼會給出

# 上面 xyxy_cxcywh 是從預測兩個頂點轉換成檢測框標註形式

outputs_coord_new

=

outputs_coord

view

bs

Nq

4

out

=

{

‘pred_boxes’

outputs_coord_new

}

return

out

outputs_coord_new

這與先前預測檢測框的方法比較有較好的優勢,作者稱是因為能夠顯式化預測中的不確定性,能夠更準確和魯棒。文章給了熱度圖後兩個頂點的計算方式,實際上就是將所有位置與對應值加權平均了:

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

P 為經過 softmax 的熱度圖;tl 左上角;br 右下角

部分程式碼:

def

conv

in_planes

out_planes

kernel_size

=

3

stride

=

1

padding

=

1

dilation

=

1

):

# 就是一層 FCN

# 3*3 Conv + BN + ReLU

return

nn

Sequential

nn

Conv2d

in_planes

out_planes

kernel_size

=

kernel_size

stride

=

stride

padding

=

padding

dilation

=

dilation

bias

=

True

),

nn

BatchNorm2d

out_planes

),

nn

ReLU

inplace

=

True

))

class

Corner_Predictor

nn

Module

):

‘’‘產生兩個預測熱度圖及生成頂點’‘’

def

__init__

self

inplanes

=

64

channel

=

256

feat_sz

=

20

stride

=

16

freeze_bn

=

False

):

super

Corner_Predictor

self

__init__

()

self

feat_sz

=

feat_sz

self

stride

=

stride

self

img_sz

=

self

feat_sz

*

self

stride

‘’‘top-left corner’‘’

self

conv1_tl

=

conv

inplanes

channel

freeze_bn

=

freeze_bn

self

conv2_tl

=

conv

channel

channel

//

2

freeze_bn

=

freeze_bn

self

conv3_tl

=

conv

channel

//

2

channel

//

4

freeze_bn

=

freeze_bn

self

conv4_tl

=

conv

channel

//

4

channel

//

8

freeze_bn

=

freeze_bn

self

conv5_tl

=

nn

Conv2d

channel

//

8

1

kernel_size

=

1

‘’‘bottom-right corner’‘’

self

conv1_br

=

conv

inplanes

channel

freeze_bn

=

freeze_bn

self

conv2_br

=

conv

channel

channel

//

2

freeze_bn

=

freeze_bn

self

conv3_br

=

conv

channel

//

2

channel

//

4

freeze_bn

=

freeze_bn

self

conv4_br

=

conv

channel

//

4

channel

//

8

freeze_bn

=

freeze_bn

self

conv5_br

=

nn

Conv2d

channel

//

8

1

kernel_size

=

1

‘’‘about coordinates and indexs’‘’

with

torch

no_grad

():

self

indice

=

torch

arange

0

self

feat_sz

view

-

1

1

*

self

stride

# generate mesh-grid 產生座標

self

coord_x

=

self

indice

repeat

((

self

feat_sz

1

))

view

((

self

feat_sz

*

self

feat_sz

,))

float

()

cuda

()

self

coord_y

=

self

indice

repeat

((

1

self

feat_sz

))

view

((

self

feat_sz

*

self

feat_sz

,))

float

()

cuda

()

def

forward

self

x

return_dist

=

False

softmax

=

True

):

score_map_tl

score_map_br

=

self

get_score_map

x

#獲取兩個熱度圖

coorx_tl

coory_tl

=

self

soft_argmax

score_map_tl

coorx_br

coory_br

=

self

soft_argmax

score_map_br

return

torch

stack

((

coorx_tl

coory_tl

coorx_br

coory_br

),

dim

=

1

/

self

img_sz

def

get_score_map

self

x

):

# top-left branch

x_tl1

=

self

conv1_tl

x

x_tl2

=

self

conv2_tl

x_tl1

x_tl3

=

self

conv3_tl

x_tl2

x_tl4

=

self

conv4_tl

x_tl3

score_map_tl

=

self

conv5_tl

x_tl4

# bottom-right branch

x_br1

=

self

conv1_br

x

x_br2

=

self

conv2_br

x_br1

x_br3

=

self

conv3_br

x_br2

x_br4

=

self

conv4_br

x_br3

score_map_br

=

self

conv5_br

x_br4

return

score_map_tl

score_map_br

def

soft_argmax

self

score_map

return_dist

=

False

softmax

=

True

):

‘’‘生成頂點’‘’

score_vec

=

score_map

view

((

-

1

self

feat_sz

*

self

feat_sz

))

# (batch, feat_sz * feat_sz)

prob_vec

=

nn

functional

softmax

score_vec

dim

=

1

exp_x

=

torch

sum

((

self

coord_x

*

prob_vec

),

dim

=

1

exp_y

=

torch

sum

((

self

coord_y

*

prob_vec

),

dim

=

1

return

exp_x

exp_y

於是,損失函式就是預測檢測框和標註框的 IoU 損失及 L1 損失:

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

以上部分均是對跟蹤目標的位置預測,作者提出在注重位置的同時也要注重時間變化對目標特徵帶來的影響。

歸納起來是額外增加了一個訓練階段和訓練分支,這個分支用來評估檢測目標時序上的置信度。該階段為第二階段,鎖定已經訓練好的位置預測主結構,只訓練置信度預測分支。

之後所有的結構會用於驗證和測試階段,輸入變成了三張圖片,額外增加了動態模板。如果在測試過程中預測置信度大於設定閾值,則認為該檢測區域可以作為時間上的動態模板並不斷更新。當然不是每一幀都換,而是隔一定數量比如文章中用了兩百幀。畢竟在長時間序列影片中,較近一幀的特徵相似度是要高一些的,具體結構如下(擴充套件為粉色區域):

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

分類埠的結構為三層 MLP,損失函式採用交叉熵:

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

這部分選取的搜尋區域會有百分之五十的機率為正確圖片,另外會隨機選取同一個影片中的不同幀作為負例,使分類埠判斷是否合理。

實驗結果和視覺化

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

在 GOT-10k 測試資料集上的實驗結果

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

在 TrackingNet 測試資料集上的實驗結果

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

在 VOT2020 資料集上的實驗結果

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

在 VOT-LT2020 資料集上的實驗結果

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

在 LaSOT 測試資料集上的精度比較

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

Transformer Encoder 和 Decoder 的 Attention 結果比較

【跟蹤任務 Transformer】Learning Spatio-Temporal Transformer for Visual Tracking

各結構貢獻的消融實驗比較,實驗中 Position Embedding 採用了 sine

論文資訊

Learning Spatio-Temporal Transformer for Visual Tracking

https://

arxiv。org/pdf/2103。1715

4。pdf