Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
multitouch
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
multitouch
Commits
cc772060
Commit
cc772060
authored
Jun 18, 2012
by
Taddeüs Kroes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added hand tracker and implemented it in the test application.
parent
adeaa561
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
181 additions
and
34 deletions
+181
-34
src/trackers/__init__.py
src/trackers/__init__.py
+2
-0
src/trackers/hand.py
src/trackers/hand.py
+127
-0
tests/testapp.py
tests/testapp.py
+52
-34
No files found.
src/trackers/__init__.py
View file @
cc772060
from
basic
import
BasicEventTracker
from
basic
import
BasicEventTracker
from
tap
import
TapTracker
from
tap
import
TapTracker
from
transform
import
TransformationTracker
from
transform
import
TransformationTracker
from
hand
import
HandTracker
# Map of gesture type to tracker type
# Map of gesture type to tracker type
...
@@ -31,3 +32,4 @@ def create_tracker(gesture_type, widget):
...
@@ -31,3 +32,4 @@ def create_tracker(gesture_type, widget):
_register_tracker
(
BasicEventTracker
)
_register_tracker
(
BasicEventTracker
)
_register_tracker
(
TapTracker
)
_register_tracker
(
TapTracker
)
_register_tracker
(
TransformationTracker
)
_register_tracker
(
TransformationTracker
)
_register_tracker
(
HandTracker
)
src/trackers/hand.py
0 → 100644
View file @
cc772060
from
..tracker
import
GestureTracker
,
Gesture
class
HandGesture
(
Gesture
):
def
__init__
(
self
,
hand
,
finger
):
self
.
hand
=
hand
self
.
finger
=
finger
def
get_hand
(
self
):
return
self
.
hand
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
FingerDownGesture
(
HandGesture
):
_type
=
'finger_down'
class
FingerMoveGesture
(
HandGesture
):
_type
=
'finger_move'
class
FingerUpGesture
(
HandGesture
):
_type
=
'finger_up'
class
Hand
(
object
):
def
__init__
(
self
):
self
.
fingers
=
[]
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
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
)
def
remove_finger
(
self
,
finger
):
self
.
fingers
.
remove
(
finger
)
def
get_centroid
(
self
):
l
=
len
(
self
.
fingers
)
coords
=
[
f
.
get_position
()
for
f
in
self
.
fingers
]
all_x
,
all_y
=
zip
(
*
coords
)
return
sum
(
all_x
)
/
l
,
sum
(
all_y
)
/
l
class
HandTracker
(
GestureTracker
):
supported_gestures
=
[
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
=
400
def
find_hand
(
self
,
finger
):
for
hand
in
self
.
hands
:
if
hand
.
contains
(
finger
,
self
.
max_finger_distance
):
return
hand
self
.
hands
.
append
(
Hand
())
return
self
.
hands
[
-
1
]
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
):
finger
=
event
.
get_touch_object
()
if
finger
.
get_id
()
not
in
self
.
finger_hands
:
return
hand
=
self
.
finger_hands
[
finger
.
get_id
()]
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
)
if
not
len
(
hand
):
self
.
hands
.
remove
(
hand
)
self
.
trigger
(
FingerUpGesture
(
hand
,
finger
))
tests/testapp.py
View file @
cc772060
...
@@ -88,7 +88,7 @@ class Polygon(BoundingBoxArea):
...
@@ -88,7 +88,7 @@ class Polygon(BoundingBoxArea):
fullscreen
=
False
fullscreen
=
False
draw_bounding_boxes
=
draw_touch_
poin
ts
=
True
draw_bounding_boxes
=
draw_touch_
objec
ts
=
True
W
,
H
=
mt
.
screen
.
screen_size
W
,
H
=
mt
.
screen
.
screen_size
...
@@ -107,8 +107,8 @@ def create_context_window(w, h, callback):
...
@@ -107,8 +107,8 @@ def create_context_window(w, h, callback):
refresh
()
refresh
()
def
handle_key
(
win
,
event
):
def
handle_key
(
win
,
event
):
"""Handle key event. 'f' toggles fullscreen, '
q' exits the program, 'b'
"""Handle key event. 'f' toggles fullscreen, '
b' toggles bounding
toggles bounding boxes, 'p' toggles touch points
."""
boxes, 'i' toggles input points, 'q' exits the program
."""
if
event
.
keyval
>=
256
:
if
event
.
keyval
>=
256
:
return
return
...
@@ -118,16 +118,16 @@ def create_context_window(w, h, callback):
...
@@ -118,16 +118,16 @@ def create_context_window(w, h, callback):
global
fullscreen
global
fullscreen
(
win
.
unfullscreen
if
fullscreen
else
win
.
fullscreen
)()
(
win
.
unfullscreen
if
fullscreen
else
win
.
fullscreen
)()
fullscreen
=
not
fullscreen
fullscreen
=
not
fullscreen
elif
key
==
'q'
:
quit
()
elif
key
==
'b'
:
elif
key
==
'b'
:
global
draw_bounding_boxes
global
draw_bounding_boxes
draw_bounding_boxes
=
not
draw_bounding_boxes
draw_bounding_boxes
=
not
draw_bounding_boxes
refresh
()
refresh
()
elif
key
==
'
p
'
:
elif
key
==
'
i
'
:
global
draw_touch_
poin
ts
global
draw_touch_
objec
ts
draw_touch_
points
=
not
draw_touch_poin
ts
draw_touch_
objects
=
not
draw_touch_objec
ts
refresh
()
refresh
()
elif
key
==
'q'
:
quit
()
# Root area (will be synchronized with GTK window)
# Root area (will be synchronized with GTK window)
global
root
,
overlay
global
root
,
overlay
...
@@ -156,7 +156,7 @@ def create_context_window(w, h, callback):
...
@@ -156,7 +156,7 @@ def create_context_window(w, h, callback):
window
.
show
()
window
.
show
()
def
draw
(
*
args
):
def
draw
():
if
not
cr
:
if
not
cr
:
return
return
...
@@ -171,26 +171,44 @@ def draw(*args):
...
@@ -171,26 +171,44 @@ def draw(*args):
obj
.
draw
(
cr
)
obj
.
draw
(
cr
)
cr
.
restore
()
cr
.
restore
()
if
draw_touch_
poin
ts
:
if
draw_touch_
objec
ts
:
ox
,
oy
=
root
.
get_position
()
ox
,
oy
=
root
.
get_position
()
cr
.
set_source_rgb
(
*
WHITE
)
cr
.
set_source_rgb
(
*
WHITE
)
for
x
,
y
in
touch_points
.
itervalues
():
for
hand
in
touch_hands
:
x
-=
ox
cx
,
cy
=
hand
.
get_centroid
()
y
-=
oy
cr
.
set_line_width
(
3
)
# Filled centroid circle
cr
.
arc
(
x
,
y
,
20
,
0
,
2
*
pi
)
if
len
(
hand
)
>
1
:
cr
.
stroke
()
cr
.
arc
(
cx
-
ox
,
cy
-
oy
,
20
,
0
,
2
*
pi
)
cr
.
fill
()
for
x
,
y
in
hand
:
x
-=
ox
y
-=
oy
# Circle outline
cr
.
set_line_width
(
3
)
cr
.
arc
(
x
,
y
,
20
,
0
,
2
*
pi
)
cr
.
stroke
()
# Line to centroid
if
len
(
hand
)
>
1
:
cr
.
move_to
(
x
,
y
)
cr
.
line_to
(
cx
-
ox
,
cy
-
oy
)
cr
.
set_line_width
(
2
)
cr
.
stroke
()
# Cross
cr
.
set_line_width
(
1
)
cr
.
move_to
(
x
-
8
,
y
)
cr
.
line_to
(
x
+
8
,
y
)
cr
.
move_to
(
x
,
y
-
8
)
cr
.
line_to
(
x
,
y
+
8
)
cr
.
stroke
()
cr
.
set_line_width
(
1
)
cr
.
move_to
(
x
-
8
,
y
)
cr
.
line_to
(
x
+
8
,
y
)
cr
.
move_to
(
x
,
y
-
8
)
cr
.
line_to
(
x
,
y
+
8
)
cr
.
stroke
()
def
refresh
():
def
refresh
(
*
args
):
window
.
queue_draw
()
window
.
queue_draw
()
...
@@ -198,10 +216,10 @@ def quit(*args):
...
@@ -198,10 +216,10 @@ def quit(*args):
gtk
.
main_quit
()
gtk
.
main_quit
()
#
Initialization
#
Global variables
window
=
cr
=
root
=
overlay
=
None
window
=
cr
=
root
=
overlay
=
None
draw_objects
=
[]
draw_objects
=
[]
touch_
points
=
{}
touch_
hands
=
[]
def
triangle_height
(
width
):
def
triangle_height
(
width
):
...
@@ -231,22 +249,22 @@ def on_show(window):
...
@@ -231,22 +249,22 @@ def on_show(window):
# Overlay catches basic events
# Overlay catches basic events
def
handle_down
(
gesture
):
def
handle_down
(
gesture
):
point
=
gesture
.
get_event
().
get_touch_object
()
if
gesture
.
is_first
():
touch_points
[
point
.
get_id
()]
=
point
.
get_position
(
)
touch_hands
.
append
(
gesture
.
get_hand
()
)
if
draw_touch_
poin
ts
:
if
draw_touch_
objec
ts
:
refresh
()
refresh
()
def
handle_up
(
gesture
):
def
handle_up
(
gesture
):
point
=
gesture
.
get_event
().
get_touch_object
()
if
gesture
.
is_last
():
del
touch_points
[
point
.
get_id
()]
touch_hands
.
remove
(
gesture
.
get_hand
())
if
draw_touch_
poin
ts
:
if
draw_touch_
objec
ts
:
refresh
()
refresh
()
overlay
.
on_
point
_down
(
handle_down
)
overlay
.
on_
finger
_down
(
handle_down
)
overlay
.
on_
point_move
(
handle_down
)
overlay
.
on_
finger_move
(
lambda
g
:
draw_touch_objects
and
refresh
()
)
overlay
.
on_
point
_up
(
handle_up
)
overlay
.
on_
finger
_up
(
handle_up
)
root
.
add_area
(
overlay
)
root
.
add_area
(
overlay
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment