CoolFace
Apppublic

fkl100/Behavior_and_Emotion_Recognition

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
utils.py136 linesDownload Raw Back to root
1# File: utils.py
2
3import math
4import numpy as np
5import cv2
6import mediapipe as mp
7
8mp_face_mesh = mp.solutions.face_mesh
9
10def norm_coordinates(normalized_x, normalized_y, image_width, image_height):
11    """
12    Converts normalized coordinates to pixel coordinates.
13
14    Args:
15        normalized_x: Normalized x-coordinate (between 0 and 1).
16        normalized_y: Normalized y-coordinate (between 0 and 1).
17        image_width: Width of the image.
18        image_height: Height of the image.
19
20    Returns:
21        Tuple of pixel coordinates (x, y).
22    """
23    x_px = min(math.floor(normalized_x * image_width), image_width - 1)
24    y_px = min(math.floor(normalized_y * image_height), image_height - 1)
25    return x_px, y_px
26
27def get_box(fl, w, h):
28    """
29    Calculates bounding box coordinates for the detected face.
30
31    Args:
32        fl: Face landmarks from MediaPipe.
33        w: Width of the image.
34        h: Height of the image.
35
36    Returns:
37        Tuple of bounding box coordinates (startX, startY, endX, endY).
38    """
39    idx_to_coors = {}
40    for idx, landmark in enumerate(fl.landmark):
41        landmark_px = norm_coordinates(landmark.x, landmark.y, w, h)
42        if landmark_px:
43            idx_to_coors[idx] = landmark_px
44
45    x_min = np.min(np.asarray(list(idx_to_coors.values()))[:, 0])
46    y_min = np.min(np.asarray(list(idx_to_coors.values()))[:, 1])
47    endX = np.max(np.asarray(list(idx_to_coors.values()))[:, 0])
48    endY = np.max(np.asarray(list(idx_to_coors.values()))[:, 1])
49
50    (startX, startY) = (max(0, x_min), max(0, y_min))
51    (endX, endY) = (min(w - 1, endX), min(h - 1, endY))
52    return startX, startY, endX, endY
53
54def display_EMO_PRED(img, box, label='', color=(128, 128, 128), txt_color=(255, 255, 255), line_width=2, font_scale=1):
55    """
56    Draws a bounding box and displays the predicted emotion on the image.
57
58    Args:
59        img: Input image.
60        box: Bounding box coordinates (startX, startY, endX, endY).
61        label: Predicted emotion label.
62        color: Color of the bounding box.
63        txt_color: Color of the text.
64        line_width: Width of the bounding box.
65        font_scale: Scale factor to adjust the font size.
66
67    Returns:
68        Image with bounding box and predicted emotion.
69    """
70    lw = line_width or max(round(sum(img.shape) / 2 * 0.003), 2)
71    text2_color = (255, 0, 255)
72    p1, p2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
73    cv2.rectangle(img, p1, p2, text2_color, thickness=lw, lineType=cv2.LINE_AA)
74    font = cv2.FONT_HERSHEY_SIMPLEX
75
76    tf = max(lw - 1, 1)
77    text_fond = (0, 0, 0)
78    text_width_2, text_height_2 = cv2.getTextSize(label, font, font_scale, tf)
79    text_width_2 = text_width_2[0] + round(((p2[0] - p1[0]) * 10) / 360)
80    center_face = p1[0] + round((p2[0] - p1[0]) / 2)
81
82    # Use the larger font scale and draw the text
83    cv2.putText(img, label,
84                (center_face - round(text_width_2 / 2), p1[1] - round(((p2[0] - p1[0]) * 20) / 360)), font,
85                font_scale, text_fond, thickness=tf, lineType=cv2.LINE_AA)
86    cv2.putText(img, label,
87                (center_face - round(text_width_2 / 2), p1[1] - round(((p2[0] - p1[0]) * 20) / 360)), font,
88                font_scale, text2_color, thickness=tf, lineType=cv2.LINE_AA)
89    return img
90
91
92def display_FPS(img, text, margin=1.0, box_scale=1.0):
93    """
94    Displays the FPS on the image.
95
96    Args:
97        img: Input image.
98        text: FPS text.
99        margin: Margin around the FPS text.
100        box_scale: Scale factor for the FPS box.
101
102    Returns:
103        Image with displayed FPS.
104    """
105    img_h, img_w, _ = img.shape
106    line_width = int(min(img_h, img_w) * 0.001)  # line width
107    thickness = max(int(line_width / 3), 1)  # font thickness
108
109    font_face = cv2.FONT_HERSHEY_SIMPLEX
110    font_color = (0, 0, 0)
111    font_scale = thickness / 1.5
112
113    t_w, t_h = cv2.getTextSize(text, font_face, font_scale, None)[0]
114
115    margin_n = int(t_h * margin)
116    sub_img = img[0 + margin_n: 0 + margin_n + t_h + int(2 * t_h * box_scale),
117              img_w - t_w - margin_n - int(2 * t_h * box_scale): img_w - margin_n]
118
119    white_rect = np.ones(sub_img.shape, dtype=np.uint8) * 255
120
121    img[0 + margin_n: 0 + margin_n + t_h + int(2 * t_h * box_scale),
122    img_w - t_w - margin_n - int(2 * t_h * box_scale):img_w - margin_n] = cv2.addWeighted(sub_img, 0.5, white_rect, .5,
123                                                                                          1.0)
124
125    cv2.putText(img=img,
126                text=text,
127                org=(img_w - t_w - margin_n - int(2 * t_h * box_scale) // 2,
128                     0 + margin_n + t_h + int(2 * t_h * box_scale) // 2),
129                fontFace=font_face,
130                fontScale=font_scale,
131                color=font_color,
132                thickness=thickness,
133                lineType=cv2.LINE_AA,
134                bottomLeftOrigin=False)
135
136    return img