想象你是一名体育场的跟拍摄影师,摄像机每秒钟拍下 25 张“连拍快照”(帧)。导演的要求是:在每一张照片里,都用红笔完整圈出 7 号运动员的轮廓——从头到脚,而不是在他脸上贴个名字标签。这个“在每一帧画面中持续圈出指定主角剪影”的工作,就是视频目标分割(Video Object Segmentation,VOS)。 难点在于:主角会跑、会转身、会被观众席遮挡、光线还会忽明忽暗。VOS 技术分两种玩法:半监督 VOS 像“起跑前裁判递给你一张运动员照片”,你带着照片去找人;无监督 VOS 则像“没人给你照片,你得自己判断谁是镜头里的主角”。早期的做法是把每张照片交给不同实习生分别圈人,结果圈出来的人影一闪一闪、身份还经常换人;后来工程师发明了“接力传递”式的 MaskTrack 模型,再后来升级为“档案册回忆”式的 STM 记忆网络。本文就用“场边盯人”这条故事线,把 VOS 的原理、模型、工程实践一次讲透。

岗位关联

掌握视频目标分割,你就能给视频编辑、自动驾驶、体育赛事直播等产品装上“自动盯人”的眼睛——这是 CV 工程师从静态图像走向动态视频理解的关键一步。

目录
  1. 可视化演示
  2. 任务定义与分类
  3. 经典方法演进
  4. MaskTrack模型
  5. 时空记忆STM
  6. 半监督VOS技术
  7. 无监督VOS技术
  8. 工程实践应用
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

通过动态展示先验分布到后验分布的更新过程,直观理解贝叶斯推断如何利用观测数据逐步修正对参数的估计。

本节配有交互动效(进入视口后自动加载,约 3KB)。

贝叶斯推断 蓝色曲线为先验分布,表示参数的初始信念 绿色曲线为后验分布,随数据更新而变化 P(θ|D) ∝ P(D|θ)P(θ) 逐步展示后验分布的收敛过程

任务定义与分类

想象你是体育场里的跟拍摄影师,摄像机每秒钟拍 25 张照片(帧),导演要求你在每一张照片里都用红笔圈出 7 号运动员的完整身影——是“圈出完整轮廓”,而不是在他脸上贴个名字标签。这个“圈出身影”的工作,就是视频目标分割。

VOS 的输入是一段视频和一个“谁是主角”的定义,输出是每一帧的“主角剪影”——一张二值掩码(mask):前景像素标 1,背景像素标 0。主角的定义方式分为两种:半监督 VOS 是“起跑前裁判递来一张 7 号运动员的照片”(第一帧给了标注掩码);无监督 VOS 是“没有人告诉你谁是主角,AI 得自己从画面里判断谁值得被圈出来”。

这和普通图像分割有本质区别:图像分割把画面里所有物体都切开;半监督 VOS 只关心“指定的那一位”,并且跨帧保持身份不换人。工程上评估有两条硬指标:区域相似度 J(预测掩码与真值掩码的交并比)和轮廓精度 F(对边界像素算精确率与召回率的调和平均)。

评判跟拍摄影师的标准也是这样:不能只看某一张照片圈得准,还要看他整场比赛 25 帧 × 60 分钟里圈得稳、圈得全。VOS 的指标设计,本质上就是在考核“长跑型选手”的稳定性。

J=∣M∩G∣∣M∪G∣,J‾=1T∑t=1TJt\displaystyle J = \frac{\lvert M \cap G \rvert}{\lvert M \cup G \rvert},\qquad \overline{J} = \frac{1}{T}\sum_{t=1}^{T} J_t
J 就是“你圈的剪影”和“真实剪影”重叠了多少;\overline{J} 是全视频所有帧的平均,防止模型只讨好某一帧。
  1. 交集$M \cap G$ 表示预测掩码 M 和真实掩码 G 重叠的像素个数,是“圈对的部分”。
  2. 并集$M \cup G$ 是两者覆盖的像素总数,用并集做分母可以惩罚“故意画大圈”的偷懒行为。
  3. 全序列平均$\overline{J}$ 对每一帧的 J 取平均,衡量整段视频的稳定性——某一帧出色没用,帧帧稳定才算赢。

经典方法演进

