fixed geom gestures

main
Eliza Moscovskaya 4 weeks ago
parent 2999f8f274
commit c72ff7ded0

@ -35,9 +35,9 @@ class SpecialGestureDetector:
}
# Повышенный порог уверенности для специальных жестов
min_conf = 0.6
min_conf = 0.5
required = ['left_shoulder', 'right_shoulder', 'left_elbow', 'right_elbow',
'left_wrist', 'right_wrist', 'left_hip', 'right_hip']
'left_wrist', 'right_wrist', 'nose']
for p in required:
if landmarks[idx[p]][3] < min_conf:
if self.debug:
@ -53,50 +53,64 @@ class SpecialGestureDetector:
r_wr = landmarks[idx['right_wrist']][:2]
l_hip = landmarks[idx['left_hip']][:2]
r_hip = landmarks[idx['right_hip']][:2]
nose = np.array(landmarks[idx['nose']][:2])
hip_center = (l_hip + r_hip) / 2
shoulder_center_y = (l_sh[1] + r_sh[1]) / 2
hip_center_y = (l_hip[1] + r_hip[1]) / 2
torso_height = hip_center_y - shoulder_center_y
shoulder_width = np.linalg.norm(r_sh - l_sh)
if shoulder_width < 50 or shoulder_width > 300:
if self.debug:
print("shoulder_width out of range")
if shoulder_width < 30 or torso_height < 10:
return 'none'
# ----- КРЕСТ (предплечья скрещены на груди) -----
# 1. Запястья перекрещены (левое правее правого) И на уровне груди (ниже плеч, выше бедер)
wrists_crossed = l_wr[0] > r_wr[0]
wrists_chest_level = (max(l_wr[1], r_wr[1]) > max(l_sh[1], r_sh[1]) and
min(l_wr[1], r_wr[1]) < hip_center[1])
# ---- Вспомогательные функции ----
def angle_between_vectors(v1, v2):
"""Угол между двумя векторами в градусах (0..180)"""
cos_a = np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2) + 1e-6)
return np.arccos(np.clip(cos_a, -1.0, 1.0)) * 180 / np.pi
# 2. Локти тоже на уровне груди (примерно)
elbows_chest_level = (max(l_el[1], r_el[1]) > max(l_sh[1], r_sh[1]) * 0.9 and
min(l_el[1], r_el[1]) < hip_center[1] * 1.1)
def elbow_angle(shoulder, elbow, wrist):
"""Угол в локте (плечо-локоть-запястье)"""
v1 = shoulder - elbow
v2 = wrist - elbow
return angle_between_vectors(v1, v2)
# 3. Руки согнуты (предплечья короче верхней части руки)
left_bent = np.linalg.norm(l_wr - l_el) < np.linalg.norm(l_el - l_sh) * 0.9
right_bent = np.linalg.norm(r_wr - r_el) < np.linalg.norm(r_el - r_sh) * 0.9
arms_bent = left_bent and right_bent
# ---- Вычисляем углы ----
l_angle = elbow_angle(l_sh, l_el, l_wr) # угол в левом локте
r_angle = elbow_angle(r_sh, r_el, r_wr) # угол в правом локте
# 4. Запястья близко к центру тела (не сильно отведены, типично для креста на груди)
body_center_x = (l_sh[0] + r_sh[0]) / 2
wrists_near_center = (abs(l_wr[0] - body_center_x) < shoulder_width * 0.6 and
abs(r_wr[0] - body_center_x) < shoulder_width * 0.6)
# ---- КРЕСТ ----
# 1. Оба локтя сильно согнуты (< 100°)
elbows_bent = (l_angle < 100 and r_angle < 100)
# 2. Левое запястье правее правого (перекрест)
wrists_crossed = l_wr[0] > r_wr[0] + 5 # небольшой запас в пикселях (можно и 0)
# 3. Запястья находятся между плечами и бёдрами по Y (уровень груди)
wrists_at_chest = (
shoulder_center_y - 0.3 * torso_height < l_wr[1] < hip_center_y + 0.3 * torso_height and
shoulder_center_y - 0.3 * torso_height < r_wr[1] < hip_center_y + 0.3 * torso_height
)
cross = (wrists_crossed and wrists_chest_level and elbows_chest_level and
arms_bent and wrists_near_center)
if self.debug and cross:
print(f"CROSS: crossed={wrists_crossed}, chest_w={wrists_chest_level}, "
f"chest_e={elbows_chest_level}, bent={arms_bent}, near_center={wrists_near_center}")
cross = elbows_bent and wrists_crossed and wrists_at_chest
if cross:
return 'cross'
# ----- ДОМИК (руки над головой) -----
head_y = landmarks[idx['nose']][1] - 50
arms_up = (l_wr[1] < head_y and r_wr[1] < head_y)
if arms_up:
dist = np.linalg.norm(l_wr - r_wr)
rel_dist = dist / shoulder_width
if rel_dist < 1.5:
return 'dome'
# ---- ДОМИК ----
# 1. Запястья выше носа
wrists_above_nose = (l_wr[1] < nose[1] and r_wr[1] < nose[1])
# 2. Локти выше плеч (верхняя граница плеч min по Y среди плеч)
shoulders_top_y = min(l_sh[1], r_sh[1])
elbows_above_shoulders = (l_el[1] < shoulders_top_y and r_el[1] < shoulders_top_y)
# 3. Расстояние между локтями > расстояние между плечами
elbow_distance = np.linalg.norm(l_el - r_el)
elbows_far_apart = elbow_distance > shoulder_width
# 4. Расстояние между запястьями < половины ширины плеч
wrist_distance = np.linalg.norm(l_wr - r_wr)
wrists_near = wrist_distance < 0.5 * shoulder_width
dome = wrists_above_nose and elbows_above_shoulders and elbows_far_apart and wrists_near
if dome:
return 'dome'
return 'none'

Loading…
Cancel
Save