-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplotting.py
202 lines (182 loc) · 5.79 KB
/
plotting.py
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
import streamlit as st
import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision
from mediapipe.framework.formats import landmark_pb2
import cv2
import numpy as np
from PIL import Image
import time
import sys
import plotly.graph_objects as go
# Set up MediaPipe for drawing landmarks
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
# Define your color tuples in RGB
_RED = "rgb(255, 48, 48)"
_GREEN = "rgb(48, 255, 48)"
_BLUE = "rgb(21, 101, 192)"
_YELLOW = "rgb(255, 204, 0)"
_GRAY = "rgb(128, 128, 128)"
_PURPLE = "rgb(128, 64, 128)"
_PEACH = "rgb(255, 229, 180)"
_WHITE = "rgb(224, 224, 224)"
_CYAN = "rgb(48, 255, 192)"
_MAGENTA = "rgb(255, 48, 192)"
# Define a list of colors for each keypoint
colors = [
_RED,
_RED,
_PEACH,
_PEACH,
_PEACH,
_RED,
_PURPLE,
_PURPLE,
_PURPLE,
_RED,
_YELLOW,
_YELLOW,
_YELLOW,
_RED,
_GREEN,
_GREEN,
_GREEN,
_RED,
_BLUE,
_BLUE,
_BLUE,
]
# Hand landmarks
WRIST = 0
THUMB_CMC = 1
THUMB_MCP = 2
THUMB_IP = 3
THUMB_TIP = 4
INDEX_FINGER_MCP = 5
INDEX_FINGER_PIP = 6
INDEX_FINGER_DIP = 7
INDEX_FINGER_TIP = 8
MIDDLE_FINGER_MCP = 9
MIDDLE_FINGER_PIP = 10
MIDDLE_FINGER_DIP = 11
MIDDLE_FINGER_TIP = 12
RING_FINGER_MCP = 13
RING_FINGER_PIP = 14
RING_FINGER_DIP = 15
RING_FINGER_TIP = 16
PINKY_MCP = 17
PINKY_PIP = 18
PINKY_DIP = 19
PINKY_TIP = 20
# Landmark groups
_PALM_LANDMARKS = [
WRIST,
INDEX_FINGER_MCP,
MIDDLE_FINGER_MCP,
RING_FINGER_MCP,
PINKY_MCP,
WRIST,
]
_PALM_LANDMARKS_2 = [WRIST, THUMB_CMC]
_THUMB_LANDMARKS = [THUMB_CMC, THUMB_MCP, THUMB_IP, THUMB_TIP]
_INDEX_FINGER_LANDMARKS = [
INDEX_FINGER_MCP,
INDEX_FINGER_PIP,
INDEX_FINGER_DIP,
INDEX_FINGER_TIP,
]
_MIDDLE_FINGER_LANDMARKS = [
MIDDLE_FINGER_MCP,
MIDDLE_FINGER_PIP,
MIDDLE_FINGER_DIP,
MIDDLE_FINGER_TIP,
]
_RING_FINGER_LANDMARKS = [
RING_FINGER_MCP,
RING_FINGER_PIP,
RING_FINGER_DIP,
RING_FINGER_TIP,
]
_PINKY_FINGER_LANDMARKS = [PINKY_MCP, PINKY_PIP, PINKY_DIP, PINKY_TIP]
def draw_landmarks_on_image(image, recognition_result):
annotated_image = image.copy()
if recognition_result.hand_landmarks:
annotated_image = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB)
for hand_landmarks in recognition_result.hand_landmarks:
hand_landmarks_proto = landmark_pb2.NormalizedLandmarkList()
hand_landmarks_proto.landmark.extend(
[
landmark_pb2.NormalizedLandmark(
x=landmark.x, y=landmark.y, z=landmark.z
)
for landmark in hand_landmarks
]
)
mp_drawing.draw_landmarks(
annotated_image,
hand_landmarks_proto,
mp_hands.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style(),
)
annotated_image = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB)
return annotated_image
def plot_hand_landmarks_3d_plotly(results):
for gesture, hand_landmarks_list in results:
if hand_landmarks_list and len(hand_landmarks_list) > 0:
# Extract x, y, z coordinates from the first (and only) list of landmarks
landmarks = hand_landmarks_list[0]
x = [landmark.x for landmark in landmarks]
y = [landmark.y for landmark in landmarks]
z = [landmark.z for landmark in landmarks]
# Create the 3D scatter plot with custom colors
scatter = go.Scatter3d(
x=x,
y=y,
z=z,
mode="markers",
marker=dict(size=10, color=colors, opacity=1),
text=[
f"Landmark {i}<br>X: {x[i]:.2f}<br>Y: {y[i]:.2f}<br>Z: {z[i]:.2f}"
for i in range(len(x))
],
hoverinfo="text",
)
# Function to draw lines between landmarks
def draw_lines(landmarks, color):
line_data = []
for i in range(len(landmarks) - 1):
line_data.append(
go.Scatter3d(
x=[x[landmarks[i]], x[landmarks[i + 1]]],
y=[y[landmarks[i]], y[landmarks[i + 1]]],
z=[z[landmarks[i]], z[landmarks[i + 1]]],
mode="lines",
line=dict(color=color, width=10),
)
)
return line_data
# Draw lines for each group
line_traces = []
line_traces.extend(draw_lines(_PALM_LANDMARKS, _GRAY))
line_traces.extend(draw_lines(_PALM_LANDMARKS_2, _GRAY))
line_traces.extend(draw_lines(_THUMB_LANDMARKS, _PEACH))
line_traces.extend(draw_lines(_INDEX_FINGER_LANDMARKS, _PURPLE))
line_traces.extend(draw_lines(_MIDDLE_FINGER_LANDMARKS, _YELLOW))
line_traces.extend(draw_lines(_RING_FINGER_LANDMARKS, _GREEN))
line_traces.extend(draw_lines(_PINKY_FINGER_LANDMARKS, _BLUE))
# Create the layout
layout = go.Layout(
scene=dict(
xaxis_title="X", yaxis_title="Y", zaxis_title="Z", aspectmode="data"
),
title=f"Gesture: {gesture.category_name}",
)
# Create the figure and add the scatter plot and lines
fig = go.Figure(data=[scatter] + line_traces, layout=layout)
fig.update_layout(showlegend=False, autosize=True, width=600, height=600)
return fig
else:
return None