浅谈Python3实现两个矩形的交并比(IoU)


Posted in Python onJanuary 18, 2020

一、前言

因为最近刚好被问到这个问题,但是自己当时特别懵逼,导致没有做出来。所以下来后自己Google了很多IoU的博客,但是很多博客要么过于简略,要么是互相转载的,有一些博客图和代码还有点问题,也导致自己这个萌新走了不少弯路。所以自己重新整理了看的博客,力求以更简单的方式展现这个问题的解答办法,方便日后自己回顾。如果朋友们觉得写的有问题的地方,非常欢迎大家在下面留言交流,避免因为我的问题导致读者走弯路。

二、交并比的概念及应用

假设平面坐标中有一个矩形,并且这个矩形的长和宽均分别与x轴和y轴平行。

那么矩形在平面坐标中的唯一位置可以通过对角线上的两个顶点坐标来确定(这里不做证明)。

如下图所示:这个矩形的唯一位置可以用左上和右下的顶点坐标,即:(xmin, ymax, xmax, ymin)来确定,也可以用左下和右上顶点坐标,即(xmin, ymin, xmax, ymax)来确定。

接下来说一下自己踩的坑:网上的大部分博客,图是标的是左上和右下的顶点坐标,但是代码清一色是通过左下和右上顶点坐标来确定矩形位置的。所以一开始看着特别晕圈。

理论上两种确定方式都可以,不过相对而言,通过左下和右上两个顶点坐标,即(xmin, ymin, xmax, ymax)来确定矩形位置更符合我们的习惯,我想这也是网上大部分代码都是这样的原因吧。

浅谈Python3实现两个矩形的交并比(IoU)

矩形的面积很好求,长X宽就行:

矩形的面积 = (xmax -xmin) X (ymax - ymin)

好了,理清楚怎么确定矩形的位置后,接下来我们就来解决交并比的计算问题。

交并比(Intersection over Union, IoU)是目标检测任务中的一个非常重要的概念。它是产生的预测框(Predicted bounding box)与原标记框(Ground-truth bounding box)的交叠率,即它们的交集(相交面积)与并集(总面积)的比值。最理想情况是完全重叠,即比值为1。一般来说,这个score > 0.5 就可以被认为是一个不错的结果。这个标准用于测量真实和预测之间的相关度,相关度越高,该值越高,它可以评估算法的准确度。

假设平面坐标中有两个矩形:原标记框(Ground-truth bounding box, G)和预测框(Predicted bounding box, P),其中G为手动标记的框,P为算法预测的框,并且这两个矩形的长和宽均分别与x轴和y轴平行。如下图所示:

浅谈Python3实现两个矩形的交并比(IoU)

IoU计算公式:

浅谈Python3实现两个矩形的交并比(IoU)

所以有:矩形G(gxmin, gymin, gxmax, gymax)和矩形P(pxmin, pymin, pxmax, pymax)

求交并比的关键是求出相交矩形G∩P的面积。

解决这个问题,我们只要确定相交矩形的左下(xmin, ymin)和右上(xmax, ymax)顶点坐标即可,即确定(xmin, ymin, xmax, ymax)。

通过看图,我们可以清楚的观察到:

# 相交矩形的左下顶点坐标, 就是两个矩形左下坐标的x和y分别取最大值
xmin = max(gxmin, pxmin)
ymin = max(gymin, pymin)
# 相交矩形的右上顶点坐标, 就是两个矩形右上坐标的x和y分别取最小值
xmax = min(gxmax, pxmax)
ymax = min(gymax, pyxmax)

如果一下没有看明白,可以自己在纸上多画画,理解下。

得到了相交矩形的坐标(xmin, ymin, xmax, ymax)那么相交矩形的面积就非常简单了。

area(G∩P) = 长 X 宽

w = xmax - xmin # 计算相交矩形的长

h = ymax - ymin # 计算相交矩形的宽

area(G∩P) = w X h # 计算相交矩形的面积

这里还有最后一个问题,当计算得到的宽或者长为0或者负数时,说明两个矩形不相交,相交面积为0,那么最后的IoU就为0。这里我们有两种处理方式:

1. 用if语句来分类讨论:

if w <=0 or h <= 0:
 return 0

2. 用max()方法来处理:

w = max(0, (x2 - x1))
h = max(0, (y1 - y2))

