非最大值抑制(NMS)函数

非最大值抑制(NMS)函数

flyfish

非最大值抑制(Non-Maximum Suppression, NMS)是计算机视觉中常用的一种后处理技术,主要用于目标检测任务。其作用是从一组可能存在大量重叠的候选边界框中,筛选出最具代表性的边界框,即通过置信度分数和重叠区域的过滤,保留最具代表性的边界框。

边界框(Bounding Boxes):一组表示候选目标区域的矩形框,每个框由左上角和右下角的坐标(x1, y1, x2, y2)表示。
置信度分数(Confidence Scores):每个边界框对应的一个置信度分数,表示该框内包含目标的可能性。

执行步骤

初始化:
boxes:输入的边界框列表。
scores:每个边界框对应的置信度得分列表。
confidence_threshold:过滤边界框的最低置信度阈值。
iou_threshold:用于确定边界框是否重叠的 IOU 阈值。

过滤低置信度边界框:
根据 confidence_threshold 过滤掉置信度低于该阈值的边界框。

按置信度排序:
对剩余的边界框按照置信度从高到低排序。

非极大值抑制:
从排序后的列表中选择置信度最高的边界框,并计算其与其他边界框的 Intersection-over-Union (IoU)。
如果 IoU大于 iou_threshold,则移除该边界框(表示重叠太多)。
重复该过程直到处理完所有边界框。

返回结果:
返回保留的边界框的索引。
在这里插入图片描述
可视化 Intersection-over-Union (IoU)

蓝色矩形表示 Box A,红色矩形表示 Box B,绿色矩形表示它们的交集区域,剩余的红色和蓝色是并集区域。
在这里插入图片描述

torchvision.ops.nms 和 cv2.dnn.NMSBoxes 的调用

import numpy as np
import torch
import torchvision.ops as ops
import cv2# 输入数据
boxes = np.array([[100, 100, 210, 210], [220, 220, 320, 330], [300, 300, 400, 400],[50, 50, 150, 200], [200, 150, 280, 320], [280, 280, 380, 380],[80, 90, 190, 210], [250, 250, 350, 370], [290, 290, 390, 390]
])# (x1, y1, x2, y2)格式
scores = np.array([0.9, 0.8, 0.75, 0.85, 0.7, 0.65, 0.82, 0.78, 0.6])
score_threshold = 0.5
nms_threshold = 0.4def convert_to_xywh(boxes): #opencv用 (x, y, w, h)格式"""将边界框从 (x1, y1, x2, y2) 格式转换为 (x, y, w, h) 格式。参数:- boxes: 形状为 (N, 4) 的数组,其中 N 是边界框的数量返回:- boxes_xywh: 形状为 (N, 4) 的数组,包含转换后的边界框"""boxes_xywh = np.zeros_like(boxes)boxes_xywh[:, 0] = boxes[:, 0]  # xboxes_xywh[:, 1] = boxes[:, 1]  # yboxes_xywh[:, 2] = boxes[:, 2] - boxes[:, 0]  # wboxes_xywh[:, 3] = boxes[:, 3] - boxes[:, 1]  # hreturn boxes_xywhdef nms_torchvision(boxes, scores, nms_threshold):boxes_tensor = torch.tensor(boxes, dtype=torch.float32)scores_tensor = torch.tensor(scores, dtype=torch.float32)keep = ops.nms(boxes_tensor, scores_tensor, nms_threshold)return keep.numpy()def nms_opencv(boxes, scores, score_threshold, nms_threshold):boxes = convert_to_xywh(boxes)indices = cv2.dnn.NMSBoxes(boxes.tolist(), scores.tolist(), score_threshold, nms_threshold)return np.array(indices).flatten()# 调用 NMS
keep_torchvision = nms_torchvision(boxes, scores, nms_threshold)
keep_opencv = nms_opencv(boxes, scores, score_threshold, nms_threshold)print("使用 torchvision.ops.nms 保留的边界框索引: ", keep_torchvision)
print("使用 cv2.dnn.NMSBoxes 保留的边界框索引: ", keep_opencv)

