Akjava commited on
Commit
0dda723
·
1 Parent(s): 6545c3e
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.task filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__
README.md CHANGED
@@ -8,7 +8,7 @@ sdk_version: 5.5.0
8
  app_file: app.py
9
  pinned: false
10
  license: mit
11
- short_description: face detection with mediapipe
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
8
  app_file: app.py
9
  pinned: false
10
  license: mit
11
+ short_description: face detection with mediapipe-landmaker and output multi-size
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import spaces
2
+ import gradio as gr
3
+ import subprocess
4
+ from PIL import Image
5
+ import json
6
+
7
+ import mp_box
8
+ '''
9
+ Face landmark detection based Face Detection.
10
+ https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker
11
+ from model card
12
+ https://storage.googleapis.com/mediapipe-assets/MediaPipe%20BlazeFace%20Model%20Card%20(Short%20Range).pdf
13
+ Licensed Apache License, Version 2.0
14
+ Train with google's dataset(more detail see model card)
15
+
16
+
17
+ Not Face Detector based
18
+ https://ai.google.dev/edge/mediapipe/solutions/vision/face_detector
19
+
20
+ Bacause this is part of getting-landmark program and need control face edge.
21
+ So I don't know which one is better.never compare these.
22
+ '''
23
+ #@spaces.GPU(duration=120)
24
+ def process_images(image,no_mesh_draw=False,square_shape=False,progress=gr.Progress(track_tqdm=True)):
25
+ progress(0, desc="Start Mediapipe")
26
+
27
+ boxes,mp_image,face_landmarker_result = mp_box.mediapipe_to_box(image)
28
+ if no_mesh_draw:
29
+ annotated_image = image
30
+ else:
31
+ annotated_image = mp_box.draw_landmarks_on_image(face_landmarker_result,image)
32
+ annotation_boxes = []
33
+
34
+ jsons ={
35
+
36
+ }
37
+ index = 1
38
+
39
+ print(boxes)
40
+ if square_shape:
41
+ xy_boxes = boxes[3:]
42
+ else:
43
+ xy_boxes = boxes[:3]
44
+
45
+ print(len(xy_boxes))
46
+ for box in xy_boxes:
47
+ label=f"type-{index}"
48
+ print(box)
49
+ print(mp_box.xywh_to_xyxy(box))
50
+ annotation_boxes.append([mp_box.xywh_to_xyxy(box),label])
51
+ index+=1
52
+
53
+ jsons[label] = boxes[index-1]
54
+ print(label)
55
+
56
+ #print(annotation_boxes)
57
+ formatted_json = json.dumps(jsons, indent=1)
58
+ #return image
59
+ return [annotated_image,annotation_boxes],formatted_json
60
+
61
+
62
+ def read_file(file_path: str) -> str:
63
+ """read the text of target file
64
+ """
65
+ with open(file_path, 'r', encoding='utf-8') as f:
66
+ content = f.read()
67
+
68
+ return content
69
+
70
+ css="""
71
+ #col-left {
72
+ margin: 0 auto;
73
+ max-width: 640px;
74
+ }
75
+ #col-right {
76
+ margin: 0 auto;
77
+ max-width: 640px;
78
+ }
79
+ .grid-container {
80
+ display: flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ gap:10px
84
+ }
85
+
86
+ .image {
87
+ width: 128px;
88
+ height: 128px;
89
+ object-fit: cover;
90
+ }
91
+
92
+ .text {
93
+ font-size: 16px;
94
+ }
95
+ """
96
+
97
+ #css=css,
98
+
99
+ with gr.Blocks(css=css, elem_id="demo-container") as demo:
100
+ with gr.Column():
101
+ gr.HTML(read_file("demo_header.html"))
102
+ gr.HTML(read_file("demo_tools.html"))
103
+ with gr.Row():
104
+ with gr.Column():
105
+ image = gr.Image(height=800,sources=['upload','clipboard'],image_mode='RGB',elem_id="image_upload", type="pil", label="Upload")
106
+ with gr.Row(elem_id="prompt-container", equal_height=False):
107
+ with gr.Row():
108
+ btn = gr.Button("Face Detect", elem_id="run_button")
109
+
110
+ with gr.Accordion(label="Advanced Settings", open=False):
111
+ with gr.Row( equal_height=True):
112
+ no_mesh_draw = gr.Checkbox(label="No Mesh Drawing")
113
+ square_shape = gr.Checkbox(label="square shape")
114
+
115
+ with gr.Column():
116
+ image_out = gr.AnnotatedImage(label="Output", elem_id="output-img")
117
+ text_out = gr.TextArea(label="JSON-Output")
118
+
119
+
120
+
121
+
122
+ btn.click(fn=process_images, inputs=[image,no_mesh_draw], outputs =[image_out,text_out], api_name='infer')
123
+ gr.Examples(
124
+ examples =["examples/00004200.jpg"],
125
+ inputs=[image]
126
+ )
127
+ gr.HTML(read_file("demo_footer.html"))
128
+
129
+ if __name__ == "__main__":
130
+ demo.launch()
demo_footer.html ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ <div>
2
+ <P> Images are generated with <a href="https://huggingface.co/black-forest-labs/FLUX.1-schnell">FLUX.1-schnell</a> and licensed under <a href="http://www.apache.org/licenses/LICENSE-2.0">the Apache 2.0 License</a>
3
+ </div>
demo_header.html ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div style="text-align: center;">
2
+ <h1>
3
+ Mediapipe Face Detect
4
+ </h1>
5
+ <div class="grid-container">
6
+ <img src="https://akjava.github.io/AIDiagramChatWithVoice-FaceCharacter/webp/128/00191245_09_00002200.webp" alt="Flux.1-schnell-WebP3Frame-TalkingAnimation" class="image">
7
+ This Space use <a href="https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker">Mediapipe face landmark detection model</a> which licensed under <a href="http://www.apache.org/licenses/LICENSE-2.0">the Apache 2.0 License</a>
8
+ <p class="text">
9
+
10
+ </p>
11
+ </div>
12
+
13
+ </div>
demo_tools.html ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <div style="text-align: center;">
2
+ <p><a href="https://huggingface.co/spaces/Akjava/mediapipe-face-detect">Mediapipe Face detector</a></p>
3
+ <p><a href="https://huggingface.co/spaces/Akjava/WebPTalkHead">[WebP-3F-TH]</a>
4
+ <a href="https://huggingface.co/spaces/Akjava/flux1-schnell-img2img">[Flux1-Img2Img(GPU)]</a>
5
+ <a href="https://huggingface.co/spaces/Akjava/flux1-schnell-mask-inpaint">[Flux1-Inpaint(GPU)]</a>
6
+ <a href="https://huggingface.co/spaces/Akjava/OpenCVInpaintCPU">[OpenCV-Inapint]</a>
7
+ <a href="https://huggingface.co/spaces/Akjava/Simple-Whitebalance-Image">[Whitebalance]</a>
8
+ <a href="https://huggingface.co/spaces/Akjava/Simple-Mask-Paste-Image">[Paste Image]</a>
9
+ <a href=" https://huggingface.co/spaces/Akjava/WebP-Resize-Convert">[WebP Resize Convert]</a></p>
10
+ </div>
examples/00004200.jpg ADDED
face_landmarker.task ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:64184e229b263107bc2b804c6625db1341ff2bb731874b0bcc2fe6544e0bc9ff
3
+ size 3758596
face_landmarker.task.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ Face landmark detection
2
+ https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker
3
+
4
+ model card page is
5
+ https://storage.googleapis.com/mediapipe-assets/MediaPipe%20BlazeFace%20Model%20Card%20(Short%20Range).pdf
6
+
7
+ license is Apache2.0
8
+ https://www.apache.org/licenses/LICENSE-2.0.html
mp_box.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import mediapipe as mp
2
+ from mediapipe.tasks import python
3
+ from mediapipe.tasks.python import vision
4
+ from mediapipe.framework.formats import landmark_pb2
5
+ from mediapipe import solutions
6
+ import numpy as np
7
+
8
+ # for X,Y,W,H to x1,y1,x2,y2(Left-top,right-bottom style)
9
+ def xywh_to_xyxy(box):
10
+ return [box[0],box[1],box[0]+box[2],box[1]+box[3]]
11
+
12
+ def convert_to_box(face_landmarks_list,indices,w=1024,h=1024):
13
+ x1=w
14
+ y1=h
15
+ x2=0
16
+ y2=0
17
+ for index in indices:
18
+ x=min(w,max(0,(face_landmarks_list[0][index].x*w)))
19
+ y=min(h,max(0,(face_landmarks_list[0][index].y*h)))
20
+ if x<x1:
21
+ x1=x
22
+
23
+ if y<y1:
24
+ y1=y
25
+
26
+ if x>x2:
27
+ x2=x
28
+ if y>y2:
29
+ y2=y
30
+
31
+
32
+ return [int(x1),int(y1),int(x2-x1),int(y2-y1)]
33
+
34
+
35
+ def box_to_square(bbox):
36
+ box=list(bbox)
37
+ if box[2]>box[3]:
38
+ diff = box[2]-box[3]
39
+ box[3]+=diff
40
+ box[1]-=diff/2
41
+ elif box[3]>box[2]:
42
+ diff = box[3]-box[2]
43
+ box[2]+=diff
44
+ box[0]-=diff/2
45
+ return box
46
+
47
+
48
+ def face_landmark_result_to_box(face_landmarker_result,width=1024,height=1024):
49
+ face_landmarks_list = face_landmarker_result.face_landmarks
50
+
51
+
52
+ full_indices = list(range(456))
53
+
54
+ MIDDLE_FOREHEAD = 151
55
+ BOTTOM_CHIN_EX = 152
56
+ BOTTOM_CHIN = 175
57
+ CHIN_TO_MIDDLE_FOREHEAD = [200,14,1,6,18,9]
58
+ MOUTH_BOTTOM = [202,200,422]
59
+ EYEBROW_CHEEK_LEFT_RIGHT = [46,226,50,1,280,446,276]
60
+
61
+ LEFT_HEAD_OUTER_EX = 251 #on side face almost same as full
62
+ LEFT_HEAD_OUTER = 301
63
+ LEFT_EYE_OUTER_EX = 356
64
+ LEFT_EYE_OUTER = 264
65
+ LEFT_MOUTH_OUTER_EX = 288
66
+ LEFT_MOUTH_OUTER = 288
67
+ LEFT_CHIN_OUTER = 435
68
+ RIGHT_HEAD_OUTER_EX = 21
69
+ RIGHT_HEAD_OUTER = 71
70
+ RIGHT_EYE_OUTER_EX = 127
71
+ RIGHT_EYE_OUTER = 34
72
+ RIGHT_MOUTH_OUTER_EX = 58
73
+ RIGHT_MOUTH_OUTER = 215
74
+ RIGHT_CHIN_OUTER = 150
75
+
76
+ # TODO naming line
77
+ min_indices=CHIN_TO_MIDDLE_FOREHEAD+EYEBROW_CHEEK_LEFT_RIGHT+MOUTH_BOTTOM
78
+
79
+ 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
80
+
81
+ box1 = convert_to_box(face_landmarks_list,min_indices,width,height)
82
+ box2 = convert_to_box(face_landmarks_list,chin_to_brow_indices,width,height)
83
+ box3 = convert_to_box(face_landmarks_list,full_indices,width,height)
84
+ #print(box)
85
+
86
+ return [box1,box2,box3,box_to_square(box1),box_to_square(box2),box_to_square(box3)]
87
+
88
+
89
+ def draw_landmarks_on_image(detection_result,rgb_image):
90
+ face_landmarks_list = detection_result.face_landmarks
91
+ annotated_image = np.copy(rgb_image)
92
+
93
+ # Loop through the detected faces to visualize.
94
+ for idx in range(len(face_landmarks_list)):
95
+ face_landmarks = face_landmarks_list[idx]
96
+
97
+ # Draw the face landmarks.
98
+ face_landmarks_proto = landmark_pb2.NormalizedLandmarkList()
99
+ face_landmarks_proto.landmark.extend([
100
+ landmark_pb2.NormalizedLandmark(x=landmark.x, y=landmark.y, z=landmark.z) for landmark in face_landmarks
101
+ ])
102
+
103
+ solutions.drawing_utils.draw_landmarks(
104
+ image=annotated_image,
105
+ landmark_list=face_landmarks_proto,
106
+ connections=mp.solutions.face_mesh.FACEMESH_TESSELATION,
107
+ landmark_drawing_spec=None,
108
+ connection_drawing_spec=mp.solutions.drawing_styles
109
+ .get_default_face_mesh_tesselation_style())
110
+
111
+ return annotated_image
112
+
113
+ def mediapipe_to_box(image_data,model_path="face_landmarker.task"):
114
+ BaseOptions = mp.tasks.BaseOptions
115
+ FaceLandmarker = mp.tasks.vision.FaceLandmarker
116
+ FaceLandmarkerOptions = mp.tasks.vision.FaceLandmarkerOptions
117
+ VisionRunningMode = mp.tasks.vision.RunningMode
118
+
119
+ options = FaceLandmarkerOptions(
120
+ base_options=BaseOptions(model_asset_path=model_path),
121
+ running_mode=VisionRunningMode.IMAGE
122
+ ,min_face_detection_confidence=0, min_face_presence_confidence=0
123
+ )
124
+
125
+
126
+ with FaceLandmarker.create_from_options(options) as landmarker:
127
+ if isinstance(image_data,str):
128
+ mp_image = mp.Image.create_from_file(image_data)
129
+ else:
130
+ mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=np.asarray(image_data))
131
+ face_landmarker_result = landmarker.detect(mp_image)
132
+ boxes = face_landmark_result_to_box(face_landmarker_result,mp_image.width,mp_image.height)
133
+ return boxes,mp_image,face_landmarker_result
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ numpy
2
+ torch
3
+ spaces
4
+ mediapipe