File size: 4,225 Bytes
58665c8 |
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 |
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
# for X,Y,W,H to x1,y1,x2,y2(Left-top,right-bottom style)
def xywh_to_xyxy(box):
return [box[0],box[1],box[0]+box[2],box[1]+box[3]]
def convert_to_box(face_landmarks_list,indices,w=1024,h=1024):
x1=w
y1=h
x2=0
y2=0
for index in indices:
x=min(w,max(0,(face_landmarks_list[0][index].x*w)))
y=min(h,max(0,(face_landmarks_list[0][index].y*h)))
if x<x1:
x1=x
if y<y1:
y1=y
if x>x2:
x2=x
if y>y2:
y2=y
return [int(x1),int(y1),int(x2-x1),int(y2-y1)]
def box_to_square(bbox):
box=list(bbox)
if box[2]>box[3]:
diff = box[2]-box[3]
box[3]+=diff
box[1]-=diff/2
elif box[3]>box[2]:
diff = box[3]-box[2]
box[2]+=diff
box[0]-=diff/2
return box
def face_landmark_result_to_box(face_landmarker_result,width=1024,height=1024):
face_landmarks_list = face_landmarker_result.face_landmarks
full_indices = list(range(456))
MIDDLE_FOREHEAD = 151
BOTTOM_CHIN_EX = 152
BOTTOM_CHIN = 175
CHIN_TO_MIDDLE_FOREHEAD = [200,14,1,6,18,9]
MOUTH_BOTTOM = [202,200,422]
EYEBROW_CHEEK_LEFT_RIGHT = [46,226,50,1,280,446,276]
LEFT_HEAD_OUTER_EX = 251 #on side face almost same as full
LEFT_HEAD_OUTER = 301
LEFT_EYE_OUTER_EX = 356
LEFT_EYE_OUTER = 264
LEFT_MOUTH_OUTER_EX = 288
LEFT_MOUTH_OUTER = 288
LEFT_CHIN_OUTER = 435
RIGHT_HEAD_OUTER_EX = 21
RIGHT_HEAD_OUTER = 71
RIGHT_EYE_OUTER_EX = 127
RIGHT_EYE_OUTER = 34
RIGHT_MOUTH_OUTER_EX = 58
RIGHT_MOUTH_OUTER = 215
RIGHT_CHIN_OUTER = 150
# TODO naming line
min_indices=CHIN_TO_MIDDLE_FOREHEAD+EYEBROW_CHEEK_LEFT_RIGHT+MOUTH_BOTTOM
chin_to_brow_indices = [LEFT_CHIN_OUTER,LEFT_MOUTH_OUTER,LEFT_EYE_OUTER,LEFT_HEAD_OUTER,MIDDLE_FOREHEAD,RIGHT_HEAD_OUTER,RIGHT_EYE_OUTER,RIGHT_MOUTH_OUTER,RIGHT_CHIN_OUTER,BOTTOM_CHIN]+min_indices
box1 = convert_to_box(face_landmarks_list,min_indices,width,height)
box2 = convert_to_box(face_landmarks_list,chin_to_brow_indices,width,height)
box3 = convert_to_box(face_landmarks_list,full_indices,width,height)
#print(box)
return [box1,box2,box3,box_to_square(box1),box_to_square(box2),box_to_square(box3)]
def draw_landmarks_on_image(detection_result,rgb_image):
face_landmarks_list = detection_result.face_landmarks
annotated_image = np.copy(rgb_image)
# Loop through the detected faces to visualize.
for idx in range(len(face_landmarks_list)):
face_landmarks = face_landmarks_list[idx]
# Draw the face landmarks.
face_landmarks_proto = landmark_pb2.NormalizedLandmarkList()
face_landmarks_proto.landmark.extend([
landmark_pb2.NormalizedLandmark(x=landmark.x, y=landmark.y, z=landmark.z) for landmark in face_landmarks
])
solutions.drawing_utils.draw_landmarks(
image=annotated_image,
landmark_list=face_landmarks_proto,
connections=mp.solutions.face_mesh.FACEMESH_TESSELATION,
landmark_drawing_spec=None,
connection_drawing_spec=mp.solutions.drawing_styles
.get_default_face_mesh_tesselation_style())
return annotated_image
def mediapipe_to_box(image_data,model_path="face_landmarker.task"):
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=0, min_face_presence_confidence=0
)
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)
boxes = face_landmark_result_to_box(face_landmarker_result,mp_image.width,mp_image.height)
return boxes,mp_image,face_landmarker_result |