facial_beauty_analysis / facial_image.py
VladyslavTalakh
examples
6f90f9d
raw
history blame
No virus
4.46 kB
from math import dist
import cv2
import mediapipe as mp
from points import points
from ratios import Ratios
from utils import *
def convert_to_numpy_array(ratios: dict[str, float]) -> numpy.array:
arr = []
for k, v in ratios.items():
arr.append(v)
return numpy.array(arr)
class FacialImage:
def __init__(self):
self.landmarks = []
self.width = 0
self.height = 0
def get_point_coordinates(self, point_num):
point = self.landmarks[point_num]
return point.x * self.width, point.y * self.height
def get_distance_two_points(self, point_num_1, point_num_2):
first = self.get_point_coordinates(point_num_1)
second = self.get_point_coordinates(point_num_2)
return dist(first, second)
def get_ratio_between_two(self, ratio1_name, ratio2_name):
first = self.get_distance_two_points(points[ratio1_name][0], points[ratio1_name][1])
second = self.get_distance_two_points(points[ratio2_name][0], points[ratio2_name][1])
return first / second
def get_landmarks(self, image: numpy.ndarray):
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh()
# Image
height, width, _ = image.shape
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# Facial landmarks
result = face_mesh.process(rgb_image)
for facial_landmarks in result.multi_face_landmarks:
for i in range(0, 468):
pt1 = facial_landmarks.landmark[i]
x = int(pt1.x * width)
y = int(pt1.y * height)
cv2.circle(image, (x, y), 1, (255, 0, 0), -1)
self.landmarks = result.multi_face_landmarks[0].landmark
self.width = width
self.height = height
def calculate_ratios(self, image: numpy.ndarray, is_normalized=False):
self.get_landmarks(image)
ratios = {
'Under eyes/Interocular': self.get_ratio_between_two(Ratios.UNDER_EYES, Ratios.INTEROCULAR),
'Under eyes/Nose width': self.get_ratio_between_two(Ratios.UNDER_EYES, Ratios.NOSE_WIDTH),
'Mouth width/Interocular': self.get_ratio_between_two(Ratios.MOUTH_WIDTH, Ratios.INTEROCULAR),
'Upper lip-jaw/Interocular': self.get_ratio_between_two(Ratios.UPPER_LIP_TO_JAW, Ratios.INTEROCULAR),
'Upper lip-jaw/Nose width': self.get_ratio_between_two(Ratios.UPPER_LIP_TO_JAW, Ratios.NOSE_WIDTH),
'Interocular/Lip height': self.get_ratio_between_two(Ratios.INTEROCULAR, Ratios.LIPS_HEIGHT),
'Nose width/Interocular': self.get_ratio_between_two(Ratios.NOSE_WIDTH, Ratios.INTEROCULAR),
'Nose width/Upper lip height': self.get_ratio_between_two(Ratios.NOSE_WIDTH, Ratios.UPPER_LIP_HEIGHT),
'Interocular/Nose mouth height': self.get_ratio_between_two(Ratios.INTEROCULAR,
Ratios.NOSE_TO_MOUTH_HEIGHT),
'Face top-eyebrows/Eyebrows-Nose': self.get_ratio_between_two(Ratios.FACE_TOP_TO_EYEBROWS,
Ratios.EYEBROWS_TO_NOSE),
'Eyebrows-nose/Nose-jaw': self.get_ratio_between_two(Ratios.EYEBROWS_TO_NOSE, Ratios.NOSE_TO_JAW),
'Face top-eyebrows/Nose-Jaw': self.get_ratio_between_two(Ratios.FACE_TOP_TO_EYEBROWS, Ratios.NOSE_TO_JAW),
'Interocular/Nose width': self.get_ratio_between_two(Ratios.INTEROCULAR, Ratios.NOSE_WIDTH),
'Face height/Face width': self.get_ratio_between_two(Ratios.FACE_HEIGHT, Ratios.FACE_WIDTH),
'Lower eyebrow length': self.get_ratio_between_two(Ratios.LEFT_LOWER_EYEBROW_LENGTH,
Ratios.RIGHT_LOWER_EYEBROW_LENGTH),
'Lower lip length': self.get_ratio_between_two(Ratios.LEFT_LOWER_LIP_LENGTH, Ratios.RIGHT_LOWER_LIP_LENGTH),
'Upper eyebrow': self.get_ratio_between_two(Ratios.LEFT_UPPER_EYEBROW_LENGTH,
Ratios.RIGHT_UPPER_EYEBROW_LENGTH),
'Upper lip': self.get_ratio_between_two(Ratios.LEFT_UPPER_LIP_LENGTH, Ratios.RIGHT_UPPER_LIP_LENGTH),
'Nose': self.get_ratio_between_two(Ratios.LEFT_NOSE_WIDTH, Ratios.RIGHT_NOSE_WIDTH)
}
if is_normalized:
return normalization(ratios), image
return ratios, image