首页 / 资讯中心 / 文章详情

大图小目标检测难题:切图训练原理与实战指南

大图小目标检测难题:切图训练原理与实战指南 ★ FEATURED ARTICLE
大图里的小目标一直是检测任务里最让人头疼的问题之一。很多人上来就调模型、换骨干网络折腾半天发现提升有限其实往往忽略了最根本的矛盾一张几千乘几千的图直接缩放到模型输入尺寸小目标可能就剩几个像素了特征早丢光了。我自己的实践里最简单、最直接、也是效果最稳的方案反而是回归本质——把大图拆成小块去训练。标题里提到“将图片拆成四个分开去放到目标去训练”这个思路完全正确而且它背后其实有一套完整的方法论不只是“切成四块”这么简单。这套做法的核心逻辑就是用小图训练、大图推理让小目标在模型眼里从“看不见”变成“看得清”。它不需要改模型结构不需要上多卡大规模分布式训练也不需要搜集额外的数据纯粹从数据预处理和推理后处理两个阶段入手就能把很多小目标场景的检测精度拉上来一大截。我自己在航拍图像、高清监控截图、扫描文档这些场景里都验证过切图方案带来的mAP提升往往比换一个更大的模型还明显。这篇文章我就围绕“大图小目标检测”这个主题把切图训练这套方法从原理到实操完整拆开讲。适合刚接触目标检测、正在被大图小目标折磨的开发者参考也适合已经在用切图但效果不理想、想优化细节的读者对照排查。我会把切图尺寸怎么定、标签怎么跟着切、推理时怎么拼回去、NMS怎么合并这些关键环节全部展开包括我踩过的坑和实测数据尽量做到你看完能直接照着复现。1. 问题本质大图小目标检测为什么这么难1.1 缩放导致的特征消失先看一张典型的大图检测场景。比如一张无人机拍的城市俯瞰图分辨率是5472x3648里面的车辆目标可能只有30x30像素左右。如果模型输入尺寸是640x640那整张图缩放后一辆车就变成了大约3.5x3.5像素——几个像素在卷积网络里经过几次下采样到深层特征图上可能连一个点都不到了。这种情况下任何检测头都无从谈起。问题本质上是信息量被压缩了。检测模型能“看到”的最小目标取决于输入分辨率下目标占的像素面积以及骨干网络的下采样倍数。以常见的YOLO系列为例输入640时特征图最大尺寸是80x80对应下采样8倍一个目标至少要在特征图上占据1个点才有响应算下来目标在原图中至少要有8x864个像素实际上建议至少16x16以上才能稳定检出。而大图缩放到640之后30x30的车辆就是这样被“抹掉”的。1.2 直接暴力切图也有问题既然大图直接缩放不行为什么不直接把大图按640尺寸切成几十块全部送进去训练和推理理论上完全可行这也是切图方案的雏形。但实际操作中会发现很多新问题一个目标恰好被切在边界上两半分别落在两个切片里两边都只剩一半特征模型很难判断这是什么。切出来的子图数量庞大训练时如果全部参与每个epoch跑的步数会激增反而拖慢收敛。大量切片是背景区域没有目标负样本比例失衡模型容易产生误检。推理时切片之间重叠区域的目标会被重复检出合并结果时如果处理不好会出现很多重复框。所以切图绝对不是“直接切成N份丢进去训练”这么简单。标题里说的“拆成四个”其实代表的是一个思路但真正要落地需要解决切片设计、标签同步、推理合并这三个核心问题。1.3 为什么切图能起作用从模型的角度来看切图起作用的本质是它把“在一张超大图上找小目标”的问题转换成了“在若干张分辨率适中的图上找中等大小目标”的问题。原本30x30的目标直接缩放后剩3.5x3.5但切成640的切片后如果目标完整落在一个切片里它依然是30x30在模型输入中占据的像素比例大大提升特征自然清晰得多。这其实是在变相“放大目标”而不是靠模型硬撑。另一个角度理解切图相当于人为制造了更多高分辨率的训练样本让模型见过更多“清晰”的小目标形态比在低分辨率图上硬学那些模糊的马赛克块要有效得多。2. 切片方案设计不只是切成四块2.1 核心原则切片尺寸要和模型输入匹配切片尺寸怎么定直接决定了方案的上限。我自己惯用的原则是切片尺寸尽量等于或略大于模型的设计输入尺寸。比如模型设计输入是640x640那切片就切成640x640如果是608就切成608。这样切出来的子图可以直接进模型不需要额外缩放信息无损。为什么不建议切片尺寸大于模型输入比如切成1280x1280再缩放到640效果其实和直接缩放整张图差不多该丢的信息还是丢了还多了一道预处理开销完全没有意义。至于“切成四块”这个具体说法要看原图尺寸。如果原图是2560x2560切成四块就是每块1280x1280这个尺寸对很多模型来说还是偏大需要进一步处理。所以“四块”更多是一个比喻意思是把大图切成模型能直接“吃下”的子图具体切多少块取决于原图尺寸和模型输入尺寸的比值。2.2 重叠区域Overlap的设计切图训练最容易被忽视但又极其重要的参数是切片之间的重叠率。为什么需要重叠回到1.2里提到的边界问题。如果不设置重叠一个目标恰好横跨相邻两张切片的边界就会同时被切断两边各留一半模型训练时既学不到完整特征推理时也会因为两边都信息残缺而漏检。重叠率怎么设我的经验是切片尺寸的10%到20%作为重叠区域。比如切片640重叠64到128像素。这个数值在大多数场景下能保证目标不会轻易被切断又不会引入太多重复计算。为什么是10%-20%而不是更多因为重叠率越高推理时重复计算的区域越大耗时越多——比如重叠率30%时相当于每张图要多算接近一半的像素量推理速度明显下降。而且在特征比较密集的场景中过高的重叠还会导致同一目标在多个切片中被反复检出NMS处理难度加大。2.3 自适应切片按目标尺寸反推如果你要处理的场景目标尺寸差异很大也可以用一种更精细的自适应切法。先统计训练集中目标框的面积分布特别是小目标的尺寸区间。然后设定目标切片尺寸至少是最大小目标尺寸的4到5倍保证目标在切片内占比合理不会出现一个切片里全是同一个目标的极端情况且切片尺寸不能超过模型输入分辨率太多。这个说法比较绕总结成实际操作就是如果小目标集中在32x32左右切片建议至少128x128以上。如果模型输入是640切片尽量不超过640太多比如可以选512或640。目标尺寸分布很散时可以做一个简单的统计分析统计所有标注框的宽高分布取小目标群的尺寸上界乘以4再往最近的模型输入尺寸上靠。这个方法适合目标尺寸跨度极大的数据集能避免固定切片尺寸下“目标太小学不到、目标太大占满全图”的两难。2.4 训练还是只用切片不用原图我在一些开源项目里看到过“原图切片混合训练”的做法即部分epoch用原图训练部分用切片训练。这种做法有一定合理性比如能保留模型对全局语义的理解但实践中我发现混着训练容易让模型在两种数据分布间摇摆收敛不稳定而且如果原图缩放到输入尺寸小目标又变回模糊状态反而干扰学习。我的建议是如果场景目标普遍偏小直接全部用切片训练别混原图。如果场景中既有大目标又有小目标非要混合那也要用“切片为主、原图为辅”的比例比如每4个step里3个用切片、1个用原图并且原图分支的loss权重适当降低。3. 标签切分与数据集准备3.1 坐标变换一套公式解决切片之后最关键的步骤就是让标注框也跟着切片坐标“搬家”。这是整个流程里最容易出错的地方。假设原图尺寸是W x H切片起点是(offset_x, offset_y)切片尺寸是crop_w x crop_h。对于原图中的任意标注框(x1, y1, x2, y2)在切片中的新坐标就是nx1 max(x1, offset_x) - offset_x ny1 max(y1, offset_y) - offset_y nx2 min(x2, offset_x crop_w) - offset_x ny2 min(y2, offset_y crop_h) - offset_y这段代码看起来简单但重点在后面两步判断如果nx1 nx2或ny1 ny2说明这个框和当前切片完全没有交集目标在切片外面直接丢弃。计算裁剪后框的面积如果剩余面积小于原框面积的某个比例比如50%也建议丢弃。第二步的判断逻辑值得斟酌这里面的关键问题是目标被切掉一大半时还要不要保留这个残缺的标注框我的做法是如果剩余面积小于原来的30%直接丢弃这个框在30%-70%之间保留但给它降低标签权重如果框架支持的话超过70%正常保留。为什么不全部保留因为训练时模型见过太多“半截目标”会学出错误的形状先验推理时反而会把完整目标误判成两个半个的。3.2 要不要保留切片内的空标注图片切片之后会有大量子图不包含任何目标纯背景。这些图对训练有用吗有用但物极必反。纯背景图能帮助模型减少误检学习背景和目标的区分但数量太多会让训练变得极其低效——大量step都在学“这里什么都没有”特征提取器得不到有效更新。我的建议是纯背景切片不全部保留按一定比例随机采样保留。比例取决于场景复杂度简单场景比如空地上少量车辆保留10%-20%就够复杂场景街道、密集人群可以保留到30%。为什么不能完全不要背景切片如果你只保留含有目标的切片训练集和推理时的数据分布就不一致——推理时模型看到的是一整张大图切出来的所有区域包括大量背景区训练时却从没见过纯背景切片很容易在背景区域产生大量误检。3.3 数据增强在切片层面的爽点切图方案在数据增强上有一个天然优势你可以在切片层面做很多原图层面做不到的操作。比如原图上一辆车只有30x30你没法对它做随机旋转因为旋转后背景信息占主导但切片是640x640的目标在里面占的比例明显更大可以放心做旋转、缩放、平移、颜色扰动等常规增强。特别是马赛克增强Mosaic在切片训练中效果非常突出。因为切片是从大图里裁出来的纹理丰富把4张切片拼成一张新图做增强目标密度和多样性都更高模型的鲁棒性会明显提升。我在项目中实测过单独切图训练比直接原图训练mAP高约8-12个点切图Mosaic增强又比只切图高3-5个点。这部分收益几乎不需要额外付出。4. 推理阶段切片预测、坐标还原与合并4.1 推理流程全景训练完成后推理阶段和训练阶段有一个关键区别训练时切片尺寸和数量是固定的推理时必须动态决定切多少块、重叠多少然后逐块预测再把结果映射回原图坐标。完整流程如下读取大图获取原图尺寸。根据预先设定的切块尺寸和重叠率计算切片起点的网格位置。按网格顺序切出所有子图逐个送入模型预测。将每个切片中预测出的框坐标加上对应切片的偏移量映射回原图坐标。所有切片的预测结果汇总后做一次全局的NMS非极大值抑制消除重复检测框。4.2 为什么要做两次NMS这里有一个值得注意的细节切片内预测时如果模型自带NMS处理那每个切片内部已经去重了但切片之间重叠区域的目标会在相邻切片中被重复检出——因为同一个目标在切片A里是完整的在切片B的重叠区域里可能还是完整的两边都会打出高置信度的框。所以合并时必须要做一次“全局NMS”。坐标已经被映射回原图所有框都在同一坐标系里用常规IOU阈值比如0.5做一次非极大值抑制把重复框去掉。我试过省略全局NMS直接输出所有框结果是同一辆车被标了2到3个框视觉上非常乱而且下游应用比如计数、跟踪会被严重干扰。所以全局NMS不能省。4.3 边界处理目标被切在边缘怎么办推理时有一个训练阶段不太会遇到的问题目标恰好落在切片边界上一半在切片A里一半在切片B里。因为设置了重叠区域很多这类目标会在某个切片里保留完整形态但有些恰好落在重叠区域之外的边界上就可能只剩一半。处理办法一般是给拼接回原图的坐标加一个“边界安全偏移”。具体操作是映射框坐标时如果框的某一边贴着切片边界距离小于某个阈值比如5像素就把这个框的置信度乘一个惩罚系数比如0.8降低它对最终结果的影响。这个技巧能有效减少边界残缺目标产生的低质量预测框。4.4 推理性能优化切图推理最大的副作用是计算量增加。比如一张5472x3648的图切成640x640、重叠128大概会切成80到90块每块都要跑一次模型前向耗时明显高于直接缩放推理。优化方案主要有三个如果目标尺寸分布允许适当增大切片尺寸比如从640提到960或1280减少切片数量但此时输入模型的图会被轻微缩放收益和损失需要权衡。我实测过1280输入相比640输入小目标精度还能再涨3-5个点但显存和时间消耗也会翻倍。用TensorRT等加速框架对模型做推理优化可以抵消一部分多切片的开销。设置置信度阈值过滤低分框减少后续NMS处理量但训练时输出的低置信度框数量本身取决于模型质量这个优化幅度有限。5. 常见问题与坑点实录5.1 模型检出的框有偏移/坐标不准这个问题的根源几乎都是标签切分时坐标变换出了问题。特别是用了某些数据增强库时增强操作的顺序和坐标变换的顺序不一致会导致标签和图像错位。排查方法是随机挑几张切片图把切分后的标注框直接画在切片图上保存下来肉眼检查——如果框和目标位置对不上先检查坐标变换代码再检查增强流程是否对标签同步生效。5.2 目标在推理时漏检如果训练是切图训练的推理也是切图推理的目标却漏检了优先排查两点推理时切片尺寸和训练时是否一致。如果训练用的是640的切片推理时擅自改成1024模型看到的尺度分布变了小目标可能就检不出来了。保持训练推理一致是第一原则。重叠率是否足够。如果推理时重叠率设置过低某些目标可能恰好落在两块切片的边界缺口里两边都不完整导致漏检。把重叠率适当提高比如从10%提到20%通常能缓解。5.3 推理结果框太碎/同一目标多个框这种情况几乎可以断定是全局NMS缺失或IOU阈值设置不当。先检查合并逻辑是否做了全局NMS再确认IOU阈值是否合理。目标密集场景中阈值设得太高比如0.7以上可能无法消除相邻切片的重复框设得太低比如0.3又可能把两个相邻的真实目标合并成一个。我通常从0.5起步根据可视化结果微调。5.4 显存不够用切片尺寸本身不大但如果你在推理时把几十个切片一次性放进batch里跑显存就会爆。解决办法很直接把推理batch size调小甚至逐张切片推理。或者用流式处理每次只加载部分切片到GPU计算算完释放再算下一批。5.5 训练时间极长切片训练的数据量确实会膨胀。比如原图5000张每张切80块就是40万张训练图单卡训练一个epoch的耗时极其可观。我的经验做法是在数据加载阶段做在线切图每次训练时实时从原图中切片而不是离线把所有切片存成文件。这能大幅节省磁盘空间同时利用数据加载器的多进程并行让切图操作和GPU计算重叠。如果训练进程还是太慢可以按比例随机采样切片比如每张原图只随机取其中的30%切片参与训练用更少的数据量换取更快的迭代速度精度损失通常在可接受范围内。6. 进阶扩展从“切成四块”到更优雅的方案6.1 多尺度切图大小切片配合固定单一尺寸切图目标形状差异大的时候会顾此失彼。一个可选的扩展方案是同时用两种切片尺寸训练比如主力用640的切片辅以1280的大切片两个分支分别预测合并时统一映射回原图坐标再做NMS。这个方案的好处是1280切片能保住更大的目标和上下文语义信息640切片对小目标更敏感两者互补。缺点是训练和推理的计算量都会进一步增加。如果你的场景目标尺寸跨度确实大这个方案值得尝试。6.2 切片与检测头的配合前面聊的都是数据层面的方案如果你的项目允许改模型可以再进一步在检测头里加上对目标尺寸的先验统计比如给不同尺寸的目标分配不同的特征层。YOLO系列本身就有多尺度检测头但默认分配策略不一定适配你的目标分布。你可以统计自己数据集中目标框的面积分布把大目标分配到浅层特征图小目标分配到深层特征图配合切图方案效果还会往上走一截。6.3 测试时增强TTA与切图结合测试时增强在切图方案里同样可行尤其是多尺度测试同一张切片分别以0.8、1.0、1.2的缩放比例输入模型得到三组预测框映射回原图坐标后合并再做NMS。实测这个操作通常能给小目标检测带来1-2个mAP点的提升代价是推理时间变成原来的三倍。如果对精度要求高、对实时性要求不高这是个很划算的加法。写在最后的个人经验这套方案我已经在好几个项目里实际落地了每次都能稳定提升小目标检测的精度。有一些体会值得单独说说。切图方案真正要做好的核心就三件事切片尺寸跟模型输入对齐、标签变换不出错、推理合并时要保持和训练一致。这三件事做到位方案就成了一大半。另一个容易忽略的点是评估方式。切图训练后的模型不要再拿原图缩放的预测结果对比——如果推理时没有用切图模型在小目标上的表现可能反而更差这不是方案的问题是评估流程没跟上。我建议评估时保持“训练怎么切推理就怎么切”的完整一致性。最后再分享一个小技巧如果你在调试阶段觉得切图后效果不明显可以先可视化一批切片和对应标签确认切图质量没问题再往下走。很多人一上来就调参结果问题出在坐标变换写错了白白浪费时间。大图小目标检测没有银弹但切图训练这套方法是我试过的所有方案里性价比最高、最不会出错的一种。希望对你有帮助。
阅读完成 · 觉得有帮助?
咨询建站