-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Gian Perrone
authored and
Gian Perrone
committed
Jan 21, 2013
1 parent
4bb5e8d
commit f996f15
Showing
11 changed files
with
534 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
############################################################################### | ||
# Event Detection Algorithm Suite | ||
# Copyright (C) 2012 Gian Perrone (http://github.com/gian) | ||
# | ||
# Permission to use, copy, modify, and distribute this software and its | ||
# documentation for any purpose and without fee is hereby granted, | ||
# provided that the above copyright notice appear in all copies and that | ||
# both the copyright notice and this permission notice and warranty | ||
# disclaimer appear in supporting documentation, and that the name of | ||
# the above copyright holders, or their entities, not be used in | ||
# advertising or publicity pertaining to distribution of the software | ||
# without specific, written prior permission. | ||
# | ||
# The above copyright holders disclaim all warranties with regard to | ||
# this software, including all implied warranties of merchantability and | ||
# fitness. In no event shall the above copyright holders be liable for | ||
# any special, indirect or consequential damages or any damages | ||
# whatsoever resulting from loss of use, data or profits, whether in an | ||
# action of contract, negligence or other tortious action, arising out | ||
# of or in connection with the use or performance of this software. | ||
############################################################################### | ||
|
||
from . import eventstream | ||
from eventstream import EventStream | ||
from eventstream import EFixation | ||
import math | ||
|
||
class SRR(EventStream): | ||
"""A velocity and acceleration threshold-based algorithm, | ||
based on the descriptions given in the SR Research EyeLink manual (1.3.0) | ||
and default parameters given by Holmqvist et al. in | ||
Eye Tracking: A comprehensive guide to methods and measures (2011). | ||
The EyeLink algorithm parameters are usually given in terms of | ||
degrees/s and degrees/s^2. Our inputs are consistently based upon | ||
pixels/s and pixels/s^2. The DegreesOfVision class contains translation | ||
calculators for converting between these. | ||
This algorithm by default does no filtering of input streams. Use one of the other | ||
filter modules to provide custom filtering behaviour prior to applying this event | ||
detector. | ||
Parameters: | ||
windowSize: the size of the window (in samples). | ||
velThresh (pixels/s) The velocity above which to detect a saccade. | ||
accelThresh (pixels/s^2) The acceleration threshold above which to detect a saccade. | ||
""" | ||
def __init__(self, sampleStream, windowSize, velThresh, accelThresh): | ||
super(SRR, self).__init__(sampleStream) | ||
self.windowSize = windowSize | ||
self.velThresh = velThresh | ||
self.accelThresh = accelThresh | ||
self.window = [] | ||
self.prevVelocity = 0.0 | ||
self.prevTime = 0 | ||
|
||
def fillWindow(self): | ||
try: | ||
while len(self.window) < self.windowSize: | ||
self.window.append(self.input.next()) | ||
except StopIteration: | ||
return | ||
|
||
def windowVelocity(self): | ||
""" Compute average inter-sample velocity over a window of samples. """ | ||
prev = self.window[0] | ||
|
||
dsum = 0 | ||
interval = 0 | ||
|
||
for curr in self.window[1:]: | ||
|
||
dx = curr.x - prev.x | ||
dy = curr.y - prev.y | ||
dt = curr.time - prev.time | ||
|
||
if dt <= 0: | ||
dt = 1 | ||
|
||
dsum = dsum + math.sqrt(dx * dx + dy * dy) | ||
interval = interval + dt | ||
|
||
if interval == 0: | ||
interval = 1 | ||
|
||
return dsum / float(interval) | ||
|
||
def windowAccel(self): | ||
""" Compute instantaneous acceleration over a window of samples. """ | ||
# We use the self.prevVelocity | ||
|
||
currTime = self.window[0].time | ||
currVelocity = self.windowVelocity() | ||
dt = currTime - self.prevTime | ||
dv = currVelocity - self.prevVelocity | ||
|
||
self.prevVelocity = currVelocity | ||
self.prevTime = currTime | ||
|
||
if dt == 0.0: | ||
dt = 1.0 | ||
|
||
return dv / float(dt) | ||
|
||
|
||
def next(self): | ||
# Fill the window with samples. | ||
self.fillWindow() | ||
|
||
if len(self.window) == 0: | ||
raise StopIteration | ||
|
||
ac = self.windowAccel() | ||
vc = self.windowVelocity() | ||
|
||
self.window = self.window[1:] | ||
|
||
print "AC: " + str(ac) + " V: " + str(vc) | ||
|
||
return 0 | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
############################################################################### | ||
# Event Detection Algorithm Suite | ||
# Copyright (C) 2012 Gian Perrone (http://github.com/gian) | ||
# | ||
# Permission to use, copy, modify, and distribute this software and its | ||
# documentation for any purpose and without fee is hereby granted, | ||
# provided that the above copyright notice appear in all copies and that | ||
# both the copyright notice and this permission notice and warranty | ||
# disclaimer appear in supporting documentation, and that the name of | ||
# the above copyright holders, or their entities, not be used in | ||
# advertising or publicity pertaining to distribution of the software | ||
# without specific, written prior permission. | ||
# | ||
# The above copyright holders disclaim all warranties with regard to | ||
# this software, including all implied warranties of merchantability and | ||
# fitness. In no event shall the above copyright holders be liable for | ||
# any special, indirect or consequential damages or any damages | ||
# whatsoever resulting from loss of use, data or profits, whether in an | ||
# action of contract, negligence or other tortious action, arising out | ||
# of or in connection with the use or performance of this software. | ||
############################################################################### | ||
|
||
from detect.sample import Sample | ||
from detect.sample import FileSampleStream | ||
|
||
from detect.dispersion import * | ||
from detect.velocity import * | ||
from detect.hmm import * | ||
from detect.prefix import * | ||
from detect.aoi import * | ||
from detect.movingaverage import * | ||
from detect.srr import * | ||
|
||
print "============= I-VT test ===============" | ||
|
||
stream = FileSampleStream('testData/UH27_img_vy_labelled_MN.txt') | ||
|
||
fstream = MovingAverageFilter(stream,9) | ||
|
||
idt = HMM(fstream, 0.001, 0.001, 0.005, 0.5, 0.95, 0.05, 0.95, 0.05) | ||
|
||
fixations = [] | ||
|
||
for i in idt: | ||
print i | ||
fixations.append(i) | ||
|
||
verifStream = FileSampleStream('testData/UH27_img_vy_labelled_MN.txt') | ||
|
||
taggedEvents = [] | ||
cfix = [] | ||
eventType = [] | ||
for i in verifStream: | ||
if i.eventType == 1: | ||
cfix.append(i) | ||
eventType.append(1) | ||
else: | ||
eventType.append(0) | ||
if len(cfix) == 0: | ||
continue | ||
print ("Fixation of length: " + str(len(cfix)) + " starting at sample " + str(cfix[0].index)) | ||
p = idt.centroid(cfix) | ||
|
||
f = EFixation(p, len(cfix), cfix[0], cfix[-1]) | ||
taggedEvents.append(f) | ||
cfix = [] | ||
|
||
verifStream = FileSampleStream('testData/UH27_img_vy_labelled_MN.txt') | ||
|
||
saccEvents = [] | ||
csacc = [] | ||
saccEventType = [] | ||
for i in verifStream: | ||
if i.eventType == 2: | ||
csacc.append(i) | ||
saccEventType.append(1) | ||
else: | ||
saccEventType.append(0) | ||
if len(csacc) == 0: | ||
continue | ||
print ("Saccade of length: " + str(len(csacc)) + " starting at sample " + str(csacc[0].index)) | ||
|
||
f = ESaccade(len(csacc), csacc[0], csacc[-1]) | ||
saccEvents.append(f) | ||
csacc = [] | ||
|
||
|
||
matchedSamples = 0 | ||
errorSamples = 0 | ||
fixCount = 0 | ||
for f in fixations: | ||
if f.type != 'fixation': | ||
continue | ||
s = f.start.index | ||
for i in range(s,s+f.length): | ||
fixCount = fixCount + 1 | ||
if eventType[i] == 1: | ||
matchedSamples = matchedSamples + 1 | ||
else: | ||
errorSamples = errorSamples + 1 | ||
|
||
mPct = matchedSamples / float(fixCount) | ||
ePct = errorSamples / float(fixCount) | ||
|
||
print "Fixations:" | ||
print "Matched Samples: " + str(matchedSamples) + " (" + str(mPct * 100) + "%)" | ||
print "Error Samples: " + str(errorSamples) + " (" + str(ePct * 100) + "%)" | ||
|
||
matchedSamples = 0 | ||
errorSamples = 0 | ||
saccCount = 0 | ||
|
||
for f in fixations: | ||
if f.type != 'saccade': | ||
continue | ||
s = f.start.index | ||
for i in range(s,s+f.length): | ||
if saccEventType[i] == 1: | ||
saccCount = saccCount + 1 | ||
matchedSamples = matchedSamples + 1 | ||
else: | ||
errorSamples = errorSamples + 1 | ||
|
||
mPct = matchedSamples / float(saccCount) | ||
ePct = errorSamples / float(saccCount) | ||
print "Saccades:" | ||
print "Matched Samples: " + str(matchedSamples) + " (" + str(mPct * 100) + "%)" | ||
print "Error Samples: " + str(errorSamples) + " (" + str(ePct * 100) + "%)" | ||
|
||
|
Oops, something went wrong.