一、前言

       最近在对实验的测试结果进行统计,需要对代码进行相应的修改来对IOU进行计算,在网上找了一些关于IOU的资料,对IOU有了一定的理解,于是就想做一个随笔以提醒自己。

二、IOU介绍

        首先我们要先知道IOU是什么东西。交并比(Intersection-over-Union,IoU),是产生的候选框(candidate bound)与原标记框(ground truth bound)的交叠率,即它们的交集与并集的比值。下图所示

python 计算现值 python 计算iou_宽高

                       

python 计算现值 python 计算iou_人工智能_02

图片展现的非常直观,通俗来说就是:

是标记框和候选框

        2、两个矩形相交的面积 / (两个矩形的面积之和 - 两个矩形相交的面积)

 三、举个栗子

python 计算现值 python 计算iou_python_03

          

   注:G表示标记框(ground truth bound),P表示候选框(candidate bound)

重点来了:

        1、这两个矩形都是按左下右上的坐标来计算,同时也要注意坐标轴的方向下面的代码也是按左下和右上的坐标来计算

         2、网上的大部分博客,图是标的是左上右下的顶点坐标,但是代码清一色是通过左下右上顶点坐标来确定矩形位置的。所以看着很混乱。

 

python 计算现值 python 计算iou_python_03

 记住:左下全大,右上全小

相交的蓝色区域的左下角坐标(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

四、代码

可以运行看一看结果,再结合上面的步骤,看图能直观点(坐标点随机生成的,多运行几遍,每次结果都不同)

相交:

python 计算现值 python 计算iou_人工智能_05

 不相交:

python 计算现值 python 计算iou_经验分享_06

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()