1. 从Anchor Box说起为什么大家开始琢磨“不用锚框”这件事如果你在2018年前后做过目标检测相关的项目大概率绕不开一个词——Anchor Box。从Faster R-CNN到SSD再到YOLOv2/v3锚框几乎是那个时代检测器的标配组件。它的逻辑很直观在特征图的每个位置上预先铺设一堆不同尺度、不同长宽比的参考框然后让网络去预测这些框相对于真实标注的偏移量。这套思路统治了相当长一段时间也确实把检测精度推到了可用的水平。但用久了就会发现锚框这东西带来的麻烦一点都不比它解决的问题少。最直接的一点是超参数爆炸。你得为每个数据集单独设计锚框的尺度、长宽比、数量换一个数据集或者换一个检测目标类型这套参数就得重新调。我在实际项目里见过太多次这样的情况同一套网络结构在某个数据集上调好的锚框配置迁移到另一个场景后mAP直接掉好几个点排查半天发现是锚框尺寸和目标尺寸分布不匹配。这种“隐式耦合”让模型的泛化能力打了折扣。第二个问题是正负样本的分配逻辑。基于IoU的匹配策略本身就很脆弱——IoU阈值设高了正样本太少训练不稳定设低了大量低质量框被当成正样本回归目标噪声大。而且锚框数量动辄几万甚至十几万其中绝大多数是背景正负样本极度不平衡训练时得靠OHEM、Focal Loss这类手段去补救。计算量也上去了大量锚框的IoU计算和NMS后处理都是实打实的开销。所以当CornerNet在2018年EECV上冒出来的时候很多人眼前一亮原来检测可以不用锚框。它把目标检测转化成关键点检测——预测目标的左上角和右下角两个角点再通过角点配对还原出边界框。这个思路一下子把锚框那一整套超参数和匹配逻辑全绕开了。紧接着ExtremeNet、CenterNet、FSAF、FCOS、FoveaBox这一批工作陆续跟进形成了“Anchor Free”这条技术路线。它们各自从不同角度切入有的用角点有的用中心点有的用极值点有的干脆用像素级预测但共同目标都是把检测从“框的回归”变成更本质的“点的定位”。这篇文章我会把这六个代表性方法逐一拆开讲清楚。不是泛泛介绍论文而是从“它到底怎么工作的”“为什么这么设计”“实际用起来什么感觉”这几个角度去聊。适合已经了解目标检测基础、想搞清楚Anchor Free这条线到底怎么回事的读者。如果你正在选型做检测项目或者想理解这批算法的设计哲学下面的内容应该能帮你省不少翻论文的时间。2. CornerNet把检测拆成两个角点配对才是关键2.1 角点检测的基本框架CornerNet的核心思想可以用一句话概括用一对关键点左上角和右下角来表示一个目标框。网络输出两张热力图一张预测所有目标的左上角位置一张预测右下角位置。每张热力图的通道数等于类别数每个通道上的峰值就对应某个类别的一个角点。这跟人体姿态估计里的关键点检测非常像区别在于姿态估计预测的是关节CornerNet预测的是框的角。具体来说输入一张图像经过主干网络原文用的是Hourglass Network提取特征然后分成两个分支一个负责左上角一个负责右下角。每个分支输出三个东西热力图Heatmap、嵌入向量Embedding和偏移量Offset。热力图告诉你角点在哪、是什么类别嵌入向量用来做角点配对——同一个目标的左上角和右下角它们的嵌入向量应该尽可能接近不同目标的角点嵌入向量应该远离偏移量则是因为特征图经过下采样后坐标有量化误差需要预测一个小数偏移来修正。这个设计里最巧妙的是嵌入向量做配对。因为网络检测到的左上角可能有几十个右下角也有几十个怎么知道哪个左上角和哪个右下角属于同一个目标CornerNet的做法是让网络自己学一个嵌入空间同一目标的角点在这个空间里距离近不同目标的距离远。训练时用push损失把不同目标的嵌入向量推开用pull损失把同一目标的拉近。推理时对每个左上角找嵌入向量最接近的右下角进行配对就得到了完整的框。2.2 角点池化为什么比普通池化好CornerNet里有一个专门设计的结构叫Corner Pooling这个值得单独说一下。普通的最大池化是在一个矩形窗口里取最大值但角点的位置有方向性——左上角点它的右侧和下侧应该是有目标的而左侧和上侧是背景。如果直接用普通池化会把背景信息也混进来对角点的定位精度有影响。Corner Pooling的做法是对左上角先沿着水平方向从右往左做最大池化再沿着垂直方向从下往上做最大池化这样每个位置聚合到的信息都来自目标的内部方向。对右下角则反过来从左往右、从上往下。这个设计看起来简单但实测对角点定位精度的提升是实打实的。论文里的消融实验也证明了去掉Corner Pooling后AP有明显下降。我在复现的时候试过用普通池化替代确实在边缘目标和小目标上掉点比较明显。原因也不难理解角点本身就在目标的边界上池化窗口稍微偏一点就会把背景特征混进来而Corner Pooling通过方向性的池化把这个问题规避了。2.3 实际训练中的坑角点配对错误与损失权重CornerNet在理论上很优雅但实际训练时会遇到几个问题。第一个是角点配对错误。嵌入向量虽然能学到一定的区分能力但在目标密集或者同类目标重叠的场景下配对错误率会上升。一个左上角可能被错误地配到另一个目标的右下角上产生一个完全错误的框。这个问题在COCO这种目标分布比较分散的数据集上还好但在密集场景比如人群检测、货架商品检测里就比较突出。第二个问题是损失函数的权重平衡。CornerNet的总损失由热力图损失、嵌入损失和偏移损失三部分组成每部分都有自己的权重系数。热力图损失用的是Focal Loss的变体因为正样本角点相对于整张特征图来说极其稀疏。嵌入损失的push和pull权重也需要调push太强会导致同一目标的角点被推开pull太强则不同目标的角点会混在一起。论文里给了一组默认值但实际用的时候还是得根据数据集特点微调。提示如果你打算复现CornerNet建议先把嵌入损失的权重调小一点跑一轮观察角点配对的可视化结果确认配对基本正确后再逐步加大权重。直接上默认参数有时候会训崩。另外CornerNet的推理速度不算快Hourglass主干本身计算量就大加上角点配对的后处理在同等精度下比YOLOv3慢不少。所以它更多是作为一个学术上的里程碑实际工业部署用得不多。但它开启的这条思路——用关键点做检测——直接影响了后面一批工作。3. ExtremeNet与CenterNet极值点和中心点的不同取舍3.1 ExtremeNet的四个极值点思路ExtremeNet的思路和CornerNet有相似之处但切入点不同。它不用左上角和右下角而是预测目标的四个极值点最上、最下、最左、最右。这四个点确定后取它们的外接矩形就是检测框。为什么用极值点而不是角点论文里的动机是对于非矩形目标比如弯曲的物体、不规则形状角点可能落在目标外部而极值点始终在目标边界上更稳定。ExtremeNet的网络结构也是基于Hourglass输出四张极值点热力图加一张中心点热力图。中心点热力图的作用是做分组——四个极值点如果共享同一个中心点就认为它们属于同一个目标。这个分组策略比CornerNet的嵌入向量更直观也更稳定因为中心点的预测相对容易不需要学一个额外的嵌入空间。但ExtremeNet的问题也很明显它假设目标可以用四个极值点的外接矩形很好地表示。对于旋转目标或者极端长宽比的目标这个假设就不太成立了。而且四个极值点的检测本身比两个角点更难因为极值点的位置对目标的姿态更敏感。实际跑下来ExtremeNet在COCO上的AP比CornerNet略低但在某些特定类别比如长条形物体上有优势。3.2 CenterNet把目标变成一个点CenterNet这里指的是Objects as Points那篇不是后面那个CenterNet的思路更激进直接把目标表示成中心点然后回归中心点到边界框四个边的距离。网络输出一张中心点热力图每个峰值对应一个目标中心然后在峰值位置回归出宽高或者到四边的距离。推理时取热力图的局部极大值每个极大值位置回归出一个框不需要NMS因为中心点本身就有排他性。这个设计的好处是极简。没有锚框没有角点配对没有嵌入向量就是一个中心点加热力图加回归分支。后处理也简单取top-k个峰值每个峰值解码出一个框就完事了。速度上比CornerNet快不少因为不需要Hourglass那么重的主干用ResNet或者DLA都能跑。但CenterNet也有它的软肋。第一个是中心点的定义问题对于非刚性目标或者遮挡目标中心点可能落在目标外部或者背景上这时候热力图的学习就会有问题。第二个是回归分支的尺度问题中心点到四边的距离差异可能很大直接回归绝对值容易不稳定通常需要对宽高做归一化或者用log空间回归。第三个是密集场景下的峰值抑制如果两个同类目标中心点靠得很近热力图的峰值可能合并成一个导致漏检。我在实际项目里用CenterNet做过货架商品检测效果整体不错但在商品排列紧密的区域确实有漏检。后来通过加大热力图的分辨率减少下采样倍数缓解了一部分但代价是计算量上升。所以CenterNet适合目标分布相对分散、对速度有要求的场景密集场景需要额外处理。3.3 三种“点表示”的对比与选型参考把CornerNet、ExtremeNet、CenterNet放在一起看它们代表了三种不同的“点表示”哲学方法表示方式关键点数量分组策略优势场景主要短板CornerNet左上右下角点2嵌入向量通用检测配对错误、速度慢ExtremeNet四极值点4中心点分组非矩形目标极值点检测难CenterNet中心点1无需分组速度优先、分散目标密集场景漏检选型的时候如果你追求精度且场景目标比较规整CornerNet系列可以考虑如果对速度敏感、目标分布不密集CenterNet更合适ExtremeNet则适合有大量非矩形目标的特殊场景。当然这只是大致参考实际还得看具体数据分布。4. FSAF与FCOS在特征金字塔上做无锚框检测4.1 FSAF让每个目标自动选合适的特征层FSAFFeature Selective Anchor-Free要解决的是特征金字塔里的一个老问题一个目标到底该由哪一层特征来负责检测在锚框时代这个问题的答案是“根据锚框和目标框的IoU来选”IoU最大的那层负责。但这个策略依赖锚框的设计如果锚框尺寸没设好目标可能被分到一个不合适的层上。FSAF的做法是在每个特征层上都做无锚框的检测分支然后让网络自己学一个“在线特征选择”机制。具体来说每个目标在每一层上都有一个检测结果和对应的损失网络根据损失大小自动选择损失最小的那层作为该目标的主负责层。这个机制不需要额外的监督信号完全靠损失驱动。效果是目标会被分配到最适合它的特征层上而不是被锚框的IoU硬性绑定。这个思路的巧妙之处在于它把“特征层选择”从一个手工设计的规则变成了一个可学习的过程。实际用下来FSAF在COCO上比同主干的RetinaNet有稳定提升而且对锚框参数的敏感度大大降低。但它的实现相对复杂需要在训练时动态计算每层的损失并做选择代码量比FCOS大不少。4.2 FCOS逐像素预测简洁到极致FCOSFully Convolutional One-Stage是我个人认为Anchor Free这条线里最优雅的一个。它的做法极其直接对特征图上的每个位置如果这个位置落在某个目标的中心区域内部就认为它是正样本然后回归这个位置到目标四条边的距离。没有锚框没有角点没有嵌入向量就是一个逐像素的回归问题。FCOS有几个关键设计值得细说。第一个是中心度Center-ness分支。因为逐像素预测会产生大量低质量的框——那些落在目标边缘的像素预测出的框往往偏离很大。FCOS加了一个center-ness分支预测每个位置到目标中心的归一化距离推理时用这个值给分类得分加权把边缘的低质量框压下去。这个设计简单有效是FCOS精度的重要保障。第二个是多尺度分配策略。FCOS也用了FPN但每个层负责的目标尺度范围是通过回归距离的范围来定义的而不是锚框的IoU。具体来说每层设定一个最大回归距离如果某个位置到目标四边的最大距离超过这个阈值就不算正样本。这个策略比IoU匹配更直接也更容易调。第三个是FCOS完全去掉了锚框相关的所有超参数代码实现比RetinaNet简洁很多。我在实际项目里用FCOS替换过RetinaNet训练稳定性明显更好调参工作量少了一大半。精度上在COCO上基本持平甚至略优速度也差不多。4.3 FSAF和FCOS的实操差异虽然FSAF和FCOS都属于“在FPN上做无锚框检测”但实际用起来差异不小。FSAF更像是在RetinaNet框架上做增量改进保留了锚框分支的同时加了无锚框分支训练时两个分支一起跑最后推理时用无锚框分支。这种设计的好处是兼容性好可以复用已有的RetinaNet代码和预训练权重坏处是训练开销大因为锚框分支还在跑。FCOS则是从头设计的无锚框框架没有锚框分支的包袱训练和推理都更干净。但它的正样本定义依赖中心度分支的质量如果中心度学不好精度会受影响。另外FCOS对小目标的检测在早期版本里偏弱后来通过调整FPN的层数和回归范围有所改善。注意FCOS的正样本定义里有一个“中心采样”策略即只有落在目标中心一定半径内的像素才算正样本。这个半径的设定对精度影响很大太小会导致正样本不足太大会引入低质量样本。建议根据数据集的目标尺寸分布来调不要直接用默认值。5. FoveaBox模仿人眼中央凹的检测策略5.1 中央凹采样与正负样本定义FoveaBox的名字来源于人眼的中央凹Fovea这是视网膜上视觉最敏锐的区域。FoveaBox的核心思想是对每个目标只在它的中心区域类似中央凹采样正样本周围区域作为负样本或者忽略。这个策略和FCOS的中心采样有点像但FoveaBox的实现更早而且它的正负样本定义是基于一个缩放后的中心区域。具体来说FoveaBox对每个目标框先把它缩放到一个中心区域比如宽高各乘0.3落在这个区域内的特征点算正样本落在外部区域比如宽高各乘0.4之外的算负样本中间地带忽略。这个设计的好处是正样本质量高都是靠近目标中心的点回归目标相对稳定。同时通过忽略中间地带避免了那些“半正半负”的模糊样本干扰训练。FoveaBox的另一个特点是它同时预测分类和框的回归但分类分支用的是sigmoid而不是softmax每个类别独立判断。这个设计在多标签场景下更灵活但也意味着分类分支的计算量稍大。5.2 FoveaBox与FCOS的异同FoveaBox和FCOS经常被放在一起比较因为它们都是逐像素预测、都用FPN、都强调中心区域采样。但细看下来有几个关键差异第一正样本定义方式不同。FCOS用中心度分支来加权正样本的范围是一个固定的半径FoveaBox用缩放后的中心区域来定义正样本范围是目标尺寸的比例。前者更依赖学习到的中心度后者更依赖手工设定的缩放比例。第二回归目标不同。FCOS回归的是到四边的距离FoveaBox回归的是相对于中心点的偏移和缩放。这两种表示在数值稳定性上有差异FoveaBox的表示在某些尺度下更稳定。第三FoveaBox对FPN的利用方式略有不同它在每层上独立做预测层间的分配策略和FCOS类似但细节有差异。实际精度上两者在COCO上的表现很接近FoveaBox在某些小目标类别上略好FCOS在大目标上略好。选哪个更多看代码习惯和工程约束。5.3 实际部署时的考量如果你打算把FoveaBox或者FCOS部署到实际产品里有几个点需要提前考虑。首先是推理速度两者都是逐像素预测特征图上的每个位置都要过分类和回归分支计算量比锚框方法在相同分辨率下其实差不多但后处理简单很多不需要NMS的IoU计算或者只需要很轻的NMS。整体延迟通常比RetinaNet低。其次是量化部署。逐像素预测的输出是密集的量化时分类分支的sigmoid输出对精度比较敏感建议用per-channel量化而不是per-tensor。回归分支的输出范围较大量化时要注意截断阈值的设定。最后是训练数据的标注质量。Anchor Free方法对标注框的精度比锚框方法更敏感因为正样本直接落在目标内部标注框偏几个像素就会影响正样本的位置和回归目标。如果标注数据质量一般建议先做一轮标注清洗再训练。6. 这条技术线走到今天选型、踩坑与个人体会6.1 六个方法的横向对比与选型建议把这六个方法放在一张表里对比能更清楚地看到各自的定位方法核心表示主干正样本定义后处理COCO AP参考适合场景CornerNet角点对Hourglass角点位置嵌入配对NMS~42精度优先、非密集ExtremeNet四极值点Hourglass极值点位置中心分组NMS~40非矩形目标CenterNet中心点ResNet/DLA中心峰值top-k解码~42速度优先、分散目标FSAF逐像素RetinaNet在线选择NMS~42兼容RetinaNetFCOS逐像素ResNetFPN中心采样NMS~43通用、易调参FoveaBox逐像素ResNetFPN中央凹区域NMS~42通用、小目标从工程角度看FCOS和FoveaBox是最好落地的因为结构简单、依赖少、调参空间小。CenterNet在速度上有优势适合实时场景。CornerNet和ExtremeNet更多是学术价值实际部署的性价比不高。FSAF适合已有RetinaNet代码想平滑迁移的情况。6.2 训练Anchor Free模型时最容易踩的三个坑第一个坑是正样本数量不足。Anchor Free方法没有锚框带来的大量正样本如果正样本定义太严格比如中心区域太小会导致正样本极少训练时梯度信号弱收敛慢甚至不收敛。我的经验是先用宽松的正样本定义跑一轮确认模型能正常收敛后再逐步收紧。第二个坑是回归目标的尺度问题。逐像素回归时不同目标的回归距离差异可能很大大目标的回归距离是小目标的几十倍。如果不做归一化或者log变换大目标的损失会主导训练小目标学不好。FCOS和FoveaBox都用了某种形式的归一化自己实现时一定要注意这一点。第三个坑是NMS的阈值设定。Anchor Free方法产生的框通常比锚框方法更密集因为每个正样本位置都会产生一个框。如果NMS阈值设得和锚框方法一样可能会过度抑制导致漏检。建议适当放宽NMS阈值或者用soft-NMS。6.3 我对这条技术线的个人判断从2018年到现在Anchor Free这条线已经从学术探索走到了工业落地。FCOS和CenterNet在不少实际产品里都有应用效果和效率都得到了验证。但我并不认为锚框方法会被完全取代——在某些特定场景下精心设计的锚框仍然有它的优势比如目标尺度分布非常集中的场景锚框可以先验地覆盖所有可能尺度收敛更快。Anchor Free真正的价值在于它降低了检测器的设计复杂度和调参门槛。你不需要再为锚框的尺度、长宽比、数量纠结也不需要设计复杂的IoU匹配策略。把检测变成逐像素或者关键点的预测整个流程更统一、更简洁。这对于快速迭代和迁移到新场景来说是实实在在的便利。如果你正在做检测项目选型我的建议是先试FCOS或CenterNet跑通baseline看看精度和速度是否满足需求。如果满足就直接用别折腾锚框了。如果不满足再考虑针对具体问题做改进比如换更强的骨干、加注意力机制、改正样本定义。Anchor Free的框架足够灵活改起来比锚框方法方便得多。最后分享一个小技巧训练Anchor Free模型时把正样本位置的可视化图打出来看看。如果正样本集中在目标中心一小块说明定义太严如果正样本铺满整个目标甚至溢出到背景说明定义太松。这个可视化检查花不了几分钟但能帮你快速定位正样本定义的问题比盲调参数高效得多。
阅读完成 · 觉得有帮助?