|
|
@@ -1,8 +1,9 @@
|
|
|
from src.tracker import GestureTracker, Gesture
|
|
|
+from src.geometry import Positionable
|
|
|
|
|
|
|
|
|
class HandGesture(Gesture):
|
|
|
- def __init__(self, hand, finger):
|
|
|
+ def __init__(self, hand, finger=None):
|
|
|
self.hand = hand
|
|
|
self.finger = finger
|
|
|
|
|
|
@@ -12,11 +13,13 @@ class HandGesture(Gesture):
|
|
|
def get_finger(self):
|
|
|
return self.finger
|
|
|
|
|
|
- def is_first(self):
|
|
|
- return len(self.hand) == 1
|
|
|
|
|
|
- def is_last(self):
|
|
|
- return not len(self.hand)
|
|
|
+class HandDownGesture(HandGesture):
|
|
|
+ _type = 'hand_down'
|
|
|
+
|
|
|
+
|
|
|
+class HandUpGesture(HandGesture):
|
|
|
+ _type = 'hand_up'
|
|
|
|
|
|
|
|
|
class FingerDownGesture(HandGesture):
|
|
|
@@ -31,9 +34,10 @@ class FingerUpGesture(HandGesture):
|
|
|
_type = 'finger_up'
|
|
|
|
|
|
|
|
|
-class Hand(object):
|
|
|
+class Hand(Positionable):
|
|
|
def __init__(self):
|
|
|
self.fingers = []
|
|
|
+ self.centroid = None
|
|
|
|
|
|
def __len__(self):
|
|
|
return len(self.fingers)
|
|
|
@@ -48,29 +52,32 @@ class Hand(object):
|
|
|
def __repr__(self):
|
|
|
return str(self)
|
|
|
|
|
|
- def contains(self, finger, max_distance):
|
|
|
- for other_finger in self.fingers:
|
|
|
- if other_finger.distance_to(finger) <= max_distance:
|
|
|
- return True
|
|
|
-
|
|
|
- return False
|
|
|
-
|
|
|
def add_finger(self, finger):
|
|
|
self.fingers.append(finger)
|
|
|
+ self.update_centroid()
|
|
|
|
|
|
def remove_finger(self, finger):
|
|
|
self.fingers.remove(finger)
|
|
|
+ self.update_centroid()
|
|
|
|
|
|
- def get_centroid(self):
|
|
|
+ def update_centroid(self):
|
|
|
l = len(self.fingers)
|
|
|
+
|
|
|
+ if not l:
|
|
|
+ self.centroid = None
|
|
|
+ return
|
|
|
+
|
|
|
coords = [f.get_position() for f in self.fingers]
|
|
|
all_x, all_y = zip(*coords)
|
|
|
- return sum(all_x) / l, sum(all_y) / l
|
|
|
+ self.centroid = sum(all_x) / l, sum(all_y) / l
|
|
|
+
|
|
|
+ def get_centroid(self):
|
|
|
+ return self.centroid
|
|
|
|
|
|
|
|
|
class HandTracker(GestureTracker):
|
|
|
- supported_gestures = [FingerDownGesture, FingerMoveGesture,
|
|
|
- FingerUpGesture]
|
|
|
+ supported_gestures = [HandDownGesture, HandUpGesture, FingerDownGesture,
|
|
|
+ FingerMoveGesture, FingerUpGesture]
|
|
|
|
|
|
configurable = ['max_finger_distance']
|
|
|
|
|
|
@@ -87,18 +94,30 @@ class HandTracker(GestureTracker):
|
|
|
self.max_finger_distance = 300
|
|
|
|
|
|
def find_hand(self, finger):
|
|
|
- for hand in self.hands:
|
|
|
- if hand.contains(finger, self.max_finger_distance):
|
|
|
- return hand
|
|
|
+ min_dist = hand = None
|
|
|
+
|
|
|
+ for h in self.hands:
|
|
|
+ dist = finger.distance_to(h.get_centroid())
|
|
|
+
|
|
|
+ if min_dist is None or dist < min_dist:
|
|
|
+ min_dist = dist
|
|
|
+ hand = h
|
|
|
+
|
|
|
+ if not hand or min_dist > self.max_finger_distance:
|
|
|
+ hand = Hand()
|
|
|
+ self.hands.append(hand)
|
|
|
|
|
|
- self.hands.append(Hand())
|
|
|
- return self.hands[-1]
|
|
|
+ self.finger_hands[finger.get_id()] = hand
|
|
|
+ hand.add_finger(finger)
|
|
|
+
|
|
|
+ if len(hand) == 1:
|
|
|
+ self.trigger(HandDownGesture(hand))
|
|
|
+
|
|
|
+ return hand
|
|
|
|
|
|
def on_point_down(self, event):
|
|
|
finger = event.get_touch_object()
|
|
|
hand = self.find_hand(finger)
|
|
|
- hand.add_finger(finger)
|
|
|
- self.finger_hands[finger.get_id()] = hand
|
|
|
self.trigger(FingerDownGesture(hand, finger))
|
|
|
|
|
|
def on_point_move(self, event):
|
|
|
@@ -108,6 +127,17 @@ class HandTracker(GestureTracker):
|
|
|
return
|
|
|
|
|
|
hand = self.finger_hands[finger.get_id()]
|
|
|
+ hand.update_centroid()
|
|
|
+
|
|
|
+ if finger.distance_to(hand.get_centroid()) > self.max_finger_distance:
|
|
|
+ hand.remove_finger(finger)
|
|
|
+
|
|
|
+ if not len(hand):
|
|
|
+ self.hands.remove(hand)
|
|
|
+ self.trigger(HandUpGesture(hand))
|
|
|
+
|
|
|
+ hand = self.find_hand(finger)
|
|
|
+
|
|
|
self.trigger(FingerMoveGesture(hand, finger))
|
|
|
|
|
|
def on_point_up(self, event):
|
|
|
@@ -120,8 +150,8 @@ class HandTracker(GestureTracker):
|
|
|
hand = self.finger_hands[finger_id]
|
|
|
del self.finger_hands[finger_id]
|
|
|
hand.remove_finger(finger)
|
|
|
+ self.trigger(FingerUpGesture(hand, finger))
|
|
|
|
|
|
if not len(hand):
|
|
|
self.hands.remove(hand)
|
|
|
-
|
|
|
- self.trigger(FingerUpGesture(hand, finger))
|
|
|
+ self.trigger(HandUpGesture(hand))
|