早期的“盯人”方案很粗糙:剪辑师把每一张照片分别交给不同的实习生去圈人,结果实习生互不相识,有人圈了背影、有人圈了观众、有人圈了号码牌——把照片拼成视频后,主角的身影一闪一闪,像坏掉的霓虹灯。

最早的 VOS 就是这么做的:逐帧独立做图像分割。帧与帧之间没有约定,于是出现两个致命问题:分割结果闪烁(同一主角这帧是红的、下帧变蓝的)和身份漂移(圈着圈着圈到别人身上去了)。随后工程师走了两条改进路:一是检测跟踪结合——先用目标检测器找到「框」,再用跟踪器把框串起来;二是掩码传播——把上一帧的分割结果“接力”给下一帧。

检测跟踪的软肋在于:检测器偶尔漏检,跟踪框一旦飘走就永远回不来。掩码传播逐渐成为主流,其核心是一个状态传递思路:当前帧的掩码由上一帧掩码经过一个变换函数得到。MaskTrack 正是这条路上的代表;而更进一步的“匹配派”认为,与其只看上一帧,不如把整段历史都当作参考,这就是后文 STM 的雏形。

从“各干各的实习生”到“接力传递”,VOS 终于明白一个朴素道理:主角不会凭空消失,上一帧的位置和样貌就是最珍贵的线索。谁先利用好时间,谁就能在流动画面里站稳脚跟。

Mt=Φ(Mt−1, It)\displaystyle M_t = \Phi(M_{t-1},\, I_t)
当前帧掩码 M_t 不是凭空产生的,而是“上一帧掩码 M_{t-1} + 当前画面 I_t”共同推出来的。
  1. 上一帧掩码$M_{t-1}$ 是上一帧的主角剪影,相当于接力赛中前一位选手递来的“位置信息”。
  2. 当前画面$I_t$ 是当前帧图像,告诉模型“主角现在可能跑到了哪个新位置”。
  3. 传递函数$\Phi$ 是神经网络学到的变换规则,输入上面两样东西,输出当前帧掩码。

MaskTrack模型

接力的 1.0 版本长这样:前一位同事在下一张照片背面只留了一个简笔剪影(上一帧掩码),后一位同事举着剪影在照片里找形状相似的地方,描一圈就交班。这就是 MaskTrack 的核心直觉。

MaskTrack 的思路非常直接:把“上一帧预测出的掩码”当作一个额外的通道,和当前帧 RGB 图像拼在一起,喂给一个分割网络。网络一边看“现在的画面长什么样”,一边参考“上一帧主角在哪、长什么样”,从而推断主角现在的位置。训练时还有一个巧妙的细节:网络输入用的不是真实掩码,而是模型自己上一帧的输出——相当于“用上一站的错误来训练选手纠错”,让模型在测试时面对自身误差也能稳住。

具体输入由三部分拼接而成:当前帧 RGB(3 通道)+ 上一帧掩码(1 通道)+ 可选的光流(2 通道,表示画面里每个像素的移动方向)。整体是单分支编码器-解码器架构,轻量、好训、推理快。

MaskTrack 像一位只能记住“上一站路况”的接力选手:在直道上他跑得飞快,可一旦遇到人群遮挡、快速转身,他手里的剪影早已过时,错误还会被一帧一帧“传染”下去。这就是它最大的局限——没有长期记忆。

It′=[ It,  Mt−1,  Ft−1→t ]\displaystyle I'_t = \bigl[\, I_t,\; M_{t-1},\; F_{t-1 \to t} \,\bigr]
把“当前画面、上一帧剪影、运动方向”三张信息叠成一张“复合画”,送给网络。
  1. 当前帧$I_t$ 是第 t 帧 RGB 图像,提供“现在长什么样”的证据。
  2. 上一帧掩码$M_{t-1}$ 是上一帧预测的主角剪影,告诉网络“你刚才把主角圈在哪”。
  3. 光流$F_{t-1 \to t}$ 是相邻帧的像素运动矢量,相当于“主角刚才往哪个方向跑”。
  4. 通道拼接$[ \cdot ]$ 表示把三者在通道维度上拼成一张多通道输入,网络一次看完所有线索。

时空记忆STM

