import numpy as np import time def IoU(box, boxes): """Compute IoU between detect box and gt boxes Parameters: ---------- box: numpy array , shape (5, ): x1, y1, x2, y2, score input box boxes: numpy array, shape (n, 4): x1, y1, x2, y2 input ground truth boxes Returns: ------- ovr: numpy.array, shape (n, ) IoU """ box_area = (box[2] - box[0] + 1) * (box[3] - box[1] + 1) area = (boxes[:, 2] - boxes[:, 0] + 1) * (boxes[:, 3] - boxes[:, 1] + 1) xx1 = np.maximum(box[0], boxes[:, 0]) yy1 = np.maximum(box[1], boxes[:, 1]) xx2 = np.minimum(box[2], boxes[:, 2]) yy2 = np.minimum(box[3], boxes[:, 3]) # compute the width and height of the bounding box w = np.maximum(0, xx2 - xx1 + 1) h = np.maximum(0, yy2 - yy1 + 1) inter = w * h ovr = np.true_divide(inter,(box_area + area - inter)) #ovr = inter / (box_area + area - inter) return ovr def convert_to_square(bbox): """Convert bbox to square Parameters: ---------- bbox: numpy array , shape n x 5 input bbox Returns: ------- square bbox """ square_bbox = bbox.copy() h = bbox[:, 3] - bbox[:, 1] + 1 w = bbox[:, 2] - bbox[:, 0] + 1 max_side = np.maximum(h,w) square_bbox[:, 0] = bbox[:, 0] + w*0.5 - max_side*0.5 square_bbox[:, 1] = bbox[:, 1] + h*0.5 - max_side*0.5 square_bbox[:, 2] = square_bbox[:, 0] + max_side - 1 square_bbox[:, 3] = square_bbox[:, 1] + max_side - 1 return square_bbox # non-maximum suppression: eleminates the box which have large interception with the box which have the largest score def nms(dets, thresh, mode="Union"): """ greedily select boxes with high confidence keep boxes overlap <= thresh rule out overlap > thresh :param dets: [[x1, y1, x2, y2 score]] :param thresh: retain overlap <= thresh :return: indexes to keep """ x1 = dets[:, 0] y1 = dets[:, 1] x2 = dets[:, 2] y2 = dets[:, 3] scores = dets[:, 4] # shape of x1 = (454,), shape of scores = (454,) # print("shape of x1 = {0}, shape of scores = {1}".format(x1.shape, scores.shape)) # time.sleep(5) areas = (x2 - x1 + 1) * (y2 - y1 + 1) order = scores.argsort()[::-1] # argsort: ascending order then [::-1] reverse the order --> descending order # print("shape of order {0}".format(order.size)) # (454,) # time.sleep(5) # eleminates the box which have large interception with the box which have the largest score in order # matain the box with largest score and boxes don't have large interception with it keep = [] while order.size > 0: i = order[0] keep.append(i) xx1 = np.maximum(x1[i], x1[order[1:]]) yy1 = np.maximum(y1[i], y1[order[1:]]) xx2 = np.minimum(x2[i], x2[order[1:]]) yy2 = np.minimum(y2[i], y2[order[1:]]) w = np.maximum(0.0, xx2 - xx1 + 1) h = np.maximum(0.0, yy2 - yy1 + 1) inter = w * h # cacaulate the IOU between box which have largest score with other boxes if mode == "Union": # area[i]: the area of largest score ovr = inter / (areas[i] + areas[order[1:]] - inter) elif mode == "Minimum": ovr = inter / np.minimum(areas[i], areas[order[1:]]) inds = np.where(ovr <= thresh)[0] order = order[inds + 1] # +1: eliminates the first element in order # print(inds) # print("shape of order {0}".format(order.shape)) # (454,) # time.sleep(2) return keep