yolov3后处理,包括网络输出、阈值过滤、多类NMS

  • pytorch版本:1.7.1+cu101
from net.yolov3 import Yolo
from PIL import Image, ImageDraw
import numpy as np
import torch, copy, time

def sigmoid(x):
	temporary = 1 + torch.exp(-x)
	return 1.0 / temporary

def get_boxes(output, anchors):
	h = output.size(2)
	w = output.size(3)
	output = output.view(3, 85, h, w).permute(0,2,3,1)
	tc = torch.sigmoid(output[..., 4])    # 3*h*w
	cl = torch.sigmoid(output[..., 5:])   # 3*h*w*80
	clv, cli = torch.max(cl,-1)
	mask = tc * clv > 0.9
	# print(torch.where(mask))
	cli = cli[mask].unsqueeze(-1)
	# 3*h*w
	tx = torch.sigmoid(output[..., 0][mask])
	ty = torch.sigmoid(output[..., 1][mask])
	tw = torch.exp(output[..., 2][mask])
	th = torch.exp(output[..., 3][mask])
	# grid
	FloatTensor = torch.cuda.FloatTensor if tx.is_cuda else torch.FloatTensor
	grid_x, grid_y = torch.meshgrid(torch.linspace(0,w-1,w), torch.linspace(0,h-1,h))
	grid_x = grid_x.repeat(3,1,1)[mask].type(FloatTensor)
	grid_y = grid_y.repeat(3,1,1)[mask].type(FloatTensor)
	tx = ((tx+grid_y) / w).unsqueeze(-1)
	ty = ((ty+grid_x) / h).unsqueeze(-1)
	# anchor
	aw = torch.Tensor(anchors[0::2]).view(3,1).repeat(1,h*w).view(3,h,w)[mask].type(FloatTensor)
	ah = torch.Tensor(anchors[1::2]).view(3,1
### YOLOv8 中集成 DIoU-NMS 的方法 要在 YOLOv8 后处理中实现 DIoU-NMS 方法,可以通过修改其源码来完成。以下是具体的操作方式: #### 修改 `non_max_suppression` 函数 YOLOv8 使用的非极大值抑制 (NMS) 实现通常位于工具模块中(如 `ultralytics/yolo/utils/ops.py` 或类似的文件路径),其中定义了一个名为 `non_max_suppression` 的函数。为了支持 DIoU-NMS,需要调整该函数。 以下是一个基于 YOLOv5 和 YOLOv8 的代码示例,展示如何将 DIoU-NMS 集成到后处理阶段[^1]: ```python import torch def non_max_suppression(prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, multi_label=True, diou_nms=True): """ 执行非极大值抑制 (NMS),可以选择使用 DIoU-NMS。 参数: prediction: 模型预测结果 (batch_size, num_boxes, [xywh, obj_conf, class_scores]) conf_thres: 置信度阈值 iou_thres: IoU 阈值 classes: 是否过滤特定类别 agnostic: 类别无关 NMS multi_label: 多标签分类模式 diou_nms: 是否启用 DIoU-NMS 返回: list of detections, on (n,6) tensor per image [xyxy, conf, cls] """ # 初始化变量 nc = prediction.shape[2] - 5 # 数字类别的数量 xc = prediction[..., 4] > conf_thres # 候选框筛选条件 # 输出列表初始化 output = [torch.zeros((0, 6), device=prediction.device)] * prediction.shape[0] for xi, x in enumerate(prediction): # 对每张图片的结果进行迭代 x = x[xc[xi]] # 过滤掉低置信度候选框 if not x.shape[0]: continue # 计算 xyxy 格式的边界框坐标 box = xywh2xyxy(x[:, :4]) # 如果启用了多标签,则按类别分别处理 if multi_label: i, j = (x[:, 5:] > conf_thres).nonzero(as_tuple=False).T x = torch.cat((box[i], x[i, j + 5, None], j[:, None].float()), 1) else: # 单一最高分数类别 conf, j = x[:, 5:].max(1, keepdim=True) x = torch.cat((box, conf, j.float()), 1)[conf.view(-1) > conf_thres] # 排序并执行 NMS n = x.shape[0] # 当前图像中的检测数 if not n: continue c = x[:, 5:6] * (0 if agnostic else max_wh) # 类别偏移 boxes, scores = x[:, :4] + c, x[:, 4] # 调整后的盒子和得分 if diou_nms: from utils.metrics import bbox_iou # 导入 DIoU 计算函数 ious = bbox_iou(boxes.unsqueeze(1), boxes.unsqueeze(0), x1y1x2y2=False, CIoU=True) # 计算 DIoU 矩阵 selected_indices = [] while True: _, idx = scores.max(0) selected_indices.append(idx.item()) if len(selected_indices) >= n or scores[idx] < conf_thres: break mask = ious[idx] <= iou_thres scores = scores[mask.squeeze()] boxes = boxes[mask.squeeze()] x = x[selected_indices] else: from torchvision.ops import nms indices = nms(boxes, scores, iou_thres) x = x[indices] output[xi] = x return output ``` #### 关键点说明 1. **DIoU 计算**: 上述代码通过调用 `bbox_iou` 函数实现了 DIoU 的计算逻辑[^1]。如果未找到对应的函数,可以从 YOLOv5 的 `utils/metrics.py` 文件复制其实现。 2. **自定义 NMS 循环**: 在启用 DIoU-NMS 的情况下,手动构建循环以逐步选择最优目标,并剔除与其他目标重叠率超过设定阈值的对象。 3. **兼容性**: 新增参数 `diou_nms` 控制是否启用 DIoU-NMS,默认设置为 False,以便保持原有功能不变。 --- ### 注意事项 - 若发现性能瓶颈,建议测试不同硬件平台下的运行效率,因为 DIoU-NMS 可能会稍微增加计算开销。 - 确保导入的辅助函数(如 `bbox_iou`)已正确配置于项目目录下。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刀么克瑟拉莫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值