两次检测之间的交叉并集
Intersection-over-union between two detections
我正在阅读论文:
Ferrari et al. 在 "Affinity Measures" 部分。我知道法拉利等人。尝试通过 :
获得亲和力
- 位置亲和力 - 使用两次检测之间的交并区域
- 外观亲和力 - 使用直方图之间的欧氏距离
- KLT 点亲和力度量
但是,我有两个主要问题:
- 我无法理解 2 个检测之间的交并并集的实际含义以及如何计算它
- 我尝试了一种略有不同的外观亲和力测量。我将 RGB 检测转换为 HSV..将色相和饱和度连接成 1 个向量,并用它与其他检测进行比较。然而,使用这种技术失败了,因为对包的检测比对同一个人的头部(不同方向)的检测具有更好的相似性得分。
对我的上述问题有什么建议或解决方案吗?谢谢,非常感谢您的帮助。
1) 你有两个重叠的边界框。您计算框的交集,即重叠区域。您计算重叠框的并集,即整个框的面积减去重叠面积的总和。然后将交集除以并集。 Computer Vision System Toolbox 中有一个函数,名为 bboxOverlapRatio。
2) 通常,您不想连接颜色通道。相反,您想要的是 3D 直方图,其中维度为 H、S 和 V。
尝试在并集上交集
并集交集是一种评估指标,用于衡量对象检测器在特定数据集上的准确性。
更正式地说,为了应用 Intersection over Union 来评估(任意)对象检测器,我们需要:
- ground-truth 边界框(即来自测试集的手标边界框,指定我们的对象在图像中的位置)。
- 我们模型的预测边界框。
下面我提供了一个 ground-truth 边界框与预测边界框的可视化示例:
预测的边界框以红色绘制,而 ground-truth(即手动标记)边界框以绿色绘制。
在上图中,我们可以看到我们的对象检测器检测到图像中存在停车标志。
因此可以通过以下方式确定并集上的计算交集:
只要我们有这两组边界框,我们就可以应用 Intersection over Union。
这是Python代码
# import the necessary packages
from collections import namedtuple
import numpy as np
import cv2
# define the `Detection` object
Detection = namedtuple("Detection", ["image_path", "gt", "pred"])
def bb_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 = (xB - xA) * (yB - yA)
# compute the area of both the prediction and ground-truth
# rectangles
boxAArea = (boxA[2] - boxA[0]) * (boxA[3] - boxA[1])
boxBArea = (boxB[2] - boxB[0]) * (boxB[3] - boxB[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
gt
和pred
是
gt
: ground-truth 边界框。
pred
:我们模型的预测边界框。
更多信息,您可以点击this post
目前的答案已经把问题说清楚了。所以在这里我提供了一个更好的 IoU 版本 Python 当两个边界框不相交时它不会中断。
import numpy as np
def IoU(box1: np.ndarray, box2: np.ndarray):
"""
calculate intersection over union cover percent
:param box1: box1 with shape (N,4) or (N,2,2) or (2,2) or (4,). first shape is preferred
:param box2: box2 with shape (N,4) or (N,2,2) or (2,2) or (4,). first shape is preferred
:return: IoU ratio if intersect, else 0
"""
# first unify all boxes to shape (N,4)
if box1.shape[-1] == 2 or len(box1.shape) == 1:
box1 = box1.reshape(1, 4) if len(box1.shape) <= 2 else box1.reshape(box1.shape[0], 4)
if box2.shape[-1] == 2 or len(box2.shape) == 1:
box2 = box2.reshape(1, 4) if len(box2.shape) <= 2 else box2.reshape(box2.shape[0], 4)
point_num = max(box1.shape[0], box2.shape[0])
b1p1, b1p2, b2p1, b2p2 = box1[:, :2], box1[:, 2:], box2[:, :2], box2[:, 2:]
# mask that eliminates non-intersecting matrices
base_mat = np.ones(shape=(point_num,))
base_mat *= np.all(np.greater(b1p2 - b2p1, 0), axis=1)
base_mat *= np.all(np.greater(b2p2 - b1p1, 0), axis=1)
# I area
intersect_area = np.prod(np.minimum(b2p2, b1p2) - np.maximum(b1p1, b2p1), axis=1)
# U area
union_area = np.prod(b1p2 - b1p1, axis=1) + np.prod(b2p2 - b2p1, axis=1) - intersect_area
# IoU
intersect_ratio = intersect_area / union_area
return base_mat * intersect_ratio
这是我实施的另一个适合我的解决方案。
大量借鉴自PyImageSearch
import numpy as np
def bbox_intersects(bbox_a, bbox_b):
if bbox_b['x0'] >= bbox_a['x0'] and bbox_b['x0'] <= bbox_a['x1'] and \
bbox_b['y0'] >= bbox_a['y0'] and bbox_b['y0'] <= bbox_a['y1']:
# top-left of b within a
return True
elif bbox_b['x1'] >= bbox_a['x0'] and bbox_b['x1'] <= bbox_a['x1'] and \
bbox_b['y1'] >= bbox_a['y0'] and bbox_b['y1'] <= bbox_a['y1']:
# bottom-right of b within a
return True
elif bbox_a['x0'] >= bbox_b['x0'] and bbox_a['x0'] <= bbox_b['x1'] and \
bbox_a['y0'] >= bbox_b['y0'] and bbox_a['y0'] <= bbox_b['y1']:
# top-left of a within b
return True
elif bbox_a['x1'] >= bbox_b['x0'] and bbox_a['x1'] <= bbox_b['x1'] and \
bbox_a['y1'] >= bbox_b['y0'] and bbox_a['y1'] <= bbox_b['y1']:
# bottom-right of a within b
return True
return False
def bbox_area(x0, y0, x1, y1):
return (x1-x0) * (y1-y0)
def get_bbox_iou(bbox_a, bbox_b):
if bbox_intersects(bbox_a, bbox_b):
x_left = max(bbox_a['x0'], bbox_b['x0'])
x_right = min(bbox_a['x1'], bbox_b['x1'])
y_top = max(bbox_a['y0'], bbox_b['y0'])
y_bottom = min(bbox_a['y1'], bbox_b['y1'])
inter_area = bbox_area(x0 = x_left, x1 = x_right, y0 = y_top , y1 = y_bottom)
bbox_a_area = bbox_area(**bbox_a)
bbox_b_area = bbox_area(**bbox_b)
return inter_area / float(bbox_a_area + bbox_b_area - inter_area)
else:
return 0
我正在阅读论文: Ferrari et al. 在 "Affinity Measures" 部分。我知道法拉利等人。尝试通过 :
获得亲和力- 位置亲和力 - 使用两次检测之间的交并区域
- 外观亲和力 - 使用直方图之间的欧氏距离
- KLT 点亲和力度量
但是,我有两个主要问题:
- 我无法理解 2 个检测之间的交并并集的实际含义以及如何计算它
- 我尝试了一种略有不同的外观亲和力测量。我将 RGB 检测转换为 HSV..将色相和饱和度连接成 1 个向量,并用它与其他检测进行比较。然而,使用这种技术失败了,因为对包的检测比对同一个人的头部(不同方向)的检测具有更好的相似性得分。
对我的上述问题有什么建议或解决方案吗?谢谢,非常感谢您的帮助。
1) 你有两个重叠的边界框。您计算框的交集,即重叠区域。您计算重叠框的并集,即整个框的面积减去重叠面积的总和。然后将交集除以并集。 Computer Vision System Toolbox 中有一个函数,名为 bboxOverlapRatio。
2) 通常,您不想连接颜色通道。相反,您想要的是 3D 直方图,其中维度为 H、S 和 V。
尝试在并集上交集
并集交集是一种评估指标,用于衡量对象检测器在特定数据集上的准确性。
更正式地说,为了应用 Intersection over Union 来评估(任意)对象检测器,我们需要:
- ground-truth 边界框(即来自测试集的手标边界框,指定我们的对象在图像中的位置)。
- 我们模型的预测边界框。
下面我提供了一个 ground-truth 边界框与预测边界框的可视化示例:
预测的边界框以红色绘制,而 ground-truth(即手动标记)边界框以绿色绘制。
在上图中,我们可以看到我们的对象检测器检测到图像中存在停车标志。
因此可以通过以下方式确定并集上的计算交集:
只要我们有这两组边界框,我们就可以应用 Intersection over Union。
这是Python代码
# import the necessary packages
from collections import namedtuple
import numpy as np
import cv2
# define the `Detection` object
Detection = namedtuple("Detection", ["image_path", "gt", "pred"])
def bb_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 = (xB - xA) * (yB - yA)
# compute the area of both the prediction and ground-truth
# rectangles
boxAArea = (boxA[2] - boxA[0]) * (boxA[3] - boxA[1])
boxBArea = (boxB[2] - boxB[0]) * (boxB[3] - boxB[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
gt
和pred
是
gt
: ground-truth 边界框。pred
:我们模型的预测边界框。
更多信息,您可以点击this post
目前的答案已经把问题说清楚了。所以在这里我提供了一个更好的 IoU 版本 Python 当两个边界框不相交时它不会中断。
import numpy as np
def IoU(box1: np.ndarray, box2: np.ndarray):
"""
calculate intersection over union cover percent
:param box1: box1 with shape (N,4) or (N,2,2) or (2,2) or (4,). first shape is preferred
:param box2: box2 with shape (N,4) or (N,2,2) or (2,2) or (4,). first shape is preferred
:return: IoU ratio if intersect, else 0
"""
# first unify all boxes to shape (N,4)
if box1.shape[-1] == 2 or len(box1.shape) == 1:
box1 = box1.reshape(1, 4) if len(box1.shape) <= 2 else box1.reshape(box1.shape[0], 4)
if box2.shape[-1] == 2 or len(box2.shape) == 1:
box2 = box2.reshape(1, 4) if len(box2.shape) <= 2 else box2.reshape(box2.shape[0], 4)
point_num = max(box1.shape[0], box2.shape[0])
b1p1, b1p2, b2p1, b2p2 = box1[:, :2], box1[:, 2:], box2[:, :2], box2[:, 2:]
# mask that eliminates non-intersecting matrices
base_mat = np.ones(shape=(point_num,))
base_mat *= np.all(np.greater(b1p2 - b2p1, 0), axis=1)
base_mat *= np.all(np.greater(b2p2 - b1p1, 0), axis=1)
# I area
intersect_area = np.prod(np.minimum(b2p2, b1p2) - np.maximum(b1p1, b2p1), axis=1)
# U area
union_area = np.prod(b1p2 - b1p1, axis=1) + np.prod(b2p2 - b2p1, axis=1) - intersect_area
# IoU
intersect_ratio = intersect_area / union_area
return base_mat * intersect_ratio
这是我实施的另一个适合我的解决方案。
大量借鉴自PyImageSearch
import numpy as np
def bbox_intersects(bbox_a, bbox_b):
if bbox_b['x0'] >= bbox_a['x0'] and bbox_b['x0'] <= bbox_a['x1'] and \
bbox_b['y0'] >= bbox_a['y0'] and bbox_b['y0'] <= bbox_a['y1']:
# top-left of b within a
return True
elif bbox_b['x1'] >= bbox_a['x0'] and bbox_b['x1'] <= bbox_a['x1'] and \
bbox_b['y1'] >= bbox_a['y0'] and bbox_b['y1'] <= bbox_a['y1']:
# bottom-right of b within a
return True
elif bbox_a['x0'] >= bbox_b['x0'] and bbox_a['x0'] <= bbox_b['x1'] and \
bbox_a['y0'] >= bbox_b['y0'] and bbox_a['y0'] <= bbox_b['y1']:
# top-left of a within b
return True
elif bbox_a['x1'] >= bbox_b['x0'] and bbox_a['x1'] <= bbox_b['x1'] and \
bbox_a['y1'] >= bbox_b['y0'] and bbox_a['y1'] <= bbox_b['y1']:
# bottom-right of a within b
return True
return False
def bbox_area(x0, y0, x1, y1):
return (x1-x0) * (y1-y0)
def get_bbox_iou(bbox_a, bbox_b):
if bbox_intersects(bbox_a, bbox_b):
x_left = max(bbox_a['x0'], bbox_b['x0'])
x_right = min(bbox_a['x1'], bbox_b['x1'])
y_top = max(bbox_a['y0'], bbox_b['y0'])
y_bottom = min(bbox_a['y1'], bbox_b['y1'])
inter_area = bbox_area(x0 = x_left, x1 = x_right, y0 = y_top , y1 = y_bottom)
bbox_a_area = bbox_area(**bbox_a)
bbox_b_area = bbox_area(**bbox_b)
return inter_area / float(bbox_a_area + bbox_b_area - inter_area)
else:
return 0