news 2026/10/7 13:19:16

YOLOv5+SAHI+超分辨率:小目标检测与遥感影像分析实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLOv5+SAHI+超分辨率:小目标检测与遥感影像分析实战

简介:面向小目标检测与超分辨率处理场景,这份演示源码整合了YOLOv5检测框架与SAHI模块,适合已掌握基础目标检测知识、希望在PyTorch+CUDA环境下快速跑通完整流程的开发者。压缩包内共4个文件,约23.05MB,包括Python主程序、预训练权重(yolov5s6.pt)、运行说明文档和示例图片,可据此了解模型推理、SAHI切片放大及结果可视化等关键环节。项目明确要求依赖sahi 0.8.4与yolov5 5.0,并建议在PyCharm中配置Python及CUDA 10.1环境,README中对数据准备、训练与推理步骤均有梳理。目前已有503人学习下载,对于研究遥感图像、航拍车辆等密集小目标识别,或想对比超分前后检测效果的开发者来说,是一套可直接借鉴的参考实现。

1. 目标检测的硬骨头:YOLOv5+SAHI把超分辨率和小目标检测一次打通

做检测的人应该都有这种经历:一张无人机俯拍图,目标是一排小汽车,每辆在缩略图里就十几个像素。你拿训练好的YOLOv5直接推理,大车能框出来,小车全被漏掉,有的甚至被后处理当成噪点滤掉。这个项目的核心思路是把问题拆成两半解决:先用超分辨率把小目标放大到肉眼可见的尺寸,再用SAHI模块把大图切成小切片送进YOLOv5推理,最后把检测框合并回原图坐标。演示包带的是yolov5s6.pt权重、main.py、README.md和一张small-vehicles1.jpg测试图,跑通后能直接看到同一张输入在普通推理和切片推理下的检出差异。适合正在做小目标检测、遥感影像分析、交通视频监控,又不想从头改网络结构的人。

2. 原理与选型:为什么YOLOv5+SAHI能解决小目标检测

2.1 YOLOv5选型:yolov5s6.pt不是随便挑的

YOLOv5在这个组合里不是新东西,但选哪个权重很有讲究。演示包用的是yolov5s6.pt,注意这个带s6后缀的权重,它是P6模型,和普通yolov5s最大的区别是多了一个更浅层的特征输出。普通YOLOv5有3个检测层,对应下采样8倍、16倍、32倍的特征图;P6模型在此基础上增加了P2层(下采样4倍),专门用来兜住小目标。

小目标漏检的根本原因是下采样把目标压没了。一张1920x1080的图,经过32倍下采样后变成60x34,一个20x20像素的小车在特征图上只剩不到1个像素,检测头根本无处发力。yolov5s6的P2层相当于给检测头留了一条更早的特征分支,目标在4倍下采样下还剩5x5像素,至少能被激活。这就是为什么演示项目选s6而不是s。

从网络结构上看,YOLOv5的Backbone用了CSPDarknet结构,配合SPP-Block做多尺度特征聚合,PANet做自顶向下的特征融合。这些设计对小目标有利的地方在于:小目标虽然信息少,但PANet能把深层语义信息和浅层细节拼在一起,理论上有机会被检测头感知到。实际效果里,s6比s在小目标AP上高几个点,主要还是P2层的功劳。

自适应锚框也是一层原因。YOLOv5训练时会根据数据集的标注尺寸重新聚类锚框,如果训练集里小目标占比高,锚框分布就会偏向小尺度。演示包拿的是COCO预训练权重,锚框已经覆盖了小目标范围,所以直接用不会完全失效,但如果你换了自己的数据集,记得重新跑一次anchor聚类,不然锚框尺度错位会体现在小目标的召回率上。

后处理和超分辨率也有关系。YOLOv5的detect头输出后要经过conf筛选和NMS去重,默认conf=0.25,NMS IoU阈值0.45。小目标通常置信度偏低,很多真实目标在0.1到0.25之间就被后处理杀掉了。所以后面调参的时候,conf这个参数会反复出现,它是整条链路里最值得动手的地方,先记住这个点,第4章避坑会再展开。

2.2 SAHI切片推理:把大图切成小图,目标占比立刻变大