接力的 2.0 版本升级了装备:每位接力选手手里多了一本“运动员档案册”,里面贴着主角从不同角度、不同时刻拍下的清晰照片。迷路时不用只依赖上一站那张过时剪影,而是翻开档案册,找到最像的那张照片重新对焦。这就是 STM(Space-Time Memory Network,时空记忆网络) 的设计哲学。

STM 建立了一个“时空记忆库”:把历史帧的特征统统存进去,每个历史位置的视觉特征作为 value(记忆内容),配合它的位置/时间信息作为 key(检索标签)。当前帧先提取出查询特征 query(当前疑问),然后通过注意力机制在记忆库中做“相似度检索”:哪段历史记忆与当前画面最像,就重点参考它。检索出的加权特征送给解码器,生成当前帧掩码。

数学上,这就是 Transformer 式的 key-value 注意力:当前帧每个像素的查询 q 与记忆键 k_i 做点积、除以特征维度的平方根防止数值过大,再经过 softmax 归一化成权重,最后对记忆值 v_i 加权求和。记忆库随时间推移不断加入新帧、保留旧帧,因此 STM 能“过目不忘”——主角被柱子挡了 3 秒,它仍能靠起跑时那张干净照片重新把人找回来。

有了档案册,即使主角被补给站人群挡住三五秒,选手翻出他起跑时的照片,依然能在人潮里重新锁定目标。STM 相对 MaskTrack 的本质飞跃,就是把“只看上一帧”升级为“回顾全部历史”。

Sij=exp⁡ ⁣(kiTqj/d)∑mexp⁡ ⁣(kmTqj/d),vj=∑iSij Vi\displaystyle S_{ij} = \frac{\exp\!\bigl(k_i^{\mathsf{T}} q_j / \sqrt{d}\bigr)}{\sum_m \exp\!\bigl(k_m^{\mathsf{T}} q_j / \sqrt{d}\bigr)},\qquad v_j = \sum_i S_{ij}\, V_i
左边是在记忆里“谁和当前画面最像”的得分,右边是按得分把记忆内容加权混合成“回顾特征”。
  1. 查询特征$q_j$ 是当前帧第 j 个位置的特征,代表“我现在看到的主角长什么样”。
  2. 键与相似度$k_i^{\mathsf{T}} q_j$ 是当前查询与第 i 条记忆的匹配得分,除以 $\sqrt{d}$ 是防止分数过大导致 softmax 过于极端。
  3. 归一化权重softmax 把得分变成和为 1 的权重 $S_{ij}$,得分越高,这条记忆越被重视。
  4. 加权读出$v_j$ 是所有记忆值 $V_i$ 按权重 $S_{ij}$ 融合后的“回忆特征”,它浓缩了与当前画面最相关的历史信息。

半监督VOS技术

裁判在起跑前递给你一张 7 号运动员的官方照片(第一帧掩码),半监督 VOS 的全部工作,就是“把这张照片带完整场比赛”。

第一帧标注是整个流程最可靠的锚点——它是唯一的“官方信息”。但只靠一张照片匹配整段视频会逐渐漂移,所以工程上发展出三板斧:在线微调、数据扩增、后处理。在线微调指测试时在首帧标注上对网络继续训练若干步,把网络“校准”成专门认这位主角的专家;数据扩增是对视频做翻转、颜色抖动、模拟遮挡,让模型见过“各种光线下的运动员”;后处理则用条件随机场或时序平滑把掩码边界修得更锋利。

训练半监督 VOS 时,损失函数也很有讲究。常规的交叉熵负责“像素分对类别”,而边界损失负责“轮廓别毛糙”。两者加权相加,让网络既能识别前景背景,又不会把掩码边界画成锯齿。

半监督就像“拿着官方照片反复确认”:出发前对照照片做热身微调,途中把各种光线变化都预演一遍,最后还把轮廓描精细——整套流程跑下来,盯人稳如磐石。

