最近在对实验的测试结果进行统计,需要对代码进行相应的修改来对IOU进行计算,在网上找了一些关于IOU的资料,对IOU有了一定的理解,于是就想做一个随笔以提醒自己。
首先我们要先知道IOU是什么东西。交并比(Intersection-over-Union,IoU),是产生的候选框(candidate bound)与原标记框(ground truth bound)的交叠率,即它们的交集与并集的比值。下图所示
图片展现的非常直观,通俗来说就是:
1、两个矩形框相交的面积 / 两个矩形框并起来的面积,(是标记框和候选框)
2、两个矩形相交的面积 / (两个矩形的面积之和 - 两个矩形相交的面积)
注:G表示标记框(ground truth bound),P表示候选框(candidate bound)
(重点来了:
1、这两个矩形都是按左下和右上的坐标来计算,同时也要注意坐标轴的方向。下面的代码也是按左下和右上的坐标来计算
2、网上的大部分博客,图是标的是左上和右下的顶点坐标,但是代码清一色是通过左下和右上顶点坐标来确定矩形位置的。所以看着很混乱。
记住:左下全大,右上全小
1、中间相交的蓝色区域的左下角坐标(xmin,ymin):要看G和P的左下角坐标对比,取这两个框横纵坐标都最大的。比如(gxmin,gymin)=(1, 2),(pxmin,pymin)=(2, 1),那么(xmin,ymin) = (2, 2)
2、右上角坐标(xmin,ymin):要看G和P的右上角坐标对比,取这两个框横纵坐标都最小的。比如(gxmax,gymax)=(4, 4),(pxmax,pymax)=(6, 3),那么(xmin,ymin) = (4, 3)
3、w(相交矩形的宽 )=(xmax-xmin),h(相交矩形的高) =(yman-ymin)
4、判断相交与否:就看第3步算出来的宽或者高是不是大于0
可以运行看一看结果,再结合上面的步骤,看图能直观点(坐标点随机生成的,多运行几遍,每次结果都不同)
相交:
不相交:
import random
import matplotlib.pyplot as plt # plot:绘制
# 注意一般bbox的表示方式有两种:
# 第一种:用中心加宽高表示 (x, y, w, h);
# 第二种:用左上右下两个角点表示 (x1, y1, x2, y2)
# 使用别人代码时注意表示方式
# 因为这是随机产生的,要保证右上横坐标 > 左下横坐标,右上纵坐标 > 左下纵坐标
# 原标记框G的坐标
gxmin, gymin, gxmax, gymax = random.sample(range(0, 6), 4)
if gxmin > gxmax:
gxmin, gxmax = gxmax, gxmin
if gymax < gymin:
gymin, gymax = gymax, gymin
print("1.蓝色标记框G的坐标是:({}, {}), ({}, {})".format(gxmin, gymin, gxmax, gymax))
# 预测框P的坐标
pxmin, pymin, pxmax, pymax = random.sample(range(0, 6), 4)
if pxmin > pxmax:
pxmin, pxmax = pxmax, pxmin
if pymax < pymin:
pymin, pymax = pymax, pymin
print("2.红色预测框P的坐标是:({}, {}), ({}, {})".format(pxmin, pymin, pxmax, pymax))
# 相交的的坐标
xmin = max(gxmin, pxmin)
ymin = max(gymin, pymin)
xmax = min(gxmax, pxmax)
ymax = min(gymax, pymax)
print("3.假定相交的的坐标是:({}, {}), ({}, {})".format(xmin, ymin, xmax, ymax))
# 假定相交的宽和高
w = xmax - xmin
h = ymax - ymin
# 判断相交与否
if w <= 0 or h <= 0:
print("4.不相交")
# 画不相交的图
fig1 = plt.figure("不相交") # 图像标题为
ax1 = fig1.add_subplot(111) # 将画布分为1*1,并且将画布定位到第一个axis系中
ax1.add_patch(
plt.Rectangle(
(gxmin, gymin), # (x,y)矩形左下角
gxmax - gxmin, # width长
gymax - gymin, # height宽
color='blue',
alpha=0.5
)
)
ax1.add_patch(
plt.Rectangle(
(pxmin, pymin), # (x,y)矩形左下角
pxmax - pxmin, # width长
pymax - pymin, # height宽
color='red',
alpha=0.5)
)
plt.xlim(0, 6)
plt.ylim(0, 6)
plt.show()
plt.close(1)
else:
print("4.相交")
# 求相交面积
area = w * h
print("5.相交的面积是:{}".format(area))
garea = (gxmax - gxmin) * (gymax - gymin)
print("6.蓝色标记框G的面积是:{}".format(garea))
parea = (pxmax - pxmin) * (pymax - pymin)
print("7.红色预测框P的面积是:{}".format(parea))
IOU = area / (garea + parea - area)
print("8.IOU = {} = {} / ({} + {} - {})".format(IOU, area, garea, parea, area))
fig1 = plt.figure("相交") # 图像标题为
ax1 = fig1.add_subplot(111) # 将画布分为1*1,并且将画布定位到第一个axis系中
ax1.add_patch(
plt.Rectangle(
(gxmin, gymin), # (x,y)矩形左下角
gxmax - gxmin, # width长
gymax - gymin, # height宽
color='blue',
alpha=0.5
)
)
ax1.add_patch(
plt.Rectangle(
(pxmin, pymin), # (x,y)矩形左下角
pxmax - pxmin, # width长
pymax - pymin, # height宽
color='red',
alpha=0.5)
)
plt.xlim(0, 6)
plt.ylim(0, 6)
plt.show()