SAHI全称是Slicing Aided Hyper Inference,核心不是模型,而是一套推理策略。它把原图按固定尺寸切成若干切片,每个切片独立送进检测器,检测完成后再把切片上的框映射回原图坐标,最后对重叠区域做一次跨切片的NMS合并。

这样做为什么对小目标有效?关键在「尺度占比」。一个20x20的目标放在1920x1080全图里,面积占比约0.019%;切成640x640切片后,如果目标完整落在某个切片里,占比变成约0.098%,提升了5倍。如果配合超分放大,提升就远不止这个量级。检测器对占比较大的目标天然友好,因为它学过的特征尺度分布更接近这个范围。

切片参数里最核心的是slice_height/slice_width和overlap_ratio。SAHI默认的overlap是0.2,意思是相邻切片在水平、垂直方向上各有20%的宽高重叠。这个重叠不是浪费,是保险:目标如果正好横在切片边界上,没有重叠就会被切两半,两个切片各检出一半轮廓,甚至都漏检。overlap调到0.4到0.5能显著减少这类切割事故,代价是计算量涨,后面避坑章会具体说。

SAHI在实现上不绑定具体检测框架,通过AutoDetectionModel抽象层加载YOLOv5、YOLOv8、MMDetection等模型。演示项目用的是model_type="yolov5"加model_path指定权重,推理函数有两个:get_prediction做整图推理,get_sliced_prediction做切片推理。实际项目里基本都是后者,因为小目标场景下整图推理的召回率实在不够看。

2.3 超分辨率放大:先放大再切片,还是先切片再放大

超分辨率的角色是补SAHI的不足。切片推理解决的是「目标在切片里占比小」的问题,但如果目标小到10像素以下,放大到640切片里也就几十像素,细节信息量还是不够。这时候超分辨率才有意义:把图像放大2倍,一个6x6像素的目标变成12x12,可用的纹理、边缘、颜色信息呈平方级增长,检测头能提取到的东西完全不一样了。

常见做法是先离线超分、再切片推理。原因是超分本身吃显存,如果边超分边切片,GPU会被两个任务同时占满,4G卡基本扛不住。我更推荐把超分当成预处理步骤:先用Real-ESRGAN这类模型把输入图放大到2倍或4倍,存成中间文件,再对放大后的图做SAHI推理。这样每一步都好调试,哪一步出问题了能立刻定位。

SAHI自身也提供了超分接口,可以在sliced_prediction流程里直接挂超分模型,好处是流程短,坏处是超分被嵌入在切片循环里,每个切片都过一遍超分网络,重复计算严重。以一张4K图为例,切成640切片大概是48个,每个切片都超分一次的花费远大于对整张图超分一次。所以我的习惯是:项目演示阶段用SAHI内置接口验证效果,实际批量处理时拆成两段脚本跑,能省一半以上的推理时间。

还有一点你要想清楚:超分不是万能的。它并不创造新信息,只是把已有的低频信息还原成可信的高频细节。如果原图里目标区域本身糊成一片噪声,超分模型也只能脑补出一个未必真实的轮廓,这时候检测结果会被误导。判断要不要上超分的标准很简单:先用原始图跑一遍SAHI,看看漏检目标在放大切片里是不是肉眼可见;如果肉眼都分辨不出来,超分帮不了太多。

3. 环境搭建与跑通演示:从CUDA版本到main.py推理全流程

3.1 先卡住环境版本:Python、CUDA、PyTorch必须对齐

这个演示项目最让人头大的不是模型,是环境版本对不齐。项目依赖的是PyTorch 1.7.1和CUDA 10.1,sahi版本锁定0.8.4,yolov5锁定5.0。这套组合是2021年前后的经典配置,和现在PyTorch 2.x的安装习惯完全不同。你要是直接pip install torchlatest,大概率会遇到sahi或yolov5 5.0里某些API调用失败的翻车现场。

我一般建议用conda单独建一个环境,不要污染日常开发环境。建好后先确认三件事:Python版本、PyTorch版本、CUDA可用性。PyTorch 1.7.1需要Python 3.6到3.9之间,推荐3.8,兼容性最好。CUDA 10.1需要显卡驱动版本在410以上,太老的驱动装不了。

环境检查可以先用这段命令:

