如何使用 numpy 和 pytorch 快速计算 IOU
前言
在目标检测中用交并比(Interection-over-unio,简称 IOU)来衡量两个边界框之间的重叠程度,下面就使用 numpy 和 pytorch 两种框架的矢量计算方式来快速计算各种情况下的 IOU。
一对一
先来计算最简单的单框对单框的交并比。假设两个预测框 \(b_0=(x_{min0},\ y_{min0},\ x_{max0},\ y_{max0})\) 和 \(b_1=(x_{min1},\ y_{min1},\ x_{max1},\ y_{max1})\) ,固定 \(b_0\) 的位置不变,移动 \(b_1\),他们之间会有四种重叠情况,如下图所示,此时交并比计算公式为 \(IOU=C/(A+B-C)\),就是交集面积除以并集面积。虽然图中有四种重叠情况,但是计算的时候可以合并为一种 \(C=w_c*h_c\):
交集 \(C\) 的宽度 \(w_c=x_2-x_1\),其中 \(x_2=\min\{x_{max0},\ x_{max1}\}\),\(x_1=\max\{x_{min0},\ x_{min1} \}\);
交集 \(C\) 的高度 \(h_c=y_2-y_1\),其中 \(y_2=\min\{y_{max0},\ y_{max1}\}\),\(y_1=\max\{y_{min0},\ y_{min1} \}\);

