show pose body lables
Browse files
.gitignore
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
.idea/
|
2 |
__pycache__/
|
3 |
-
|
4 |
-
|
|
|
1 |
.idea/
|
2 |
__pycache__/
|
3 |
+
playground.py
|
4 |
+
|
Arial.ttf
ADDED
Binary file (276 kB). View file
|
|
app.py
CHANGED
@@ -11,6 +11,7 @@ def predict(image: PIL.Image):
|
|
11 |
input_size = 256
|
12 |
size = (1280, 1280)
|
13 |
image = PIL.ImageOps.fit(image, size, PIL.Image.LANCZOS)
|
|
|
14 |
image_tf = tf.keras.preprocessing.image.img_to_array(image)
|
15 |
# Resize and pad the image to keep the aspect ratio and fit the expected size.
|
16 |
input_image = tf.expand_dims(image_tf, axis=0)
|
@@ -18,8 +19,9 @@ def predict(image: PIL.Image):
|
|
18 |
keypoints = movenet(input_image)
|
19 |
keypoints = np.array(keypoints)
|
20 |
image = tf.keras.preprocessing.image.array_to_img(image_tf)
|
21 |
-
draw_bones(image, keypoints)
|
22 |
-
|
|
|
23 |
|
24 |
|
25 |
footer = r"""
|
@@ -39,9 +41,18 @@ with gr.Blocks(title="MoveNet") as app:
|
|
39 |
run_btn = gr.Button(variant="primary")
|
40 |
with gr.Column():
|
41 |
output_img = gr.Image(type="numpy", label="Output image")
|
42 |
-
gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
-
run_btn.click(predict, [input_img], [output_img])
|
45 |
|
46 |
with gr.Row():
|
47 |
blobs = [[f"examples/{x:02d}.jpg"] for x in range(1, 4)]
|
|
|
11 |
input_size = 256
|
12 |
size = (1280, 1280)
|
13 |
image = PIL.ImageOps.fit(image, size, PIL.Image.LANCZOS)
|
14 |
+
# image = PIL.ImageOps.contain(image, size)
|
15 |
image_tf = tf.keras.preprocessing.image.img_to_array(image)
|
16 |
# Resize and pad the image to keep the aspect ratio and fit the expected size.
|
17 |
input_image = tf.expand_dims(image_tf, axis=0)
|
|
|
19 |
keypoints = movenet(input_image)
|
20 |
keypoints = np.array(keypoints)
|
21 |
image = tf.keras.preprocessing.image.array_to_img(image_tf)
|
22 |
+
joints = draw_bones(image, keypoints)
|
23 |
+
points = [f"{x}#{y}" for p, x, y in joints]
|
24 |
+
return image, joints, points
|
25 |
|
26 |
|
27 |
footer = r"""
|
|
|
41 |
run_btn = gr.Button(variant="primary")
|
42 |
with gr.Column():
|
43 |
output_img = gr.Image(type="numpy", label="Output image")
|
44 |
+
with gr.Accordion("See Positions", open=False):
|
45 |
+
positions = gr.Dataframe(
|
46 |
+
interactive=True,
|
47 |
+
headers=["x", "y", "label"],
|
48 |
+
datatype=["str", "number", "number"],
|
49 |
+
row_count=16,
|
50 |
+
col_count=(3, "fixed"),
|
51 |
+
)
|
52 |
+
data = gr.Textbox(label="Positions", lines=17)
|
53 |
+
gr.ClearButton(components=[input_img, output_img, positions, data], variant="stop")
|
54 |
|
55 |
+
run_btn.click(predict, [input_img], [output_img, positions, data])
|
56 |
|
57 |
with gr.Row():
|
58 |
blobs = [[f"examples/{x:02d}.jpg"] for x in range(1, 4)]
|
poser.py
CHANGED
@@ -10,23 +10,31 @@ import PIL.ImageOps
|
|
10 |
import numpy as np
|
11 |
import tensorflow as tf
|
12 |
from PIL import ImageDraw
|
|
|
13 |
from huggingface_hub import snapshot_download
|
14 |
|
15 |
-
|
16 |
# Dictionary that maps from joint names to keypoint indices.
|
17 |
KEYPOINT_DICT = {
|
18 |
'nose': 0,
|
19 |
-
'left_eye': 1,
|
20 |
-
'
|
21 |
-
'
|
22 |
-
'
|
23 |
-
'
|
24 |
-
'
|
25 |
-
'
|
26 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
}
|
28 |
|
29 |
-
|
30 |
(0, 1): 'Magenta',
|
31 |
(0, 2): 'Cyan',
|
32 |
(1, 3): 'Magenta',
|
@@ -48,11 +56,11 @@ COLOR_DICT = {
|
|
48 |
}
|
49 |
|
50 |
|
51 |
-
def process_keypoints(
|
52 |
"""Returns high confidence keypoints and edges for visualization.
|
53 |
|
54 |
Args:
|
55 |
-
|
56 |
the keypoint coordinates and scores returned from the MoveNet model.
|
57 |
height: height of the image in pixels.
|
58 |
width: width of the image in pixels.
|
@@ -67,52 +75,57 @@ def process_keypoints(keypoints, height, width, threshold=0.22):
|
|
67 |
"""
|
68 |
keypoints_all = []
|
69 |
keypoint_edges_all = []
|
70 |
-
|
71 |
-
num_instances, _, _, _ = keypoints.shape
|
72 |
for idx in range(num_instances):
|
73 |
-
kpts_x =
|
74 |
-
kpts_y =
|
75 |
-
kpts_scores =
|
76 |
-
|
77 |
-
|
78 |
-
kpts_above_thresh_absolute = kpts_absolute_xy[
|
79 |
-
kpts_scores > threshold, :]
|
80 |
keypoints_all.append(kpts_above_thresh_absolute)
|
81 |
|
82 |
-
for edge_pair, color in
|
83 |
-
if
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
y_end = kpts_absolute_xy[edge_pair[1], 1]
|
89 |
line_seg = np.array([[x_start, y_start], [x_end, y_end]])
|
90 |
-
keypoint_edges_all.append(line_seg)
|
91 |
-
colors.append(color)
|
92 |
if keypoints_all:
|
93 |
-
|
94 |
else:
|
95 |
-
|
96 |
|
97 |
if keypoint_edges_all:
|
98 |
-
|
99 |
else:
|
100 |
-
|
101 |
-
return
|
102 |
|
103 |
|
104 |
def draw_bones(pixmap: PIL.Image, keypoints):
|
105 |
draw = ImageDraw.Draw(pixmap)
|
106 |
-
joints, bones
|
|
|
|
|
|
|
107 |
|
108 |
-
for bone, color in
|
|
|
109 |
draw.line((*bone[0], *bone[1]), fill=color, width=4)
|
110 |
|
111 |
radio = 3
|
112 |
|
113 |
-
for c_x, c_y in joints:
|
|
|
|
|
114 |
shape = [(c_x - radio, c_y - radio), (c_x + radio, c_y + radio)]
|
115 |
draw.ellipse(shape, fill="red", outline="red")
|
|
|
|
|
|
|
116 |
|
117 |
|
118 |
def movenet(image):
|
@@ -136,6 +149,3 @@ def movenet(image):
|
|
136 |
outputs = model(image)
|
137 |
# Output is a [1, 1, 17, 3] tensor.
|
138 |
return outputs['output_0'].numpy()
|
139 |
-
|
140 |
-
|
141 |
-
|
|
|
10 |
import numpy as np
|
11 |
import tensorflow as tf
|
12 |
from PIL import ImageDraw
|
13 |
+
from PIL import ImageFont
|
14 |
from huggingface_hub import snapshot_download
|
15 |
|
|
|
16 |
# Dictionary that maps from joint names to keypoint indices.
|
17 |
KEYPOINT_DICT = {
|
18 |
'nose': 0,
|
19 |
+
'left_eye': 1,
|
20 |
+
'right_eye': 2,
|
21 |
+
'left_ear': 3,
|
22 |
+
'right_ear': 4,
|
23 |
+
'left_shoulder': 5,
|
24 |
+
'right_shoulder': 6,
|
25 |
+
'left_elbow': 7,
|
26 |
+
'right_elbow': 8,
|
27 |
+
'left_wrist': 9,
|
28 |
+
'right_wrist': 10,
|
29 |
+
'left_hip': 11,
|
30 |
+
'right_hip': 12,
|
31 |
+
'left_knee': 13,
|
32 |
+
'right_knee': 14,
|
33 |
+
'left_ankle': 15,
|
34 |
+
'right_ankle': 16
|
35 |
}
|
36 |
|
37 |
+
KEYPOINT_EDGE_INDS_TO_COLOR = {
|
38 |
(0, 1): 'Magenta',
|
39 |
(0, 2): 'Cyan',
|
40 |
(1, 3): 'Magenta',
|
|
|
56 |
}
|
57 |
|
58 |
|
59 |
+
def process_keypoints(keypoints_with_scores, height, width, threshold=0.11):
|
60 |
"""Returns high confidence keypoints and edges for visualization.
|
61 |
|
62 |
Args:
|
63 |
+
keypoints_with_scores: A numpy array with shape [1, 1, 17, 3] representing
|
64 |
the keypoint coordinates and scores returned from the MoveNet model.
|
65 |
height: height of the image in pixels.
|
66 |
width: width of the image in pixels.
|
|
|
75 |
"""
|
76 |
keypoints_all = []
|
77 |
keypoint_edges_all = []
|
78 |
+
num_instances, _, _, _ = keypoints_with_scores.shape
|
|
|
79 |
for idx in range(num_instances):
|
80 |
+
kpts_x = keypoints_with_scores[0, idx, :, 1]
|
81 |
+
kpts_y = keypoints_with_scores[0, idx, :, 0]
|
82 |
+
kpts_scores = keypoints_with_scores[0, idx, :, 2]
|
83 |
+
kpts_dict = list(KEYPOINT_DICT.keys())
|
84 |
+
kpts_absolute_xy = np.stack([kpts_dict, width * np.array(kpts_x), height * np.array(kpts_y)], axis=-1)
|
85 |
+
kpts_above_thresh_absolute = kpts_absolute_xy[kpts_scores > threshold, :]
|
|
|
86 |
keypoints_all.append(kpts_above_thresh_absolute)
|
87 |
|
88 |
+
for edge_pair, color in KEYPOINT_EDGE_INDS_TO_COLOR.items():
|
89 |
+
if kpts_scores[edge_pair[0]] > threshold and kpts_scores[edge_pair[1]] > threshold:
|
90 |
+
x_start = kpts_absolute_xy[edge_pair[0], 1]
|
91 |
+
y_start = kpts_absolute_xy[edge_pair[0], 2]
|
92 |
+
x_end = kpts_absolute_xy[edge_pair[1], 1]
|
93 |
+
y_end = kpts_absolute_xy[edge_pair[1], 2]
|
|
|
94 |
line_seg = np.array([[x_start, y_start], [x_end, y_end]])
|
95 |
+
keypoint_edges_all.append([line_seg, color])
|
|
|
96 |
if keypoints_all:
|
97 |
+
keypoints_xy = np.concatenate(keypoints_all, axis=0)
|
98 |
else:
|
99 |
+
keypoints_xy = np.zeros((0, 17, 2))
|
100 |
|
101 |
if keypoint_edges_all:
|
102 |
+
edges_xy = np.stack(keypoint_edges_all, axis=0)
|
103 |
else:
|
104 |
+
edges_xy = np.zeros((0, 2, 2))
|
105 |
+
return keypoints_xy, edges_xy
|
106 |
|
107 |
|
108 |
def draw_bones(pixmap: PIL.Image, keypoints):
|
109 |
draw = ImageDraw.Draw(pixmap)
|
110 |
+
joints, bones = process_keypoints(keypoints, pixmap.height, pixmap.width)
|
111 |
+
|
112 |
+
font = ImageFont.truetype("./Arial.ttf", 22)
|
113 |
+
print(joints)
|
114 |
|
115 |
+
for bone, color in bones:
|
116 |
+
bone = bone.astype(np.float32)
|
117 |
draw.line((*bone[0], *bone[1]), fill=color, width=4)
|
118 |
|
119 |
radio = 3
|
120 |
|
121 |
+
for label, c_x, c_y in joints:
|
122 |
+
c_x = float(c_x)
|
123 |
+
c_y = float(c_y)
|
124 |
shape = [(c_x - radio, c_y - radio), (c_x + radio, c_y + radio)]
|
125 |
draw.ellipse(shape, fill="red", outline="red")
|
126 |
+
draw.text((c_x, c_y), label, font=font, align="left", fill="blue")
|
127 |
+
|
128 |
+
return joints
|
129 |
|
130 |
|
131 |
def movenet(image):
|
|
|
149 |
outputs = model(image)
|
150 |
# Output is a [1, 1, 17, 3] tensor.
|
151 |
return outputs['output_0'].numpy()
|
|
|
|
|
|