非极大值抑制中的DIOU-nms

目录

什么是非极大值抑制?

DIoU NMS

公式


什么是非极大值抑制?

非极大值抑制(Non-maximum supression)简称NMS,其作用是去除冗余的检测框,去冗余手段是剔除与极大值重叠较多的检测框结果

简单来说,非极大值抑制的作用就是模型检测出了很多框,我应该留下哪些。

 核心思想是搜索目标局部范围内的边界框置信度最大的这个最优值,去除目标邻域内的冗余边界框。

DIoU NMS

论文:   https://arxiv.org/pdf/1911.08287.pdf.

一个成熟的IoU衡量指标应该要考虑预测框与真实框的重叠面积、中心点距离、长宽比三个方面。但是IoU 只考虑到了预测框与真实框重叠区域,并没有考虑到中心点距离、长宽比。

基于此,DIOU-NMS就不仅仅考虑IOU,还考虑两个框中心点之间的距离。如果两个框之间IOU比较大,但是两个框的中心距离比较大时,可能会认为这是两个物体的框而不会被过滤掉。
具体的GIoU、DIoU、CIoU的细节可以看我的以下博客:GIoU、DIoUCIoU

公式

DIoU (Distance-IoU )。简单地在IoU loss基础上添加一个惩罚项,该惩罚项用于最小化两个bbox的中心点距离。

DIoU公式:

如下图,绿色框代表真实框,黑色框代表预测框,b 为预测框的中心,b^{gt}为真实框的中心,\rho ^{2}(b,b^{gt})代表真实框与预测框中心距离的平方d^{2},c表示两个框的最小闭包区域(同时包含了预测框和真实框的最小矩形框)的对角线长度。

### 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`)已正确配置于项目目录下。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值