File size: 5,848 Bytes
661ec13 4c7255e 661ec13 4c7255e 661ec13 4c7255e 661ec13 4c7255e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
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
# 2024-11-27 -extract_landmark :add args
# add get_pixel_xyz
# 2024-11-28 add get_normalized_xyz
# 2024-11-30 add get_normalized_landmarks,sort_triangles_by_depth
# 2024-12-04 add get_normalized_landmarks args
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:
#print(pt)
value = [int(pt[0]),int(pt[1])]
#print(value)
ints.append(value)
return ints
debug = False
def divide_line_to_points(points,divided): # return divided + 1
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]) # last one
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
#normalized value index see mp_constants
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]
#need aspect?
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)
# z is normalized
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
|