输出

使用 torchvision.ops.nms 保留的边界框索引:  [0 3 1 7 2 4]
使用 cv2.dnn.NMSBoxes 保留的边界框索引:  [0 3 1 7 2 4]

用纯 NumPy 实现的非最大值抑制(NMS)函数

import numpy as npdef nms(boxes, scores, score_threshold, nms_threshold):"""单类 NMS 使用 NumPy 实现。"""# 过滤掉低置信度的框indices = np.where(scores > score_threshold)[0]boxes = boxes[indices]scores = scores[indices]# 如果没有剩余的框,返回空列表if len(boxes) == 0:return []# 提取每个边界框的坐标x1 = boxes[:, 0]y1 = boxes[:, 1]x2 = boxes[:, 2]y2 = boxes[:, 3]# 计算每个边界框的面积areas = (x2 - x1 + 1) * (y2 - y1 + 1)# 根据分数进行排序(从高到低)order = scores.argsort()[::-1]keep = []while order.size > 0:i = order[0]keep.append(indices[i])# 计算当前边界框与其余边界框的交集坐标xx1 = np.maximum(x1[i], x1[order[1:]])yy1 = np.maximum(y1[i], y1[order[1:]])xx2 = np.minimum(x2[i], x2[order[1:]])yy2 = np.minimum(y2[i], y2[order[1:]])# 计算交集的宽度和高度w = np.maximum(0.0, xx2 - xx1 + 1)h = np.maximum(0.0, yy2 - yy1 + 1)# 计算交集面积inter = w * h# 计算交并比(IOU)ovr = inter / (areas[i] + areas[order[1:]] - inter)# 只保留 IOU 小于阈值的边界框inds = np.where(ovr <= nms_threshold)[0]order = order[inds + 1]return keep# 示例数据
boxes = np.array([[100, 100, 210, 210], [220, 220, 320, 330], [300, 300, 400, 400],[50, 50, 150, 200], [200, 150, 280, 320], [280, 280, 380, 380],[80, 90, 190, 210], [250, 250, 350, 370], [290, 290, 390, 390]
])
scores = np.array([0.9, 0.8, 0.75, 0.85, 0.7, 0.65, 0.82, 0.78, 0.6])
score_threshold = 0.5
nms_threshold = 0.4# 调用NMS
keep_indices = nms(boxes, scores, score_threshold, nms_threshold)
print("使用 NumPy 实现的 NMS 保留的边界框索引: ", keep_indices)
使用 NumPy 实现的 NMS 保留的边界框索引:  [0, 3, 1, 7, 2, 4]

关于语法的解释

在 NumPy 中,冒号 : 用于数组切片。它们可以用来提取数组的子集、重排数组或选取特定的元素。

示例1

scores.argsort()[::-1]
scores.argsort():返回 scores 中元素的索引数组,这些索引会将 scores 排序。
[::-1]:表示反转数组。
在这个例子中,[::-1] 表示从开始到结束,步长为 -1,因此数组会被反转。这里的两个冒号是为了清楚地表示切片的完整语法 [start:stop:step],其中省略了 start 和 stop,只指定了 step 为 -1。

import numpy as npscores = np.array([0.9, 0.8, 0.75, 0.85, 0.7, 0.65, 0.82, 0.78, 0.6])
sorted_indices = scores.argsort()  # 升序排序的索引
print("sorted_indices:", sorted_indices)# 反转排序索引(降序排序)
reversed_indices = sorted_indices[::-1]
print("reversed_indices:", reversed_indices)
sorted_indices: [8 5 4 2 7 1 6 3 0]
reversed_indices: [0 3 6 1 7 2 4 5 8]

示例2