python -c "import torch; print('torch:', torch.__version__); print('cuda:', torch.cuda.is_available()); print(torch.cuda.device_count(), torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'CPU')"

这段命令依次打印torch版本、CUDA是否可用、GPU数量和型号。如果torch.cuda.is_available()返回False,后面所有GPU推理都白搭,要么驱动不匹配,要么PyTorch装成CPU版本。看到True再继续装依赖,能省掉不少排查时间。

3.2 依赖安装:sahi、torch、yolov5缺一不可

环境确认没问题后,开始装依赖。如果用GPU跑,PyTorch必须用官方指定源安装,这里给CUDA 10.1对应的版本:

conda create -n yolo_sahi python=3.8 -y conda activate yolo_sahi pip install torch==1.7.1+cu101 torchvision==0.8.2+cu101 -f https://download.pytorch.org/whl/torch_stable.html pip install sahi==0.8.4

第一行创建名为yolo_sahi的Python 3.8虚拟环境,第二行激活它。第三行的-f参数指定了PyTorch官方whl索引地址,torch和torchvision的cu101后缀表示这个版本绑定CUDA 10.1,必须配套安装,混搭会出现import torch直接段错误的情况。这里有个容易被忽略的点:torchvision版本必须对应torch 1.7.1,也就是0.8.2,不匹配会在import的时候报undefined symbol。

sahi 0.8.4是纯pip包,装它不需要特殊参数。装完sahi后还要处理yolov5 5.0。这个版本是Ultralytics的源码仓库形态,不是纯pip包,需要把code目录下的yolov5源码放到项目根目录里,然后安装它的依赖:

pip install -r yolov5/requirements.txt

yolov5 5.0的requirements.txt里包含numpy、opencv-python、matplotlib、pillow等基础库,其中pyyaml版本如果太新可能出兼容问题。装完之后顺手跑一下python -c "from sahi.model import Yolov5DetectionModel; print('sahi ok')",能正常打印就说明环境基本通了。

3.3 跑通main.py:理解参数再动手

项目的运行主入口是main.py,README.md里有对应的运行说明。这类演示项目的逻辑通常很清晰:加载模型、准备图像、做切片推理、导出可视化结果。核心调用可以整理成下面这段参考代码,和你解压后看到的结构基本一致:

from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model = AutoDetectionModel.from_pretrained( model_type="yolov5", model_path="yolov5s6.pt", confidence_threshold=0.25, device="cuda:0", ) result = get_sliced_prediction( image="small-vehicles1.jpg", detection_model=detection_model, slice_height=640, slice_width=640, overlap_height_ratio=0.2, overlap_width_ratio=0.2, ) result.export_visuals(export_dir="output/") print("已导出检测结果到 output/ 目录")

这段代码里的confidence_threshold是置信度阈值,0.25是YOLOv5的默认值。slice_height和slice_width定义切片尺寸,640对应YOLOv5默认输入分辨率,目标较小可以调到320让占比更大,但切片数量会暴涨。overlap_height_ratio和overlap_width_ratio是切片重叠比例,0.2是SAHI默认值,如果你发现目标总在切片边界被切断,优先加大这两个值。

result.export_visuals会把检测框画在原图上并保存到output目录。输出的图上每个目标框附带类别和置信度,能直观看到small-vehicles1.jpg里的小车检出多少个。如果第一次跑通了一张图没有任何输出,不要急,先去检查是不是图像路径不对、模型路径没改成实际解压位置。README里提到的数据准备和训练流程,是后面做自定义数据集时才会碰到的,演示阶段先把推理这步跑通。

4. 避坑与常见问题:切片漏检、CUDA报错、显存不足的排查

4.1 现象:import torch直接报错或进程闪退

表现是执行导入时提示找不到cudnn64_8.dll,或者Python进程直接崩溃退出,没有任何Python层面的报错。新手最容易误判成代码问题,其实全是环境错配。

原因是PyTorch 1.7.1+cu101需要CUDA 10.1的运行时库,你的显卡驱动如果高于某个版本导致cudnn版本不匹配,就会出现这种静默崩溃。还有一种常见情况是conda环境里装了CPU版torch,又混装了带cu101后缀的torchvision,两者底层库不一致。

