EE6427-P5-视频分析与理解
目标检测
引入
目标检测主要是在图像/视频中预测对象类别,并使用边界框进行定位。
它本质是一个一个回归(regression) + 分类(classification)任务。回归是找到边界框,分类是识别边界框内的类别。
应用
目标检测和跟踪的是多个下游计算机视觉任务的关键步骤,例如:
- 物体跟踪(Object tracking)
- 姿态估计(Pose Estimation)
- 动作识别(Action recognition)
它的实际应用有:
- 自动驾驶
- 视频监控、监测
发展历史

在早期,AI出现之前,2001 年的 VJ 检测器、2006 年的 HOG 检测器、2008 年的 DPM,是这个阶段的里程碑。但传统方法有一个致命的短板:它极度依赖人工设计的特征,泛化能力极差,一旦遇到视角变化、光照变化、物体遮挡、背景杂乱的场景,检测效果就会急剧下滑。
转折点出现在AlexNet出现之后,AlexNet是一个CNN模型。在此之后,深度学习彻底改写了目标检测的技术路线,我们也进入了基于深度学习的检测时代。这个阶段又分化出了两条核心技术路线,也就是我们后面会重点讲解的双阶段(Two-stage)检测器和单阶段(One-stage)检测器。
所谓双阶段(Two-stage)检测器:
- 在第一阶段,尝试提出一些真实的候选区域,指出可能出现感兴趣目标的位置。也就是下图的Proposal Generator,它生成的信息随后会被传入Detection Generator完成裁切。
- 在第二阶段,对裁切后的东西尝试进行回归找到位置,同时进行分类。

而单阶段(One-stage)检测器:它是一种端到端检测器,输入之后直接得到输出。在这些模型里面,很可能 Yolo 是你会使用的首选方法。

未来挑战
- 不同的成像条件,包括视角、比例、光照、背景杂乱、遮挡等的变化。例如工业项目中检测一些非常小的部件。
- 计算效率
- 封闭世界问题 vs 开放世界问题:所谓封闭世界,是必须提前定义想要检测的感兴趣目标。而开放世界,则是不受此限制,会受此限制不仅需要检测那些你定义的物体,还可能想检测其他之前未定义的物体。
公开数据库

MS-COCO 微软上下文通用目标数据集:这是目前目标检测领域用于训练和评估的关键基准数据集。训练集、验证集和测试集包含超过200,000张图像和80个对象类别。
ImageNet 数据集:它最初是为了将图像分类到 1000 个类别。人工筛选了 200 个类别用于目标检测任务。它的训练集单张图片平均只有 1.05 个目标,绝大多数图片里只有一个目标。
- Google Open Images 谷歌开放图像数据集:这是三个数据集里规模最大、类别最多、标注维度最丰富的数据集。600 个目标类别,训练集有 174 万多张图片,标注了超 1461 万个目标,单张图片平均有 8.38 个目标,配套 1600 万个标注框。
评价性能的方法:mAP
评价模型最常用的指标是 mAP(mean Average Precision 平均精度均值),在很多文献中大家也会为了省事直接称它为 AP。
交并比的概念
我们先搞懂一个最底层的几何概念:交并比(IoU,Intersection over Union):假设实际的物体位置是下图Object的框,模型回归出的物体位置是下图Detected Box的框。IoU就是用两框的交集,比上两框的并集,如下图所示。常用mAP50,mAP@0.5 $mAP_{0.5}$这样的符号来表示IoU采用0.5的阈值。