boxes[:, 0]
boxes[:, 0]:选取 boxes 数组中第 0 列的所有元素。
: 表示选择所有行,0 表示选择第 0 列。
这段代码的作用是提取 boxes 数组中每个边界框的 x1 坐标(左上角的 x 坐标)。

import numpy as np
boxes = np.array([[100, 100, 210, 210],[220, 220, 320, 330],[300, 300, 400, 400],[50, 50, 150, 200]
])x1 = boxes[:, 0]
print("x1:", x1)
x1: [100 220 300  50]

可视化数据的代码

def plot_boxes(boxes, keep_indices):fig, ax = plt.subplots(1, figsize=(12, 12))for i, box in enumerate(boxes):x1, y1, x2, y2 = boxwidth = x2 - x1height = y2 - y1# 所有输入框用蓝色绘制edgecolor = 'blue'if i in keep_indices:# NMS 保留的框用绿色绘制edgecolor = 'green'else:# 被抑制的框用红色绘制edgecolor = 'red'rect = patches.Rectangle((x1, y1), width, height, linewidth=2, edgecolor=edgecolor, facecolor='none')ax.add_patch(rect)# 设置坐标范围ax.set_xlim(0, np.max(boxes[:, [0, 2]]) + 50)ax.set_ylim(0, np.max(boxes[:, [1, 3]]) + 50)ax.invert_yaxis()  # 图像坐标系和实际坐标系相反时需要plt.show()# 示例数据
boxes = np.array([[100, 100, 210, 210], [220, 220, 320, 330], [300, 300, 400, 400],[50, 50, 150, 200], [200, 150, 280, 320], [280, 280, 380, 380],[80, 90, 190, 210], [250, 250, 350, 370], [290, 290, 390, 390]
])
scores = np.array([0.9, 0.8, 0.75, 0.85, 0.7, 0.65, 0.82, 0.78, 0.6])
score_threshold = 0.5
nms_threshold = 0.4# 调用NMS
keep_indices = nms(boxes, scores, score_threshold, nms_threshold)
print("使用 NumPy 实现的 NMS 保留的边界框索引: ", keep_indices)# 绘图
plot_boxes(boxes, keep_indices)

可视化 Intersection-over-Union (IoU)的代码

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patchesdef plot_iou(boxA, boxB):fig, ax = plt.subplots(1, figsize=(8, 8))# 绘制 Box Ax1A, y1A, x2A, y2A = boxAwidthA = x2A - x1AheightA = y2A - y1ArectA = patches.Rectangle((x1A, y1A), widthA, heightA, linewidth=2, edgecolor='blue', facecolor='blue', label='Box A')ax.add_patch(rectA)# 绘制 Box Bx1B, y1B, x2B, y2B = boxBwidthB = x2B - x1BheightB = y2B - y1BrectB = patches.Rectangle((x1B, y1B), widthB, heightB, linewidth=2, edgecolor='red', facecolor='red', label='Box B')ax.add_patch(rectB)# 计算交集xx1 = np.maximum(x1A, x1B)yy1 = np.maximum(y1A, y1B)xx2 = np.minimum(x2A, x2B)yy2 = np.minimum(y2A, y2B)w = np.maximum(0, xx2 - xx1)h = np.maximum(0, yy2 - yy1)intersection_area = w * h# 计算并集areaA = (x2A - x1A) * (y2A - y1A)areaB = (x2B - x1B) * (y2B - y1B)union_area = areaA + areaB - intersection_area# 计算 IoUiou = intersection_area / union_area# 绘制交集if w > 0 and h > 0:rect_intersection = patches.Rectangle((xx1, yy1), w, h, linewidth=2, edgecolor='green', facecolor='green', linestyle='--', label='Intersection')ax.add_patch(rect_intersection)# 显示图例handles, labels = ax.get_legend_handles_labels()plt.legend(handles=handles)plt.xlim(0, 500)plt.ylim(0, 500)plt.gca().set_aspect('equal', adjustable='box')plt.title(f'IoU = {iou:.2f}')plt.show()# 示例框
boxA = [100, 100, 300, 300]
boxB = [200, 200, 400, 400]plot_iou(boxA, boxB)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/36354.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初学51单片机之长短键应用定时炸弹及扩展应用