L=Lce(Mt,Gt)+λ Ledge(Mt,Gt)\displaystyle \mathcal{L} = \mathcal{L}_{\mathrm{ce}}(M_t, G_t) + \lambda\, \mathcal{L}_{\mathrm{edge}}(M_t, G_t)
总损失 = 像素分类损失 + 边界精修损失,λ 控制边界在训练中的分量。
  1. 交叉熵$\mathcal{L}_{\mathrm{ce}}$ 逐像素比较预测掩码与真值,前景/背景分错的都要惩罚。
  2. 边界损失$\mathcal{L}_{\mathrm{edge}}$ 专门惩罚轮廓附近的错误,让掩码边缘贴合物体真实边界。
  3. 平衡系数$\lambda$ 调节边界惩罚的权重,太小则轮廓糙,太大则挤压分类学习。

无监督VOS技术

换一个场景:没有照片、没有名单,你第一次走进体育场,该怎么判断“谁是主角”?答案是靠直觉——广播里全场最沸腾的方向、跑得最快的身影、镜头一直追随的那个人,多半就是主角。

无监督 VOS 的核心任务就是“自动发现主角”,常用的线索有三类。第一是显著性检测:视觉上最抓眼球的区域(颜色最跳、纹理最独特)优先被认为是目标。第二是运动线索:用帧差或光流判断“谁在动”——背景通常静止,目标通常运动,动得最“与众不同”的就是主角。第三是轨迹聚类:把逐帧检测出的候选区域按外观和位置串成轨迹,选择最长、最连贯、最“主角相”的那条作为最终目标。

此外还有一条更前沿的路——自监督学习:把“视频本身”当作免费标注。比如设计“跟踪一致性”任务,让模型学会“同一个目标在相邻帧里应被分割成同一片区域”,用这种预训练让模型天然具备“找主角”的底色。无监督 VOS 的一个经典运动线索公式极其朴素:两帧相减,差异大的地方就是“有动静”的地方,再设个阈值变成掩码。

无监督 VOS 像一位聪明的“新观众”——他不靠名单,靠“显眼、活跃、持续”三条直觉来判断主角。虽然不如半监督精准,但在海量无标注视频分析场景中,它是性价比极高的“免费劳动力”。

Dt=∣It−It−1∣,Mt=1[Dt>τ]\displaystyle D_t = \lvert I_t - I_{t-1} \rvert,\qquad M_t = \mathbf{1}\bigl[D_t > \tau \bigr]
帧差大的像素判为前景,τ 是“动静多大才算动”的门槛。
  1. 帧差$D_t$ 是当前帧与上一帧逐像素相减取绝对值,静止区域接近 0,运动区域明显非 0。
  2. 阈值判定$\mathbf{1}[D_t > \tau]$ 表示“差异超过 τ 就标为 1(前景)”,τ 控制灵敏度。
  3. 掩码输出$M_t$ 是二值掩码,运动区域为 1、静止背景为 0,构成最朴素的无监督初稿。

工程实践应用

盯人技术打磨成熟之后,就该装进真实的“转播车”(产品)里了。本节聊聊三个典型落地场景与两个绕不开的工程难题。

视频编辑是最成熟的落地场景:剪辑师想要把嘉宾从绿幕里“扣”出来贴到虚拟背景上,传统做法是逐帧手绘遮罩,或者搭绿幕拍摄。有了半监督 VOS,只需在第一帧粗略涂一下人物轮廓,模型自动生成整段时序掩码,剪辑软件插件直接取用。自动驾驶则是无监督 VOS 的主场:道路上的“非典型障碍物”(掉落的轮胎、施工牌、流浪动物)目标检测器没见过,但运动+显著性线索能兜底——凡是“与背景不一致的运动区域”就先分割出来警示。体育与监控直播中,VOS 被用来持续圈定重点运动员,即使被人群遮挡也能靠 STM 记忆恢复。

工程难点集中在两个地方:一是速度,STM 的记忆检索是推理瓶颈,常见的优化有记忆剪枝(只保留关键帧)、混合精度、TensorRT 加速;二是稳定性,分辨率降采样能提速,但边界会糊,所以常用“低分辨率推理 + 边界上采样精修”的组合拳。

工具箱里既要有 MaskTrack 这类轻量选手负责“跟得上”,也要有 STM 这类记忆型选手负责“丢不了”,再配好后处理的“化妆师”,你的转播车才能在全天候比赛中稳定出片。

