|
import math |
|
|
|
import mediapipe as mp |
|
from mediapipe.tasks import python |
|
from mediapipe.tasks.python import vision |
|
from mediapipe.framework.formats import landmark_pb2 |
|
from mediapipe import solutions |
|
import numpy as np |
|
|
|
|
|
|
|
|
|
|
|
|
|
def calculate_distance(p1, p2): |
|
""" |
|
|
|
""" |
|
return math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2) |
|
|
|
|
|
|
|
def to_int_points(points): |
|
ints=[] |
|
for pt in points: |
|
|
|
value = [int(pt[0]),int(pt[1])] |
|
|
|
ints.append(value) |
|
return ints |
|
|
|
debug = False |
|
def divide_line_to_points(points,divided): |
|
total_length = 0 |
|
line_length_list = [] |
|
for i in range(len(points)-1): |
|
pt_length = calculate_distance(points[i],points[i+1]) |
|
total_length += pt_length |
|
line_length_list.append(pt_length) |
|
|
|
splited_length = total_length/divided |
|
|
|
def get_new_point(index,lerp): |
|
pt1 = points[index] |
|
pt2 = points[index+1] |
|
diff = [pt2[0] - pt1[0], pt2[1]-pt1[1]] |
|
new_point = [pt1[0]+diff[0]*lerp,pt1[1]+diff[1]*lerp] |
|
if debug: |
|
print(f"pt1 ={pt1} pt2 ={pt2} diff={diff} new_point={new_point}") |
|
|
|
return new_point |
|
|
|
if debug: |
|
print(f"{total_length} splitted = {splited_length} line-length-list = {len(line_length_list)}") |
|
splited_points=[points[0]] |
|
for i in range(1,divided): |
|
need_length = splited_length*i |
|
if debug: |
|
print(f"{i} need length = {need_length}") |
|
current_length = 0 |
|
for j in range(len(line_length_list)): |
|
line_length = line_length_list[j] |
|
current_length+=line_length |
|
if current_length>need_length: |
|
if debug: |
|
print(f"over need length index = {j} current={current_length}") |
|
diff = current_length - need_length |
|
|
|
lerp_point = 1.0 - (diff/line_length) |
|
if debug: |
|
print(f"over = {diff} lerp ={lerp_point}") |
|
new_point = get_new_point(j,lerp_point) |
|
|
|
splited_points.append(new_point) |
|
break |
|
|
|
splited_points.append(points[-1]) |
|
splited_points=to_int_points(splited_points) |
|
|
|
if debug: |
|
print(f"sp={len(splited_points)}") |
|
return splited_points |
|
|
|
|
|
|
|
def expand_bbox(bbox,left=5,top=5,right=5,bottom=5): |
|
left_pixel = bbox[2]*(float(left)/100) |
|
top_pixel = bbox[3]*(float(top)/100) |
|
right_pixel = bbox[2]*(float(right)/100) |
|
bottom_pixel = bbox[3]*(float(bottom)/100) |
|
new_box = list(bbox) |
|
new_box[0] -=left_pixel |
|
new_box[1] -=top_pixel |
|
new_box[2] +=left_pixel+right_pixel |
|
new_box[3] +=top_pixel+bottom_pixel |
|
return new_box |
|
|
|
|
|
def get_normalized_cordinate(face_landmarks_list,index): |
|
x=face_landmarks_list[0][index].x |
|
y=face_landmarks_list[0][index].y |
|
return x,y |
|
|
|
def get_normalized_xyz(face_landmarks_list,index): |
|
x=face_landmarks_list[0][index].x |
|
y=face_landmarks_list[0][index].y |
|
z=face_landmarks_list[0][index].z |
|
return x,y,z |
|
|
|
def get_normalized_landmarks(face_landmarks_list,recentering=False,recentering_index=4,z_multiply=0.8): |
|
cordinates = [get_normalized_xyz(face_landmarks_list,i) for i in range(0,468)] |
|
if recentering: |
|
normalized_center_point = cordinates[recentering_index] |
|
offset_x = normalized_center_point[0] |
|
offset_y = normalized_center_point[1] |
|
|
|
|
|
cordinates = [[point[0]-offset_x,point[1]-offset_y,point[2]*z_multiply] for point in cordinates] |
|
|
|
return cordinates |
|
|
|
|
|
|
|
def sort_triangles_by_depth(landmark_points,mesh_triangle_indices): |
|
assert len(landmark_points) == 468 |
|
mesh_triangle_indices.sort(key=lambda triangle: sum(landmark_points[index][2] for index in triangle) / len(triangle) |
|
,reverse=True) |
|
|
|
def get_pixel_xyz(face_landmarks_list,landmark,width,height): |
|
point = get_normalized_cordinate(face_landmarks_list,landmark) |
|
z = y=face_landmarks_list[0][landmark].z |
|
return int(point[0]*width),int(point[1]*height),z |
|
|
|
def get_pixel_cordinate(face_landmarks_list,landmark,width,height): |
|
point = get_normalized_cordinate(face_landmarks_list,landmark) |
|
return int(point[0]*width),int(point[1]*height) |
|
|
|
def get_pixel_cordinate_list(face_landmarks_list,indices,width,height): |
|
cordinates = [] |
|
for index in indices: |
|
cordinates.append(get_pixel_cordinate(face_landmarks_list,index,width,height)) |
|
return cordinates |
|
|
|
def extract_landmark(image_data,model_path="face_landmarker.task",min_face_detection_confidence=0, min_face_presence_confidence=0,output_facial_transformation_matrixes=False): |
|
BaseOptions = mp.tasks.BaseOptions |
|
FaceLandmarker = mp.tasks.vision.FaceLandmarker |
|
FaceLandmarkerOptions = mp.tasks.vision.FaceLandmarkerOptions |
|
VisionRunningMode = mp.tasks.vision.RunningMode |
|
|
|
options = FaceLandmarkerOptions( |
|
base_options=BaseOptions(model_asset_path=model_path), |
|
running_mode=VisionRunningMode.IMAGE |
|
,min_face_detection_confidence=min_face_detection_confidence, min_face_presence_confidence=min_face_presence_confidence, |
|
output_facial_transformation_matrixes=output_facial_transformation_matrixes |
|
) |
|
|
|
with FaceLandmarker.create_from_options(options) as landmarker: |
|
if isinstance(image_data,str): |
|
mp_image = mp.Image.create_from_file(image_data) |
|
else: |
|
mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=np.asarray(image_data)) |
|
face_landmarker_result = landmarker.detect(mp_image) |
|
return mp_image,face_landmarker_result |
|
|
|
|