51单片机RAM区域划分 51单片机的RAM分为两个部分&#xff0c;一块是片内RAM&#xff0c;一块是片外RAM。 data&#xff1a; 片内RAM从 0x00 ~0x7F 寻址范围&#xff08;0-127&#xff09; 容量共128B idata: 片外RAM从 0x00~0xFF 寻址范围(0-255) 容量共256B pdata&am…

定位问题6.27 petal数据接口问题

petal接口响应结果 响应结果为空的数据&#xff0c;而我们需要的是正确的响应结果。 排查问题 确认接口是否正确 以下是爬虫的配置文件内容&#xff0c;我查看了PETAL_URL的接口&#xff0c;并询问接口开发人员&#xff0c;得知接口地址并未改变 确认接口请求体是否正确 我使…

记一次对ouija渗透测试c语言逆向学习

概要 初始知识 web应用枚举 二进制逆向 文件枚举 堆栈溢出 学到知识 hash长度攻击 任意文件读取 二进制逆向分析 信息收集 端口扫描 nmap --min-rate 1000 -p- 10.129.30.104 发现22&#xff0c;80&#xff0c;3000端口 网站探测 目录枚举 feroxbuster -u http://10.1…

“数字政协”平台如何提高政协工作效率?正宇软件助力建设!

随着信息技术的飞速发展&#xff0c;数字化已成为推动各行各业转型升级的重要力量。在政协工作中&#xff0c;数字政协平台的建设与运用&#xff0c;正成为提高政协工作效率、促进民主协商的重要手段。本文将从数字政协平台的功能特点、优势分析以及实践应用等方面&#xff0c;…

何用Vue3和Plotly.js打造交互式3D图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 利用 Plotly.js 创建交互式动画图表 应用场景 本代码适用于需要创建交互式动画图表的数据可视化项目。例如&#xff0c;可以用来展示时间序列数据或比较不同函数的行为。 基本功能 该代码使用 Plotly.js 库…

架构师篇-5、架构语言-ArchiMate

内容摘要&#xff1a; TOGAF内容元模型TOGAF架构语言ArchiMate3ArchiMate实践案例分享 TOGAF内容框架【核心内容元模型】 作为一个通用且开放式的标准&#xff0c;TOGAF需要采用一种非常灵活的方式来对其内容元模型进行定义&#xff0c;从而使得不同的企业可以根据自身需要对…

头歌——机器学习——决策树案例

第1关&#xff1a;基于决策树模型的应用案例 任务描述 本关任务&#xff1a;使用决策树算法完成成人收入预测。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.数据特征处理&#xff0c;2.使用决策树算法完成成人收入预测。 数据处理及特征工程 本次任务…

2024最新特种设备(锅炉作业)题库分享。

1.锅炉蒸发量大小是由(  )决定的。 A.压力的高低 B.受压元件多少 C.受热面积大小 答案:C 2.哪项不是自然循环的故障?&#xff08; &#xff09; A.停滞 B.倒流 C.下降管带汽 D.上升管带汽 答案:D 3.水冷壁被现代大型锅炉广泛采用的是(  )。 A.光管水冷壁 B.膜…

【C++】继承(详解)

前言&#xff1a;今天我们正式的步入C进阶内容的学习了&#xff0c;当然了既然是进阶意味着学习难度的不断提升&#xff0c;各位一起努力呐。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:高质量&#xff23;学习 &#x1f448; &#…

RabbitMQ安装部署

