从「是什么」到「在哪里」
在上一篇指南里,你搭起了一个 图像分类器:喂进一张图片,得到一个标签——*猫*。这确实有用,但它只回答了一个问题。一辆自动驾驶汽车需要的不仅仅是知道画面里*某处存在*一个行人;它得知道在哪里、有多大、画面里是三个行人还是一个。从「每张图一个标签」迈向*定位*物体,正是从分类跨向检测与分割的那一跃。
这里有一道越来越精确的阶梯。分类给整张图一个标签。物体检测 在每个物体周围画一个 边界框 并打上标签——*这里有只猫,那里有条狗*。语义分割更进一步,把每一个像素都按类别打标签。实例分割最精细:它既给每个像素打标签,*又*把这只猫和那只猫区分开。每升一级,模型都要承诺更多,训练和评估也都更难。
框,以及我们如何给框打分:IoU
一个边界框无非是四个数——通常是角点坐标,或者中心点加宽高——再配上一个类别标签和一个置信度分数。预测框把问题的一部分变成了*回归*:网络不再是从类别里挑一个,而是输出实数坐标,并被训练着把它们推向真实的框。但这引出一个尖锐的问题:如果模型预测了一个框,而真实标注是一个略有不同的框,那它*到底有多对*?你不能要求像素级的完全相等。
整个领域达成共识的答案是 [[intersection-over-union|交并比]],即 IoU。把预测框和真实框拿来;量出它们重叠的面积,再除以它们合在一起覆盖的面积。如果两个框完全重合,IoU 就是 1;如果它们根本不沾边,就是 0。一个常用的规则是:只有当一个检测框与某个真实框的 IoU 越过某个阈值(常常是 0.5)时,才算它「正确」。这一个比值无处不在——在训练中、在判断哪个预测对应哪个物体时、在排行榜指标里都有它。
IoU = area(overlap) / area(union)
true box predicted box
+--------+
| +----|-----+ overlap = the shared rectangle
| | | | union = both boxes combined
+---|----+ |
+----------+ IoU = overlap / union (0 .. 1)由于 IoU 衡量的只是区域重叠,它并不专属于框——同样的这个比值也用来给分割掩码打分,那时你比较的是预测像素和真实像素。请记住这一点:IoU 是贯穿本指南一切内容的连接组织。当一篇论文吹嘘「0.5 下的 mAP」时,它是在用 0.5 的 IoU 阈值判定命中与失误,再把各类别的检测 精确率 平均起来。
两条检测路线:先找区域,还是一步到位
第一个真正好用的家族是 [[r-cnn|R-CNN]] 及其后代(Fast R-CNN、Faster R-CNN)。它的思路是一条两阶段流水线:先*提出*几百个可能含有物体的区域,再对每个候选区域跑一个分类器,说出它是什么并微调它的框。它很准确,因为第二阶段能仔细地端详每一个候选。代价是速度——对每张图的几百个区域都跑一遍分类器很沉重,这使得早期的 R-CNN 用在视频上慢得不像话。
第二个家族把设计颠倒了过来。[[yolo|YOLO]]——「你只看一次」(You Only Look Once)——在单次前向传播中把一切搞定。它把图像切成一个网格,对每个格子直接预测框和类别概率。没有单独的候选阶段;一个网络,看一眼。这让它快到足以在实时视频上运行,也正因如此,YOLO 及其单阶段同类支撑着你在现实里见到的大多数实时检测——摄像头、无人机、体育分析。
从框到像素:分割
框是个粗钝的工具。一个框套住一条蜿蜒的道路、一只蜷成一圈的猫、或一个张开双臂的人,会框进许多它并不意指的背景。分割通过对每个像素分类来解决这个问题。在 [[semantic-segmentation-vision|语义分割]] 中,每个像素得到一个*类别*标签——*道路*、*天空*、*汽车*——但所有汽车共用同一个标签。它回答的是「这个像素是什么?」,并不在意有多少个各自独立的物体。
[[instance-segmentation|实例分割]] 补上了那处缺失的区分:它既给每个像素打标签,*又*把一个物体和另一个区分开,于是一个场景里的三辆车得到三张各自的掩码。一种流行的做法是 Mask R-CNN,它干脆把一个小小的掩码预测头螺接到 Faster R-CNN 检测器上——先找到框,再涂出框内哪些像素属于该物体。这清爽地说明了检测与分割并非对手;像素掩码常常是*建在*一个检测出来的框*之上*的。
网络是怎么输出一张全分辨率的标签图的呢?骨干网络会把图像缩小成粗糙的 特征图,所以分割模型必须*上采样*回原始尺寸。为此有一个优雅的设计——U-Net:一条收缩路径用来捕捉上下文,一条对称的扩张路径用来恢复空间细节,再加上跳跃连接,把早期层里细粒度的边缘直接横递给后期的层。它最初是为生物医学影像而造,其形状如今在分割世界里反复出现。
要让这套真正管用,需要什么——又会在哪里崩坏
这一切都不是魔法;它的代价是标注数据。一个分类样本每张图只需一个标签。一个检测样本需要给*每一个*物体画上框。一个实例分割样本需要把*每一个*物体的轮廓手工描出来——这是费力、昂贵的 标注。这正是为什么像 COCO 这样、含有几十万个被仔细勾勒出轮廓的物体的基准数据集会是里程碑式的成就:模型的上限,是由这些标签的质量与覆盖面所定下的。
- 选定任务:框(检测)、逐像素类别(语义)、还是逐像素加逐物体(实例)——每一种都要求不同的标签格式和预算。
- 拿一个在大型图像数据集上预训练好的骨干网络来微调;你很少从零开始训练。
- 用一个把分类、框回归、以及(对分割而言)逐像素项组合起来的损失函数来训练。
- 用基于 IoU 的指标来评估,然后去看真实的错误——而不只是那个头条数字。
要诚实地面对失效模式,因为在已部署的系统里它们随处可见。检测器在微小、遥远或严重重叠的物体上会吃力;它们可能在空无一物处自信地幻想出框,也可能在不寻常的光照下漏掉一个明显的物体。一个在白天城市街道上训练的模型,到了雪地或夜里会急剧退化——这是一种 分布偏移,你测试集上的 IoU 永远不会就此向你示警。高高的基准分数衡量的是在「长得像训练集」的数据上的表现,而不是面对乱糟糟现实世界的稳健性。
接下来去哪?同样的「定位加打标签」机制可以推广:把这些框跨视频帧追踪、把它们抬升到三维用于机器人、或者把卷积骨干换成一个 视觉 Transformer——那正是下一篇指南的主题。你现在握住的核心观念——框对掩码、语义对实例、以及作为一切量尺的 IoU——会一路直通过去。