FPS=1Tinfer+Tpost\displaystyle \mathrm{FPS} = \frac{1}{T_{\mathrm{infer}} + T_{\mathrm{post}}}
每秒能处理多少帧,取决于单帧推理时间和后处理时间的总和。
  1. 推理时间$T_{\mathrm{infer}}$ 是网络前向计算一帧所需的时间,优化记忆检索主要就是为了压它。
  2. 后处理时间$T_{\mathrm{post}}$ 包括边界精修、时序平滑等,占比虽小但不能忽视。
  3. 帧率FPS 是两者的倒数,工程上通常要求不低于 25 才能达到“实时”。

AI 应用场景

视频剪辑中的自动抠像与遮罩

阶段:模型推理与应用部署

解决的问题:传统视频剪辑要逐帧用钢笔工具抠像,或者依赖昂贵的绿幕拍摄;半监督 VOS 只需第一帧框选目标,就能自动生成整段抠像掩码,还能应对轻微遮挡与形变,把剪辑师从重复劳动中解放出来。

具体案例:综艺节目后期想把一位嘉宾“贴”到虚拟演播厅背景上。剪辑师用 VOS 插件在第一帧用画笔粗略涂出人物轮廓,模型随即输出完整的时序掩码,Premiere/AE 插件直接取用,原本半天的抠像工作压缩到 10 分钟。

自动驾驶中的通用目标分割

阶段:感知与数据闭环

解决的问题:道路上的“非典型障碍物”——掉落的轮胎、施工牌、流浪动物——目标检测器没有训练过,容易漏检;无监督 VOS 用运动+显著性线索把“与背景不一致的运动区域”分割出来,作为感知系统的兜底防线。

具体案例:某自动驾驶团队对海量未标注路采视频跑无监督 VOS,自动挑出异常运动目标,生成伪标注用于训练检测器,将标注成本降低了约 70%,同时让系统首次能感知训练集之外的罕见障碍物。

体育直播与安防监控的长时跟踪

阶段:模型推理与性能优化

解决的问题:直播中要持续圈出重点运动员,普通跟踪框容易跟丢或框错人;半监督 VOS + STM 记忆能够扛住遮挡、镜头切换和相似着装运动员的干扰。

具体案例:马拉松直播系统在第一帧圈定重点运动员,STM 记忆库保存其多个角度的外观特征。即使选手被补给站人群完全遮挡 10 秒,系统依然能在遮挡结束后通过档案册重新锁定,并在画面上持续渲染高亮轮廓。

Python 演示

