ARTrack
序列构建和坐标映射
假设,我们根据前三个序列(t=0,t=1,t=2)坐标预测当前位置(t=3)
帧 | 全局框坐标(xmin,ymin,xmax,ymax) |
---|---|
t=0 | (100, 50, 200, 150) |
t=1 | (130, 70, 230, 170) |
t=2 | (160, 90, 260, 190) |
-
首先确定搜索区域
即根据上一帧的中心坐标(cx, cy)得到坐标轴的左上角(坐标轴的原点位置),得到剪裁过后的坐标轴,由于实际剪裁是可能会触及到边界,若触及到边届则将其化为0。
以t=2预测框为中心,向外扩192个像素(因为我们要剪裁当前帧的384*384大小作为搜索区域)
剪裁坐标:
- 中心
cx = (160+260)/2 = 210
,cy = (90+190)/2 = 140
- 左上角
(x1,y1) = (210-192, 140-192) = (18, ‑52)
- 由于越界,实际裁剪会 clamp 到图像边缘,这里假设
(0,0)
开始,因此最终裁剪框:
crop_box = [0, 0, 384, 384]
(刚好整图左上角 384×384)。
- 中心
-
坐标映射:全局 → \rightarrow →局部
假设:
- 大图里裁剪窗口的 左上角坐标 是
(x1, y1)
- 窗口 边长 是
S
(论文里 S=384) - 大图里某个框的坐标是
(xmin, ymin, xmax, ymax)
则 小图坐标 为:
x s m a l l = x b i g − x 1 S , y s m a l l = y b i g − y 1 S x_{small}=\frac{x_{big}-x_1}{S},y_{small}=\frac{y_{big}-y_1}{S} xsmall=Sxbig−x1,ysmall=Sybig−y1全局坐标 局部坐标公式 结果(局部) (100,50,200,150) (x-0)/384
,(y-0)/384
(0.26, 0.13, 0.52, 0.39) (130,70,230,170) 同上 (0.34, 0.18, 0.60, 0.44) (160,90,260,190) 同上 (0.42, 0.23, 0.68, 0.49) - 大图里裁剪窗口的 左上角坐标 是
-
离散化(即将坐标映射到共享词汇表的序号上)
然后将模型规定的预测当前帧的前几帧位置坐标映射到剪裁区域,并规范化到(0, 1),实际部分框会超出剪裁区域,所以我们扩大范围到(-0.5, 1.5 )的范围。然后根据公式:
t o k e n i d = ⌊ c + 0.5 2.0 × 800 ⌋ , t o k e n i d ∈ [ 0 , 799 ] token_{id}=\lfloor \frac{c+0.5}{2.0} \times 800 \rfloor,token_{id} \in[0,799] tokenid=⌊2.0c+0.5×800⌋,tokenid∈[0,799]
比如说:原始坐标 c 计算过程 token_id −0.4 (−0.4+0.5)/2×800 = 40 40 0.0 (0.0+0.5)/2×800 = 200 200 0.5 (0.5+0.5)/2×800 = 400 400 1.2 (1.2+0.5)/2×800 = 680 680 1.5 (1.5+0.5)/2×800 = 800 → clip 799 799 局部坐标 离散化公式 Token ID 0.26 floor((0.26+0.5)/2.0*800)
304 0.13 … 252 0.52 … 408 0.39 … 356 … … …
在最后,我们会一个构造共享词汇表,表中序号为0~799,它的作用是把坐标映射到[0,799],从表中取出坐标对应的768-d的编码。(类似于NLP的词向量表),这个768-d时随机初始化的,在训练过程中会一直变化,推理是不变的。
最终输入到decoder的数据
剪裁变换后的序列与特征:
名称 | 来源 | 形状/内容 |
---|---|---|
Template Z | 原图 bbox0 裁剪 | [3,192,192] |
Search X | 原图 384×384 裁剪 | [3,384,384] |
Trajectory Tokens | 映射 + 离散化 | [12] |
其中Template Z是模版区域特征,我们只需要它的视觉特征,不需要坐标信息,所以直接剪裁成192*192即可,Search X是对搜索区域剪裁得到的,Trajectory Tokens对前三个框位置信息映射+离散化。
最后进入到decoder的数据:
-
token序列
名称 形状 内容 coord_tokens
[1, 4N]
过去 N 帧的 4 个离散 token ID
例:N=3 →[304,252,408,356, 344,…]
→ 经 nn.Embedding
[1, 4N, 768]
每个 token 查 800×768 共享表 → 768-d 向量 → 加位置编码 [1, 4N, 768]
再叠 4 个固定 768-d 向量(区分 xmin/ymin/xmax/ymax) -
command token(提示)
名称 形状 内容 C
[1, 1, 768]
可学习的 768-d 向量,每帧复制 1 次,告诉模型“现在开始跟踪” -
视觉特征
名称 形状 内容 enc_out
[1, 1536, 768]
ViT 对 模板 patch + 搜索 patch 的联合特征,Decoder 通过 交叉注意力 读取 -
causal mask(保证自回归)
名称 形状 作用 causal_mask
[1+4N, 1+4N]
下三角 0/1 矩阵,让 token_i 只能看到 token_0…i-1 形状里面的+1表示加上一个command token
Decoder 的输入 = 命令 token + 历史 4N 个坐标 token(已转成 768-d)+ 整张 384×384 视觉特征,用因果掩码保持自回归。
最后的预测头输出
模型先预测 800 个“分数”,挑出分数最高的那个 token ID,再用这个 ID 反查对应的离散坐标,最后把离散坐标还原成连续值。
步骤 | 实际发生的事情 |
---|---|
① 输出 logits | Decoder 最后得到 logits: [4, 800] ,对应 4 个坐标各自 800 个 bin 的分数。 |
② 选最高分 | 对每一行做 argmax ,得到 4 个 token ID,例如 [208, 104, 416, 312] 。 |
③ 反查坐标 | 用 ID 乘以 bin 宽再减去平移量,得到离散坐标,例如 208 → 0.26 。 |
④ 得到连续坐标 | 结果就是最终预测的 (xmin, ymin, xmax, ymax) 。 |
伪代码:
ids = logits.argmax(dim=-1) # [4] token IDs
coords = (ids / 800 * 2.0) - 0.5 # 反归一化到 [-0.5, 1.5]
coords = coords * 384 + crop_x1 # 再映射回大图像素
decoder是怎么同时处理序列和视觉信息的
序列 token 走自注意力,视觉 token 走交叉注意力,二者交替堆叠,最后从序列头输出坐标 logits
1️⃣ 输入张量(形状固定)
张量 | 形状 | 说明 |
---|---|---|
seq | [B, L, 768] | 序列:1 个命令 token + 4N 个坐标 token(已 Embedding+PosEmbed) |
vis | [B, 1536, 768] | 视觉:ViT 给模板+搜索图的全部 patch token |
2️⃣ 自注意力(Causal Self-Attn)
-
Mask:下三角,保证第 i 个坐标 token 只能看到前面的 token。
-
计算:
Q = K = V = seq seq = softmax(Q@K^T + mask) V
-
作用:让历史轨迹彼此传递运动信息。
3️⃣ 交叉注意力(Cross-Attn)
-
Q 来自序列,
K, V
来自视觉 token:Q = seq K = V = vis seq = softmax(Q@K^T) V
-
作用:把“运动上下文”与“当前画面”对齐,得到“视觉-运动混合”表示。
4️⃣ 交替堆叠
- 论文默认 6 层 Decoder,每层 =
Self-Attn → Cross-Attn → FFN
。 - 视觉 token 只与序列 token 交互,不自我更新,保持一次编码即可。
5️⃣ 输出头(无额外参数)
-
取 最后 4 个位置(对应当前帧 4 个坐标 token):
logits = Linear(768 → 800) # 共享权重 shape: [B, 4, 800]
-
对每行做
argmax
→ 4 个 token ID → 反量化成连续坐标。
6️⃣ 一张流程图
seq token ─┬─[Self-Attn]─┬─[Cross-Attn]─┬─[FFN]─...─┬→ logits
↓ ↓ ↓ ↓
causal vis K,V add&Norm Linear
✅ 一句话总结
序列先自注意,再用交叉注意去“看”视觉 token,交替 6 次后,最后 4 个 token 直接输出 800-way softmax 作为坐标预测。