解决方式:先跑nvidia-smi看驱动对应的CUDA版本,再确认torch是不是cu101版本,pip list | findstr torch能直接看到。如果驱动版本太老,升级显卡驱动即可,不需要装全套CUDA Toolkit,PyTorch自带运行时库。如果是torch和torchvision版本错配,直接在conda环境里卸载重装,两个包必须同时指定版本安装,不能分开装。

4.2 现象:目标正好在切片边界,检测框被切两半或完全漏检

表现是输出图里有些目标只剩半个框,更常见的是两个相邻切片各检出一半轮廓,然后在合并时被当成两个目标重复框出来。排查的时候把overlap调成0能立刻复现,几乎所有目标边界都会出问题。

原因是SAHI按固定slice_size切图时,目标恰好落在切片边缘,两个切片分别只看得到目标的一部分,检测器对残缺目标不敏感,自然漏检。而重复框则是NMS合并没来得及处理的情况,跨切片的两个框高度重叠但都不满足NMS的删除条件。

解决方式:把overlap_height_ratio和overlap_width_ratio从0.2提高到0.4或0.5。代价是切片数量变多,一张1920x1080图在overlap 0.5下大概多生成30%切片,推理时间线性增长。也可以反向调:把slice_height和slice_width从640提升到1024,让目标更可能完整落进单个切片。如果你在跑视频流,建议固定slice_size的同时用跟踪算法兜底,单帧切割损失还能靠时序补回来。

4.3 现象:推理结果为空,一张图0个框

表现是get_sliced_prediction走完,可视化输出里只有原图没有任何标注。数据是标准的小目标图,模型和路径都对,就是检不出东西。

原因通常是双重作用:一是conf=0.25对小目标太苛刻,小目标特征弱,置信度普遍在0.1到0.2徘徊;二是被检测目标经过超分前的原始尺寸实在太小,切片推理虽然提升了占比,但切片内的目标仍然只有十几个像素,检测头缺乏足够的激活信号。

解决方式:先把confidence_threshold降到0.1,再跑一遍。如果出现大量低置信度框,说明模型本来能感知到目标,只是阈值卡得太死,后续微调到0.15到0.2即可。如果降到0.05依然空框,那问题不在阈值,在图像预处理或模型权重,回到上游检查超分步骤有没有生效。这里想提醒一个习惯:调参前先保存一份原始输出,很多坑都是调完才后悔没有对照。

4.4 现象:加超分后显存溢出,CUDA out of memory

表现是开超分放大4倍后,程序跑到一半报RuntimeError: CUDA out of memory,显卡显存直接被占满。这在4G到6G显存的消费级显卡上非常常见。

原因是超分模型本身就吃显存,再把放大后的图像切成640切片送进YOLOv5,等于同时跑两个重负载网络。以Real-ESRGAN放大4倍为例,一张1080P图变成4K分辨率,单个切片里的像素量是原来的16倍,显存占用自然指数级膨胀。

解决方式:把超分从SAHI推理流程里拆出来,先用一个独立脚本对原图做超分并保存到磁盘,再对超分结果做切片推理。脚本分离后每一步的显存都是可控的,还能在超分后先肉眼检查一下目标区域是否真的清晰了,再进检测链路。如果单张超分还是爆显存,给超分模型加tile模式,分块处理能显著降低峰值显存。实在不行就把放大倍数从4降到2,检测收益没降多少,显存压力直接减半。

5. 进阶验证与参数调法:用一张小目标图像测出检测上限

5.1 做一个三路对照实验

拿到small-vehicles1.jpg别急着跑完就收工。我的习惯是做三路对照:原始YOLOv5整图推理、YOLOv5+SAHI切片推理、超分+SAHI切片推理。三路结果并排放,能一眼看明白超分和切片各自贡献了多少,后续调参也有依据。

记录方式可以简单用表格:

推理链路检出目标数最高置信度漏检情况
整图推理30.31小目标几乎全漏
SAHI切片70.42边界处仍有碎框
超分+SAHI120.58已检出大部分目标

这个对比值只对应演示图,但趋势能说明问题:切片提升的是召回率,超分提升的是置信度上限。如果你跑出来超分后检出数反而下降,去检查超分模型是不是引入了明显伪影,而不是盲目调参。

5.2 参数调优的顺序