IoU 的值介于 0 到 1 之间。0 代表完全没挨着,1 代表完美重合。 我们在评价预测结果时,通常会设定一个阈值(Threshold),比如 0.5, 0.7等等。
根据模型的识别是否超过阈值,定义了:
- 真正例(True Positive, TP):如果模型不仅类别猜对了,而且算出来的 IoU > 阈值,我们才认为这是一次成功的检测。
- 假正例(False Positive, FP):如果类别猜对了,但位置偏得太离谱(IoU < 0.5),那这也算作一次“误检”或“假阳性”。
mAP的计算
mAP是通过为每个类别计算AP,然后对所有类别取平均值来得出的。
mAP的计算步骤是:
- 生成预测:让模型在测试集上跑一遍,输出所有的预测框和预测标签。
- 统计混淆矩阵:根据 IoU 阈值,统计出哪些是 TP(真正例,找对且框准了),哪些是 FP(假正例,误报),以及哪些是 FN(假负例,也就是真实存在但模型漏报了,没找出来)。
- 计算精准率(Precision)和召回率(Recall)
- Recall(召回率):$Recall=\frac{TP}{TP+FN}=\frac{TP}{#ground Truth}$。通俗地说就是:所有真实的物体中,你“找出来多少”?衡量的是模型漏不漏。
- Precision(精准率) $Precision=\frac{TP}{TP+FP}=\frac{TP}{#predictions}$。通俗地说就是:你报警说检测到了的物体中,有“多少是真家伙”?衡量的是模型准不准。
- 计算单类别的 AP:有了不同阈值下的 Precision 和 Recall,我们可以在坐标系里画P-R曲线。这条曲线下方的面积,就是当前这个特定类别(比如专门针对“猫”)的 AP 值。如下图(纵轴是Precision,横轴是Recall)

- 计算总 mAP:最后一步,我们把所有类别(比如猫、狗、车等 N 个类别的)的 AP 值全部加起来,除以类别数 N 求个平均,这就是最终的 mAP!
常用的mAP是$mAP_{0.5}$,$mAP_{coco}$。$mAP_{coco}$的计算公式如下:
mAPcoco解决的主要问题是,若采用单一阈值,你的性能矩阵对所选择的 IoU 阈值非常敏感。因此选择一堆阈值(0.5,0.55,一直到0.95),然后取平均(除以10)。它对所选择的任何单一 IOU 阈值都不那么敏感。
计算复杂度指标 :浮点运算 (FLOPs)
简单来说,FLOPs 是用来衡量一个 AI 模型计算复杂度的核心指标。大家可以把它理解为模型的“工作量”。
它衡量的是模型在进行一次前向传播(Single forward pass)时,总共需要进行多少次浮点运算。通俗点说,也就是当模型处理“一张”图片,从输入到输出结果,计算机的 CPU 或 GPU 到底要做多少次加减乘除的数学计算。
- 如果一个模型 FLOPs 很大,说明它计算繁重,处理一张图片要花很久,必须依赖昂贵的高性能显卡。
- 如果 FLOPs 很小,说明这是一个轻量级的模型,跑起来非常快,甚至可以部署在算力有限的手机、车载摄像头或无人机上,实现实时的目标检测。
Two Stage Detectors
引入
第一阶段(Proposal 阶段):用类似 Region Proposal Network (RPN,区域生成网络) 的技术,先从图像里 “圈出” 可能存在目标的候选区域。
对这些候选区域,再做精确的分类和边界框回归,最终输出目标的类别和位置。
代表方法:Faster-RCNN、Mask-RCNN(这俩是 R-CNN 系列的巅峰之作,也是行业标杆)。
也有SPP-Net(空间金字塔池化网络,解决了输入图像尺寸固定的问题)、FPN(特征金字塔网络,解决多尺度目标检测问题)等其他算法。
与单阶段检测器的对比:模型结构更复杂,速度更慢。但检测精度普遍更高。
RCNN 系列检测器(Region-based Convolutional Neural Network)
- R-CNN:开山之作,奠定了两阶段检测的基本思路,但速度极慢。
- Fast R-CNN:解决了 R-CNN 重复计算的问题,大幅提升了速度和精度。
- Faster R-CNN:引入 RPN 网络,把候选框生成也交给神经网络处理,实现了端到端的训练,是真正意义上的 “实时” 两阶段检测器。
- Mask R-CNN:在 Faster R-CNN 的基础上,增加了掩码分支,不仅能检测目标,还能做实例分割,是后续很多图像任务的基础。
R-CNN架构
下图是R-CNN的网络处理流程图

- 输入图像:接收一张待检测的图片。
- 生成候选区域:从图像中生成可能包含目标的候选框(大约 2000 个)。
- 提取 CNN 特征:把每个候选框里的图像裁剪、缩放成固定尺寸(warped),送入 CNN 网络提取特征向量。
- 分类与回归:使用线性 SVM(支持向量机)对每个特征向量做分类和回归。
Faster-RCNN架构
整体流程

- 输入图像经过卷积层,得到共享的特征图。
- 特征图送入 Region Proposal Network (RPN,区域生成网络),生成候选区域(proposals)。
- 候选区域经过 RoI Pooling 层,变成固定尺寸的特征。
- 最后送入分类器和回归器,输出目标类别和精确的边界框。
Faster-RCNN提出了RPN:
- RPN 与检测分支共享全图卷积特征,从而实现几乎无计算成本的区域建议。
- RPN同时预测 对象边界(boundaries) 和 对象性(objectness) 得分。
Faster-RCNN相较于RCNN,速度快了非常多。

One Stage Detectors
引入
代表方法:YOLO 系列、SSD。YOLO系列是近年来的主流方法。也有其他的方法例如CenterNet、EfficientDet 等。
与两段检测器的对比:相较于两段检测器,它复杂度更低,更快。
YOLO的总体架构
YOLO模型有多个版本的迭代。每次迭代都进行了微调。但是它的总体架构没有变。

Yolo的整体架构如下图。

Input(输入层):接收输入图像,并通过数据增强(随机裁剪、缩放、色彩扰动、马赛克增强等)扩充训练数据,提升模型的鲁棒性。
Backbone(骨干网络):骨干网络实际上是一个预训练的分类模块,用于执行特征提取。随着网络层数的加深,图像的尺寸(分辨率)被不断压缩,但提取到的特征变得越来越高级和抽象。
Neck(颈部网络):因为如果只用高层特征,会丢失细节,小物体就找不到了;如果只用底层特征,又缺乏宏观认知,容易误判。Neck 通过上采样(up-sampling)等技术,将不同层级、不同尺度的特征图进行拼接(concatenation)和融合。
- 头部网络 (Head):经过 Backbone 提取和 Neck 融合后,Head负责算出图片里存在什么类别的物体(分类 predictions to classes),并且精准地画出它们的边界框坐标(回归 bounding boxes)。
下图是近年来Yolo模型(YOLOv7: 2022; YOLOv10: 2024, YOLOv12: 2025)的性能对比。纵轴就是我们之前提到的mAP。

Lightweight Detectors(轻量级检测器)
这类检测器是专门为资源受限的设备(Resource limited devices)量身定制的。它们的网络结构被设计得非常小巧(Small)、快速(Fast)且高效(Efficient)。它们的核心目标不是在比赛中刷出最高的 mAP 精度,而是保证在算力极差的设备上也能流畅运行。
最有代表性的方法是基于 MobileNetV2 搭配 SSD 架构的方法(在谷歌著名的开源跨平台框架 MediaPipe 中被广泛使用)。此外还有 SqueezeNet、ShuffleNet 等。
它的优点毫无疑问是极快、极高效(ultra fast, efficient);但付出的代价(Cons)就是精度相对较低(less accurate)。
MobileNet
以 MobileNet 为例,它减轻计算量的核心是深度可分离卷积(Depth-wise separable convolutions)。
在标准的卷积操作中(看左图中 (a) Standard Convolution Filters),这个 DK 是卷积核大小,这里的 M 指的是通道的数量。回顾前面学习过的卷积,M个通道使用卷积核的卷积结果相加,就是该滤波器的输出。也就是说一个卷积滤波器会输出右图中的一个通道。假设你想在这里生成 n 个输出通道,那么你将在这里使用 n 个滤波器。这么做的计算量和存储要求很高。

深度可分离卷积将这个分为了两步走:
- 深度卷积(Depth-wise convolution):它不再让一个卷积核去管所有的通道。而是给输入的每一个通道单独分配一个滤波(上图左(b))。也就是说,红通道只用一个特征核扫一遍,绿通道用另一个扫一遍,蓝通道再用一个扫一遍。这一步只提取空间上的特征,完全不混合通道间的特征。
- 逐点卷积(Pointwise convolution):单通道的特征提取完了,怎么把它们融合起来呢?模型使用了一种非常精巧的 多通道1x1 卷积核(上图左(c))。它直接穿透所有的通道,把刚才各个通道提取出来的特征在深度方向上进行加权组合,最后输出成不同的通道。
新兴物体检测方法
Swin Transformer
Swin Transformer 是一种非常流行的图像分类和目标检测方法,它被设计成了一个通用的计算机视觉 Backbone(骨干网络)(Backbone 的作用是提取特征)。
回顾前面讲过的ViT,它将图像裁切为16x16Patch作为token输入,对于每一层的特征,ViT都需要把它切成16x16的块来token化。这存在问题:1. 使用16x16的块作为一个token,所代表的区域还是比较大,这会导致机器理解图像的分辨率较低;2.当执行注意力机制时,你需要取当前token的q,并与所有token的k进行比较,这带来了庞大计算量。
而Swin Transformer解决了这两个问题。1. 它首先使用4x4的patch,这样机器理解的分辨率较高。而到了下一层,它将2个4x4的token输出1个8x8的token,以此类推。这样就从图片的高分局部上采样到了低分宏观。2. Swin transformer定义了一些“局部窗口(local window)”,注意力机制只在局部窗口内执行,这样就降低了计算量。

局部窗口存在一个问题:注意力机制只能观察到窗口内的token关联。如何解决呢?这就引入了SW-MSA 。
- W-MSA (Window-based Multi-head Self-Attention):在第 $l$ 层,图片被划分成了4 个红色的local window(每个窗口里包含若干个灰色的 patch)。计算注意力时,只在这四个方框内部各自进行。此时,窗口之间是隔绝的。
- SW-MSA (Shifted Window-based Multi-head Self-Attention):到了 $l+1$层(下一层),窗口划分的网格整体向右下角平移(Shift)了半个窗口的距离。 如下图Layer l+1,左上角的框移到了中间,右下角的框移动后有1/4在右下角,1/4在左上角,1/4在右上角,1/4在左下角。对新的local window再次执行注意力机制,就可以让他打破单次local window的局限。
对应下图左边,第一个windows使用左边的网络处理一次,输出下一个layer时,执行shift window,然后再使用网络处理第二次。

下图是Swin Transformer 的架构

- 输入与切块(Patch Partition):一张普通的 RGB 图片输入后,第一步是被切成4x4 的小块(Patches),这些小块有48个维度。
- 线性嵌入(Linear Embedding):接着,这些小块被映射成向量。每个向量最初是 48 维的,现在将被嵌入器到 C 维,这个C是一个常数,取决于你的性能预算。随后被送入Transformer网络处理。
- 分级处理:当第一层的输出被送入下一层的嵌入器时,它两个两个的 token,然后将它们组合成一个token输出。然后再次送入网络。
下图是不同检测模型的性能对比,可以看到Swin性能强劲。

Detection Transformer(DETR)
这是一种近期流行的端到端物体检测方法,它同时使用了CNN和Transformer,可以并行检测。

- CNN:它首先还是利用经典的 CNN(比如 ResNet)来“看”输入的图片,提取出浓缩了图像特征的 特征图 (set of image features)(2维)
- 位置编码 (Positional Encoding):Transformer 架构有一个特点,它天生是处理一维序列的,且它是“路痴”,不知道特征在图片里的空间上下左右关系。因此,模型必须把 2D 特征图“展平”成一维序列,并强行给每个特征加上一个“位置标签”(也就是图中的 positional encoding),告诉模型“这个特征来自图片的左上角”,那个“来自右下角”。这一点与纯transformer架构一致。
- Transformer 编码器:使用Transformer 编码器,来将输入的token使用自注意力机制,映射成输出的向量。
- Transformer 解码器与“对象查询” (Decoder & Object Queries):Encoder的输出被传入Transformer Decoder。这个Decoder还会输入一个固定数量、可学习的序列(比如 100 个“对象查询”槽位)(类比于之前Transformer架构循环输入已输出的token)。在这里面执行自注意力和交叉注意力,再次输出包含图像与对象查询关联的向量。
- 并行预测头 (Prediction Heads):最后将输出的向量放入不同的前馈网络(FNN),这些不同的前馈网络能够将Decoder的向量翻译成边界框在哪里,以及属于哪个类别等等。
Grounding DINO
而 Grounding DINO 是一个“开放集”检测器。它的核心动机就是:让模型能够根据你输入的任意自然语言文本提示(Text prompts),去检测图片中对应的物体。
它的名字其实已经剧透了它的配方:Grounding DINO = DINO + Grounding。
- DINO:这是一个基于 DETR 架构演变而来的、目前非常顶尖的纯视觉目标检测器。
- Grounding(对齐/接地):指的是将文本(词语)和图像(像素)对应起来的技术(类似于 CLIP 模型的能力)。
下面这张图展示了Closed Set和Open Set图像检测的区别:
- (a):闭合集目标检测要求模型能够识别属于预先定义类别的目标,例如我们说人,它就能把人全部框出来。
- (b)对于Open Set,你可以提供一些自然语义的提示,例如左边的狮子,它就只会框出来左边那个狮子。
- (c)结合图像生成技术,Open Set的检测器可以做更多有意思的事情,比如把左边的狮子替换成狗

下面是这个模型的整体架构图

输入:文本和图像同时输入,然后各自经过Backbone网络提取特征(词嵌入$\rightarrow$特征向量,图$\rightarrow$ 原始图像特征 (Vanilla Image Features))。对于图像,常使用Swin Transformer;对于文本,常使用BERT。
跨模态特征增强 (Feature Enhancer):在这个模块里,图像和文本的特征开始对齐。这个模块的结构如下图所示,他们首先使用自注意力模块生成各自的上下文向量。然后使用交叉注意力,分别执行 图到文本 和 文本到图 的交叉注意力。最后通过前馈网络,输出增强后的词特征和图特征。

语言引导的查询选择 (Language-guide Query Selection):传统的检测器会盲目地在全图生成成千上万个候选框。但在这里,模型利用刚刚融合好的文本特征,去指导图像特征的筛选。它就像一个向导,提前告诉模型:“重点关注图像里那些和文字高度相关的区域”。
跨模态解码器 (Cross-Modality Decoder):这个模块接受语言引导的查询选择筛选出的特征作为输入,同时,之前提取的增强版图像特征和文本特征作为“线索字典”(Keys & Values)也输入到了这里。通过自注意力层,交叉注意力层,进一步提纯和明确自己所代表的物体信息,最终输出精炼后的模型输出 (Model Outputs)。每个解码器层相比 DINO 解码器层多了一个额外的文本交叉注意力层,因为我们需要将文本信息注入查询中以实现更好的模态对齐。

双重监督与预测输出:
- 右侧分支 - 定位 (Localization loss):红色的箭头指向图片上的猫。这部分负责预测物体的确切物理位置(输出精准的边界框 Bounding Boxes),如果框得不准,就会产生定位损失。
- 右上方矩阵 - 对比学习 (Contrastive loss):这是一个非常关键的矩阵。它的行代表模型预测出的物体框,列代表输入的文本单词(如 cat, person, mouse)。模型需要判断哪个框对应哪个词。如果模型把猫认成了老鼠,或者没认出来,就会产生对比损失,以此来逼迫模型学会“看图识字”。
目标跟踪
引入
目标跟踪主要是在视频的连续帧中跟踪相同的人或物体。
在目标检测中,物体被用一些边界框(Bounding Box)框起来,在目标跟踪中,这些边界框有一个ID来指示它分别是谁。
要执行跟踪,可以使用外观特征(看起来是什么)+运动特征(在做什么运动+下一帧中将位于何处)
多目标跟踪 Multiple Object Tracking (MOT)
引入
什么是多目标跟踪:多目标跟踪 (MOT) 旨在同时跟踪所有的目标(例如,行人)。因此每一个框都要有一个ID,来识别谁是谁。
主要挑战:
- 多个具有相似外观的目标,比如行人。
- 其他不感兴趣的物体干扰(例如,背景、消防栓)。
- 严重的遮挡。
基于检测的跟踪(Tracking by Detection)
这是目前解决 MOT 问题最主流的范式:Tracking-by-Detection(基于检测的跟踪)。它的思路很直白,分两步走:先当做单张图片做“目标检测”,然后再把前一帧和后一帧的检测框进行“连线匹配(数据关联)”。
当然,它的短板也很明显:它极其依赖第一步检测器的质量。如果检测器漏看了一个人,或者把柱子误认成了人,后一步的跟踪就会直接跟着出错。例如下图,蓝色的人每一帧都被追踪到了。但是绿色的人在第二帧中失去了追踪,在第三帧中被打上了紫色的ID。

基于检测的MOT的步骤
- 检测 (Detection):在当前时刻(第 t 帧),我们先用目标检测模型把画面中的三个行人都找出来,画上红色的检测框。这相当于是给他们三个人建了初始档案。
- 运动预测 (Motion prediction):在还没开始检测之前,模型会先根据这三个人刚才的行走速度和方向,进行一个“盲猜”,常用的模型如卡尔曼滤波,或粒子滤波。图中的黄色框就是模型预测这三个人在第 t+1 帧大概会走到的位置。
- 数据关联 (Data association):现在,我们在第 t+1 帧真正运行一次目标检测,又得到了三个新的红框(实际位置)。接着,算法会把刚才“猜的黄框”和“实际看到的红框”进行比对匹配(通常就是计算 IoU ,但是还会用到外貌特征)。因为预测的黄框和实际检测的红框高度重合,算法就能非常自信地确认:“没错,这个新出现的红框,就是刚才第 t 帧里的那个人。

我们现在来详细看看数据关联这个步骤
建立评分矩阵:系统会把每一个“预测框”和每一个“实际检测框”进行两两配对,计算它们之间的“距离”或相似度。最常用的相似度指标就是我们之前学过的 IoU(交并比)。如下图,行(Detections)代表4个实际检测到的人,列(Predictions)代表4个预测的位置。表格里的数字就是它们之间的匹配得分。

求解最优分配:有了这张得分表,再使用匈牙利算法(Hungarian algorithm)来解这个矩阵。它的目的是找到一个全局最优的“一对一(one-to-one)”连线方案,确保总体的 IoU 得分最高,且绝不产生冲突。
现有的方法看似完美,但如果在拥挤的街头,两个人刚好擦肩而过,互相遮挡了,或者一个人被路灯挡住消失了半秒钟,卡尔曼滤波预测的位置就会失效,IoU 甚至会变成 0。这时候匈牙利算法就“抓瞎”了,行人的 ID 就会跟丢或者串号。
了解决这个致命痛点,提出了Deep SORT 算法。
Deep SORT 算法:既然单靠“位置(空间距离)”已经不可靠了,那我们就加上“长相(外观特征)”!Deep SORT 在原有的预测体系外,额外加入了一个 Deep Appearance Descriptor(深度外观描述子),描述某个视觉内容外观的向量,这样就可以在二次检测后计算出他们与前一帧的目标的特征向量之间的距离(Distance)。这个外观距离和IoU一起进入评价矩阵。

我们来看看这个外观描述子是怎么被提取出来的:对于每一个被检测出来的行人,算法会把他们的图片“抠”下来,送进一个 CNN。一旦这个CNN网络被训练定型,它就具备去用全连接层分类的能力,即,用全连接层计算外貌向量的Distance。

新兴多目标跟踪方法
Trackformer
Trackformer 用 Transformer 架构将它们融为了一体,实现了真正意义上的端到端(End-to-End)多目标跟踪。
它的底层结构(Encoder 和 Decoder)和我们在目标检测里学过的 DETR 非常相似:
- Encoder (编码器):依然是用 CNN + Transformer Encoder 来提取每一帧画面的全局特征。
- 预测头 (MLP):依然是用多层感知机来输出最终的边界框和类别。
- 对于每一帧图像,让他们通过一个CNN,来提取图像特征。特征向量被分割为不同的patch,送入Transformer Encoder内,Encoder的输出是一堆上下文向量,由于自注意力机制,这些向量得到了优化。
- 上下文向量被送入Transformer Decoder,它和DETR的Decoder类似。Decoder的输出被送入前馈网络,就可以检测出目标了。
- 与DETR不同的是,它的Transformer Decoder除了输入传统的Object Queries,还会输入来自上一阵的track queries。Object queries 负责“发现新目标”并捕获它,Track Queries主要负责根据识别到的

- 一开始,系统完全没有记忆,输入给 Decoder(解码器)的只有底部的Object queries。Object queries在画面中发现了三个行人,于是 Decoder 输出了三个带着颜色的结果:红框、绿框、蓝框。
- 现在,这三个代表特定行人的特征向量,正式化身为 Track queries(轨迹查询),并被送入下一个时间步!现在输入给 Decoder 的,除了之前的Object queries,还有上一帧传过来的红、绿、蓝三个Track queries。
- 与此同时,画面左侧走进来一个新人。之前的红绿蓝盒子都不认识他,但是没关系,那些白色的“对象查询”发现了他!于是,系统初始化新的紫色轨迹。
姿态估计(Pose Estimation)
引入
姿态估计简述
姿态估计的主要目标是从图像或视频中定位人体/面部关键点,如下图所示。

它的主要应用场景是:动作识别(使用身体关键点来分类人体动作);动画与动作捕捉
在早期,姿态估计以单人算法为主。后来逐渐发展出了多人估计算法。

基础评估指标(Performance Metrics)
在姿态识别中,因为图像里的人有大有小,我们不能单纯用“像素距离”来衡量预测准不准,必须进行归一化(Normalization)处理。
PCK (Percentage of Correct Keypoint - 正确关键点比例):
核心思想: 如果模型预测的关节点与真实关节点的距离,小于某个设定的“相对阈值”,就认为这个点预测正确了。
在Flic 数据集中采用躯干直径(torso diameter)作为参照。例如 $PCK@0.2$ 表示容忍误差在躯干直径的 20% 以内。
在MPII 数据集中采用头部线段长度(head segment line)作为参照,这个指标专门被称为 PCKh。例如 $PCKh@0.5$ 表示容忍误差在头部长度的 50% 以内。
PCP (Percentage of Correct Parts - 正确部位/肢体比例):
- 核心思想: PCK 看的是“点”,PCP 看的是“线”(肢体,如小臂、大腿)。
- 判定标准: 如果预测出的一段肢体的两个端点(比如手腕和手肘),距离真实肢体的偏差小于该真实肢体长度的某一个比例(通常是 0.1 到 0.5 之间),就认为这部分肢体被正确检测到了。
基于OKS (Object Keypoint Similarity - 目标关键点相似度)的AP和AR:
- OKS是指预测点与真实关节点之间的距离,按人的尺度进行归一化。
- 平均精度 (Average Precision AP)、平均召回率 (Average Recall AR) 及其变体在 COCO、MPII 和 PoseTrack 中使用
姿态检测方法总览
2D Single-person (2D 单人姿态估计)
- Regression Method (回归方法)
- Body Part Detection (身体部位检测)
2D Multi-person (2D 多人姿态估计)
- Top-down (自顶向下方法),代表模型: HRNet, TransPose
- Bottom-up (自底向上方法),代表模型: OpenPose
单人姿态估计算法
回归方法(Regression Method)
回归方法的核心思想是“端到端”直接预测坐标。网络看着图片,直接输出每个关节点对应的 $(x, y)$ 坐标值。
它通过卷积神经网络(CNN)提取图像的特征图。基于这些特征图,通过回归器(通常是全连接层)直接计算并输出关键点的坐标。

Pros (优点): easy and fast (简单、快速)。 因为网络结构相对简单,直接输出一维的坐标向量,计算量小,推理速度快。
Cons (缺点): less accurate (准确率较低)。 图像空间到坐标向量的映射是一个高度非线性的过程,丢失了空间位置信息,导致模型在精确定位上存在困难。
身体部位检测(Body Part Detection)
这种方法不直接输出坐标,而是为每个关键点输出一张“概率图”(热力图 Heatmap)。
如果人体有 K 个关键点(比如16个),网络就会生成 K 张热力图。每一张热力图对应一个部位(如“左手腕”),图上高亮(发热)的区域代表该部位可能存在的概率最高的位置。
找到每张热力图的最高峰(最大概率点)作为关键点位置,然后将它们组合拼凑成完整的人体骨架。

Pros (优点): accuracy (准确率高)。 热力图保留了图像的空间结构信息,使得模型更容易学习到“手腕通常在手臂末端”这类局部特征,定位极其精准。
Cons (缺点): slower and complex (速度较慢且更复杂)。 生成多张高分辨率的热力图需要大量的显存和计算资源,后处理(从热力图提取坐标并关联)也增加了复杂度。
多人姿态估计算法
自顶向下方法(Top-Down Methods )
顾名思义,“自顶向下”的逻辑是先抓“大”再抓“小”,先找“人”再找“关节点”。
方法流程:
- 第一步: 使用现成的目标检测器在图像中检测出所有人。这就像是用一个框把每个人单独框出来(也就是生成 Bounding Box)。
- 第二步: 对每一个检测到的人,单独进行单人姿态估计。
Pros (优点): 网络复杂度较低,准确率高。 因为第二步处理的都是裁剪好的单人图像,网络不需要去分辨这个手是谁的、那个脚是谁的,不受其他人的干扰,所以精度通常是最高的。
Cons (缺点): 运行时间会随着检测到的人数增加而增加。 这是它的致命伤。如果图里有 1个人,姿态网络跑 1 次;图里有 100 个人,姿态网络就要跑 100 次。人越多,算得越慢。
它的典型算法是HRNet (High-Resolution Net)
HRNet的架构如下图,整个网络类似于CNN:
- 它有一条通路,这条路头到尾始终保持着一条高分辨率的特征通路(下图上)
- 并行连接多分辨率子网:在合适的地方对当前的特征图进行下采样,得到低分辨率通路(下图中)。这些低分辨率通路可以有多条,他们是并行的。
- 多尺度融合 (Multi-scale fusions):图中的那些红线和蓝线,代表高分辨率分支和低分辨率分支在不断地互相“交流”。低分辨率分支提供全局上下文(比如这是个手臂的宏观特征),高分辨率分支提供精准的空间位置。

自底向上方法(Bottom-up Methods)
“自底向上”的逻辑和 Top-Down 完全相反。它是先抓“小”再拼成“大”,先找“所有零件”,再“组装成人”。
方法流程:
- 第一步: 检测图像中的所有身体部件/关节点)。不管三七二十一,先把图里所有的头、手腕、膝盖全找出来(下图中间那张,满屏的红点)。
- 第二步: (Body Part Association)将这些身体部件组装成不同人的姿态。

Pros (优点): 运行时间基本保持不变,与检测到的人数无关。 因为它是一次性处理整张图,找出所有点,图里有 1 个人还是 50 个人,第一步找点的时间几乎是一样的。速度非常快。
Cons (缺点): complex (复杂)。 这里的复杂主要指后处理(组装过程)非常复杂。当几个人抱在一起或者发生严重遮挡时,把一堆散乱的关节点正确地“拼凑”到对应的人身上,是一个极具挑战性的数学优化问题,容易出现“张冠李戴”的错误。
新兴姿态估计算法
TransPose
TransPose 将 CNN 和 Transformer 结合在了一起。它的整体架构分为三个关键部分:Backbone(主干)、Transformer Encoder(编码器)和 Head(预测头)。
- Backbone:使用常见的 CNN(卷积神经网络)来提取特征,拿到特征图的输出之后,将它切割成特定大小的patches,然后将每个patch展平成为一个向量。
- Transformer Encoder:首先对输入的patch进行位置编码,然后进行Transformer的QKV操作,Attention机制会学到人体各个部件之间的结构依赖关系(Dependencies),找到关节处重点关注,如下图所示。最终输出是跟人体有关的上下文向量。
- Head :Head是一个小型的卷积层,负责把这些特征重新转换回 Heatmaps(热力图),图上高亮的红点就是最终预测的关节点位置。

3D姿态估计算法
2D姿态估计的局限性
2D姿态识别:
- 缺乏深度信息,导致无法理解现实世界中的空间排列。比如,一只手臂正对着镜头指过来,在 2D 图像上看起来可能只有短短一截(透视缩短效应),2D 模型无法分辨手臂是短还是朝向了镜头。
- 遮挡歧义:没有深度信息,当人体重叠或相互遮挡时,从根本上就很难区分不同的身体部位到底是在前面还是后面。
- 无法满足现实世界应用:像机器人技术 (Robotics)、增强/虚拟现实 (AR/VR)、动作捕捉 (motion capture) 等应用,都是在三维物理空间中运行的。纯 2D 的输出对它们来说是不够用的。
3D姿态识别的挑战
- Depth Ambiguity (深度歧义): 从单目(单摄像头)的 2D 图像中推断深度极其困难。数学上来说,无数种不同的 3D 姿态投影到 2D 平面上,可能看起来是完全一样的。
- Occlusion (遮挡): 相比 2D,3D 对遮挡更加敏感。部位被肢体、物体或其他人遮挡后,预测缺失的三维坐标是个大难题。
- Variability in Appearance (外观多变性): 衣服、体型、光照、相机的拍摄视角千变万化,模型很容易被这些因素干扰。
- Complex Poses & Interactions (复杂姿态与交互): 复杂的关节运动、多人抱在一起或互动的场景,极难用数学模型准确描述。
- Data Limitations (数据限制 - 极其关键): 带标注的 3D 数据集既稀缺又昂贵。2D 数据可以让标注员在电脑上用鼠标点,但 3D 数据无法人工标注,必须要在专业的动作捕捉实验室(MoCap)里让人穿戴上传感器来采集。
- Generalization Across Domains (跨领域泛化能力差): 因为 3D 数据多是在室内实验室采集的(背景单调),模型一旦放到自然生活场景(in-the-wild,即“野外”或“不受控环境”)中,表现就会大打折扣。
- Computational Complexity (计算复杂度高): 预测三维坐标比二维计算量大得多,很难在手机等设备上做到实时运行。
- Multi-view vs. Monocular Trade-off (多视角与单视角的权衡): 多摄像头(多视角)能提供准确的深度,但在现实中不实用(普通人只有一台手机);单摄像头(单目)很实用,但深度预测又极具歧义性。
主流的3D姿态识别方法
Direct 3D Pose Estimation / End-to-End (端到端直接预测 3D)
- 方法: 模型直接接收输入图像或视频,一口气输出 3D 关节坐标。
- Pros (优点): Pipeline(流程)简单,没有中间商赚差价,没有中间步骤。
- Cons (缺点): 训练难度极高。因为 3D 数据本来就少,还要克服深度歧义。
- Examples: 基于端到端的 CNN 或 Transformers 直接进行 3D 回归。
Two-Stage / 2D-to-3D Methods (两阶段法:先 2D,后 3D)
- Stage 1 (第一阶段): 先用我们非常成熟的 2D 模型,在图像上找出 2D 关键点。
- Stage 2 (第二阶段): 将这些 2D 关键点 “提升/映射” (Lift) 到 3D 空间中。也就是训练一个网络,它的输入是一堆 2D 坐标,输出是 3D 坐标。
- Pros (优点): 可以充分利用海量的 2D 姿态数据集。把找特征点(2D 的强项)和推断深度(3D 映射网络)分离开来,模块化设计更好优化。
- Cons (缺点): 误差传播 (Error propagation)。 如果第一步 2D 关键点就找错了(比如把左手认成了右手),第二步提升出来的 3D 骨架就一定会是个扭曲的怪物。
- Examples: 2D 检测器 (OpenPose) + 3D 提升网络 (比如著名的 MotionBERT)。
MotionBERT算法
MotionBERT是一个2 stage的3D姿态识别算法,通过2D关键点再lift到3D空间的方式实现姿态识别。
这个网络的训练分为两个步骤:
- 预训练:预训练 (pretraining) 一个 运动编码器 (motion encoder),来完成 2D到3D提升 (2D-3D lifting) 的任务。
- 微调: 对预先训练好的运动编码器进行 微调 (finetuning),以适应不同的 下游任务 (downstream tasks)。例如专门做 3D 姿态估计、动作识别 (Action Recognition) 或者 网格恢复 (Mesh Recovery)。

这个网络的架构如下:
这个motion encoder的核心是双流时空 Transformer (Dual-stream Spatio-temporal Transformer, 简称 DSTformer)。DSTformer接受2D骨骼数据的输入。
- Spatial MHSA Block (空间多头自注意力模块): 对 同一个时间步 内各关节之间的关系进行建模,如下图右侧黄色部分。它的自注意力机制看的是“全身的静态骨架结构”。
- Temporal MHSA Block (时间多头自注意力模块):对 某一个身体关节 (a body joint) 跨时间步的关系进行建模。它的自注意力机制不再看全身,而是死死盯住你的某一个关节(比如“右手腕”)。它看第一帧、第二帧…直到最后一帧,你的右手腕画出了一条什么样的轨迹。它看的是“单个局部的动态运动轨迹”。如下图右侧绿色部分。

输入的2D骨骼型号在经过FFN展平为向量后,执行两种不同的嵌入:空间位置嵌入+时间位置嵌入。这两种嵌入旨在标记 在空间域中不同关节的位置 和 在时间域中帧出现的位置。
人类动作识别( Human Action Recognition)
引入
作用与应用
人类动作识别顾名思义,即识别视频中的人类动作。它在监控、危险识别、事件识别、遥控等领域都有应用。

有非常多的动作识别算法被提出。本小节会着重介绍Two-Stream Network和3D CNN这两个较为有代表性和里程碑意义的算法。

常用数据集
下表是一些常用的动作识别训练数据库
| 数据集 (Dataset) | 年份 (Year) | 样本数 (# Samples) | 平均时长 (Ave. Len) | 动作类别 (# Actions) | 备注 (Comments) |
|---|---|---|---|---|---|
| HMDB51 | 2011 | 7K | ~5s | 51 | - |
| UCF101 | 2012 | 13.3K | ~6s | 101 | - |
| Sports1M | 2014 | 1.1M | ~5.5s | 487 | 首个大规模视频动作数据集 |
| ActivityNet | 2015 | 28K | [5, 10]m | 200 | 人类日常生活动作 |
| YouTube8M | 2016 | 8M | 229.6s | 3862 | 最大规模视频数据集 |
| Charades | 2016 | 9.8K | 30.1s | 157 | 多标签室内日常活动 |
| Kinetics400 | 2017 | 306K | 10s | 400 | 最广泛采用的基准 |
| Kinetics600 | 2018 | 482K | 10s | 600 | 最广泛采用的基准 |
| Kinetics700 | 2019 | 650K | 10s | 700 | 最广泛采用的基准 |
| Sth-Sth V1 | 2017 | 108.5K | [2, 6]s | 174 | 需要强时序建模 |
| Sth-Sth V2 | 2017 | 220.8K | [2, 6]s | 174 | - |
| AVA | 2017 | 385K | 15m | 80 | 首个大规模时空动作检测数据集 |
| AVA-kinetics | 2020 | 624K | 15m | 80 | - |
| Moments in Time | 2018 | 1M | 3s | 339 | 为事件理解而设计 |
| HACS Clips | 2019 | 1.585M | 2s | 200 | 由片段组成 |
| HVU | 2020 | 572K | 10s | 739 | 六类任务:场景、物体、动作、事件、属性、概念 |
| AViD | 2020 | 450K | [3, 15]s | 887 | 移除人脸身份以保护隐私 |
| NTU RGB+D (S) | 2016 | - | - | 120 | 引入深度与骨架信息 |
Two-Stream Networks
双流网络(Two-Stream Networks)包含一个空间流(spatial stream)、一个时间流(temporal stream)和一个分数融合模块(score fusion module):
- 空间流(Spatial Stream):本质上处理的是图像分类任务。它输入单张彩色的RGB图像,利用CNN提取空间特征,然后全连接层执行分类任务,给出一个“当前执行的动作的分类 score”
- 时间流(Temporal Stream):时间流用于提取帧间的时间信息。它的输入不是彩色图像,而是光流图(由帧间估计而来,分为垂直光流和水平光流),用来告诉网络“物体是怎么动的”。它首先拼接两帧光流图输入CNN吗,然后使用FC层根据时间的特征执行一次分类,也给出一个“当前执行的动作的分类 score”
分数融合:两路网络各自得出一个分类预测,最后通过融合模块得出最终结论。

为何使用光流图来提取时间特征?它为 RGB 图像提供了正交信息
光流图完全剥离了人物的衣服颜色、背景纹理等“外观信息”,只保留了运动的轮廓和方向。所谓正交,意味着光流提供的信息与RGB图像信息是互不重叠、互为补充的。RGB提供静态外观,光流提供纯粹的动态趋势,两者结合能大幅提升模型的鲁棒性。
- 优点(Pros):提供与RGB图像正交的信息(orthogonal information)。
- 缺点(Cons):获取光流图的计算量大(computationally intensive)且具有较大的存储需求(storage requirement)。
双流网络中的优缺点(Pros and Cons in Two-Stream Networks)
- 优点(Pros):网络结构简单。光流是表示运动信息的一种精确方式。
- 缺点(Cons):光流的提取和存储成本高昂。
3D CNNs
传统的2D CNN的输入是单张图片,而3D CNN的输入是一系列的帧(时间+高度+宽度三维数据),直接在这个三维数据块上进行卷积,池化,展平等操作,从而端到端地同时提取空间外观特征和时间运动特征。

与2D CNN最关键的不同的是,3D CNN使用的是3D卷积,如果强行用普通的2D CNN去处理视频序列,网络通常会把多帧画面在“通道(Channel)”维度上堆叠起来。这会导致时间维度在第一次卷积后就被“压扁”或融合了,后续的网络层将丢失时间上的先后顺序信息。而3D卷积核本身就是一个三维的立方体,它在进行点积时保留了对时间维度的感知。
二维卷积与三维卷积的差异
下图左是2D CNN,右是3D CNN。可以看到,3D CNN的卷积核可以贯穿多个帧来执行卷积。

下面是一个3D CNN的例子,左侧4x4x4 Cube表示4个连续的帧。3x3x3 Filter表示这个卷积核是3x3,贯穿3帧。首先,第一次卷积分别对前三帧(下图左)执行卷积操作,得到2x2x2Output中上面那个卷积结果。然后向后移一帧(下图右),再次执行卷积操作,得到得到2x2x2Output中下面那个卷积结果。

3D CNN的优劣势
- 优势:特征提取器可以同时获取时间和空间信息。
- 劣势:由于模型庞大且推理效率低,难以训练和部署
Efficient Video Modelling:Time Shift Module
在前面讲到的双流网络(提取光流极其耗时)和三维卷积网络(计算量巨大)之后,学术界开始思考:能不能用二维卷积的计算代价,达到三维卷积的时间建模效果?这就引出了时间偏移模块(TSM)。
- TSM对每一帧独立提取特征,构成下图(a)的Channel C,每一帧的特征堆叠。
- 若有完整视频(b):为了实现不同帧之间的信息交换,将一些通道移至过去的帧或未来的帧,如下图(b)。这个移动是双向的,即,可以去未来的帧,也可以去过去的帧。
- 若是在线视频流(c):对于在线的视频流,没有完整的帧,因此只能将通道往过去的帧间移动。

时间偏移模块(TSM)的优点是快速且高效,但缺点是准确率不如3D CNN。
新兴算法
Video Swin Transformer
如果使用 3D CNN,因为感受的视野只集中在一些相邻的帧上,范围相当小,因此存在一些局限性。
Transformer模型可以捕捉到长期依赖关系。但缺点是计算成本高,需要大量数据来进行训练。
Transformer用于视频处理的代表算法就是Video Swin Transformer。
回顾前面学过的ViT,它将图片切割成小patch作为token,然后全部计算注意力。如果把视频里的每一个token,并让它们两两计算注意力,计算量会随着视频长度呈指数级爆炸。
解决这个痛点的正是Swin架构的核心思想——局部窗口与层次化设计。从底部的流程图可以看出,它与处理图像的Swin架构在宏观上是一脉相承的,通过“图块合并”操作逐渐降低空间分辨率、增加通道数,从而提取深层的抽象语义特征。
因此,Video Swin Transformer:旨在降低模型复杂度的同时,保持捕捉长期依赖关系的能力。
Video Swin Transformer的架构如下图。

3D patch 切分:输入的视频维度是(Time x Height x Width x 3(RGB)),将其切分为$2 \times 4 \times 4 \times 3$的小patch,这意味着一个patch包含2帧。
- 来看到第一个输入的$\frac{T}{2}\times\frac{H}{4}\times\frac{W}{4}\times96$,这个式子是怎么来的?在第一次patch切分时,一个通道会被空间切分成$W/4\times H/4$个patch,时间上有有$T/2$个path。每一帧图像有3个通道,2帧就有6个通道,每个通道是4x4=16个像素,最终$6\times16=96$,因此输入数据的维度是$\frac{T}{2}\times\frac{H}{4}\times\frac{W}{4}\times96$。

线性嵌入:随后,这些“小砖块”会被拉平,并通过一个全连接层(线性投影),将其原始的像素特征映射到一个维度为 $C$ 的更高维语义空间中。C根据性能自行定义。
经过Video Transformer Block执行自注意力机制。输出传入下一级
输入下一级时,与Swin transformer一样,执行patch合并操作(两次空间下采样,H和W都2个token合一个)。同时,使用线性映射将维度变为2倍。
Video Transformer Block
与Swin Transformer类似,Video Swin Transformer也将它划分为多个local window。每个local window由$T/2\times H/2 \times W/2$个token组成。例如$8\times 8 \times 8$像素的 3D token,window就是$4\times 4 \times 4$个token。
- 在第 $l$ 层,将三维标记划分为尺寸为 $P \times M \times M$ 的窗口,并在每个局部窗口内执行自注意力计算。
- 在第 $l+1$ 层,以一定的步长($P/2 \times M/2 \times M/2$)移动窗口,将标记组织成新的窗口,并在每个移动后的窗口内计算自注意力。

基于骨架的网络(Skeleton Based Network)
实际上,要判断一个人在做什么动作(比如跑步、打球、摔倒),背景像素往往是冗余的,真正核心的是人体关键点的运动轨迹。
这需要用到时空图卷积网络(ST-GCN) 的核心思想,它的处理流程主要分为两步:
降维抽象:姿态估计(Pose Estimation):提取出视频内的骨架动作。
图论视角的特征提取:图神经网络(GNN/GCN):传统的二维卷积(只能在规则的像素网格上滑动)在此不适用。因为人体的关节分布是不规则的。此时,需要用到图论(Graph Theory) 。
- 节点(Nodes): 人体的每一个关节(如手腕、手肘、膝盖)就是一个图节点。
- 空间边(Spatial Edges): 按照人体的自然生理结构,将相邻的关节连接起来,形成单帧画面内的空间拓扑结构。这在图论中可以通过邻接矩阵(或拉普拉斯矩阵)来精确定义。
- 时间边(Temporal Edges): 将当前帧的某个关节(如左手腕)与上一帧和下一帧的同一个关节连接起来,形成时间维度的轨迹。
通过多层这样的图卷积操作,网络能够理解极其复杂的局部与全局协同运动(比如“挥手”是手臂几个节点的协同,“跑步”是全身节点的周期性协同),最终输出动作分类结果。
