hand.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. from src.tracker import GestureTracker, Gesture
  2. class HandGesture(Gesture):
  3. def __init__(self, hand, finger):
  4. self.hand = hand
  5. self.finger = finger
  6. def get_hand(self):
  7. return self.hand
  8. def get_finger(self):
  9. return self.finger
  10. def is_first(self):
  11. return len(self.hand) == 1
  12. def is_last(self):
  13. return not len(self.hand)
  14. class FingerDownGesture(HandGesture):
  15. _type = 'finger_down'
  16. class FingerMoveGesture(HandGesture):
  17. _type = 'finger_move'
  18. class FingerUpGesture(HandGesture):
  19. _type = 'finger_up'
  20. class Hand(object):
  21. def __init__(self):
  22. self.fingers = []
  23. def __len__(self):
  24. return len(self.fingers)
  25. def __iter__(self):
  26. return iter(self.fingers)
  27. def __str__(self):
  28. return '<Hand fingers=%s centroid=%s>' \
  29. % (self.fingers, self.get_centroid())
  30. def __repr__(self):
  31. return str(self)
  32. def contains(self, finger, max_distance):
  33. for other_finger in self.fingers:
  34. if other_finger.distance_to(finger) <= max_distance:
  35. return True
  36. return False
  37. def add_finger(self, finger):
  38. self.fingers.append(finger)
  39. def remove_finger(self, finger):
  40. self.fingers.remove(finger)
  41. def get_centroid(self):
  42. l = len(self.fingers)
  43. coords = [f.get_position() for f in self.fingers]
  44. all_x, all_y = zip(*coords)
  45. return sum(all_x) / l, sum(all_y) / l
  46. class HandTracker(GestureTracker):
  47. supported_gestures = [FingerDownGesture, FingerMoveGesture,
  48. FingerUpGesture]
  49. configurable = ['max_finger_distance']
  50. def __init__(self, area):
  51. super(HandTracker, self).__init__(area)
  52. # Map of finger id's to corresponding hand objects
  53. self.finger_hands = {}
  54. # All hands being tracked
  55. self.hands = []
  56. # Maximum distance between two fingers to be assigned to the same hand
  57. self.max_finger_distance = 300
  58. def find_hand(self, finger):
  59. for hand in self.hands:
  60. if hand.contains(finger, self.max_finger_distance):
  61. return hand
  62. self.hands.append(Hand())
  63. return self.hands[-1]
  64. def on_point_down(self, event):
  65. finger = event.get_touch_object()
  66. hand = self.find_hand(finger)
  67. hand.add_finger(finger)
  68. self.finger_hands[finger.get_id()] = hand
  69. self.trigger(FingerDownGesture(hand, finger))
  70. def on_point_move(self, event):
  71. finger = event.get_touch_object()
  72. if finger.get_id() not in self.finger_hands:
  73. return
  74. hand = self.finger_hands[finger.get_id()]
  75. self.trigger(FingerMoveGesture(hand, finger))
  76. def on_point_up(self, event):
  77. finger = event.get_touch_object()
  78. finger_id = finger.get_id()
  79. if finger_id not in self.finger_hands:
  80. return
  81. hand = self.finger_hands[finger_id]
  82. del self.finger_hands[finger_id]
  83. hand.remove_finger(finger)
  84. if not len(hand):
  85. self.hands.remove(hand)
  86. self.trigger(FingerUpGesture(hand, finger))