☰
目标检测技术演进:从手工特征到深度学习
2026/10/14 14:59:50 网站建设 项目流程

做目标检测的人,可能已经把“喂图片给模型、拿框出来”当作吃饭喝水一样自然的事情。但你有没有想过,这个看似理所当然的过程,二十年前根本不是这样的。那时候没有端到端的网络,没有一键下载的预训练权重,检测一张图里的物体,要先定义滑动窗口,再手工设计特征,最后交给分类器去判断。整套流程拆成好几段,每一段都有讲究,也每一段都有让人头皮发麻的坑。

这篇文章我想把这条技术主线从头捋一遍,从传统方法怎么一步步走到深度学习,把其中的关键思路、为什么会被淘汰、以及今天哪些老思想其实还活在现代模型里,都摊开讲清楚。不管你是刚入行的学生,还是已经在用检测模型做项目的工程师,这条演进史都能帮你少走很多弯路。很多今天看起来很酷的设计,背后其实是对十年前某个痛点的回应。理解了“为什么”,你调参和改代码时才不会两眼一抹黑。

1. 二十年的主线:检测到底在解决什么问题

1.1 目标检测的核心矛盾

目标检测任务的本质,用大白话说就两件事:一是把图片里感兴趣的东西“找出来”,二是告诉别人找到的“是什么”。找出来意味着要回归坐标,框要贴得准;是什么意味着要做分类,类别要判断对。这两个问题看起来简单,放在一起就变得很难。分类任务只需要回答“图里有没有猫”,检测任务需要回答“图里哪里有猫、有几只猫、每只猫占多大范围”。同一张图上往往有多个目标,目标之间还可能互相遮挡,形变各异,光照条件也随时在变。

早期方法之所以慢,是因为它们把这两个问题拆分得很开,先用一个模块扫描图片里的所有可能位置,再用另一个模块对每个位置做分类。扫描位置的过程,就是大家熟知的滑动窗口。窗口大小、步长、缩放尺度都要预先定好,否则目标太大或太小都会漏检。那个阶段的检测器,本质上更像“穷举候选框加分类器筛选”,而不是真正意义上的“感知”。后来深度学习把分类和回归塞进了同一个网络,端到端地训练,形式上看起来简洁了,但核心矛盾并没有消失,只是变成了在特征图上去平衡分类分支和回归分支的损失。

1.2 为什么要看这一段历史

不少同学一上来就接触某个现代检测框架,用起来是爽,可一旦模型效果不好,根本不知道从哪里下手。你不了解框是怎么生成的、特征是怎么组织的、损失是怎么把梯度传回去的,就只能在阈值、学习率、数据增强这几个旋钮上来回拧。理解了过去二十年间方法更替的内在逻辑,就等于拿到了一张完整的地图:你知道哪些组件是用来解决漏检的,哪些是用来对齐框的,哪些是针对小目标优化的。这些组件的来龙去脉,恰恰就藏在传统方法到深度学习的那几次关键转折里。

看这段历史还有一个非常实际的好处:面试也好,汇报也好,别人问你“为什么用这个结构”“为什么这里要加FPN”,你能从原理层面讲清楚,而不是只会说“大家都这么用”。二十年的演进,本质上就是一个从“手动设计”到“自动学习”的过程。你能说清楚这个过程的每一步取舍,才算真的入了门。

2. 传统方法:当视觉特征还靠手工雕琢时

2.1 滑动窗口与图像金字塔:最朴素的暴力美学

在深度学习之前,检测器普遍采取的策略可以归结为四个字:滑动窗口。想象一下,你拿一张图片,用一个固定大小的矩形框,从上到下、从左到右地移动,每移动一步,就把框住的那一小块图像单独取出来,送去分类器判断。判断完一个尺寸,再把图片缩放一下,换个尺度继续扫。这种做法简单粗暴,但问题也很明显:计算量巨大,而且窗口的尺寸和缩放比例很难适应所有目标。

