非最大值抑制(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…

即时和及时的微妙区别

即时与及时在汉语中的确存在一些微妙的区别&#xff0c;以下是对这两个词的分析&#xff0c;并通过例子进行说明&#xff1a; 一、词义与词性 即时&#xff1a;具有立刻、马上的意思&#xff0c;强调在某个时间段立即出现、产生或做出&#xff0c;侧重于和当时实际情况同步。…

Leetcode-Java 无重复字符的最长子串

给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串的长度。 示例 1:输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。 示例 2:输入: s "bbbbb" 输出: 1 解释: 因为无重复…

无缝集成的艺术:iCloud与Apple TV的协同之旅

无缝集成的艺术&#xff1a;iCloud与Apple TV的协同之旅 在苹果构建的生态系统中&#xff0c;iCloud和Apple TV是两个重要的组成部分&#xff0c;它们共同为用户提供了一种无缝的娱乐体验。iCloud作为苹果的云服务&#xff0c;不仅存储用户的照片、视频、文档等数据&#xff0…

定位问题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;从而使得不同的企业可以根据自身需要对…

stp、rstp、mstp学习

文章目录 STP&#xff08;生成树协议&#xff09;RSTP&#xff08;快速生成树协议&#xff09;MSTP&#xff08;多生成树协议&#xff09;三者区别 STP&#xff08;生成树协议&#xff0c;Spanning Tree Protocol&#xff09;、RSTP&#xff08;快速生成树协议&#xff0c;Rapi…

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

第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; &#…

Grafana调整等待时间,避免Gateway timeout报错

使用Grafana的HTTP时&#xff0c;有些即时数据需要运算量与时间&#xff0c;而grafana的默认timeout是30秒&#xff0c;因此需要通过修改配置文件&#xff0c;避免grafana提前中断连接 修改原始配置文件: 删除;调整timeout30为timeout60 # This setting also applies to cor…

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/…

python线程池的使用ThreadPoolExecutor

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、使用步骤1.引入库 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a; 提示&#xff1a;以下是本篇文章正文内容…

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;…

mysql存储图片

""" save image.py 二进制文件存储演示 """import pymysql """ 写操作实例 """ #链接数据库 db pymysql.connect(hostlocalhost,port3306,userroot,password123456,databasestu,charsetutf8) #获取游标(操作数据…

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

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