简介 RabbitMQ一款知名的开源消息队列系统&#xff0c;为企业提供消息的发布、订阅、点对点传输等消息服务。 RabbitMQ在企业开发中十分常见&#xff0c;课程为大家演示快速搭建RabbitMQ环境。 安装 rabbitmq在yum仓库中的版本比较老&#xff0c;所以我们需要手动构建yum仓库…

# Kafka_深入探秘者(8):kafka 高级应用

Kafka_深入探秘者&#xff08;8&#xff09;&#xff1a;kafka 高级应用 一、kafka 消费组管理 1、kafka 命令行工具 参考官网: http://kafka.apache.org/22/documentation.html 2、kafka 消费组管理&#xff1a;查看消费组 # 切换到 kafka 安装目录 cd /usr/local/kafka/…

leetCode.91. 解码方法

leetCode.91. 解码方法 题目思路 题解 class Solution { public:int numDecodings(string s) {int n s.size();// dp 中f[0]一般不做使用&#xff0c;只是存一个初值1&#xff0c;表示默认由一种方案s s;vector<int> f( n 1 );f[0] 1;for ( int i 1; i < n;…

【数学】100332. 包含所有 1 的最小矩形面积 II

本文涉及知识点 数学 LeetCode100332. 包含所有 1 的最小矩形面积 II 给你一个二维 二进制 数组 grid。你需要找到 3 个 不重叠、面积 非零 、边在水平方向和竖直方向上的矩形&#xff0c;并且满足 grid 中所有的 1 都在这些矩形的内部。 返回这些矩形面积之和的 最小 可能值…

vant4的组件气泡弹出框van-popover,在列表中遍历后点击一个全部/显示隐藏,解决办法

环境&#xff1a;vue3 vant-ui4 <div v-for"(info, index) in item.infoListVOs" :key"index"><van-popoverv-model:show"showPopover":actions"actions"overlayplacement"bottom-end"select"onSelect(info…

软件工程全套学习培训资料,实际优质项目编制及各类建设方案,信息安全,运维资料

目的&#xff1a;规范系统开发流程&#xff0c;提高系统开发效率。 立项申请需求分析方案设计方案评审开发调整测试阶段系统培训试运行测试验收投入使用 所有文档过去进主页获取。 获取方式&#xff1a;本文末个人名片直接获取。 软件资料清单列表部分文档清单&#xff1a;工作…

AGI 远不止 ChatGPT!一文入门 AGI 通识及应用开发_通向agi之路网站使用什么开发的网站

AI 大语言模型进入爆发阶段 2022 年 12 月 ChatGPT 突然爆火&#xff0c;原因是其表现出来的智能化已经远远突破了我们的常规认知。虽然其呈现在使用者面前仅仅只是一个简单的对话问答形式&#xff0c;但是它的内容化水平非常强大&#xff0c;甚至在某些方面已经超过人类了&am…

程序的调试技术,设置断点

断点&#xff08;break point&#xff09;是指在代码中指定位置&#xff0c;当程序运行到此位置时变中断下来&#xff0c;并让开发者可查看此时各变量的值。因断点中断的程序并没有结束&#xff0c;可以选择继续执行。 在程序的调试过程中&#xff0c;设置断点是一个很有用的分…

可用的搜索引擎

presearchhttps://presearch.com/yandexhttps://ya.ru

书归正传,说说颍川士族

我的非遗项目是《颍川士族传说》&#xff0c;此前做的视频只是触及了边缘&#xff0c;属于气氛的营造&#xff0c;今后就正式转入主题了。 首先说说什么是士族&#xff0c;它有两个同义词&#xff1a;世族和势族。“世”是一代又一代的意思&#xff0c;“势”是权势&#xff0…

python中类的继承详解

面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力&#xff1a;它可以使用现有类的所有功能&#xff0c;并在无需重新编写原来的类的情况下对这些功能进行扩展 &#xff08;1&#xff09;在类的继承中&#xff0c;存在父类跟子类&#xff0c;子类可以继…