我早年做行人检测时就深受其苦。为了不漏检一个中等距离的行人,常常要扫描七八个尺度的金字塔,每层还要按四分之一或八分之一步长移动窗口。一张普通的测试图,跑完整套流程要几秒钟,这还不算后续还要做重复框合并。后来大家意识到,不是所有区域都需要认真检测,有些地方一眼过去就是背景。于是出现了候选区域生成的概念,希望在图片里先快速圈出“可能有物体”的区域,再只对这些区域做精细分类。这个思想直接催生了后来深度学习时代的两阶段检测器,其实很多人不知道,R-CNN里那个用来生成候选框的模块,就是从传统视觉那会儿演变过来的。

2.2 手工特征:从Haar到HOG再到DPM

光有窗口还不够,每一块被框住的图像,都要用一个特征来描述,才能交给分类器。传统方法里面有三个特征非常有代表性。一是用来做人脸检测的Haar特征,本质是对矩形区域内的像素做差分计算,把局部明暗变化编码成特征值。二是用于行人检测的HOG特征,把窗口内的梯度方向统计成直方图,能很好地刻画物体的轮廓和边缘形状。三是后来在DPM里大放异彩的部件模型,不再用一个整体窗口描述目标,而是把目标拆成头部、四肢等多个部件,分别建模,再用空间位置关系约束它们。

这些手工特征的生命力超出了很多人的想象。HOG这套思路,到今天仍然会用在一些工业级场景里,因为它在无GPU环境下跑得动,而且对小规模数据还相当稳。Haar虽然老,但在嵌入式硬件上做人脸检测仍然很常见。DPM则把传统方法推到了顶峰:它通过可变形部件组合的办法,在处理遮挡和形变时比HOG高出不少,曾连续多届拿下过公开检测榜单的第一。但DPM的缺点也致命——特征和部件结构都是人设计的,遇到那些没见过的目标类别,泛化能力非常有限。你没法想象手工给一千个类别各设计一套部件模板会是什么工作量。

2.3 传统方法为什么输给了深度学习

传统方法不是不努力,而是撞上了三堵墙。第一堵墙是特征表达能力的上限。HOG和DPM能把边缘轮廓描述得很好,但描述不了复杂的语义信息。比如要检测“开车时手持手机”这种行为,HOG根本无能为力,因为这里面有大量的上下文信息,不是靠梯度直方图能概括的。第二堵墙是计算效率。滑动窗口加多尺度扫描太费时间,实际项目里经常要在精度和速度之间做痛苦取舍。第三堵墙是扩展能力。每引入一个新类别,几乎都要重新设计特征和训练流程,这也让规模化落地变得极其困难。

到了2012年前后,深度卷积网络在图像分类任务上取得了巨大突破。大家突然发现,卷积网络可以通过数据自动学习特征,低层提取边缘纹理,高层提取语义部件,这种层级化的特征表达,远比手工设计的HOG要丰富得多。于是检测领域的思路开始转变:既然分类器可以使用深度特征,那检测器为什么不直接把特征提取这件事也交给网络呢?这个念头,直接打开了深度学习检测的大门。

3. 深度学习接管:从区域建议到端到端

3.1 两阶段检测:R-CNN系列铺平了道路

真正意义上的深度学习检测,在我看来是从区域建议加深度分类开始的。最初的做法是先用传统图像分割方法生成一批候选框,再把这些框里的图片区域缩放到固定尺寸,送到卷积网络里提取特征,最后接分类器和回归器。思路本身并不复杂,难点在于如何把卷积网络用起来:抠出来的区域尺寸不一,需要缩放;每个区域都要单独过一遍网络,导致大量重复计算;训练流程还要分好几个阶段,非常繁琐。

随后出现的空间金字塔池化和对应的快速版本,解决了重复计算和尺寸缩放的问题。它们让网络在处理不同尺寸输入时,不必先把图片裁剪成同一大小,而是通过空间金字塔池化把特征图统一成固定维度。再接下来出现的区域建议网络,把原来用传统方法生成候选框的环节也换成了一个小型卷积网络,放在特征图后面端到端地训练。到这一步,检测器的骨架已经相当现代了:主干网络提特征,区域建议网络提候选,后接分类回归头做精细预测。现在很多需求里还在用的两阶段架构,基本就是那时候定下来的。

3.2 单阶段检测:YOLO和SSD的取舍