python96 行
import numpy as np  def make_frames(n=80, size=128, r=8, occ_start=16, occ_len=8):    """合成视频帧:白色方块左右往返运动,中间一段被柱子遮挡"""    frames, gts = [], []    for i in range(n):        f = np.zeros((size, size))        x = int(16 + (size - 32) * (0.5 - 0.5 * np.cos(2 * np.pi * i / n)))        y = size // 2        f[y - r:y + r, x - r:x + r] = 1.0        if occ_start <= i < occ_start + occ_len:            f[:, 52:76] = 0.6        frames.append(f)        gts.append((x, y))    return frames, gts  def best_match(im, tmpl, cx, cy, radius, stride=3):    """NCC 模板匹配:radius 为局部搜索半径,None 表示全图搜索"""    h, w = tmpl.shape    if radius is None:        xs = range(0, im.shape[1] - w, stride)        ys = range(0, im.shape[0] - h, stride)    else:        xs = range(cx - w // 2 - radius, cx - w // 2 + radius + 1)        ys = range(cy - h // 2 - radius, cy - h // 2 + radius + 1)    best, bx, by = -1.0, cx, cy    for y0 in ys:        for x0 in xs:            if x0 < 0 or y0 < 0 or x0 + w > im.shape[1] or y0 + h > im.shape[0]:                continue            p = im[y0:y0 + h, x0:x0 + w]            pa = p - p.mean()            ta = tmpl - tmpl.mean()            denom = p.std() * tmpl.std() + 1e-6            s = float(np.sum(pa * ta) / (denom * h * w))            if s > best:                best, bx, by = s, x0 + w // 2, y0 + h // 2    return best, bx, by  class MaskTrack:    """只保留上一帧掩码做模板,小范围局部搜索接力"""     def __init__(self, f0, cx, cy, r=8):        self.r = r        self.tmpl = f0[cy - r:cy + r, cx - r:cx + r]        self.cx, self.cy = cx, cy     def track(self, frame):        _, x, y = best_match(frame, self.tmpl, self.cx, self.cy, 5)        self.tmpl = frame[y - self.r:y + self.r, x - self.r:x + self.r]        self.cx, self.cy = x, y        return x, y  class STM:    """维护最近数帧的记忆库,用干净旧记忆做全图检索"""     def __init__(self, f0, cx, cy, r=8):        self.r = r        self.cx, self.cy = cx, cy        self.memory = [(f0[cy - r:cy + r, cx - r:cx + r], cx, cy)]     def track(self, frame):        best, x, y = -1.0, self.cx, self.cy        for tmpl, tx, ty in self.memory:            score, px, py = best_match(frame, tmpl, tx, ty, None, 3)            if score > best:                best, x, y = score, px, py        if best > 0.3:            self.memory.append(                (frame[y - self.r:y + self.r, x - self.r:x + self.r], x, y))            self.memory = self.memory[-4:]        self.cx, self.cy = x, y        return x, y  def run():    frames, gts = make_frames()    mt = MaskTrack(frames[0], *gts[0])    stm = STM(frames[0], *gts[0])    mt_err, stm_err = [], []    for i, (f, (gx, gy)) in enumerate(zip(frames, gts)):        mx, my = mt.track(f)        sx, sy = stm.track(f)        mt_err.append(abs(mx - gx) + abs(my - gy))        stm_err.append(abs(sx - gx) + abs(sy - gy))    print("平均误差   MaskTrack: %.2f   STM: %.2f" % (np.mean(mt_err), np.mean(stm_err)))    print("遮挡期间   MaskTrack: %.2f   STM: %.2f" % (np.mean(mt_err[16:24]), np.mean(stm_err[16:24])))    print("遮挡之后   MaskTrack: %.2f   STM: %.2f" % (np.mean(mt_err[24:]), np.mean(stm_err[24:])))  if __name__ == "__main__":    run()
目的:用 NumPy 从零模拟两代 VOS 思路——MaskTrack 只依赖上一帧掩码做局部接力,STM 用记忆库做全图检索,在合成视频上对比二者遮挡前后的跟踪误差。
  1. frames, gts = make_frames()生成一段带“柱子遮挡”的合成视频,白色方块就是那位“主角运动员”。
  2. best_match(...)用归一化互相关(NCC)衡量模板与画面某处的相似度,得分最高处就是主角当前位置。
  3. radius=5MaskTrack 只在上一帧位置附近 5 像素内找目标,“接力范围”很小。
  4. radius=NoneSTM 采用全图检索,相当于翻开档案册在整张画面里找“最像主角”的位置。
  5. self.tmpl = frame[...]MaskTrack 每帧都更新模板,遮挡时会把柱子当成主角,错误开始“传染”。
  6. self.memory.append(...)` / `self.memory = self.memory[-4:]STM 把新记忆写入档案并只保留最近 4 条,既更新又不让记忆库无限膨胀。
  7. if best > 0.3:只有匹配得分够高才写入记忆,防止把遮挡期的脏模板存进档案。
  8. print("遮挡之后 ...")对比遮挡结束后两者的误差,你会看到 MaskTrack 回不来、STM 能恢复。

常见误区

误区我以为视频目标分割就是把视频拆成一帧一帧的图片,每帧跑一遍图像分割模型,再拼回去就是结果。反正单张图片分割技术已经很成熟了,直接套用不就行了吗?

正解单帧分割忽略了帧与帧之间的时序关系,会出现两个致命问题:一是闪烁,同一目标在不同帧中被分成不同的形状和颜色;二是身份漂移,这一帧圈的是 7 号运动员,下一帧可能圈成了 8 号。VOS 的核心价值恰恰在于“利用时序一致性”——上一帧的掩码、整段历史的记忆,都是单帧分割用不上的宝贵线索。就像盯人不能每张照片重新猜一次谁是主角,而要靠“刚才他在哪、他长什么样”来连续跟踪。

为何常见:因为图像分割确实是 VOS 的“近亲”,很多初学者从图像分割入门,自然会把成熟经验直接平移,忽视了视频特有的时间维度。

误区MaskTrack 既然把上一帧掩码也喂给网络了,信息应该很充足。目标被遮挡几帧、快速转身、外观突变,这些情况它应该都能应付吧?

