$1 Unistroke Recognizer (2007)
depts.washington.edu
depts.washington.edu
The paper (citation 11 for the $1 version) goes into more detail. One neat feature is rotation invariance, where you can draw a tilted version and still have it be recognized.
Differentiating from lowercase y and g was next to impossible, though...
It would nail the zigzag and most of the star/box shapes even if I intentionally started in a different place (Very first thing I tested, I'm left handed and start characters/shapes in different places)
It did not handle shapes that are rotationally similar - ex: right square bracket starting from the bottom is always detected as left square bracket, probably because the gesture matches the left bracket, rotated 180 degrees.
It also flubs arrows going right to left (they always come up as v for me)
Take the time derivative of the trajectory, and ignore it until it's "large"
Once it becomes "large" normalize it to one of 8 directions (N NE E SE S SW W NW) and push the direction into a list then repeat until the derivative becomes "large" in a new direction or you stop getting input.
At the end you have a string you can look up in a table to get the character.
EDIT: after reading the comments apparently the algorithm PalmOS uses is slightly different.
https://news.ycombinator.com/item?id=12310029
Fun fact: You can implement a "classic" Unistroke recognizer just by dividing the character up into quadrants. Every glyph had a unique sequence of quadrant traversals. http://www.yorku.ca/mack/ExperimentSoftware/javadoc/ca/yorku...
> Every glyph had a unique sequence of quadrant traversals.
That's pretty clever.
I really liked their products on so many levels, especially the build quality. I thought they would be around forever.
...which I’ve reimplemented in SQL (yes, SQL) a while ago: https://github.com/doersino/handwriting/blob/master/code/han...
The $1 algorithm could be used to implement gesture typing keyboard like SwiftKey/Swype, where direction matters, eg another project of mine [2]
[0] http://depts.washington.edu/acelab/proj/dollar/qdollar.html
It is actually cheap enough to run per-frame in real-time, which is a fun way to see it in action and to check how soon it arrives at correct answer.
Other commenters focused on 'issue' of gestures being directional. This is a great feature as you can fit more gestures into a set with correct recognition. For example you can have space and backspace as lines in different directions. It is also trivial to just add the reversed variants if needed.
I had bigger problem with the algorithm being rotation-invariant. This means that '7' will easily be recognized as 'L'. Thankfully this is easy to fix.
The recognizer can quite reliably recognize whole alphabet. I used Palm Graffiti designs as reference for training. One training sample was always enough.
I checked out other multi-stroke recognizers on that page. They don't seem any more reliable, but all add more complexity. You have to detect when multi-stroke gesture is over which is not trivial. This uni-stroke version works wonderfully because gesture is done as soon as mouse button is released.
Thank you for this submission! As say in the published article, this is often needed functionality and most of us think it's too complex to be worth it. Turns out the algorithm is quite simple and reliable.
The Lua fork I worked on is available here: https://github.com/jmiskovic/lua-gestures
- normalize the draw height/width
- use polar coordinates before normalizing
- normalize the length of the drawn path
- DAG to recognize shapes faster, using partial paths
- only taking into account corners with angles over a certain treshold
- ...
The possibilities are endless, and this is a good exercise to explain that slight alterations on your problem space can have a huge impact on your solution space.
[update - formatting]
[0] https://github.com/kivy/kivy/blob/master/kivy/multistroke.py
[1] https://github.com/kivy/kivy/tree/master/examples/demo/multi...
It was very cool at the time, but I don’t think it saved me much time :)
You must have the Numpy and Scipy libraries installed.
Setting aside OSI's definition of OSS, has this been explored as a OSS funding model?
Bruce Perens recently published some thoughts on that:
https://perens.com/2020/08/24/what-comes-after-open-source/
https://perens.com/2020/10/06/post-open-source-license-early...
So I drew a heart.
Drawn clockwise, I get a carrot :).
So now I know what to send to my loved ones.
Drawn counter-clockwise, I get a square. And maybe where the carrot will be left to be.
Triangle -> Delete / Caret
X -> Delete
Rectangle -> Caret
Circle -> Caret
Check -> Right square bracket / Arrow
Caret -> V
Zig-zag -> Zig-zag
Arrow -> V
Left square bracket -> Right square bracket
Right square bracket -> Left square bracket
V -> Caret
Delete -> X
Left curly bracket -> Right curly bracket
Right curly bracket -> Left curly bracket
Star -> Left curly bracket / Delete
Pigtail -> Delete
I only played that game for a month or two, but it stuck with me and now more than a decade later I still draw my 9s differently.