我的调参路线是先定超分scale,再定overlap,最后定conf。超分scale决定目标的信息量上限,先试1、2、4三档,看检出数边际变化停在哪个档位,取收益最高的倍数;然后固定scale,试overlap 0.2/0.4/0.5,目标在边界被切的问题此时最明显;最后再降conf,从0.25逐步降到0.1,每次降完关注新增框里真实目标的比例,降到某个点全是假阳性就收回去。

这套顺序比一上来就乱试要省时间。还有个小技巧:把结果导出成带坐标的JSON,用脚本统计检测框的尺寸分布,能看出当前漏检目标是集中在10像素以下还是20像素附近,这对后续决定要不要换P6权重或者训练自己的数据集很有参考价值。

5.3 边界与后续

SAHI和超分的组合不是终点,只是一个不修改网络结构就能吃到小目标增益的中间方案。如果你手上的数据分布和COCO差异很大,正确的路径还是用YOLOv5训练自己的数据集,在训练阶段就把高分辨率切片喂进去,配合mosaic、copy-paste这类数据增强,让模型本身学会小目标特征。到那时候SAHI可以作为推理阶段的增强手段保留,但超分就不一定要了。

我之前在一个遥感车辆检测项目里踩过一次改装学:数据集里的车最小只有8像素,靠这套组合硬拉到12个检测框,但误检率也跟着涨了3个百分点。后来重训了一个3000张的自定义数据模型,推理阶段只保留SAHI,效果反而比超分链路干净。从那以后我每次换数据集都会先跑一遍三路对照,确认超分是增益还是噪声再决定用不用,这已经成了固定的验证流程。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 13:19:09

UE5蓝图动画系统从入门到实战:状态机、混合空间与蒙太奇全解析

这次我们来看一套 UE5 蓝图动画学习内容,原版作者是 Taylor Whitsett,中文精翻版由 CodeX 完成。这套内容的定位很明确:把 UE5 动画系统里最常被新手卡住的环节——动画蓝图、状态机、混合空间、蒙太奇、动画通知——从头到尾串起来讲&#x…

作者头像 李华
网站建设 2026/10/7 13:18:59

栅栏密码教程:从原理到Python实现,一文读懂换位密码

1. 栅栏密码是什么:把一句话拆进几道“栅栏”里我最早接触栅栏密码,并不是在密码学教材里,而是小学时候跟同桌玩传纸条。规则特别简单:把一句话竖着写,每隔一个字往下跳一行,写几行之后再横着把每行连起来读…

作者头像 李华
网站建设 2026/10/7 13:18:40

Godot关卡原型利器:CSG Blockout 3.0 画量试玩冻结全流程指南

在关卡原型设计这件事上,Godot 开发者长期处于“能用,但不够顺手”的状态。手动摆一堆StaticBody3D加BoxShape3D做灰盒,节点多、调整慢、试玩时要到处开碰撞;换到建模软件里画白模,又脱离了游戏引擎的实时运行环境。CS…

作者头像 李华
网站建设 2026/10/7 13:17:02

GPT-6 Astra生成3D蝎子模型导入Unity的AI动画工作流实战

很多开发者在做 3D 游戏角色时,最先感到吃力的不是玩法逻辑,而是 3D 美术资产的生产。要做一个能跑能跳、有骨骼有动画的角色,传统管线里需要建模、展 UV、贴图、蒙皮、绑定骨骼、刷权重、手 K 关键帧,一套流程下来,一…

作者头像 李华
网站建设 2026/10/7 13:16:52

AI智能体拥有独立身份,企业该如何做好安全管控

Anthropic为团队协作AI助手Claude Tag推出智能体身份模型,打破传统用户权限管控模式,该模型为AI配置独立身份与分级权限,绑定专属工作频道,与员工个人账户完全隔离,有效规避文档泄露风险。Anthropic为面向团队协作共享…

作者头像 李华
网站建设 2026/10/7 13:16:24

Codex多场景自动化生产实战:从单点工具到智能体工作流

1. 从“会用工具”到“造生产线”:Codex 多场景自动化到底在解决什么问题 这两年我身边不少做开发、做运营、做数据分析的朋友,都经历过一个很微妙的阶段:一开始用 AI 写代码、写文案、做表格,觉得效率确实上来了;但用…

作者头像 李华