FaceRecognition-LivenessDetection-SDK
/
face_recognition
/face_detect
/vision
/utils
/box_utils_numpy.py
import numpy as np | |
def convert_locations_to_boxes(locations, priors, center_variance, | |
size_variance): | |
"""Convert regressional location results of SSD into boxes in the form of (center_x, center_y, h, w). | |
The conversion: | |
$$predicted\_center * center_variance = \frac {real\_center - prior\_center} {prior\_hw}$$ | |
$$exp(predicted\_hw * size_variance) = \frac {real\_hw} {prior\_hw}$$ | |
We do it in the inverse direction here. | |
Args: | |
locations (batch_size, num_priors, 4): the regression output of SSD. It will contain the outputs as well. | |
priors (num_priors, 4) or (batch_size/1, num_priors, 4): prior boxes. | |
center_variance: a float used to change the scale of center. | |
size_variance: a float used to change of scale of size. | |
Returns: | |
boxes: priors: [[center_x, center_y, h, w]]. All the values | |
are relative to the image size. | |
""" | |
# 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): | |
# priors can have one dimension less | |
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. | |
Args: | |
left_top (N, 2): left top corner. | |
right_bottom (N, 2): right bottom corner. | |
Returns: | |
area (N): return the area. | |
""" | |
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): | |
return np.concatenate([locations[..., :2] - locations[..., 2:] / 2, | |
locations[..., :2] + locations[..., 2:] / 2], len(locations.shape) - 1) | |
def corner_form_to_center_form(boxes): | |
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): | |
""" | |
Args: | |
box_scores (N, 5): boxes in corner-form and probabilities. | |
iou_threshold: intersection over union threshold. | |
top_k: keep top_k results. If k <= 0, keep all the results. | |
candidate_size: only consider the candidates with the highest scores. | |
Returns: | |
picked: a list of indexes of the kept boxes | |
""" | |
scores = box_scores[:, -1] | |
boxes = box_scores[:, :-1] | |
picked = [] | |
# _, indexes = scores.sort(descending=True) | |
indexes = np.argsort(scores) | |
# indexes = indexes[:candidate_size] | |
indexes = indexes[-candidate_size:] | |
while len(indexes) > 0: | |
# current = 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:] | |
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, :] | |