两阶段虽然准,但速度一直是个问题。区域建议网络生成候选框后,还要对这些候选框逐个做分类回归,即使做了不少优化,推理速度也很难达到实时。这时候就有团队想到另一条路:干脆放弃“先提候选再精修”的流程,直接在特征图的每个位置上预测一组框和对应的类别概率。这类方法后来统称为单阶段检测。其中最有影响力的代表,把检测任务完全当作回归问题来处理,把图片划分成网格,每个网格负责预测中心点落在其中的目标。这种做法简洁高效,但早期对重叠密集目标和小目标的处理并不好。

另一条路线(类似SSD的思路)采用了在不同尺度特征图上设置预设框的做法,多尺度地预测目标,在速度和精度之间取得了不错的平衡。单阶段检测真正流行起来,是在解决了训练时的难易样本不平衡问题之后。早期单阶段检测器训练时,背景框数量远多于目标框,网络很容易被大量简单负样本淹没,导致模型偏保守,什么都不敢预测。后来的焦点损失函数专门针对这个问题做了优化,通过降低简单样本的权重,让模型更关注那些难以分辨的框,从此单阶段方法的精度追平甚至反超了两阶段。

3.3 从卷积到注意力:检测器也赶上了新浪潮

卷积网络统治检测领域的时间非常长,长到很多人已经觉得检测就等于深度卷积网络加预测头。但近几年,基于自注意力机制的检测模型横空出世,把检测从人工设计的锚点框和候选区域里彻底解放出来。这类模型把目标检测看作一个集合预测问题:输入一张图,输出一个包含物体类别和坐标的集合,整个流程不再需要预设一堆候选框,也不需要非极大值抑制这个后处理环节。它通过匈牙利匹配算法,把预测集合和真实标注集合一一配对,然后计算损失。

这个思路听起来很优雅,但代价是训练收敛慢,对小数据集不太友好。后来的一些改进工作通过引入多尺度特征和更高效的注意力机制,把收敛速度和精度都拉了上来。到了这一代方法,检测器的核心组件已经和传统方法时期的滑动窗口、手工特征完全隔了代。但有意思的是,现代模型里的很多结构,比如特征金字塔、多层特征融合、上下文建模,本质上还是在回应那些一直存在的老问题,只是解题工具换了。

4. 内行人不会明说的关键技术点

4.1 锚点框:预设框背后的动机与代价

很多人在看检测模型结构时,最大的困惑就是锚点框这个玩意儿到底有什么用。简单说,目标的位置和尺寸千变万化,让网络直接从图片去回归任意坐标,学习难度非常大。锚点框的思路是预先在特征图每个位置设置多个不同形状、不同大小的框作为参考,网络只需要学“相对于预设框做多大偏移、缩放宽高多少”,任务难度一下子降下来了。

这个技巧在传统方法时代就有影子,因为滑动窗口其实也是一种隐式的锚点框。深度学习时代把锚点框变成了可学习过程中非常关键的先验知识。但锚点框不是白给的,它有三个很现实的问题。一是超参数敏感,框的数量、长宽比、尺度都要根据数据集仔细调,调不好召回率就会明显下降。二是正负样本不均衡加剧,一张图可能生成几万个锚点框,但真正包含目标的只有很少一部分。三是设计复杂,不同尺度的目标需要不同层级的锚点框来匹配。正因为这些麻烦,后续很多模型都在尝试去锚点化,用中心点、角点或查询向量来替代,这也是检测架构持续演进的重要动力。

4.2 非极大值抑制:预测完还要再“打架”

检测模型输出的原始预测框往往会非常多,同一个物体周围可能重叠着十几个框。如果直接把这些框画出来,画面会非常乱。后处理阶段通常要做一次非极大值抑制,基本逻辑是:按置信度从高到低排序,先保留置信度最高的框,然后删除与它重叠度超过阈值的所有框,再在剩下框里重复这个过程,直到处理完毕。