三、Python3 实现代码

经过以上分析,思路应该已经非常清晰了,这里我就直接放出完整Python3代码。

def calculate_IoU(predicted_bound, ground_truth_bound):
 """
 computing the IoU of two boxes.
 Args:
  box: (xmin, ymin, xmax, ymax),通过左下和右上两个顶点坐标来确定矩形位置
 Return:
  IoU: IoU of box1 and box2.
 """
 pxmin, pymin, pxmax, pymax = predicted_bound
 print("预测框P的坐标是:({}, {}, {}, {})".format(pxmin, pymin, pxmax, pymax))
 gxmin, gymin, gxmax, gymax = ground_truth_bound
 print("原标记框G的坐标是:({}, {}, {}, {})".format(gxmin, gymin, gxmax, gymax))

 parea = (pxmax - pxmin) * (pymax - pymin) # 计算P的面积
 garea = (gxmax - gxmin) * (gymax - gymin) # 计算G的面积
 print("预测框P的面积是:{};原标记框G的面积是:{}".format(parea, garea))

 # 求相交矩形的左下和右上顶点坐标(xmin, ymin, xmax, ymax)
 xmin = max(pxmin, gxmin) # 得到左下顶点的横坐标
 ymin = max(pymin, gymin) # 得到左下顶点的纵坐标
 xmax = min(pxmax, gxmax) # 得到右上顶点的横坐标
 ymax = min(pymax, gymax) # 得到右上顶点的纵坐标

 # 计算相交矩形的面积
 w = xmax - xmin
 h = ymax - ymin
 if w <=0 or h <= 0:
  return 0

 area = w * h # G∩P的面积
 # area = max(0, xmax - xmin) * max(0, ymax - ymin) # 可以用一行代码算出来相交矩形的面积
 print("G∩P的面积是:{}".format(area))

 # 并集的面积 = 两个矩形面积 - 交集面积
 IoU = area / (parea + garea - area)

 return IoU

if __name__ == '__main__':
 IoU = calculate_IoU( (1, -1, 3, 1), (0, 0, 2, 2))
 print("IoU是:{}".format(IoU))

这里也放一下通过左上和右下顶点坐标来确定矩形的位置的Python3代码。原理是一样的,不要弄混就好。

浅谈Python3实现两个矩形的交并比(IoU)

def calculate_IoU(predicted_bound, ground_truth_bound):
 """
 computing the IoU of two boxes.
 Args:
  box: (x1, y1, x2, y2),通过左上和右下两个顶点坐标来确定矩形
 Return:
  IoU: IoU of box1 and box2.
 """
 px1, py1, px2, py2 = predicted_bound
 print("预测框P的坐标是:({}, {}, {}, {})".format(px1, py1, px2, py2))

 gx1, gy1, gx2, gy2 = ground_truth_bound
 print("原标记框G的坐标是:({}, {}, {}, {})".format(gx1, gy1, gx2, gy2))

 parea = (px2 - px1) * (py1 - py2) # 计算P的面积
 garea = (gx2 - gx1) * (gy1 - gy2) # 计算G的面积
 print("预测框P的面积是:{};原标记框G的面积是:{}".format(parea, garea))

 # 求相交矩形的左上和右下顶点坐标(x1, y1, x2, y2)
 x1 = max(px1, gx1) # 得到左上顶点的横坐标
 y1 = min(py1, gy1) # 得到左上顶点的纵坐标
 x2 = min(px2, gx2) # 得到右下顶点的横坐标
 y2 = max(py2, gy2) # 得到右下顶点的纵坐标

 # 利用max()方法处理两个矩形没有交集的情况,当没有交集时,w或者h取0,比较巧妙的处理方法
 # w = max(0, (x2 - x1)) # 相交矩形的长,这里用w来表示
 # h = max(0, (y1 - y2)) # 相交矩形的宽,这里用h来表示
 # print("相交矩形的长是:{},宽是:{}".format(w, h))
 # 这里也可以考虑引入if判断
 w = x2 - x1
 h = y1 - y2
 if w <=0 or h <= 0:
  return 0

 area = w * h # G∩P的面积
 print("G∩P的面积是:{}".format(area))

 # 并集的面积 = 两个矩形面积 - 交集面积
 IoU = area / (parea + garea - area)

 return IoU

