| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- from src.tracker import GestureTracker, Gesture
- from src.geometry import Positionable
- class HandGesture(Gesture):
- def __init__(self, hand, finger=None):
- self.hand = hand
- self.finger = finger
- def get_hand(self):
- return self.hand
- def get_finger(self):
- return self.finger
- class HandDownGesture(HandGesture):
- _type = 'hand_down'
- class HandUpGesture(HandGesture):
- _type = 'hand_up'
- class FingerDownGesture(HandGesture):
- _type = 'finger_down'
- class FingerMoveGesture(HandGesture):
- _type = 'finger_move'
- class FingerUpGesture(HandGesture):
- _type = 'finger_up'
- class Hand(Positionable):
- def __init__(self):
- self.fingers = []
- self.centroid = None
- def __len__(self):
- return len(self.fingers)
- def __iter__(self):
- return iter(self.fingers)
- def __str__(self):
- return '<Hand fingers=%s centroid=%s>' \
- % (self.fingers, self.get_centroid())
- def __repr__(self):
- return str(self)
- 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 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)
- self.centroid = sum(all_x) / l, sum(all_y) / l
- def get_centroid(self):
- return self.centroid
- class HandTracker(GestureTracker):
- supported_gestures = [HandDownGesture, HandUpGesture, FingerDownGesture,
- FingerMoveGesture, FingerUpGesture]
- configurable = ['max_finger_distance']
- def __init__(self, area):
- super(HandTracker, self).__init__(area)
- # Map of finger id's to corresponding hand objects
- self.finger_hands = {}
- # All hands being tracked
- self.hands = []
- # Maximum distance between two fingers to be assigned to the same hand
- self.max_finger_distance = 300
- def find_hand(self, finger):
- 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.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)
- self.trigger(FingerDownGesture(hand, finger))
- def on_point_move(self, event):
- finger = event.get_touch_object()
- if finger.get_id() not in self.finger_hands:
- 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):
- finger = event.get_touch_object()
- finger_id = finger.get_id()
- if finger_id not in self.finger_hands:
- return
- 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(HandUpGesture(hand))
|