正解MaskTrack 只有“一帧记忆”,属于典型的短视模型。一旦目标被完全遮挡,上一帧掩码就变成了“过时剪影”,网络只能基于错误信息预测,误差会逐帧累积甚至彻底跟丢。真正能应对长时遮挡的是 STM 这类带记忆库的模型——它能回溯到遮挡前甚至视频第一帧的干净特征,通过注意力匹配重新锁定目标。MaskTrack 的优势在于轻量快速,适合遮挡少、形变小的场景。

为何常见:因为“上一帧掩码”确实比完全没有时序信息先进,人们容易高估短时接力的能力,而低估了长时遮挡的破坏力。

误区无监督 VOS 既然叫“无监督”,那就是完全不用任何标注,模型自己从零学。那它应该比半监督 VOS 更强大更通用吧?

正解无监督 VOS 指的是“测试时不需要提供第一帧标注”,但训练阶段仍然依赖大量无标注视频 + 自监督信号(如跟踪一致性、时序平滑性),或者用显著性、运动等先验来“免费生成”伪标签。它并不是“什么标注都不用”,而是“不需要人工逐帧标注主角”。这就像一位新观众虽然没人告诉他谁是主角,但他会利用“谁最显眼、谁在动、谁一直出现”这些通用规则来推断。无监督方案通常精度低于半监督,优势在于省去了昂贵的首帧人工标注,适合海量视频批处理。

为何常见:“无监督”这个词本身就容易让人望文生义,以为是完全不需要任何人类先验,实际上大量自监督设计本身就是人为设定的“免费监督”。

误区STM 靠记忆库取胜,那我把每一帧的特征都存进记忆,记忆越全,匹配越准,效果一定越好。

正解记忆库无限增长会带来三重代价:显存占用线性上升、注意力检索耗时增加、冗余或低质量记忆反而干扰匹配。早期帧特征与当前帧外观差异过大时,强行匹配还会引入噪声。工程上普遍采用记忆剪枝——只保留关键帧、代表性帧或最近 N 帧,配合显存池复用。这就像档案册不是越厚越好:贴满了泛黄旧照,反而翻不到最新的那张清晰照片。

为何常见:因为 STM 的成功确实建立在“记忆”上,人们很容易把“更多记忆”直接等同于“更强效果”,忽略了计算代价和信息冗余的副作用。

面试题

Q1. 半监督视频目标分割中“半监督”指的是什么?

单选题 · easy

  • A.训练时一半数据有标注
  • B.只有第一帧提供目标标注← 正确答案
  • C.只标注关键帧不标注全部
  • D.用弱标签代替逐像素标注

答案:B。半监督 VOS 的精髓是“测试时只给第一帧的目标掩码”,后续所有帧的掩码都由模型自动生成,属于“一次标注、全程跟踪”。A 描述的是训练数据配比,C 和 D 都不是 VOS 中“半监督”的标准含义。好比起跑前裁判给你一张照片,之后全靠你自己盯人。

Q2. MaskTrack 模型的核心输入是什么?

单选题 · easy

  • A.仅当前帧彩色图像
  • B.当前帧与上一帧掩码← 正确答案
  • C.全部历史帧的视频
  • D.目标检测框的位置

答案:B。MaskTrack 把“当前帧 RGB + 上一帧预测掩码”(有时再加光流)拼接后送入网络,本质是“用上一帧的结果引导当前帧分割”。A 忽略了时序,C 是 STM 的做法而非 MaskTrack,D 是检测跟踪路线。就像接力选手只接上一站的剪影,不翻阅整本档案。

Q3. STM 模型通过什么机制应对长时间遮挡?

单选题 · mid

  • A.光流外推目标位置
  • B.记忆库与注意力匹配← 正确答案
  • C.目标检测器重新识别
  • D.每帧独立分割前景

答案:B。STM 把历史帧特征存入记忆库,当前帧查询特征通过注意力机制与记忆做相似度匹配,加权读出后解码成掩码。即使目标被遮挡数帧,模型仍能依靠遮挡前的干净记忆找回目标。光流外推只能短时预测,检测器需要目标类别先验,逐帧分割则完全没有时序信息。

Q4. 无监督视频目标分割的主要难点是什么?

