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

Improved hand tracking.

parent 1cf29d18
......@@ -2,8 +2,5 @@ Code:
- Rotation has a 'bump' at angle = 0.
- Polygon tracker verplaatsen naar framework.
Tests:
- Improve hand tracker.
Report/appendix reference gesture detection:
- Point_leave(+point_enter) kan niet -> flaw v/h systeem/driver?
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.finger_hands[finger.get_id()] = hand
hand.add_finger(finger)
if len(hand) == 1:
self.trigger(HandDownGesture(hand))
self.hands.append(Hand())
return self.hands[-1]
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))
......@@ -269,14 +269,12 @@ def on_show(window):
# Overlay catches finger events to be able to draw touch points
def handle_down(gesture):
if gesture.is_first():
touch_hands.append(gesture.get_hand())
if draw_touch_objects:
refresh()
def handle_up(gesture):
if gesture.is_last():
touch_hands.remove(gesture.get_hand())
if draw_touch_objects:
......@@ -288,9 +286,9 @@ def on_show(window):
screen.add_area(root)
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_up(handle_up)
overlay.on_hand_up(handle_up)
# 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