看似简单,实际用起来有讲究。阈值设得大了,重叠较近的多个目标可能被误删,导致漏检;设得小了,重复框又清理不干净,造成误检。工业项目里,我经常要针对具体场景调整这个阈值,还会在输出端加一些规则,比如某个类别的框和另一个类别的框重叠太厉害时,额外再判断一次,减少错乱。这也是后来有工作提出端到端检测器的原因之一,希望直接把后处理融进网络,减少人工调参的环节。但直到今天,非极大值抑制仍然是大多数检测系统里必不可少的一环。你别把它当成一个不重要的细节,很多模型精度的差距,最后往往就差在这几行后处理代码上。

4.3 特征金字塔:小目标检测的救命稻草

小目标检测是目标检测里的老大难问题。小目标在整张图里只占几十个像素,经过多层卷积和池化之后,到了深层特征图里可能只剩下两三个像素,信息几乎丢光。早期模型直接在最后一层特征图上做预测,对小目标效果很差。后来大家意识到,不同层级的特征图其实编码了不同尺度的信息:浅层特征图分辨率高,保留了更多细节,适合检测小目标;深层特征图语义强,适合检测大目标。

特征金字塔的思路就是把浅层和深层特征融合起来。具体做法是:从深层向浅层依次上采样并相加,让高层的语义信息向低层传播。这样一来,每一层特征图同时具备细节和语义,不同尺度的目标可以在不同层上被预测。这个设计几乎成了深度学习检测器的标配,我自己的项目中,凡是涉及小目标的场景,加了特征金字塔结构之后,检测率常常能提升好几个点。这里有一个容易被忽略的实操点:特征融合时通常要加一层卷积来消除上采样带来的混叠效应,如果不做这个操作,直接相加的特征图会比较粗糙,最终框的边界精度也会受影响。

4.4 训练策略:数据增强、损失函数和难例挖掘

模型架构只是第一步,真正决定上限的往往在训练策略里。数据增强是其中最基础也最有效的手段,随机裁剪、颜色抖动、马赛克增强这些方法,本质上是让模型看到更多变体,减少过拟合。但增强不是越多越好,我在项目里曾经出现过增强过度导致模型在正常图片上反而效果变差的情况,因为训练数据和实际部署数据差距太大了。做增强之前,一定要先想清楚部署场景是什么样的,别让数据增强变成对手。

损失函数的设计同样关键。分类分支常用交叉熵,回归分支用平滑的L1损失或变体,两者之间的权重配比需要调。有些模型不管怎么训都出现框定位不准的问题,其实就是回归损失的梯度在训练后期被分类损失压过去了。另一个容易被忽视的点是难例挖掘。传统方法时期就需要对困难样本反复处理,深度学习时代虽然有了焦点损失这类自动平衡机制,但有些场景下手动加一些难例挖掘逻辑仍然很有效。我自己训练检测模型时,会定期看一遍模型在当前验证集上犯了哪些错,把那些反复出错的样本挑出来单独放到训练集里加重权重,这个方法虽然笨,却一直很实用。

5. 数据、评估与落地中的真实坑

5.1 评估指标没那么简单

一个检测模型好不好,不能只看一眼直观效果。行业里最常用的评估指标是平均精度均值,它把各类别的精确率、召回率综合成一个分数。听上去标准,实际细节很多。平均精度的计算依赖于预测框与真实框的重叠度阈值,阈值取0.5还是一系列从0.5到0.95的平均值,会得到完全不同的结论。前者对框的定位要求低,后者要求框得非常准。一个只关心“有没有框出来”的项目,和一个人脸识别门禁项目,对定位精度的要求天差地别,选的指标自然是两套。

我在项目验收时吃过一个亏:对方只看可视化效果,觉得框都画上了就算好,结果用严格指标一评,模型在小目标类别上的分数低得吓人。后来我养成一个习惯,无论需求多紧急,先和对方对齐评估口径,再谈模型优化方向。不然你花大把时间把平均精度提升了,对方却觉得“框还是不够准”,方向完全跑偏。

5.2 标注质量决定上限

检测模型的输出上限,很大程度上在标注阶段就已经决定了。框标得偏了、漏标了、类别标错了,模型学到的就是带噪声的映射。网上很多公开数据集质量很高,但你自己业务里的数据往往没这么理想。我在处理工业数据时,会先花一天时间检查标注质量,看看不同标注员之间的框是否一致,框边界是否贴合目标轮廓。如果标注噪声大,宁可先做一轮标注清洗,也不要急着训练。经常有人问为什么同一个模型别人跑得那么好、自己跑就拉胯,绝大部分原因都在数据上,而不是模型结构上。

