Commit 4fdba920 authored by Taddeüs Kroes's avatar Taddeüs Kroes

Improved hand tracking.

parent 1cf29d18
...@@ -2,8 +2,5 @@ Code: ...@@ -2,8 +2,5 @@ Code:
- Rotation has a 'bump' at angle = 0. - Rotation has a 'bump' at angle = 0.
- Polygon tracker verplaatsen naar framework. - Polygon tracker verplaatsen naar framework.
Tests:
- Improve hand tracker.
Report/appendix reference gesture detection: Report/appendix reference gesture detection:
- Point_leave(+point_enter) kan niet -> flaw v/h systeem/driver? - Point_leave(+point_enter) kan niet -> flaw v/h systeem/driver?
from src.tracker import GestureTracker, Gesture from src.tracker import GestureTracker, Gesture
from src.geometry import Positionable
class HandGesture(Gesture): class HandGesture(Gesture):
def __init__(self, hand, finger): def __init__(self, hand, finger=None):
self.hand = hand self.hand = hand
self.finger = finger self.finger = finger
...@@ -12,11 +13,13 @@ class HandGesture(Gesture): ...@@ -12,11 +13,13 @@ class HandGesture(Gesture):
def get_finger(self): def get_finger(self):
return self.finger return self.finger
def is_first(self):
return len(self.hand) == 1
def is_last(self): class HandDownGesture(HandGesture):
return not len(self.hand) _type = 'hand_down'
class HandUpGesture(HandGesture):
_type = 'hand_up'
class FingerDownGesture(HandGesture): class FingerDownGesture(HandGesture):
...@@ -31,9 +34,10 @@ class FingerUpGesture(HandGesture): ...@@ -31,9 +34,10 @@ class FingerUpGesture(HandGesture):
_type = 'finger_up' _type = 'finger_up'
class Hand(object): class Hand(Positionable):
def __init__(self): def __init__(self):
self.fingers = [] self.fingers = []
self.centroid = None
def __len__(self): def __len__(self):
return len(self.fingers) return len(self.fingers)
...@@ -48,29 +52,32 @@ class Hand(object): ...@@ -48,29 +52,32 @@ class Hand(object):
def __repr__(self): def __repr__(self):
return str(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): def add_finger(self, finger):
self.fingers.append(finger) self.fingers.append(finger)
self.update_centroid()
def remove_finger(self, finger): def remove_finger(self, finger):
self.fingers.remove(finger) self.fingers.remove(finger)
self.update_centroid()
def get_centroid(self): def update_centroid(self):
l = len(self.fingers) l = len(self.fingers)
if not l:
self.centroid = None
return
coords = [f.get_position() for f in self.fingers] coords = [f.get_position() for f in self.fingers]
all_x, all_y = zip(*coords) 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): class HandTracker(GestureTracker):
supported_gestures = [FingerDownGesture, FingerMoveGesture, supported_gestures = [HandDownGesture, HandUpGesture, FingerDownGesture,
FingerUpGesture] FingerMoveGesture, FingerUpGesture]
configurable = ['max_finger_distance'] configurable = ['max_finger_distance']
...@@ -87,18 +94,30 @@ class HandTracker(GestureTracker): ...@@ -87,18 +94,30 @@ class HandTracker(GestureTracker):
self.max_finger_distance = 300 self.max_finger_distance = 300
def find_hand(self, finger): def find_hand(self, finger):
for hand in self.hands: min_dist = hand = None
if hand.contains(finger, self.max_finger_distance):
return hand 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))
self.hands.append(Hand()) return hand
return self.hands[-1]
def on_point_down(self, event): def on_point_down(self, event):
finger = event.get_touch_object() finger = event.get_touch_object()
hand = self.find_hand(finger) hand = self.find_hand(finger)
hand.add_finger(finger)
self.finger_hands[finger.get_id()] = hand
self.trigger(FingerDownGesture(hand, finger)) self.trigger(FingerDownGesture(hand, finger))
def on_point_move(self, event): def on_point_move(self, event):
...@@ -108,6 +127,17 @@ class HandTracker(GestureTracker): ...@@ -108,6 +127,17 @@ class HandTracker(GestureTracker):
return return
hand = self.finger_hands[finger.get_id()] 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)) self.trigger(FingerMoveGesture(hand, finger))
def on_point_up(self, event): def on_point_up(self, event):
...@@ -120,8 +150,8 @@ class HandTracker(GestureTracker): ...@@ -120,8 +150,8 @@ class HandTracker(GestureTracker):
hand = self.finger_hands[finger_id] hand = self.finger_hands[finger_id]
del self.finger_hands[finger_id] del self.finger_hands[finger_id]
hand.remove_finger(finger) hand.remove_finger(finger)
self.trigger(FingerUpGesture(hand, finger))
if not len(hand): if not len(hand):
self.hands.remove(hand) self.hands.remove(hand)
self.trigger(HandUpGesture(hand))
self.trigger(FingerUpGesture(hand, finger))
...@@ -269,14 +269,12 @@ def on_show(window): ...@@ -269,14 +269,12 @@ def on_show(window):
# Overlay catches finger events to be able to draw touch points # Overlay catches finger events to be able to draw touch points
def handle_down(gesture): def handle_down(gesture):
if gesture.is_first():
touch_hands.append(gesture.get_hand()) touch_hands.append(gesture.get_hand())
if draw_touch_objects: if draw_touch_objects:
refresh() refresh()
def handle_up(gesture): def handle_up(gesture):
if gesture.is_last():
touch_hands.remove(gesture.get_hand()) touch_hands.remove(gesture.get_hand())
if draw_touch_objects: if draw_touch_objects:
...@@ -288,9 +286,9 @@ def on_show(window): ...@@ -288,9 +286,9 @@ def on_show(window):
screen.add_area(root) screen.add_area(root)
screen.add_area(overlay) screen.add_area(overlay)
overlay.on_finger_down(handle_down) overlay.on_hand_down(handle_down)
overlay.on_finger_move(lambda g: draw_touch_objects and refresh()) overlay.on_finger_move(lambda g: draw_touch_objects and refresh())
overlay.on_finger_up(handle_up) overlay.on_hand_up(handle_up)
# Root area rotation leads to rotation of all polygons around the centroid # Root area rotation leads to rotation of all polygons around the centroid
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment