| |
| |
| |
| |
| |
| |
| horizontal_points_pair = [ |
| [ |
| "inner-eye",133,362,6 |
| ], |
| [ |
| "outer-eye",33,263,168 |
| ], |
| [ |
| "mouth",61,291,13 |
| ], |
| [ |
| "eyeblow",105,334,9 |
| ],[ |
| "nose",98,327,2 |
| ],[ |
| "contour",143,372,6 |
| ], |
| [ |
| "chin",32,262,200 |
| ], [ |
| "cheek",123,352,5 |
| ], [ |
| "cheek2",192,416,0 |
| ], [ |
| "nose1",129,358,1 |
| ], [ |
| "nose2",47,277,195 |
| ], [ |
| "cheek3",206,426,2 |
| ], [ |
| "cheek4",101,330,5 |
| ], [ |
| "cheek5",153,380,6 |
| ] |
| ] |
| def angle_between_points_and_x_axis(A, B): |
| """ |
| 2点A, Bを結ぶ線分とx軸の正方向との角度を計算する |
| |
| Args: |
| A: A点の座標 (x, y) のタプルまたはNumPy配列 |
| B: B点の座標 (x, y) のタプルまたはNumPy配列 |
| |
| Returns: |
| 角度(ラジアン) |
| """ |
| x = B[0] - A[0] |
| y = B[1] - A[1] |
| return np.arctan2(y, x) |
|
|
| vertical_points_pair=[ |
| ["forehead-chin",8,1,199] |
| ] |
| |
| feature_ratios_indices=[ |
| ["forehead",67,69,66], |
| ["forehead",10,151,9], |
| ["forehead",297,299,296], |
| |
| |
| ["middle",168,195,2], |
| ["right",153,101,206], |
| ["right2",133,47,129], |
| ["left",380,330,426], |
| ["left2",362,277,358], |
| ["right-contour",143,123,192], |
| ["left-contour",372,352,416], |
| ["nose",4,1,2], |
| ] |
|
|
| feature_angles_indices =[ |
| ["forehead1",9,6], |
| ["forehead2",69,299], |
| ["eyes1",133,362], |
| ["eyes2",133,33], |
| ["eyes3",362,263], |
| ["nose1",6,2], |
| ["nose1",98,327], |
| ["nose1",2,1], |
| ["nose1",1,6], |
| ["lip",61,291], |
| ["lip",0,17], |
| ["jaw",152,199], |
| ["jaw",194,418], |
| ["cheek",118,214], |
| ["cheek",347,434], |
| ["contour",389,397], |
| ["contour",127,172], |
| ] |
| def get_feature_angles_cordinate(face_landmarks,angles=feature_angles_indices): |
| points = [get_normalized_cordinate(face_landmarks,i) for i in range(468)] |
| return get_feature_angles_cordinate_points(points,angles) |
|
|
| def get_feature_angles_cordinate_points(points,angles=feature_angles_indices): |
| cordinates=[] |
| result_angles = [] |
| for indices in angles: |
| points_cordinate = get_points_by_indices(points,indices[1:]) |
| angle_rad =angle_between_points_and_x_axis(points_cordinate[0][:2],points_cordinate[1][:2]) |
| result_angles.append(angle_rad) |
| cordinates.append(points_cordinate) |
| return cordinates,result_angles |
|
|
| def get_feature_ratios_cordinate(face_landmarks,ratios=feature_ratios_indices): |
| points = [get_normalized_cordinate(face_landmarks,i) for i in range(468)] |
| return get_feature_angles_cordinate_points(points,ratios) |
|
|
| def ratios_cordinates(cordinates): |
| |
| distance_a = calculate_distance(cordinates[0],cordinates[1]) |
| distance_b = calculate_distance(cordinates[-2],cordinates[-1]) |
| if distance_a == 0 or distance_b == 0: |
| return 0 |
| else: |
| return distance_a/distance_b |
| |
| def get_feature_ratios_cordinate_points(points,ratios=feature_ratios_indices): |
| cordinates=[] |
| result_ratios = [] |
| for indices in ratios: |
| points_cordinate = get_points_by_indices(points,indices[1:]) |
| result_ratios.append(ratios_cordinates(points_cordinate)) |
| cordinates.append(points_cordinate) |
| return cordinates,result_ratios |
|
|
|
|
| |
| forehead_chin_points_pair=[ |
| [ |
| "forehead-chin",8,1,199 |
| ] |
| ] |
| horizontal_contour_points_pair=[ |
| [ |
| "contour",143,6,372 |
| ] |
| ] |
| import math |
| def calculate_distance(xy, xy2): |
| return math.sqrt((xy2[0] - xy[0])**2 + (xy2[1] - xy[1])**2) |
|
|
| def create_detail_labels(values,radian=False,pair_data=horizontal_points_pair): |
| assert len(values) == len(pair_data) |
| lines = [] |
| for i,value in enumerate(values): |
| if radian: |
| value=math.degrees(value) |
| lines.append(f"{pair_data[i][0]} = {value:.2f}") |
| return "\n".join(lines) |
|
|
| import numpy as np |
| from mp_utils import get_normalized_cordinate |
| def estimate_horizontal(face_landmarks,pair_data = horizontal_points_pair): |
| points = [get_normalized_cordinate(face_landmarks,i) for i in range(468)] |
| return estimate_horizontal_points(points,pair_data) |
|
|
| def get_points_by_indices(face_landmark_points,indices): |
| points = [face_landmark_points[index] for index in indices] |
| return points |
|
|
| def normalized_to_pixel(cordinates,width,height): |
| pixel_point = [[pt[0]*width,pt[1]*height] for pt in cordinates] |
| return pixel_point |
|
|
| def estimate_horizontal_points(face_landmark_points,pair_data = horizontal_points_pair): |
| z_angles=[] |
| y_ratios = [] |
| cordinates = [] |
| for compare_point in pair_data: |
| points_cordinate = get_points_by_indices(face_landmark_points,compare_point[1:]) |
| cordinates.append(points_cordinate) |
| angle_rad =angle_between_points_and_x_axis(points_cordinate[0][:2],points_cordinate[1][:2]) |
| |
| z_angles.append(angle_rad) |
| right_distance = calculate_distance(points_cordinate[0],points_cordinate[2]) |
| left_distance = calculate_distance(points_cordinate[1],points_cordinate[2]) |
| y_ratios.append(left_distance/(right_distance+left_distance)) |
| return z_angles,y_ratios,cordinates,pair_data |
|
|
| def estimate_vertical(face_landmarks,pair_data = vertical_points_pair): |
| points = [get_normalized_cordinate(face_landmarks,i) for i in range(468)] |
| return estimate_vertical_points(points,pair_data) |
|
|
|
|
| def estimate_rotations_v2(face_landmarker_result): |
| points = get_normalized_landmarks(face_landmarker_result.face_landmarks,True) |
| values1_text=estimate_rotations_point(points) |
| result3,ratios = get_feature_ratios_cordinate_points(points) |
| key_cordinates,angles = get_feature_angles_cordinate_points(points) |
| angles_str=[str(angle) for angle in angles] |
| ratios_str=[str(ratio) for ratio in ratios] |
| return f"{values1_text},{','.join(angles_str)},{','.join(ratios_str)}" |
| |
| from mp_utils import get_normalized_landmarks |
| def estimate_rotations(face_landmarker_result): |
| points = get_normalized_landmarks(face_landmarker_result.face_landmarks,True) |
| return estimate_rotations_point(points) |
| def estimate_rotations_point(points): |
| z_angles,y_ratios,h_cordinates,_ =estimate_horizontal_points(points) |
| z_angle = np.mean(z_angles) |
| y_ratio = np.mean(y_ratios) |
| _,x_ratios,h_cordinates,_ =estimate_vertical_points(points) |
| x_ratio = np.mean(x_ratios) |
|
|
| x_angle,_,_,_ =estimate_vertical_points(points,forehead_chin_points_pair) |
| x_angle=np.mean(x_angle) |
| |
| length_ratio = estimate_ratio(points) |
|
|
| result = f"{x_ratio:.6f},{y_ratio:.6f},{z_angle:.6f},{x_angle:.6f},{length_ratio:.6f}" |
| return result |
|
|
| def estimate_ratio(face_landmark_points,a_line=forehead_chin_points_pair,b_line=horizontal_contour_points_pair): |
| points_cordinate_a = get_points_by_indices(face_landmark_points,a_line[0][1:]) |
| points_cordinate_b = get_points_by_indices(face_landmark_points,b_line[0][1:]) |
| |
| distance_a = calculate_distance(points_cordinate_a[0],points_cordinate_a[2]) |
| distance_b = calculate_distance(points_cordinate_b[0],points_cordinate_b[2]) |
| if distance_a == 0 or distance_b == 0: |
| return 0 |
| else: |
| return distance_a/distance_b |
|
|
| def estimate_vertical_points(face_landmarks,pair_data = vertical_points_pair): |
| angles = [] |
| ratios = [] |
| cordinates = [] |
| for compare_point in pair_data: |
| points_cordinate = get_points_by_indices(face_landmarks,compare_point[1:]) |
| cordinates.append(points_cordinate) |
| angle_rad =angle_between_points_and_x_axis(points_cordinate[0][:2],points_cordinate[2][:2]) |
| |
| angles.append(angle_rad) |
| up_distance = calculate_distance(points_cordinate[0],points_cordinate[1]) |
| down_distance = calculate_distance(points_cordinate[1],points_cordinate[2]) |
| ratios.append(down_distance/(down_distance+up_distance)) |
| return angles,ratios,cordinates,pair_data |
| def mean_std_label(values,radian=False): |
| mean_value = np.mean(values) |
| std_value = np.std(values) |
| if radian: |
| mean_value = math.degrees(mean_value) |
| std_value = math.degrees(std_value) |
| value_text = f"mean:{mean_value:.3f} std:{std_value:.3f}" |
| return value_text |