【YOLOv8-Ultralytics】 【目标检测】【v8.3.235版本】 模型专用预测器代码predict.py解析
【YOLOv8-Ultralytics】 【目标检测】【v8.3.235版本】 模型专用预测器代码predict.py解析
·
【YOLOv8-Ultralytics】 【目标检测】【v8.3.235版本】 模型专用预测器代码predict.py解析
文章目录
前言
代码路径:ultralytics\models\yolo\detect\predict.py
这段代码是 Ultralytics YOLO 框架中目标检测模型专用预测器 DetectionPredictor 的核心实现,继承自基础预测器 BasePredictor,专门适配 YOLO 目标检测的推理全流程。其核心作用是将模型输出的原始预测张量,通过「非极大值抑制(NMS)过滤冗余框→坐标缩放还原至原始图像尺寸→结构化封装为 Results 对象」的流程,转换为可直接用于可视化、保存、下游分析的检测结果,同时支持可选的目标特征提取能力,是 YOLO 检测模型推理阶段的核心组件。
所需的库和模块
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
# 从ultralytics引擎预测器模块导入基础预测器基类
# (封装YOLO通用推理全流程,包含多源输入加载(图片/视频/摄像头/批量文件)、图像预处理(归一化/缩放/格式转换)、模型前向推理、结果初步解析等核心环节)
from ultralytics.engine.predictor import BasePredictor
# 从ultralytics引擎结果模块导入Results类
# (结构化封装YOLO推理结果,包含预测框坐标、置信度、类别ID/名称、原始图像张量、掩码(分割任务)等信息,提供结果解析、可视化、格式导出(JSON/CSV)等便捷接口)
from ultralytics.engine.results import Results
# 从ultralytics工具模块导入:非极大值抑制(NMS)函数
# (过滤YOLO推理输出的重复检测框,按置信度和IoU阈值筛选最优框,是检测任务后处理核心步骤)、通用操作函数集(包含检测框缩放(适配原图尺寸)、坐标格式转换(xyxy/xywh互转)、图像拼接/裁剪等推理后处理核心操作)
from ultralytics.utils import nms, ops
DetectionPredictor 类
整体概览
| 项目 | 详情 |
|---|---|
| 类名 | DetectionPredictor |
| 父类 | BasePredictor(YOLO通用预测器基类,封装多源输入加载、图像预处理、模型推理等通用流程) |
| 核心定位 | YOLO目标检测专用预测器,继承BasePredictor通用推理框架,定制检测任务专属后处理流程:NMS过滤冗余检测框、检测框坐标缩放至原始尺寸、目标级特征提取、空结果兼容处理、Results结构化封装、特征向量绑定,支撑检测推理全流程 |
| 核心依赖模块 | ultralytics.engine.predictor(BasePredictor)、ultralytics.engine.results(Results)、ultralytics.utils(nms/ops)、torch(张量/特征处理)、numpy(图像格式转换) |
| 关键特性 | 1. 多模式NMS适配(跨类别NMS/旋转框NMS/端到端模型输出兼容);2. 检测框自动缩放至原始图像尺寸(消除预处理缩放/填充影响);3. 多尺度特征图提取目标级特征(支持下游匹配/检索/重识别);4. 空检测结果兼容处理(避免特征提取/坐标缩放异常);5. 结果结构化封装为Results对象(统一可视化/保存/解析接口);6. 特征向量与检测结果绑定(扩展下游任务能力);7. 多格式原始图像兼容(张量/列表,自动转换为NumPy+通道反转);8. 支持PyTorch/ONNX/TensorRT等多格式模型推理 |
| 典型使用流程 | 初始化预测器→配置参数(conf/iou/max_det等)→加载YOLO检测模型→输入源预处理(图片/视频/摄像头)→模型前向推理→NMS过滤冗余框→(可选)提取目标特征→检测框缩放至原始尺寸→构建Results对象→(可选)绑定特征向量→返回结构化结果(可视化/保存/下游分析) |
1. DetectionPredictor 类属性说明表
| 属性名 | 类型 | 说明 |
|---|---|---|
| args | namespace | 预测器配置参数命名空间,核心参数: - conf:置信度阈值(过滤低置信框) - iou:NMS的IoU阈值(合并重叠框) - classes:指定检测类别(None检测所有) - agnostic_nms:是否跨类别NMS - max_det:单图最大检测框数 - task:固定为"detect" |
| model | nn.Module | 加载完成的YOLO检测模型实例(支持PyTorch/ONNX/TensorRT等多格式) |
| batch | list | 当前处理的批次数据列表,包含图像路径、预处理后张量、原始图像等 |
2. DetectionPredictor 类方法说明表
| 方法名 | 功能说明 |
|---|---|
| postprocess | 核心后处理:执行NMS过滤冗余框→格式转换(张量→NumPy+通道反转)→(可选)提取目标特征→批量构建Results→(可选)绑定特征向量,返回结构化结果列表 |
| get_obj_feats | 从多尺度特征图提取目标级特征向量:统一特征维度→拼接多尺度特征→按NMS索引提取目标特征,支持下游特征匹配/检索/重识别 |
| construct_results | 批量构建Results对象:遍历批次内每张图像,调用单张构建逻辑(construct_result),返回Results列表 |
| construct_result | 单张图像结果构建:将检测框从模型输入尺寸缩放到原始图像尺寸,封装为包含原始图像、路径、类别名、检测框的Results对象 |
预测后处理:postprocess
def postprocess(self, preds, img, orig_imgs, **kwargs):
"""
对模型原始预测执行后处理(NMS+结果结构化),返回结构化Results对象列表
核心逻辑:NMS过滤冗余框→格式转换→特征提取(可选)→构建Results对象→附加特征(可选)
参数:
preds (torch.Tensor): 模型原始预测张量(维度:[B, N, 4+1+NC],4=框坐标,1=置信度,NC=类别数)
img (torch.Tensor): 预处理后的输入图像张量(模型输入格式,已缩放/归一化)
orig_imgs (torch.Tensor | list): 预处理前的原始图像(张量/列表格式,RGB/BGR需适配)
**kwargs (Any): 额外关键字参数(预留扩展)
返回:
(list[Results]): 结构化推理结果列表,每个元素对应单张图像的检测结果(含框、类别、置信度等)
示例:
# >>> predictor = DetectionPredictor(overrides=dict(model="yolo11n.pt"))
# >>> results = predictor.predict("path/to/image.jpg")
# >>> processed_results = predictor.postprocess(preds, img, orig_imgs)
"""
# 判断是否需要保存目标特征:检测是否存在_feats属性(模型推理时提取的特征图)
save_feats = getattr(self, "_feats", None) is not None
# 执行NMS后处理(过滤冗余检测框):
# - conf: 置信度阈值(过滤低置信度框)
# - iou: NMS的IoU阈值(合并重叠框)
# - classes: 指定仅检测的类别(None则检测所有类别)
# - agnostic_nms: 跨类别NMS(单类别/agnostic模式下启用)
# - max_det: 单图最大检测框数量
# - nc: 类别数(0表示自动识别,非detect任务时用模型类别数)
# - end2end: 适配端到端模型的输出格式
# - rotated: 适配旋转框检测(OBB任务)
# - return_idxs=save_feats: 需要提取特征时返回目标索引(用于特征映射)
preds = nms.non_max_suppression(
preds,
self.args.conf,
self.args.iou,
self.args.classes,
self.args.agnostic_nms,
max_det=self.args.max_det,
nc=0 if self.args.task == "detect" else len(self.model.names),
end2end=getattr(self.model, "end2end", False),
rotated=self.args.task == "obb",
return_idxs=save_feats,
)
# 格式转换:若原始图像是张量(非列表),转换为NumPy批次并反转通道(BGR→RGB,适配OpenCV格式)
if not isinstance(orig_imgs, list):
orig_imgs = ops.convert_torch2numpy_batch(orig_imgs)[..., ::-1]
# 特征提取:需要保存特征时,从特征图提取目标级特征
if save_feats:
# 提取目标特征(按NMS返回的索引映射)
obj_feats = self.get_obj_feats(self._feats, preds[1])
# 分离NMS结果(preds[0]为检测框,preds[1]为目标索引)
preds = preds[0]
# 批量构建结构化Results对象
results = self.construct_results(preds, img, orig_imgs, **kwargs)
# 特征附加:将提取的目标特征绑定到Results对象
if save_feats:
for r, f in zip(results, obj_feats):
r.feats = f
return results
| 项目 | 详情 |
|---|---|
| 函数名 | postprocess |
| 功能概述 | 对模型原始预测结果执行NMS过滤冗余框,适配原始图像尺寸,可选提取目标特征,最终构造Results结果列表 |
| 返回值 | list[Results]:每个元素为单张图的检测结果对象(包含框、类别、置信度、特征等) |
| 核心逻辑 | 1. 判断是否提取目标特征;2. 执行NMS过滤预测框;3. 转换原始图像格式(张量→列表);4. 提取目标特征(可选);5. 构造Results结果列表;6. 绑定目标特征到结果(可选) |
| 设计亮点 | 1. 按需提取目标特征,不影响常规预测流程;2. 自动适配原始图像的张量/列表格式;3. 兼容多种NMS配置(旋转框、类别无关、end2end) |
| 注意事项 | 1. 提取目标特征时需确保模型推理过程中保存了_feats特征图;2. 旋转框检测需设置self.args.task="obb",否则NMS逻辑不匹配 |
概念 含义 对应代码控制逻辑 单类别检测任务 整个检测任务仅需识别一种目标(如只检测“人”、只检测“汽车”)。 self.args.single_cls = True单标签预测(每框一类) 每个检测框仅预测一个类别(vs 多标签:一个框预测多个类别,如“人+背包”) nms.non_max_suppression的multi_label参数根据配置自动切换 NMS 的类别处理逻辑,单类别任务强制开启类别无关 NMS 提升效率,多类别任务可手动开启只保留置信度最高的一个以减少重复检测,适配不同检测场景的需求。
模式 逻辑 适用场景 常规NMS(agnostic=False) 按类别分组,对每个类别单独执行NMS;不同类别间的框即使重叠度极高,也不会互相过滤 多类别目标边界清晰的场景(如人、自行车、汽车无重叠),避免误过滤不同类别的合法框 类别无关NMS(agnostic=True) 忽略类别信息,将所有框合并后执行一次NMS;只要框的IoU超过阈值,无论类别是否相同,只保留置信度最高的框 单类别检测、或多类别目标易混淆/重叠的场景(如汽车/卡车、猫/狗),减少重复检测 预测张量形状为 [B, N, 4 + 1 + nc],当 nc=0 时NMS 函数内部会自动从预测张量的维度推断类别数nc
目标特征提取:get_obj_feats
def get_obj_feats(self, feat_maps, idxs):
"""
从模型特征图中提取目标级特征(用于下游任务:特征匹配、检索、重识别等)
核心逻辑:统一特征维度→拼接多尺度特征→按NMS索引提取目标特征
参数:
feat_maps (list[torch.Tensor]): 模型输出的多尺度特征图列表(如8x8、16x16、32x32)
idxs (list[torch.Tensor]): 批次内每张图像的目标索引(NMS返回,映射特征图到检测目标)
返回:
(list[torch.Tensor]): 批次内每张图像的目标特征列表(空列表表示无检测目标)
"""
# 延迟导入(避免推理时未使用特征提取的情况下加载冗余依赖)
import torch
# 找到所有特征图中最短的向量长度(统一特征维度,避免维度不匹配)
s = min(x.shape[1] for x in feat_maps)
# 多尺度特征拼接:
# 1. permute(0,2,3,1): 特征图维度从[B,C,H,W]→[B,H,W,C](通道维度后置)
# 2. reshape: 将通道维度拆分为[s, C/s],便于均值降维到统一长度s,[B,H,W,C]→[B,H*W,s,C/s]
# 3. mean(dim=-1): 对拆分后的维度取均值,将所有特征向量统一为长度s,[B,H*W,s,C/s]→[B,H*W,s]
# 4. cat(dim=1): 拼接多尺度特征(维度:[B, 总特征数, s]),总特征数即不同的尺度H*W的总数
obj_feats = torch.cat(
[x.permute(0, 2, 3, 1).reshape(x.shape[0], -1, s, x.shape[1] // s).mean(dim=-1) for x in feat_maps], dim=1
)
# 按索引提取每张图像的目标特征(无目标则返回空列表)
return [feats[idx] if idx.shape[0] else [] for feats, idx in zip(obj_feats, idxs)]
| 项目 | 详情 |
|---|---|
| 函数名 | get_obj_feats |
| 功能概述 | 从模型输出的特征图中提取目标对应的特征向量,统一特征维度后按预测框索引筛选 |
| 返回值 | `list[torch.Tensor |
| 核心逻辑 | 1. 确定特征向量最短长度;2. 多尺度特征图维度统一+均值降维;3. 按索引提取单图目标特征 |
| 设计亮点 | 1. 自动适配多尺度特征图,统一特征维度;2. 无目标时优雅返回空列表,避免运行时错误;3. 均值降维保证特征长度一致,便于后续使用 |
| 注意事项 | 1. 特征图需为模型前向传播时保存的_feats属性,且维度需为[batch, channels, h, w];2. 索引idxs需与NMS返回的索引一一对应,否则特征提取错误 |
结果列表构造:construct_results
def construct_results(self, preds, img, orig_imgs):
"""
批量构建Results对象(遍历批次内所有图像,调用construct_result处理单张图像)
参数:
preds (list[torch.Tensor]): 批次内每张图像的NMS后检测结果(张量维度:[N,6],N=检测框数)
img (torch.Tensor): 预处理后的批次图像张量(模型输入格式)
orig_imgs (list[np.ndarray]): 批次内原始图像列表(NumPy格式)
返回:
(list[Results]): 批次内每张图像的结构化Results对象列表
"""
return [
self.construct_result(pred, img, orig_img, img_path)
for pred, orig_img, img_path in zip(preds, orig_imgs, self.batch[0])
]
| 项目 | 详情 |
|---|---|
| 函数名 | construct_results |
| 功能概述 | 遍历批量预测结果,逐张图像调用construct_result构造单图Results对象,最终返回结果列表 |
| 返回值 | list[Results]:批量图像的检测结果对象列表 |
| 核心逻辑 | 按批次维度遍历预测框、原始图像、图像路径,逐张构造Results对象 |
| 设计亮点 | 1. 简洁的列表推导式实现批量结果构造;2. 严格按批次顺序匹配,避免结果错位;3. 复用单图构造逻辑,降低代码冗余 |
| 注意事项 | 1. preds、orig_imgs、self.batch[0]的长度需一致,否则会触发维度不匹配错误;2. self.batch[0]需为图像路径列表,依赖BasePredictor的批量数据加载逻辑 |
单图结果构造:construct_result
def construct_result(self, pred, img, orig_img, img_path):
"""
为单张图像构建结构化Results对象(核心:框坐标缩放+结果封装)
将模型输入尺寸的框坐标缩放到原始图像尺寸,确保坐标与原始图像匹配
参数:
pred (torch.Tensor): 单张图像的NMS后检测结果(维度:[N,6],6=xyxy+conf+cls)
img (torch.Tensor): 预处理后的图像张量(模型输入格式)
orig_img (np.ndarray): 原始图像(未预处理,NumPy格式)
img_path (str): 原始图像文件路径(用于Results对象溯源)
返回:
(Results): 结构化Results对象,包含:
- orig_img: 原始图像
- path: 图像路径
- names: 模型类别名映射
- boxes: 缩放后的检测框(xyxy+conf+cls)
"""
# 框坐标缩放:从模型输入尺寸→原始图像尺寸(消除预处理的缩放/填充影响)
pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)
# 构建并返回Results对象(封装所有推理结果)
return Results(orig_img, path=img_path, names=self.model.names, boxes=pred[:, :6])
| 项目 | 详情 |
|---|---|
| 函数名 | construct_result |
| 功能概述 | 将单图预测框缩放到原始图像尺寸,封装为Results对象(包含图像、路径、类别名、检测框) |
| 返回值 | Results:单图检测结果对象(包含原始图像、路径、类别名、缩放后的检测框) |
| 核心逻辑 | 1. 预测框缩放(模型输入尺寸→原始图像尺寸);2. 封装为Results对象 |
| 设计亮点 | 1. 自动适配模型输入与原始图像的尺寸差异,保证预测框位置精准;2. 结果对象封装所有核心信息,便于后续可视化/解析 |
| 注意事项 | 1. pred的前4列必须为xyxy格式,否则缩放后框位置错误;2. orig_img需为RGB通道,否则可视化时颜色异常 |
完整代码
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
# 从ultralytics引擎预测器模块导入基础预测器基类
# (封装YOLO通用推理全流程,包含多源输入加载(图片/视频/摄像头/批量文件)、图像预处理(归一化/缩放/格式转换)、模型前向推理、结果初步解析等核心环节)
from ultralytics.engine.predictor import BasePredictor
# 从ultralytics引擎结果模块导入Results类
# (结构化封装YOLO推理结果,包含预测框坐标、置信度、类别ID/名称、原始图像张量、掩码(分割任务)等信息,提供结果解析、可视化、格式导出(JSON/CSV)等便捷接口)
from ultralytics.engine.results import Results
# 从ultralytics工具模块导入:非极大值抑制(NMS)函数
# (过滤YOLO推理输出的重复检测框,按置信度和IoU阈值筛选最优框,是检测任务后处理核心步骤)、通用操作函数集(包含检测框缩放(适配原图尺寸)、坐标格式转换(xyxy/xywh互转)、图像拼接/裁剪等推理后处理核心操作)
from ultralytics.utils import nms, ops
class DetectionPredictor(BasePredictor):
"""
YOLO目标检测专用预测器,继承自通用预测器BasePredictor
核心作用:为YOLO检测模型定制端到端的推理后处理流程,在通用推理框架基础上扩展检测专属能力,包含:
- 非极大值抑制(NMS)过滤冗余检测框(支持跨类别NMS/旋转框NMS/端到端模型适配)
- 检测框坐标缩放(从模型输入尺寸还原至原始图像尺寸)
- 目标级特征提取(从多尺度特征图中提取检测目标的特征向量)
- 空检测结果的兼容处理(避免特征提取/坐标缩放异常)
- 检测结果结构化封装为Results对象(统一格式便于可视化/保存/下游分析)
- 特征向量与检测结果的绑定(支持特征匹配/检索/重识别等下游任务)
属性:
args (namespace): 预测器配置参数命名空间,核心参数包含:
- conf: 置信度阈值(过滤低置信度检测框)
- iou: NMS的IoU阈值(合并重叠检测框)
- classes: 指定检测的目标类别(None表示检测所有类别)
- agnostic_nms: 是否启用跨类别NMS
- max_det: 单张图像最大检测框数量
- task: 推理任务类型(固定为detect)
model (nn.Module): 加载完成的YOLO检测模型实例(支持PyTorch/ONNX/TensorRT等多格式)
batch (list): 当前处理的批次数据列表,包含图像路径、预处理后张量、原始图像等
方法:
postprocess: 核心后处理方法(NMS过滤→格式转换→特征提取→Results封装)
get_obj_feats: 从多尺度特征图提取目标级特征向量(支持下游特征匹配/检索)
construct_results: 批量构建检测结果对象(遍历批次,调用单张构建逻辑)
construct_result: 单张图像检测结果构建(坐标缩放+Results结构化封装)
示例:
# >>> from ultralytics.utils import ASSETS
# >>> from ultralytics.models.yolo.detect import DetectionPredictor
# >>> args = dict(model="yolo11n.pt", source=ASSETS)
# >>> predictor = DetectionPredictor(overrides=args)
# >>> predictor.predict_cli() # 命令行模式推理
# >>> results = predictor.predict("path/to/image.jpg") # 编程模式推理
"""
def postprocess(self, preds, img, orig_imgs, **kwargs):
"""
对模型原始预测执行后处理(NMS+结果结构化),返回结构化Results对象列表
核心逻辑:NMS过滤冗余框→格式转换→特征提取(可选)→构建Results对象→附加特征(可选)
参数:
preds (torch.Tensor): 模型原始预测张量(维度:[B, N, 4+1+NC],4=框坐标,1=置信度,NC=类别数)
img (torch.Tensor): 预处理后的输入图像张量(模型输入格式,已缩放/归一化)
orig_imgs (torch.Tensor | list): 预处理前的原始图像(张量/列表格式,RGB/BGR需适配)
**kwargs (Any): 额外关键字参数(预留扩展)
返回:
(list[Results]): 结构化推理结果列表,每个元素对应单张图像的检测结果(含框、类别、置信度等)
示例:
# >>> predictor = DetectionPredictor(overrides=dict(model="yolo11n.pt"))
# >>> results = predictor.predict("path/to/image.jpg")
# >>> processed_results = predictor.postprocess(preds, img, orig_imgs)
"""
# 判断是否需要保存目标特征:检测是否存在_feats属性(模型推理时提取的特征图)
save_feats = getattr(self, "_feats", None) is not None
# 执行NMS后处理(过滤冗余检测框):
# - conf: 置信度阈值(过滤低置信度框)
# - iou: NMS的IoU阈值(合并重叠框)
# - classes: 指定仅检测的类别(None则检测所有类别)
# - agnostic_nms: 跨类别NMS(单类别/agnostic模式下启用)
# - max_det: 单图最大检测框数量
# - nc: 类别数(0表示自动识别,非detect任务时用模型类别数)
# - end2end: 适配端到端模型的输出格式
# - rotated: 适配旋转框检测(OBB任务)
# - return_idxs=save_feats: 需要提取特征时返回目标索引(用于特征映射)
preds = nms.non_max_suppression(
preds,
self.args.conf,
self.args.iou,
self.args.classes,
self.args.agnostic_nms,
max_det=self.args.max_det,
nc=0 if self.args.task == "detect" else len(self.model.names),
end2end=getattr(self.model, "end2end", False),
rotated=self.args.task == "obb",
return_idxs=save_feats,
)
# 格式转换:若原始图像是张量(非列表),转换为NumPy批次并反转通道(BGR→RGB,适配OpenCV格式)
if not isinstance(orig_imgs, list):
orig_imgs = ops.convert_torch2numpy_batch(orig_imgs)[..., ::-1]
# 特征提取:需要保存特征时,从特征图提取目标级特征
if save_feats:
# 提取目标特征(按NMS返回的索引映射)
obj_feats = self.get_obj_feats(self._feats, preds[1])
# 分离NMS结果(preds[0]为检测框,preds[1]为目标索引)
preds = preds[0]
# 批量构建结构化Results对象
results = self.construct_results(preds, img, orig_imgs, **kwargs)
# 特征附加:将提取的目标特征绑定到Results对象
if save_feats:
for r, f in zip(results, obj_feats):
r.feats = f
return results
def get_obj_feats(self, feat_maps, idxs):
"""
从模型特征图中提取目标级特征(用于下游任务:特征匹配、检索、重识别等)
核心逻辑:统一特征维度→拼接多尺度特征→按NMS索引提取目标特征
参数:
feat_maps (list[torch.Tensor]): 模型输出的多尺度特征图列表(如8x8、16x16、32x32)
idxs (list[torch.Tensor]): 批次内每张图像的目标索引(NMS返回,映射特征图到检测目标)
返回:
(list[torch.Tensor]): 批次内每张图像的目标特征列表(空列表表示无检测目标)
"""
# 延迟导入(避免推理时未使用特征提取的情况下加载冗余依赖)
import torch
# 找到所有特征图中最短的向量长度(统一特征维度,避免维度不匹配)
s = min(x.shape[1] for x in feat_maps)
# 多尺度特征拼接:
# 1. permute(0,2,3,1): 特征图维度从[B,C,H,W]→[B,H,W,C](通道维度后置)
# 2. reshape: 将通道维度拆分为[s, C/s],便于均值降维到统一长度s,[B,H,W,C]→[B,H*W,s,C/s]
# 3. mean(dim=-1): 对拆分后的维度取均值,将所有特征向量统一为长度s,[B,H*W,s,C/s]→[B,H*W,s]
# 4. cat(dim=1): 拼接多尺度特征(维度:[B, 总特征数, s]),总特征数即不同的尺度H*W的总数
obj_feats = torch.cat(
[x.permute(0, 2, 3, 1).reshape(x.shape[0], -1, s, x.shape[1] // s).mean(dim=-1) for x in feat_maps], dim=1
)
# 按索引提取每张图像的目标特征(无目标则返回空列表)
return [feats[idx] if idx.shape[0] else [] for feats, idx in zip(obj_feats, idxs)]
def construct_results(self, preds, img, orig_imgs):
"""
批量构建Results对象(遍历批次内所有图像,调用construct_result处理单张图像)
参数:
preds (list[torch.Tensor]): 批次内每张图像的NMS后检测结果(张量维度:[N,6],N=检测框数)
img (torch.Tensor): 预处理后的批次图像张量(模型输入格式)
orig_imgs (list[np.ndarray]): 批次内原始图像列表(NumPy格式)
返回:
(list[Results]): 批次内每张图像的结构化Results对象列表
"""
return [
self.construct_result(pred, img, orig_img, img_path)
for pred, orig_img, img_path in zip(preds, orig_imgs, self.batch[0])
]
def construct_result(self, pred, img, orig_img, img_path):
"""
为单张图像构建结构化Results对象(核心:框坐标缩放+结果封装)
将模型输入尺寸的框坐标缩放到原始图像尺寸,确保坐标与原始图像匹配
参数:
pred (torch.Tensor): 单张图像的NMS后检测结果(维度:[N,6],6=xyxy+conf+cls)
img (torch.Tensor): 预处理后的图像张量(模型输入格式)
orig_img (np.ndarray): 原始图像(未预处理,NumPy格式)
img_path (str): 原始图像文件路径(用于Results对象溯源)
返回:
(Results): 结构化Results对象,包含:
- orig_img: 原始图像
- path: 图像路径
- names: 模型类别名映射
- boxes: 缩放后的检测框(xyxy+conf+cls)
"""
# 框坐标缩放:从模型输入尺寸→原始图像尺寸(消除预处理的缩放/填充影响)
pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)
# 构建并返回Results对象(封装所有推理结果)
return Results(orig_img, path=img_path, names=self.model.names, boxes=pred[:, :6])
适配YOLO检测的核心特性
| 特性 | 实现方式 |
|---|---|
| 多场景NMS适配 | postprocess中NMS支持普通检测/旋转框、类别无关、end2end模型、类别过滤 |
| 目标特征提取 | get_obj_feats统一多尺度特征维度,按预测框索引提取目标特征并绑定到结果 |
| 预测框精准缩放 | construct_result调用scale_boxes自动适配模型输入/原始图像尺寸差异 |
| 结果标准化封装 | 统一使用Results对象封装结果,包含图像、路径、类别名、检测框、特征等 |
| 批量/单图兼容 | construct_results遍历批量数据,复用单图构造逻辑,保证批次一致性 |
工程化核心优化
| 优化点 | 实现方式 |
|---|---|
| 按需特征提取 | 通过save_feats标记控制特征提取流程,不影响常规预测性能 |
| 维度兼容处理 | 无目标时返回空列表,避免张量维度错误;自动转换原始图像的张量/列表格式 |
| 代码冗余减少 | 批量结果构造复用单图逻辑,NMS参数复用预测器配置,降低代码重复 |
| 通道顺序适配 | 原始图像张量转numpy时执行[...,::-1],保证RGB通道顺序匹配 |
扩展与易用性能力
| 扩展项 | 用途 |
|---|---|
| 预留kwargs参数 | postprocess的**kwargs为后续功能扩展(如自定义后处理)预留接口 |
| 特征绑定到结果 | 提取的目标特征绑定到Results.feats,支持下游任务(如特征匹配) |
| 统一结果对象 | Results对象提供可视化、保存、解析等通用方法,降低下游使用成本 |
关键注意事项
- 模型类型匹配:需确保
model为检测模型(如yolo11n.pt),若传入分类/分割模型,NMS后处理会因预测格式不匹配报错; - 特征提取启用条件:需在模型推理时保存
_feats特征图(如自定义模型前向传播时赋值self._feats),否则get_obj_feats不会执行; - 旋转框检测配置:检测旋转框(OBB)时需设置
args.task="obb",否则NMS会按普通框处理,导致旋转框过滤错误; - 图像通道顺序:原始图像需为RGB通道,若输入为BGR(如OpenCV读取),需手动转换,否则可视化结果颜色异常;
- 批量结果一致性:确保
preds、orig_imgs、img_path的长度一致,避免批量结果构造时出现索引错位; - 置信度阈值调整:低置信度阈值(如0.001)会增加检测框数量,可能导致NMS耗时增加,需根据场景平衡召回率与速度。
总结
详细介绍了 Ultralytics 框架中继承自 DetectionPredictor 的 YOLO 目标检测专用预测器。
更多推荐



所有评论(0)