numpy
def iou(box0: np.ndarray, box1: np.ndarray):
""" 计算一对一交并比
Parameters
----------
box0, box1: `~np.ndarray` of shape `(4, )`
边界框
"""
xy_max = np.minimum(box0[2:], box1[2:])
xy_min = np.maximum(box0[:2], box1[:2])
# 计算交集
inter = np.clip(xy_max-xy_min, a_min=0, a_max=np.inf)
inter = inter[0]*inter[1]
# 计算并集
area_0 = (box0[2]-box0[0])*(box0[3]-box0[1])
area_1 = (box1[2]-box1[0])*(box1[3]-box1[1])
union = area_0 + area_1- inter
return inter/union
pytorch
def iou(box0: torch.Tensor, box1: torch.Tensor):
""" 计算一对一交并比
Parameters
----------
box0, box1: Tensor of shape `(4, )`
边界框
"""
xy_max = torch.min(box0[2:], box1[2:])
xy_min = torch.max(box0[:2], box1[:2])
# 计算交集
inter = torch.clamp(xy_max-xy_min, min=0)
inter = inter[0]*inter[1]
# 计算并集
area_0 = (box0[2]-box0[0])*(box0[3]-box0[1])
area_1 = (box1[2]-box1[0])*(box1[3]-box1[1])
union = area_0 + area_1- inter
return inter/union
一对多
一对多的代码和一对一几乎是一模一样的,就是有一个参数多了一个维度而已。
numpy
def iou(box: np.ndarray, boxes: np.ndarray):
""" 计算一个边界框和多个边界框的交并比
Parameters
----------
box: `~np.ndarray` of shape `(4, )`
边界框
boxes: `~np.ndarray` of shape `(n, 4)`
其他边界框
Returns
-------
iou: `~np.ndarray` of shape `(n, )`
交并比
"""
# 计算交集
xy_max = np.minimum(boxes[:, 2:], box[2:])
xy_min = np.maximum(boxes[:, :2], box[:2])
inter = np.clip(xy_max-xy_min, a_min=0, a_max=np.inf)
inter = inter[:, 0]*inter[:, 1]
# 计算面积
area_boxes = (boxes[:, 2]-boxes[:, 0])*(boxes[:, 3]-boxes[:, 1])
area_box = (box[2]-box[0])*(box[3]-box[1])
return inter/(area_box+area_boxes-inter)
pytorch
def iou(box: torch.Tensor, boxes: torch.Tensor):
""" 计算一个边界框和多个边界框的交并比
Parameters
----------
box: Tensor of shape `(4, )`
一个边界框
boxes: Tensor of shape `(n, 4)`
多个边界框
Returns
-------
iou: Tensor of shape `(n, )`
交并比
"""
# 计算交集
xy_max = torch.min(boxes[:, 2:], box[2:])
xy_min = torch.max(boxes[:, :2], box[:2])
inter = torch.clamp(xy_max-xy_min, min=0)
inter = inter[:, 0]*inter[:, 1]
# 计算并集
area_boxes = (boxes[:, 2]-boxes[:, 0])*(boxes[:, 3]-boxes[:, 1])
area_box = (box[2]-box[0])*(box[3]-box[1])
return inter/(area_box+area_boxes-inter)
多对多
假设边界框矩阵 boxes0 的维度为 (A, 4),boxes1 的维度为 (B, 4),要计算这二者间的交并比,一种直观的想法是开个循环,一次从 boxes0 中拿出一个边界框 box,然后和 boxes1 里面的所有边界框计算交并比。但是在边界框很多的情况下,这种计算是很低效的。有没有什么办法可以代替循环呢?
来仔细思考一下:开循环的原因是我们不能像之前那样对两个边界框矩阵进行切片,然后计算 \([x_2, y_2]\) 以及 \([x_1, y_1]\)。所以我们只要想个办法能像之前那样切片就好了。 这时候就需要使用广播机制,将 boxes0 广播为 (A, B, 4) 维度的矩阵,boxes1 也广播为 (A, B, 4) 维度的矩阵。广播之后的 boxes0 任意沿着某行切下来的矩阵 boxes0[:, i, :]都是相同的(就是广播前的 boxes0),广播之后的 boxes1 沿着某一个通道切下来的矩阵 boxes1[i, :, :] 也是相同的。
numpy
def iou(boxes0: np.ndarray, boxes1: np.ndarray):
""" 计算多个边界框和多个边界框的交并比
Parameters
----------
boxes0: `~np.ndarray` of shape `(A, 4)`
边界框
boxes1: `~np.ndarray` of shape `(B, 4)`
边界框
Returns
-------
iou: `~np.ndarray` of shape `(A, B)`
交并比
"""
A = boxes0.shape[0]
B = boxes1.shape[0]
xy_max = np.minimum(boxes0[:, np.newaxis, 2:].repeat(B, axis=1),
np.broadcast_to(boxes1[:, 2:], (A, B, 2)))
xy_min = np.maximum(boxes0[:, np.newaxis, :2].repeat(B, axis=1),
np.broadcast_to(boxes1[:, :2], (A, B, 2)))
# 计算交集面积
inter = np.clip(xy_max-xy_min, a_min=0, a_max=np.inf)
inter = inter[:, :, 0]*inter[:, :, 1]
# 计算每个矩阵的面积
area_0 = ((boxes0[:, 2]-boxes0[:, 0])*(
boxes0[:, 3] - boxes0[:, 1]))[:, np.newaxis].repeat(B, axis=1)
area_1 = ((boxes1[:, 2] - boxes1[:, 0])*(
boxes1[:, 3] - boxes1[:, 1]))[np.newaxis, :].repeat(A, axis=0)
return inter/(area_0+area_1-inter)
pytorch
def iou(boxes0: Tensor, boxes1: Tensor):
""" 计算多个边界框和多个边界框的交并比
Parameters
----------
boxes0: Tensor of shape `(A, 4)`
边界框
boxes1: Tensor of shape `(B, 4)`
边界框
Returns
-------
iou: Tensor of shape `(A, B)`
交并比
"""
A = boxes0.size(0)
B = boxes1.size(0)
# 将先验框和边界框真值的 xmax、ymax 以及 xmin、ymin进行广播使得维度一致,(A, B, 2)
# 再计算 xmax 和 ymin 较小者、xmin 和 ymin 较大者,W=xmax较小-xmin较大,H=ymax较小-ymin较大
xy_max = torch.min(boxes0[:, 2:].unsqueeze(1).expand(A, B, 2),
boxes1[:, 2:].broadcast_to(A, B, 2))
xy_min = torch.max(boxes0[:, :2].unsqueeze(1).expand(A, B, 2),
boxes1[:, :2].broadcast_to(A, B, 2))
# 计算交集面积
inter = (xy_max-xy_min).clamp(min=0)
inter = inter[:, :, 0]*inter[:, :, 1]
# 计算每个矩形的面积
area_boxes0 = ((boxes0[:, 2]-boxes0[:, 0]) *
(boxes0[:, 3]-boxes0[:, 1])).unsqueeze(1).expand(A, B)
area_boxes1 = ((boxes1[:, 2]-boxes1[:, 0]) *
(boxes1[:, 3]-boxes1[:, 1])).broadcast_to(A, B)
return inter/(area_boxes0+area_boxes1-inter)
如何使用 numpy 和 pytorch 快速计算 IOU的更多相关文章
- Pytorch快速入门及在线体验
本文搭配了Pytorch在线环境,可以直接在线体验. Pytorch是Facebook 的 AI 研究团队发布了一个基于 Python的科学计算包,旨在服务两类场合: 1.替代numpy发挥GPU潜能 ...
- 【笔记】PyTorch快速入门:基础部分合集
PyTorch快速入门 Tensors Tensors贯穿PyTorch始终 和多维数组很相似,一个特点是可以硬件加速 Tensors的初始化 有很多方式 直接给值 data = [[1,2],[3, ...
- 使用pytorch快速搭建神经网络实现二分类任务(包含示例)
使用pytorch快速搭建神经网络实现二分类任务(包含示例) Introduce 上一篇学习笔记介绍了不使用pytorch包装好的神经网络框架实现logistic回归模型,并且根据autograd实现 ...
- Sql优化(二) 快速计算Distinct Count
原创文章,始发自本人个人博客站点,转载请务必注明出自http://www.jasongj.com 个人博客上本文链接http://www.jasongj.com/2015/03/15/count_di ...
- Paths on a Grid POJ - 1942 组合数学 (组合数的快速计算)
题意:格路问题 没什么难度 难点在于如何快速计算相对较大的组合数 思路:运用手写计算组合数的方式进行计算 如c(8,3) 如果手算就是 8*7*6/(3*2*1)这样可以很快得解出 计算代码为: ...
- [Swift通天遁地]五、高级扩展-(14)扩展String快速计算字符串中的各种数学表达式
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- numpy中的快速的元素级数组函数
numpy中的快速的元素级数组函数 一元(unary)ufunc 对于数组中的每一个元素,都将元素代入函数,将得到的结果放回到原来的位置 >>> import numpy as np ...
- 【瞎讲】 Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18)
[背诵瞎讲] Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18) 看CSP看到一题"线性递推式",不会做,去问了问zsy怎么做,他并 ...
- Excel怎样根据出生日期,快速计算出其年龄呢?
问题:怎样根据出生日期,快速计算出其年龄呢? 方法:DATEDIF函数 Step1:在编辑栏中输入公式:=DATEDIF(E2,TODAY(),”Y”),按回车键. Step2:用鼠标向下拖拽复制公式 ...
随机推荐
- ZOJ 3872: Beauty of Array(思维)
Beauty of Array Time Limit: 2 Seconds Memory Limit: 65536 KB Edward has an array A with N integers. ...
- FreeSql.Provider.SqliteCore如何加密
FreeSql.Provider.SqliteCore 是FreeSql基于微软提供的最新的Microsoft.Data.Sqlite.Core驱动的实现. 支持的版本 .NETStandard2.0 ...
- WHT, SLANT, Haar
目录 基本 酉变换 WALSH-HADAMARD TRANSFORMS sequency-ordered WHT SLANT TRANSFORM Haar Transform Gonzalez R. ...
- Distillation as a Defense to Adversarial Perturbations against Deep Neural Networks
目录 概 主要内容 算法 一些有趣的指标 鲁棒性定义 合格的抗干扰机制 Nicolas Papernot, Patrick McDaniel, Xi Wu, Somesh Jha, Ananthram ...
- Python Revisited Day10 (进程与线程)
目录 10.1 使用多进程模块 10.2 将工作分布到多个线程 <Python 3 程序开发指南>学习笔记 有俩种方法可以对工作载荷进行分布,一种是使用多进程,另一种是使用多线程. 10. ...
- 【云开发】10分钟零基础学会做一个快递查询微信小程序,快速掌握微信小程序开发技能(轮播图、API请求)
大家好,我叫小秃僧 这次分享的是10分钟零基础学会做一个快递查询微信小程序,快速掌握开发微信小程序技能. 这篇文章偏基础,特别适合还没有开发过微信小程序的童鞋,一些概念和逻辑我会讲细一点,尽可能用图说 ...
- .NET 云原生架构师训练营(ASP .NET Core 整体概念推演)--学习笔记
演化与完善整体概念 ASP .NET Core 整体概念推演 整体概念推演到具体的形式 ASP .NET Core 整体概念推演 ASP .NET Core 其实就是通过 web framework ...
- 编写Java程序,车站只剩 50 张从武汉到北京的车票,现有 3 个窗口售卖,用程序模拟售票的过程,使用Runnable解决线程安全问题
查看本章节 查看作业目录 需求说明: 车站只剩 50 张从武汉到北京的车票,现有 3 个窗口售卖,用程序模拟售票的过程,要求使用同步方法保证售票过程中票数的正确性 实现思路: 创建 Java 项目,在 ...
- Android 悬浮窗
悬浮窗是一种比较常见的需求.例如把视频通话界面缩小成一个悬浮窗,然后用户可以在其他界面上处理事情. 本文给出一个简单的悬浮窗实现.可缩小activity和还原大小.可悬浮在其他activity上.使用 ...
- GeoWave实践2:使用命令行将本地矢量数据注入hbase并发布至GeoServer
目录 步骤 补充 步骤 在GeoWave所在的节点打开两个会话窗口. 会话1 //运行GeoServer,默认端口8080 geowave gs run 会话2 //为GeoWave创建数据库Test ...