还有一个非常实际的问题:类别不平衡。工业场景里往往某些类别特别多,某些类别特别少,模型天然会偏向多样本类别。除了调整采样权重和损失函数,我还有一个土办法——给少样本类别单独做增强。把这类目标在训练时复制粘贴到不同背景上,人为增加样本数,同时注意不要破坏真实分布。这个方法不算高级,但操作简单,效果可控,比盲目上复杂平衡算法更稳妥。

5.3 部署环境里的速度优化和资源限制

模型在实验环境里跑得再快,到了部署端都可能翻车。边缘设备上的算力有限,内存也紧张,这时候就非常考验工程能力。常见做法有模型剪枝、注意力蒸馏、动态推理和低比特量化。量化是部署最常见的手段,把浮点模型转成低精度推理模型,可以大幅减少内存占用和推理延迟。但量化后精度会掉,尤其是一些对边界回归要求高的场景,掉得更明显。建议先在上线前做逐层的精度对比,找到量化后损失最大的层,做混合精度处理,而不是一刀切全量化。

还有个容易被忽略的点是输入分辨率。很多项目为了追求精度,把输入图片设得很大,结果测试速度惨不忍睹。实际部署时我会先做一次分辨率扫描,从较低分辨率开始逐档提升,找出精度和速度的拐点。找到那个拐点之后,固定的输入尺寸往往比大分辨率模型效果还要理想,因为分辨率提升的同时计算量也暴涨,边际收益很容易变成负的。

5.4 长尾分布和动态场景

真实世界的数据分布不是均匀的。常见的东西样本多、模型学得好;罕见的东西样本少、模型学得差。长尾分布是工业落地里最头疼的问题之一。应对思路有两个方向:一是让网络模型具备更强的少样本学习能力,二是用数据手段补足尾部类别。前者在论文里很漂亮,但工程实现复杂度高;后者虽然土,却能在短期见效。我的做法是优先收集尾部类别数据,实在收集不到,再考虑用生成式手段做数据合成,或者通过调整分类边界的阈值来改善尾部类别的召回。

动态场景则更考验系统设计。光照变了、相机角度变了、目标外观变化了,模型性能都会肉眼可见地下降。这种问题不是重新训练一次就能解决的,更稳妥的办法是做持续学习和动态更新机制:定期用新采集的数据微调模型,同时做严格的回归测试,防止旧能力被破坏。我见过太多团队只追求上线时的惊艳效果,忽略了上线后数据漂移的问题,半年不到,模型就废了。

6. 走了这段路之后的一些个人体会

如果让我说这二十年最值得琢磨的一点,不是某个具体网络结构有多强,而是整个领域对待问题的方式发生了根本变化。传统方法时代,我们总想着怎么更巧妙地描述世界,设计特征、设计模板、设计规则;深度学习时代,我们更倾向于让模型自动从数据里找规律。这个转变让很多老问题迎刃而解,但也带来一个副作用:现在的人越来越不关心方法底下的机理了,出了问题只会调参或者加数据。

我的建议是,把二十年的发展史当成一个工具库来用。传统方法里的很多概念,比如尺度空间、候选区域、特征金字塔、难例挖掘,今天依然潜藏在一个个现代模型里。你不需要背下所有模型的细节,但要建立起“每个组件到底在解决什么问题”的意识。有了这个意识,你在做项目时就有判断力:这个场景最重要的是召回还是精确,是速度还是小目标能力,然后顺着历史里那些经典方案的思路去找解药。

最后分享一个小习惯:每次拿到一个新的检测新方案,我会先问三个问题。第一,它解决了老方案的哪个痛点;第二,它引入了什么新限制;第三,如果我要在资源受限的机器上部署,它会不会带来额外负担。带着这三个问题去看论文、跑实验,比盲目追新模型效率高得多。目标检测这二十年的历史其实就是一个很好的学习框架,每篇经典工作都在回答你怎么在前人的坑上面再进一步。读懂这些,你踩过的坑就会少很多,遇到问题也更清楚该往哪里找答案。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询