validation / src /gesturedetection /utils /box_utils_numpy.py
tommulder's picture
Deploy gesture detection & validation API
95db528
import numpy as np
def convert_locations_to_boxes(locations, priors, center_variance, size_variance):
"""
Convert regression location results of SSD into boxes in the form of (center_x, center_y, h, w).
Parameters
----------
locations: numpy.ndarray
Regression location results, sized [num_priors,4].
priors: numpy.ndarray
Prior boxes in center-offset form, sized [num_priors,4].
center_variance: float
The center variance for decoding.
size_variance: float
The size variance for decoding.
Returns
-------
boxes: numpy.ndarray
Boxes in corner form, sized [num_priors,4].
"""
# priors can have one dimension less.
if len(priors.shape) + 1 == len(locations.shape):
priors = np.expand_dims(priors, 0)
return np.concatenate(
[
locations[..., :2] * center_variance * priors[..., 2:] + priors[..., :2],
np.exp(locations[..., 2:] * size_variance) * priors[..., 2:],
],
axis=len(locations.shape) - 1,
)
def convert_boxes_to_locations(center_form_boxes, center_form_priors, center_variance, size_variance):
"""
Convert boxes to locations with respect to priors, which are encoded as (cx, cy, w, h).
Parameters
----------
center_form_boxes: numpy.ndarray
Boxes to be converted to locations, sized [num_priors,4].
center_form_priors: numpy.ndarray
Prior boxes in center-form, sized [num_priors,4].
center_variance: float
The center variance for encoding.
size_variance: float
The size variance for encoding.
Returns
-------
locations: numpy.ndarray
Encoded locations, sized [num_priors,4].
"""
if len(center_form_priors.shape) + 1 == len(center_form_boxes.shape):
center_form_priors = np.expand_dims(center_form_priors, 0)
return np.concatenate(
[
(center_form_boxes[..., :2] - center_form_priors[..., :2]) / center_form_priors[..., 2:] / center_variance,
np.log(center_form_boxes[..., 2:] / center_form_priors[..., 2:]) / size_variance,
],
axis=len(center_form_boxes.shape) - 1,
)
def area_of(left_top, right_bottom):
"""
Compute the areas of rectangles given two corners.
Parameters
----------
left_top: numpy.ndarray
Left top corner of the rectangles, sized [N,2].
right_bottom: numpy.ndarray
Right bottom corner of the rectangles, sized [N,2].
Returns
-------
area: numpy.ndarray
Computed areas, sized [N,].
"""
hw = np.clip(right_bottom - left_top, 0.0, None)
return hw[..., 0] * hw[..., 1]
def iou_of(boxes0, boxes1, eps=1e-5):
"""Return intersection-over-union (Jaccard index) of boxes.
Args:
boxes0 (N, 4): ground truth boxes.
boxes1 (N or 1, 4): predicted boxes.
eps: a small number to avoid 0 as denominator.
Returns:
iou (N): IoU values.
"""
overlap_left_top = np.maximum(boxes0[..., :2], boxes1[..., :2])
overlap_right_bottom = np.minimum(boxes0[..., 2:], boxes1[..., 2:])
overlap_area = area_of(overlap_left_top, overlap_right_bottom)
area0 = area_of(boxes0[..., :2], boxes0[..., 2:])
area1 = area_of(boxes1[..., :2], boxes1[..., 2:])
return overlap_area / (area0 + area1 - overlap_area + eps)
def center_form_to_corner_form(locations):
"""
Convert center-form boxes to corner-form.
Parameters
----------
locations: numpy.ndarray
Center-form boxes to be converted to corner-form, sized [num_priors,4].
Returns
-------
boxes: numpy.ndarray
Corner-form boxes, sized [num_priors,4].
"""
return np.concatenate(
[locations[..., :2] - locations[..., 2:] / 2, locations[..., :2] + locations[..., 2:] / 2],
len(locations.shape) - 1,
)
def corner_form_to_center_form(boxes):
"""
Convert corner-form boxes to center-form.
Parameters
----------
boxes: numpy.ndarray
Corner-form boxes to be converted to center-form, sized [num_priors,4].
Returns
-------
locations: numpy.ndarray
Center-form boxes, sized [num_priors,4].
"""
return np.concatenate(
[(boxes[..., :2] + boxes[..., 2:]) / 2, boxes[..., 2:] - boxes[..., :2]], len(boxes.shape) - 1
)
def hard_nms(box_scores, iou_threshold, top_k=-1, candidate_size=200):
"""
Perform hard non-maximum-supression to filter out boxes with iou greater
than threshold
Parameters
----------
box_scores: numpy.ndarray
boxes in corner-form and probabilities.
iou_threshold: float
intersection over union threshold.
top_k: int
keep top_k results. If k <= 0, keep all the results.
candidate_size: int
only consider the candidates with the highest scores.
Returns
-------
picked: numpy.ndarray
a list of indexes of the kept boxes
"""
scores = box_scores[:, -1]
boxes = box_scores[:, :-1]
picked = []
indexes = np.argsort(scores)
indexes = indexes[-candidate_size:]
while len(indexes) > 0:
current = indexes[-1]
picked.append(current)
if 0 < top_k == len(picked) or len(indexes) == 1:
break
current_box = boxes[current, :]
indexes = indexes[:-1]
rest_boxes = boxes[indexes, :]
iou = iou_of(
rest_boxes,
np.expand_dims(current_box, axis=0),
)
indexes = indexes[iou <= iou_threshold]
return box_scores[picked, :]