Python 计算两个列表中所有IOU的有效方法

Python 计算两个列表中所有IOU的有效方法,python,numpy,Python,Numpy,我有一个函数来计算两个矩形/边界框的IoU def intersection_over_union(boxA, boxB): # determine the (x, y)-coordinates of the intersection rectangle xA = max(boxA[0], boxB[0]) yA = max(boxA[1], boxB[1]) xB = min(boxA[2], boxB[2]) yB = min(boxA[3], box

我有一个函数来计算两个矩形/边界框的IoU

def intersection_over_union(boxA, boxB):
    # determine the (x, y)-coordinates of the intersection rectangle
    xA = max(boxA[0], boxB[0])
    yA = max(boxA[1], boxB[1])
    xB = min(boxA[2], boxB[2])
    yB = min(boxA[3], boxB[3])

    # compute the area of intersection rectangle
    interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)

    # compute the area of both the prediction and ground-truth
    # rectangles
    boxAArea = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1)
    boxBArea = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1)

    # compute the intersection over union by taking the intersection
    # area and dividing it by the sum of prediction + ground-truth
    # areas - the interesection area
    iou = interArea / float(boxAArea + boxBArea - interArea)

    # return the intersection over union value
    return iou
现在,我想用另一个列表的BBox计算一个列表的所有BBox,也就是说,如果列表A包含4个BBox,列表B包含3个BBox,那么我想要一个包含所有可能IOU的4x3矩阵

当然,我可以用两个这样的循环来完成

import numpy as np

n_i = len(bboxes_a)
n_j = len(bboxes_b)
iou_mat = np.empty((n_i, n_j))
for i in range(n_i):
    for j in range(n_j):
        iou_mat[i, j] = intersection_over_union(bboxes_a[i], bboxes_b[j])
但这种方法非常缓慢,尤其是当列表变得非常大时

我正在努力寻找一种更有效的方法。必须有一种方法利用numpy来消除循环,但我不明白。现在的复杂性也是O(m*n)。是否有可能降低复杂性?

您可以在python中使用
product()
来替换嵌套的for循环。我认为使用内置函数总是更好。例如:

将numpy导入为np
l1=np.random.randint(0,10,(4,4))
l2=np.random.randint(0,10,(3,4))
打印(f'l1:\n{l1})
打印(f'l2:\n{l2}')
来自itertools进口产品
ious=np.数组(乘积(l1,l2)中box1,box2的[u与u并集(box1,box2)的交点])。重塑(len(l2),len(l1))
打印(文件:\n{ious})
此外,您应该将
iou=interrea/float(boxarea+boxBArea-interrea)
更改为
iou=interrea/float(boxarea+boxBArea-interrea+1e-16)
以避免
除以零错误。
您可以使用
产品()
在python中替换嵌套for循环。我认为使用内置函数总是更好。例如:

将numpy导入为np
l1=np.random.randint(0,10,(4,4))
l2=np.random.randint(0,10,(3,4))
打印(f'l1:\n{l1})
打印(f'l2:\n{l2}')
来自itertools进口产品
ious=np.数组(乘积(l1,l2)中box1,box2的[u与u并集(box1,box2)的交点])。重塑(len(l2),len(l1))
打印(文件:\n{ious})

此外,您应该将
iou=interrea/float(boxarea+boxBArea-interrea)
更改为
iou=interrea/float(boxarea+boxBArea-interrea+1e-16)
以避免
除以零错误。
矢量化:

low = np.s_[...,:2]
high = np.s_[...,2:]

def iou(A,B):
    A,B = A.copy(),B.copy()
    A[high] += 1; B[high] += 1
    intrs = (np.maximum(0,np.minimum(A[high],B[high])
                        -np.maximum(A[low],B[low]))).prod(-1)
    return intrs / ((A[high]-A[low]).prod(-1)+(B[high]-B[low]).prod(-1)-intrs)

AB = iou(A[:,None],B[None])
复杂性:

low = np.s_[...,:2]
high = np.s_[...,2:]

def iou(A,B):
    A,B = A.copy(),B.copy()
    A[high] += 1; B[high] += 1
    intrs = (np.maximum(0,np.minimum(A[high],B[high])
                        -np.maximum(A[low],B[low]))).prod(-1)
    return intrs / ((A[high]-A[low]).prod(-1)+(B[high]-B[low]).prod(-1)-intrs)

AB = iou(A[:,None],B[None])
由于您正在计算mxn值,因此不可能将复杂性降低到mxn以下,除非大多数值为零,并且可以接受矩阵的稀疏表示


这可以通过对A和B的所有端点进行argsorting(分别针对x和y)来完成。这就是O((M+N)log(M+N))编辑,因为坐标是整数,这里可能存在线性复杂度编辑结束然后可用于预过滤A x B。过滤和计算非零的复杂性为O(M+N+非零数量)。

矢量化:

low = np.s_[...,:2]
high = np.s_[...,2:]

def iou(A,B):
    A,B = A.copy(),B.copy()
    A[high] += 1; B[high] += 1
    intrs = (np.maximum(0,np.minimum(A[high],B[high])
                        -np.maximum(A[low],B[low]))).prod(-1)
    return intrs / ((A[high]-A[low]).prod(-1)+(B[high]-B[low]).prod(-1)-intrs)

AB = iou(A[:,None],B[None])
复杂性:

low = np.s_[...,:2]
high = np.s_[...,2:]

def iou(A,B):
    A,B = A.copy(),B.copy()
    A[high] += 1; B[high] += 1
    intrs = (np.maximum(0,np.minimum(A[high],B[high])
                        -np.maximum(A[low],B[low]))).prod(-1)
    return intrs / ((A[high]-A[low]).prod(-1)+(B[high]-B[low]).prod(-1)-intrs)

AB = iou(A[:,None],B[None])
由于您正在计算mxn值,因此不可能将复杂性降低到mxn以下,除非大多数值为零,并且可以接受矩阵的稀疏表示

这可以通过对A和B的所有端点进行argsorting(分别针对x和y)来完成。这就是O((M+N)log(M+N))编辑,因为坐标是整数,这里可能存在线性复杂度编辑结束然后可用于预过滤A x B。过滤和计算非零的复杂性为O(M+N+非零数量)