Spaces:
Sleeping
Sleeping
| import numpy as np | |
| def paired_intersection(boxes1, boxes2): | |
| """Compute paired intersection areas between boxes. | |
| Args: | |
| boxes1: a numpy array with shape [N, 4] holding N boxes | |
| boxes2: a numpy array with shape [N, 4] holding N boxes | |
| Returns: | |
| a numpy array with shape [N,] representing itemwise intersection area | |
| References: | |
| `core.box_list_ops.matched_intersection` in Tensorflow object detection API | |
| Notes: | |
| can called as itemwise_intersection, matched_intersection, aligned_intersection | |
| """ | |
| max_x_mins = np.maximum(boxes1[:, 0], boxes2[:, 0]) | |
| max_y_mins = np.maximum(boxes1[:, 1], boxes2[:, 1]) | |
| min_x_maxs = np.minimum(boxes1[:, 2], boxes2[:, 2]) | |
| min_y_maxs = np.minimum(boxes1[:, 3], boxes2[:, 3]) | |
| intersect_widths = np.maximum(0, min_x_maxs - max_x_mins) | |
| intersect_heights = np.maximum(0, min_y_maxs - max_y_mins) | |
| return intersect_widths * intersect_heights | |
| def pairwise_intersection(boxes1, boxes2): | |
| """Compute pairwise intersection areas between boxes. | |
| Args: | |
| boxes1: a numpy array with shape [N, 4] holding N boxes. | |
| boxes2: a numpy array with shape [M, 4] holding M boxes. | |
| Returns: | |
| a numpy array with shape [N, M] representing pairwise intersection area. | |
| References: | |
| `core.box_list_ops.intersection` in Tensorflow object detection API | |
| `utils.box_list_ops.intersection` in Tensorflow object detection API | |
| """ | |
| if boxes1.shape[0] * boxes2.shape[0] == 0: | |
| return np.zeros((boxes1.shape[0], boxes2.shape[0]), dtype=boxes1.dtype) | |
| swap = False | |
| if boxes1.shape[0] > boxes2.shape[0]: | |
| boxes1, boxes2 = boxes2, boxes1 | |
| swap = True | |
| intersect_areas = np.empty((boxes1.shape[0], boxes2.shape[0]), dtype=boxes1.dtype) | |
| for i in range(boxes1.shape[0]): | |
| max_x_mins = np.maximum(boxes1[i, 0], boxes2[:, 0]) | |
| max_y_mins = np.maximum(boxes1[i, 1], boxes2[:, 1]) | |
| min_x_maxs = np.minimum(boxes1[i, 2], boxes2[:, 2]) | |
| min_y_maxs = np.minimum(boxes1[i, 3], boxes2[:, 3]) | |
| intersect_widths = np.maximum(0, min_x_maxs - max_x_mins) | |
| intersect_heights = np.maximum(0, min_y_maxs - max_y_mins) | |
| intersect_areas[i, :] = intersect_widths * intersect_heights | |
| if swap: | |
| intersect_areas = intersect_areas.T | |
| return intersect_areas | |
| def paired_overlap_ratio(boxes1, boxes2, ratio_type='iou'): | |
| """Compute paired overlap ratio between boxes. | |
| Args: | |
| boxes1: a numpy array with shape [N, 4] holding N boxes | |
| boxes2: a numpy array with shape [N, 4] holding N boxes | |
| ratio_type: | |
| iou: Intersection-over-union (iou). | |
| ioa: Intersection-over-area (ioa) between two boxes box1 and box2 is defined as | |
| their intersection area over box2's area. Note that ioa is not symmetric, | |
| that is, IOA(box1, box2) != IOA(box2, box1). | |
| min: Compute the ratio as the area of intersection between box1 and box2, | |
| divided by the minimum area of the two bounding boxes. | |
| Returns: | |
| a numpy array with shape [N,] representing itemwise overlap ratio. | |
| References: | |
| `core.box_list_ops.matched_iou` in Tensorflow object detection API | |
| `structures.boxes.matched_boxlist_iou` in detectron2 | |
| `mmdet.core.bbox.bbox_overlaps`, see https://mmdetection.readthedocs.io/en/v2.17.0/api.html#mmdet.core.bbox.bbox_overlaps | |
| """ | |
| intersect_areas = paired_intersection(boxes1, boxes2) | |
| areas1 = (boxes1[:, 2] - boxes1[:, 0]) * (boxes1[:, 3] - boxes1[:, 1]) | |
| areas2 = (boxes2[:, 2] - boxes2[:, 0]) * (boxes2[:, 3] - boxes2[:, 1]) | |
| if ratio_type in ['union', 'iou', 'giou']: | |
| union_areas = areas1 - intersect_areas | |
| union_areas += areas2 | |
| intersect_areas /= union_areas | |
| elif ratio_type == 'min': | |
| min_areas = np.minimum(areas1, areas2) | |
| intersect_areas /= min_areas | |
| elif ratio_type == 'ioa': | |
| intersect_areas /= areas2 | |
| else: | |
| raise ValueError('Unsupported ratio_type. Got {}'.format(ratio_type)) | |
| if ratio_type == 'giou': | |
| min_xy_mins = np.minimum(boxes1[:, 0:2], boxes2[:, 0:2]) | |
| max_xy_mins = np.maximum(boxes1[:, 2:4], boxes2[:, 2:4]) | |
| # mebb = minimum enclosing bounding boxes | |
| mebb_whs = np.maximum(0, max_xy_mins - min_xy_mins) | |
| mebb_areas = mebb_whs[:, 0] * mebb_whs[:, 1] | |
| union_areas -= mebb_areas | |
| union_areas /= mebb_areas | |
| intersect_areas += union_areas | |
| return intersect_areas | |
| def pairwise_overlap_ratio(boxes1, boxes2, ratio_type='iou'): | |
| """Compute pairwise overlap ratio between boxes. | |
| Args: | |
| boxes1: a numpy array with shape [N, 4] holding N boxes | |
| boxes2: a numpy array with shape [M, 4] holding M boxes | |
| ratio_type: | |
| iou: Intersection-over-union (iou). | |
| ioa: Intersection-over-area (ioa) between two boxes box1 and box2 is defined as | |
| their intersection area over box2's area. Note that ioa is not symmetric, | |
| that is, IOA(box1, box2) != IOA(box2, box1). | |
| min: Compute the ratio as the area of intersection between box1 and box2, | |
| divided by the minimum area of the two bounding boxes. | |
| Returns: | |
| a numpy array with shape [N, M] representing pairwise overlap ratio. | |
| References: | |
| `utils.np_box_ops.iou` in Tensorflow object detection API | |
| `utils.np_box_ops.ioa` in Tensorflow object detection API | |
| `utils.np_box_ops.giou` in Tensorflow object detection API | |
| `mmdet.core.bbox.bbox_overlaps`, see https://mmdetection.readthedocs.io/en/v2.17.0/api.html#mmdet.core.bbox.bbox_overlaps | |
| `torchvision.ops.box_iou`, see https://pytorch.org/vision/stable/ops.html#torchvision.ops.box_iou | |
| `torchvision.ops.generalized_box_iou`, see https://pytorch.org/vision/stable/ops.html#torchvision.ops.generalized_box_iou | |
| http://ww2.mathworks.cn/help/vision/ref/bboxoverlapratio.html | |
| """ | |
| intersect_areas = pairwise_intersection(boxes1, boxes2) | |
| areas1 = (boxes1[:, 2] - boxes1[:, 0]) * (boxes1[:, 3] - boxes1[:, 1]) | |
| areas2 = (boxes2[:, 2] - boxes2[:, 0]) * (boxes2[:, 3] - boxes2[:, 1]) | |
| if ratio_type in ['union', 'iou', 'giou']: | |
| union_areas = np.expand_dims(areas1, axis=1) - intersect_areas | |
| union_areas += np.expand_dims(areas2, axis=0) | |
| intersect_areas /= union_areas | |
| elif ratio_type == 'min': | |
| min_areas = np.minimum(np.expand_dims(areas1, axis=1), np.expand_dims(areas2, axis=0)) | |
| intersect_areas /= min_areas | |
| elif ratio_type == 'ioa': | |
| intersect_areas /= np.expand_dims(areas2, axis=0) | |
| else: | |
| raise ValueError('Unsupported ratio_type. Got {}'.format(ratio_type)) | |
| if ratio_type == 'giou': | |
| min_xy_mins = np.minimum(boxes1[:, None, 0:2], boxes2[:, 0:2]) | |
| max_xy_mins = np.maximum(boxes1[:, None, 2:4], boxes2[:, 2:4]) | |
| # mebb = minimum enclosing bounding boxes | |
| mebb_whs = np.maximum(0, max_xy_mins - min_xy_mins) | |
| mebb_areas = mebb_whs[:, :, 0] * mebb_whs[:, :, 1] | |
| union_areas -= mebb_areas | |
| union_areas /= mebb_areas | |
| intersect_areas += union_areas | |
| return intersect_areas | |