if __name__ == '__main__':
 IoU = calculate_IoU( (1, 1, 3, -1), (0, 2, 2, 0))
 print("IoU是:{}".format(IoU))

以上这篇浅谈Python3实现两个矩形的交并比(IoU)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现多线程的方式及多条命令并发执行
Jun 07 Python
Python实现将一个大文件按段落分隔为多个小文件的简单操作方法
Apr 17 Python
Python实现Windows和Linux之间互相传输文件(文件夹)的方法
May 08 Python
python中返回矩阵的行列方法
Apr 04 Python
TensorFlow损失函数专题详解
Apr 26 Python
pytorch绘制并显示loss曲线和acc曲线,LeNet5识别图像准确率
Jan 02 Python
python操作docx写入内容,并控制文本的字体颜色
Feb 13 Python
Python如何使用正则表达式爬取京东商品信息
Jun 01 Python
音频处理 windows10下python三方库librosa安装教程
Jun 20 Python
Alpine安装Python3依赖出现的问题及解决方法
Dec 25 Python
python利用proxybroker构建爬虫免费IP代理池的实现
Feb 21 Python
Python干货实战之八音符酱小游戏全过程详解
Oct 24 Python
利用setuptools打包python程序的方法步骤
Jan 18 #Python
python计算二维矩形IOU实例
Jan 18 #Python
解决python replace函数替换无效问题
Jan 18 #Python
使用Python来做一个屏幕录制工具的操作代码
Jan 18 #Python
pytorch 状态字典:state_dict使用详解
Jan 17 #Python
Python标准库itertools的使用方法
Jan 17 #Python
Python实现投影法分割图像示例(二)
Jan 17 #Python
You might like
第五节 克隆 [5]
2006/10/09 PHP
关于PHP语言构造器介绍
2013/07/08 PHP
php字符比较函数similar_text、strnatcmp与strcasecmp用法分析
2014/11/18 PHP
php创建桌面快捷方式实现方法
2015/12/31 PHP
PHP抓取及分析网页的方法详解
2016/04/26 PHP
可以文本显示的公告栏的js代码
2007/03/11 Javascript
javascript 清除输入框中的数据
2009/04/13 Javascript
javascript学习笔记(十五) js间歇调用和超时调用
2012/06/20 Javascript
网站内容禁止复制和粘贴、另存为的js代码
2014/02/26 Javascript
javascript实现des解密加密全过程
2014/04/03 Javascript
jQuery控制网页打印指定区域的方法
2015/04/07 Javascript
jQuery增加自定义函数的方法
2015/07/18 Javascript
JS实现下拉菜单赋值到文本框的方法
2015/08/18 Javascript
JavaScript实现的DOM树遍历方法详解【二叉DOM树、多叉DOM树】
2018/05/07 Javascript
微信小程序实现分享到朋友圈功能
2018/07/19 Javascript
VueCli生产环境打包部署跨域失败的解决
2020/11/13 Javascript
探寻python多线程ctrl+c退出问题解决方案
2014/10/23 Python
小小聊天室Python代码实现
2016/08/17 Python
关于Python 3中print函数的换行详解
2017/08/08 Python
python 3.0 模拟用户登录功能并实现三次错误锁定
2017/11/01 Python
PyCharm代码格式调整方法
2018/05/23 Python
Python3.6.0+opencv3.3.0人脸检测示例
2018/05/25 Python
python实现抽奖小程序
2020/04/15 Python
在Python中构建增广矩阵的实现方法
2019/07/01 Python
Numpy 理解ndarray对象的示例代码
2020/04/03 Python
Python参数传递及收集机制原理解析
2020/06/05 Python
Keras中 ImageDataGenerator函数的参数用法
2020/07/03 Python
python装饰器实现对异常代码出现进行自动监控的实现方法
2020/09/15 Python
is_file和file_exists效率比较
2021/03/14 PHP
乌克兰数字设备、配件和智能技术的连锁商店:KTC
2020/08/18 全球购物
Order by的几种用法
2013/06/16 面试题
Python面试题集
2012/03/08 面试题
公司试用期员工自我评价
2014/09/17 职场文书
美术教师求职信范文
2015/03/20 职场文书
在校生证明
2015/06/17 职场文书
Python opencv缺陷检测的实现及问题解决
2021/04/24 Python