|
|
|
# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
|
|
|
|
"""
|
|
|
|
Model validation metrics
|
|
|
|
"""
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
import torch
|
|
|
|
|
|
|
|
|
|
|
|
def box_area(box):
|
|
|
|
# box = xyxy(4,n)
|
|
|
|
return (box[2] - box[0]) * (box[3] - box[1])
|
|
|
|
|
|
|
|
|
|
|
|
def bbox_ioa(box1, box2, eps=1e-7):
|
|
|
|
"""Returns the intersection over box2 area given box1, box2. Boxes are x1y1x2y2
|
|
|
|
box1: np.array of shape(4)
|
|
|
|
box2: np.array of shape(nx4)
|
|
|
|
returns: np.array of shape(n)
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Get the coordinates of bounding boxes
|
|
|
|
b1_x1, b1_y1, b1_x2, b1_y2 = box1
|
|
|
|
b2_x1, b2_y1, b2_x2, b2_y2 = box2.T
|
|
|
|
|
|
|
|
# Intersection area
|
|
|
|
inter_area = (np.minimum(b1_x2, b2_x2) - np.maximum(b1_x1, b2_x1)).clip(0) * \
|
|
|
|
(np.minimum(b1_y2, b2_y2) - np.maximum(b1_y1, b2_y1)).clip(0)
|
|
|
|
|
|
|
|
# box2 area
|
|
|
|
box2_area = (b2_x2 - b2_x1) * (b2_y2 - b2_y1) + eps
|
|
|
|
|
|
|
|
# Intersection over box2 area
|
|
|
|
return inter_area / box2_area
|
|
|
|
|
|
|
|
|
|
|
|
def box_iou(box1, box2, eps=1e-7):
|
|
|
|
# https://github.com/pytorch/vision/blob/master/torchvision/ops/boxes.py
|
|
|
|
"""
|
|
|
|
Return intersection-over-union (Jaccard index) of boxes.
|
|
|
|
Both sets of boxes are expected to be in (x1, y1, x2, y2) format.
|
|
|
|
Arguments:
|
|
|
|
box1 (Tensor[N, 4])
|
|
|
|
box2 (Tensor[M, 4])
|
|
|
|
Returns:
|
|
|
|
iou (Tensor[N, M]): the NxM matrix containing the pairwise
|
|
|
|
IoU values for every element in boxes1 and boxes2
|
|
|
|
"""
|
|
|
|
|
|
|
|
# inter(N,M) = (rb(N,M,2) - lt(N,M,2)).clamp(0).prod(2)
|
|
|
|
(a1, a2), (b1, b2) = box1[:, None].chunk(2, 2), box2.chunk(2, 1)
|
|
|
|
inter = (torch.min(a2, b2) - torch.max(a1, b1)).clamp(0).prod(2)
|
|
|
|
|
|
|
|
# IoU = inter / (area1 + area2 - inter)
|
|
|
|
return inter / (box_area(box1.T)[:, None] + box_area(box2.T) - inter + eps)
|