I'm working on creating a gesture recognition system, and I saw one simple implementation that isn't as accurate, but is really easy to implement. The idea is that you have a unit circle with the 8 significant angles (0, 45, 90, 135, 180, etc) and you map those angles to a value of 1-8. So 45 would be 2, 180 would be 5, etc. Then you just use the Levenshtein distance algorithm to find the closest matching gesture.
I have a prototype that is "almost" working, but I'm having some trouble getting the math functions to play nicely with my algorithm. Right now, I have a list of points representing segments of a defined size that make up the gesture. I iterate over these points and get the theta value of the segment like so:
start = points[i]
end = points[i + 1]
theta = math.atan2((p2[1] - p1[1]), (p2[0] - p1[0]))
theta = ((theta + (math.pi * 2)) % (math.pi * 2))
The math.pi correction is so that I'll have all positive radian values. Makes it a lot easier to compare them. I also have a list containing the radian equivalent values of [0, 45, 90, 135, 180, 225, 270, 315, 360]. I iterate over the segments and compare the theta value to each of those 8 directions (360 is a redundancy so that I can compare values greater than 315 to 0). I use the index of the direction + 1 to get my mapped value.
So if I have a drawing of a box like so:
Then according to the algorithm, I should get the values "1357" to indicate the directions being 0, 90, 180, and 270 degrees in change.
However, something seems to be off about the way I calculate my theta values, or the way I compare them, because for that drawing, I get "1753" indicating that it's flipping the theta values for the second and third lines (the vertical ones). Here is how I'm comparing the points:
for i in range(len(points) - 1):
p1 = points[i]
p2 = points[i + 1]
theta = math.atan2((p2[1] - p1[1]), (p2[0] - p1[0]))
theta = ((theta + TWO_PI) % TWO_PI)
closest = 0
cDiff = TWO_PI
for i in range(len(DIRECTIONS)):
direction = DIRECTIONS[i]
diff = abs(direction - theta)
if diff < cDiff:
cDiff = diff
closest = I
if closest == (len(DIRECTIONS) - 1):
dir.append(1)
else:
dir.append(closest + 1)
So my theta values seem to be increasing clockwise, rather than counter-clockwise, so for the following angle:
...I would expect the theta value to be (pi / 4), but instead, it seems to be (7pi / 4).
Can anyone spot a flaw in my logic? This same math works in my game written in Java. Are Python's math functions different somehow?
Edit: Added a diagram to explain the encoded gesture movement values.