单选题 · mid

  • A.缺少数十帧人工标注
  • B.难以判定谁是前景主角← 正确答案
  • C.无法获取任何训练数据
  • D.不需要区分动静物体

答案:B。无监督 VOS 没有首帧标注,模型必须先自动判断“画面里谁才是主角”,再逐帧分割它。这个“选主角”的过程极其依赖显著性、运动、轨迹等先验,且容易受复杂背景干扰。A 不是难点(它恰恰想省掉标注),C 说法错误(训练数据来自自监督),D 与无监督 VOS 的目标相反。

Q5. 下列哪些属于视频目标分割常用的评估指标?

多选题 · mid

  • A.区域相似度指标J← 正确答案
  • B.轮廓精度指标F← 正确答案
  • C.像素准确率指标← 正确答案
  • D.目标检测mAP指标

答案:ABC。VOS 的标准指标是区域相似度 J(预测掩码与真值的交并比)和轮廓精度 F(边界像素的精确率/召回率调和平均),像素准确率也可作为辅助参考。mAP 是目标检测的指标,衡量的是“框”而非“掩码”,因此不选。就像考核摄影师要看圈得准不准、轮廓贴不贴,而不是看他有没有喊出运动员名字。

Q6. 视频目标分割的最终输出是什么?

单选题 · easy

  • A.一串包含位置的文本
  • B.逐帧前景背景掩码← 正确答案
  • C.目标的类别置信度分数
  • D.画面所有物体包围框

答案:B。VOS 的输出是每一帧的二值掩码——前景像素为 1、背景为 0,精确到像素级。文本、置信度、包围框分别是目标跟踪、分类、检测的输出形式。用跟拍画面类比,VOS 要的是“完整人影剪影”,而不是“人脸上贴个名字标签”。

Q7. 在 STM 的 key-value 记忆中,key 和 value 各自的作用是?

单选题 · hard

  • A.key匹配value读出← 正确答案
  • B.key读出value匹配
  • C.key存储value压缩
  • D.key增强value剪枝

答案:A。STM 中 key 用于和当前帧查询特征计算相似度(匹配),value 是存下来的历史视觉特征,按匹配权重加权求和读出“回忆特征”。如果把记忆库比作档案册,key 是档案的标签目录,value 才是照片本身。匹配用 key、读出用 value,二者职责不可互换。

Q8. 以下哪些措施可以提升半监督 VOS 的精度?

多选题 · hard

  • A.首帧标注在线微调← 正确答案
  • B.测试时多尺度增强← 正确答案
  • C.随机丢弃视频帧训练
  • D.时序平滑后处理掩码← 正确答案

答案:ABD。在线微调让模型针对当前目标校准参数,多尺度增强让推理对尺度变化更鲁棒,时序平滑消除掩码抖动的“闪烁感”,三者都是常用提分手段。随机丢弃视频帧会破坏时序连续性,对 VOS 这类依赖时序的任务有害,因此不选。

Q9. 无监督 VOS 中常用的“运动线索”指的是什么?

单选题 · mid

  • A.光流与帧差求运动区← 正确答案
  • B.颜色直方图聚类分割
  • C.深度估计找出前景
  • D.纹理特征逐帧分类

答案:A。运动线索的核心是“谁在动、谁静止”——通过光流或相邻帧差分找出运动区域,再从中筛选主角。颜色聚类和纹理分类都是外观线索,不依赖帧间变化;深度估计属于几何线索。就像新观众判断主角,会看“谁在跑”而不仅看“谁穿得花”。

Q10. 关于 MaskTrack 与 STM 的对比,下列说法正确的是?

多选题 · extreme

  • A.MaskTrack 计算量更小← 正确答案
  • B.STM 能更好应对遮挡← 正确答案
  • C.STM 需要更多显存开销← 正确答案
  • D.MaskTrack 长时间不漂移

答案:ABC。MaskTrack 只看上一帧,网络轻、推理快,但一旦遮挡或形变就会误差累积、长期漂移,所以 D 错误。STM 用记忆库 + 注意力匹配,能利用历史干净特征恢复目标,但记忆库的存储和检索带来更高显存与计算开销。二者是“轻量实时”与“鲁棒恢复”的权衡,工程上常搭配使用。