Created
February 22, 2018 16:10
-
-
Save AruniRC/c629c2df0e68e23aff7dcaeef87c72d4 to your computer and use it in GitHub Desktop.
Object detector util: match a set of detected bounding boxes and a set of ground-truth bounding boxes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import division | |
import scipy.optimize | |
import numpy as np | |
def bbox_iou(boxA, boxB): | |
# https://www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/ | |
# ^^ corrected. | |
# 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]) | |
interW = xB - xA + 1 | |
interH = yB - yA + 1 | |
# Correction: reject non-overlapping boxes | |
if interW <=0 or interH <=0 : | |
return -1.0 | |
interArea = interW * interH | |
boxAArea = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1) | |
boxBArea = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1) | |
iou = interArea / float(boxAArea + boxBArea - interArea) | |
return iou | |
def match_bboxes(bbox_gt, bbox_pred, IOU_THRESH=0.5): | |
''' | |
Given sets of true and predicted bounding-boxes, | |
determine the best possible match. | |
Parameters | |
---------- | |
bbox_gt, bbox_pred : N1x4 and N2x4 np array of bboxes [x1,y1,x2,y2]. | |
The number of bboxes, N1 and N2, need not be the same. | |
Returns | |
------- | |
(idxs_true, idxs_pred, ious, labels) | |
idxs_true, idxs_pred : indices into gt and pred for matches | |
ious : corresponding IOU value of each match | |
labels: vector of 0/1 values for the list of detections | |
''' | |
n_true = bbox_gt.shape[0] | |
n_pred = bbox_pred.shape[0] | |
MAX_DIST = 1.0 | |
MIN_IOU = 0.0 | |
# NUM_GT x NUM_PRED | |
iou_matrix = np.zeros((n_true, n_pred)) | |
for i in range(n_true): | |
for j in range(n_pred): | |
iou_matrix[i, j] = bbox_iou(bbox_gt[i,:], bbox_pred[j,:]) | |
if n_pred > n_true: | |
# there are more predictions than ground-truth - add dummy rows | |
diff = n_pred - n_true | |
iou_matrix = np.concatenate( (iou_matrix, | |
np.full((diff, n_pred), MIN_IOU)), | |
axis=0) | |
if n_true > n_pred: | |
# more ground-truth than predictions - add dummy columns | |
diff = n_true - n_pred | |
iou_matrix = np.concatenate( (iou_matrix, | |
np.full((n_true, diff), MIN_IOU)), | |
axis=1) | |
# call the Hungarian matching | |
idxs_true, idxs_pred = scipy.optimize.linear_sum_assignment(1 - iou_matrix) | |
if (not idxs_true.size) or (not idxs_pred.size): | |
ious = np.array([]) | |
else: | |
ious = iou_matrix[idxs_true, idxs_pred] | |
# remove dummy assignments | |
sel_pred = idxs_pred<n_pred | |
idx_pred_actual = idxs_pred[sel_pred] | |
idx_gt_actual = idxs_true[sel_pred] | |
ious_actual = iou_matrix[idx_gt_actual, idx_pred_actual] | |
sel_valid = (ious_actual > IOU_THRESH) | |
label = sel_valid.astype(int) | |
return idx_gt_actual[sel_valid], idx_pred_actual[sel_valid], ious_actual[sel_valid], label | |
C0NGTRI123
commented
Jul 5, 2023
Thanks! Didn't know about scipy.optimize.linear_sum_assignment
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment