Team Ai
Apppublic

conciomith/RetinaFace_FaceDetector_Extractor

sourceHugging Faceapache-2.0updated 5y agoView on Hugging Face
14likes
postprocess.py179 linesDownload Raw Back to root
1import numpy as np2from PIL import Image3import math4 5def findEuclideanDistance(source_representation, test_representation):6    euclidean_distance = source_representation - test_representation7    euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))8    euclidean_distance = np.sqrt(euclidean_distance)9    return euclidean_distance10 11#this function copied from the deepface repository: https://github.com/serengil/deepface/blob/master/deepface/commons/functions.py12def alignment_procedure(img, left_eye, right_eye, nose):13 14    #this function aligns given face in img based on left and right eye coordinates15 16    left_eye_x, left_eye_y = left_eye17    right_eye_x, right_eye_y = right_eye18 19    #-----------------------20    upside_down = False21    if nose[1] < left_eye[1] or nose[1] < right_eye[1]:22        upside_down = True23 24    #-----------------------25    #find rotation direction26 27    if left_eye_y > right_eye_y:28        point_3rd = (right_eye_x, left_eye_y)29        direction = -1 #rotate same direction to clock30    else:31        point_3rd = (left_eye_x, right_eye_y)32        direction = 1 #rotate inverse direction of clock33 34    #-----------------------35    #find length of triangle edges36 37    a = findEuclideanDistance(np.array(left_eye), np.array(point_3rd))38    b = findEuclideanDistance(np.array(right_eye), np.array(point_3rd))39    c = findEuclideanDistance(np.array(right_eye), np.array(left_eye))40 41    #-----------------------42 43    #apply cosine rule44 45    if b != 0 and c != 0: #this multiplication causes division by zero in cos_a calculation46 47        cos_a = (b*b + c*c - a*a)/(2*b*c)48        49        #PR15: While mathematically cos_a must be within the closed range [-1.0, 1.0], floating point errors would produce cases violating this50        #In fact, we did come across a case where cos_a took the value 1.0000000169176173, which lead to a NaN from the following np.arccos step51        cos_a = min(1.0, max(-1.0, cos_a))52        53        54        angle = np.arccos(cos_a) #angle in radian55        angle = (angle * 180) / math.pi #radian to degree56 57        #-----------------------58        #rotate base image59 60        if direction == -1:61            angle = 90 - angle62 63        if upside_down == True:64            angle = angle + 9065 66        img = Image.fromarray(img)67        img = np.array(img.rotate(direction * angle))68 69    #-----------------------70 71    return img #return img anyway72 73#this function is copied from the following code snippet: https://github.com/StanislasBertrand/RetinaFace-tf2/blob/master/retinaface.py74def bbox_pred(boxes, box_deltas):75    if boxes.shape[0] == 0:76        return np.zeros((0, box_deltas.shape[1]))77 78    boxes = boxes.astype(np.float, copy=False)79    widths = boxes[:, 2] - boxes[:, 0] + 1.080    heights = boxes[:, 3] - boxes[:, 1] + 1.081    ctr_x = boxes[:, 0] + 0.5 * (widths - 1.0)82    ctr_y = boxes[:, 1] + 0.5 * (heights - 1.0)83 84    dx = box_deltas[:, 0:1]85    dy = box_deltas[:, 1:2]86    dw = box_deltas[:, 2:3]87    dh = box_deltas[:, 3:4]88 89    pred_ctr_x = dx * widths[:, np.newaxis] + ctr_x[:, np.newaxis]90    pred_ctr_y = dy * heights[:, np.newaxis] + ctr_y[:, np.newaxis]91    pred_w = np.exp(dw) * widths[:, np.newaxis]92    pred_h = np.exp(dh) * heights[:, np.newaxis]93 94    pred_boxes = np.zeros(box_deltas.shape)95    # x196    pred_boxes[:, 0:1] = pred_ctr_x - 0.5 * (pred_w - 1.0)97    # y198    pred_boxes[:, 1:2] = pred_ctr_y - 0.5 * (pred_h - 1.0)99    # x2100    pred_boxes[:, 2:3] = pred_ctr_x + 0.5 * (pred_w - 1.0)101    # y2102    pred_boxes[:, 3:4] = pred_ctr_y + 0.5 * (pred_h - 1.0)103 104    if box_deltas.shape[1]>4:105        pred_boxes[:,4:] = box_deltas[:,4:]106 107    return pred_boxes108 109# This function copied from the following code snippet: https://github.com/StanislasBertrand/RetinaFace-tf2/blob/master/retinaface.py110def landmark_pred(boxes, landmark_deltas):111    if boxes.shape[0] == 0:112      return np.zeros((0, landmark_deltas.shape[1]))113    boxes = boxes.astype(np.float, copy=False)114    widths = boxes[:, 2] - boxes[:, 0] + 1.0115    heights = boxes[:, 3] - boxes[:, 1] + 1.0116    ctr_x = boxes[:, 0] + 0.5 * (widths - 1.0)117    ctr_y = boxes[:, 1] + 0.5 * (heights - 1.0)118    pred = landmark_deltas.copy()119    for i in range(5):120        pred[:,i,0] = landmark_deltas[:,i,0]*widths + ctr_x121        pred[:,i,1] = landmark_deltas[:,i,1]*heights + ctr_y122    return pred123 124# This function copied from rcnn module of retinaface-tf2 project: https://github.com/StanislasBertrand/RetinaFace-tf2/blob/master/rcnn/processing/bbox_transform.py125def clip_boxes(boxes, im_shape):126    # x1 >= 0127    boxes[:, 0::4] = np.maximum(np.minimum(boxes[:, 0::4], im_shape[1] - 1), 0)128    # y1 >= 0129    boxes[:, 1::4] = np.maximum(np.minimum(boxes[:, 1::4], im_shape[0] - 1), 0)130    # x2 < im_shape[1]131    boxes[:, 2::4] = np.maximum(np.minimum(boxes[:, 2::4], im_shape[1] - 1), 0)132    # y2 < im_shape[0]133    boxes[:, 3::4] = np.maximum(np.minimum(boxes[:, 3::4], im_shape[0] - 1), 0)134    return boxes135 136#this function is mainly based on the following code snippet: https://github.com/StanislasBertrand/RetinaFace-tf2/blob/master/rcnn/cython/anchors.pyx137def anchors_plane(height, width, stride, base_anchors):138    A = base_anchors.shape[0]139    c_0_2 = np.tile(np.arange(0, width)[np.newaxis, :, np.newaxis, np.newaxis], (height, 1, A, 1))140    c_1_3 = np.tile(np.arange(0, height)[:, np.newaxis, np.newaxis, np.newaxis], (1, width, A, 1))141    all_anchors = np.concatenate([c_0_2, c_1_3, c_0_2, c_1_3], axis=-1) * stride + np.tile(base_anchors[np.newaxis, np.newaxis, :, :], (height, width, 1, 1))142    return all_anchors143 144#this function is mainly based on the following code snippet: https://github.com/StanislasBertrand/RetinaFace-tf2/blob/master/rcnn/cython/cpu_nms.pyx145#Fast R-CNN by Ross Girshick146def cpu_nms(dets, threshold):147    x1 = dets[:, 0]148    y1 = dets[:, 1]149    x2 = dets[:, 2]150    y2 = dets[:, 3]151    scores = dets[:, 4]152 153    areas = (x2 - x1 + 1) * (y2 - y1 + 1)154    order = scores.argsort()[::-1]155 156    ndets = dets.shape[0]157    suppressed = np.zeros((ndets), dtype=np.int)158 159    keep = []160    for _i in range(ndets):161        i = order[_i]162        if suppressed[i] == 1:163            continue164        keep.append(i)165        ix1 = x1[i]; iy1 = y1[i]; ix2 = x2[i]; iy2 = y2[i]166        iarea = areas[i]167        for _j in range(_i + 1, ndets):168            j = order[_j]169            if suppressed[j] == 1:170                continue171            xx1 = max(ix1, x1[j]); yy1 = max(iy1, y1[j]); xx2 = min(ix2, x2[j]); yy2 = min(iy2, y2[j])172            w = max(0.0, xx2 - xx1 + 1); h = max(0.0, yy2 - yy1 + 1)173            inter = w * h174            ovr = inter / (iarea + areas[j] - inter)175            if ovr >= threshold:176                suppressed[j] = 1177 178    return keep179