Spaces:
Running
Running
# This code is a copy and paste with small modifications of the code: | |
# https://github.com/rafaelpadilla/review_object_detection_metrics/blob/main/src/evaluators/coco_evaluator.py | |
from typing import List | |
import numpy as np | |
class MaskEvaluator(object): | |
def iou( | |
dt: List[List[float]], gt: List[List[float]], iscrowd: List[bool] | |
) -> np.ndarray: | |
""" | |
Calculate the intersection over union (IoU) between detection bounding boxes (dt) and \ | |
ground truth bounding boxes (gt). | |
Reference: https://github.com/rafaelpadilla/review_object_detection_metrics | |
Args: | |
dt (List[List[float]]): List of detection bounding boxes in the \ | |
format [x, y, width, height]. | |
gt (List[List[float]]): List of ground-truth bounding boxes in the \ | |
format [x, y, width, height]. | |
iscrowd (List[bool]): List indicating if each ground-truth bounding box \ | |
is a crowd region or not. | |
Returns: | |
np.ndarray: Array of IoU values of shape (len(dt), len(gt)). | |
""" | |
assert len(iscrowd) == len(gt), "iou(iscrowd=) must have the same length as gt" | |
if len(dt) == 0 or len(gt) == 0: | |
return [] | |
ious = np.zeros((len(dt), len(gt)), dtype=np.float64) | |
for g_idx, g in enumerate(gt): | |
for d_idx, d in enumerate(dt): | |
ious[d_idx, g_idx] = _jaccard(d, g, iscrowd[g_idx]) | |
return ious | |
def _jaccard(a: List[float], b: List[float], iscrowd: bool) -> float: | |
""" | |
Calculate the Jaccard index (intersection over union) between two bounding boxes. | |
For "crowd" regions, we use a modified criteria. If a gt object is | |
marked as "iscrowd", we allow a dt to match any subregion of the gt. | |
Choosing gt' in the crowd gt that best matches the dt can be done using | |
gt'=intersect(dt,gt). Since by definition union(gt',dt)=dt, computing | |
iou(gt,dt,iscrowd) = iou(gt',dt) = area(intersect(gt,dt)) / area(dt) | |
For crowd gt regions we use this modified criteria above for the iou. | |
Args: | |
a (List[float]): Bounding box coordinates in the format [x, y, width, height]. | |
b (List[float]): Bounding box coordinates in the format [x, y, width, height]. | |
iscrowd (bool): Flag indicating if the second bounding box is a crowd region or not. | |
Returns: | |
float: Jaccard index between the two bounding boxes. | |
""" | |
eps = 4e-12 | |
xa, ya, x2a, y2a = a[0], a[1], a[0] + a[2], a[1] + a[3] | |
xb, yb, x2b, y2b = b[0], b[1], b[0] + b[2], b[1] + b[3] | |
# innermost left x | |
xi = max(xa, xb) | |
# innermost right x | |
x2i = min(x2a, x2b) | |
# same for y | |
yi = max(ya, yb) | |
y2i = min(y2a, y2b) | |
# calculate areas | |
Aa = max(x2a - xa, 0.) * max(y2a - ya, 0.) | |
Ab = max(x2b - xb, 0.) * max(y2b - yb, 0.) | |
Ai = max(x2i - xi, 0.) * max(y2i - yi, 0.) | |
if iscrowd: | |
return Ai / (Aa + eps) | |
return Ai / (Aa + Ab - Ai + eps) | |