[HN Gopher] $1 Unistroke Recognizer (2007)
       ___________________________________________________________________
        
       $1 Unistroke Recognizer (2007)
        
       Author : jlturner
       Score  : 191 points
       Date   : 2021-05-05 06:28 UTC (16 hours ago)
        
 (HTM) web link (depts.washington.edu)
 (TXT) w3m dump (depts.washington.edu)
        
       | kuroguro wrote:
       | It keeps telling me my curly brackets are square :/
        
         | [deleted]
        
       | peey wrote:
       | I expected it to cost $1, and then I thought "I'd gladly pay $1
       | for a perpetual licence to a good quality library".
       | 
       | Setting aside OSI's definition of OSS, has this been explored as
       | a OSS funding model?
        
         | st_goliath wrote:
         | > 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...
        
       | ramtatatam wrote:
       | Draw a circle with multiple turns :)
        
       | rbinv wrote:
       | Cool. Those examples remind me of Palm OS' Graffiti (which worked
       | really well at the time):
       | https://en.wikipedia.org/wiki/Graffiti_(Palm_OS)
        
         | hellbannedguy wrote:
         | It's to bad Palm was run into the ground.
         | 
         | I really liked their products on so many levels, especially the
         | build quality. I thought they would be around forever.
        
         | mdp2021 wrote:
         | Sorry, correction: <<which _works_ really well _right now_ >>.
         | I still use Graffiti, on Android, as the only keyboard on
         | almost all of my devices. (Exceptions are relevant to technical
         | constraints - no touch, low framerate screens etc.)
        
         | doersino wrote:
         | Right, or the handwriting recognition built into RAND's GRAIL
         | system back in the 60s:
         | https://jackschaedler.github.io/handwriting-recognition/
         | 
         | ...which I've reimplemented in SQL (yes, SQL) a while ago:
         | https://github.com/doersino/handwriting/blob/master/code/han...
        
         | obrajesse wrote:
         | There's a good reason for that. Graffiti was....derivative of
         | Unistroke, which was developed at PARC as, IIRC, part of the
         | Parctab project. Xerox even sued.
         | 
         | 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...
        
           | rbinv wrote:
           | Huh, TIL. Thanks for linking the comment!
           | 
           | > Every glyph had a unique sequence of quadrant traversals.
           | 
           | That's pretty clever.
        
             | seg_lol wrote:
             | Somewhat analogous to marching squares
             | 
             | https://en.wikipedia.org/wiki/Marching_squares
        
         | [deleted]
        
       | philsnow wrote:
       | Is this roughly how the various swipe-typing apps on phones work?
       | Use the shape traced to do a range query in a table of words, and
       | use textual context to prioritize the guesses?
        
       | ToJans wrote:
       | I recall experimenting with similar approaches about 2 decades
       | ago; depending on your gestures you can actually simplify a lot:
       | 
       | - 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]
        
       | [deleted]
        
       | wcchoi wrote:
       | There is an improved version of this algorithm called $Q Super-
       | Quick Recognizer [0] which allows multi-stroke gesture and
       | drawing stroke in different direction, a demo I implemented
       | before [1]
       | 
       | 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
       | 
       | [1] https://github.com/wcchoi/dollar-q
       | 
       | [2] https://github.com/wcchoi/swell.sh
        
       | lucioperca wrote:
       | Related: Draw LaTeX-Symbols
       | 
       | https://detexify.kirelabs.org/classify.html
        
       | swiley wrote:
       | Unistroke recognizer are super easy to write and a nice little
       | afternoon project:
       | 
       | 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.
        
       | greencore wrote:
       | Is it hard to make it recognize mirror strokes?
        
       | bionoid wrote:
       | In case anyone is interested, the $N-Protractor algorithm was
       | ported to Python for use in the Kivy framework [0]. Unfortunately
       | it's tied to kivy's clock among other things, but easy to rip it
       | out should you need it in a different context. There is also
       | anexample application that can be used to create gesture
       | templates [1]
       | 
       | [0] https://github.com/kivy/kivy/blob/master/kivy/multistroke.py
       | 
       | [1]
       | https://github.com/kivy/kivy/tree/master/examples/demo/multi...
        
       | porlune wrote:
       | This might be obvious to everyone but me, but how do you read
       | "$1" in this context? Do I read it as "one-dollar", or "dollar-
       | sign one", something else? Thank you in advance
        
         | bionoid wrote:
         | My interpretation is $1 reads as "unistroke"/"singlestroke"
         | while $N = "multistroke"
        
         | Hnaomyiph wrote:
         | I read it as "one-dollar" and assume most people would read it
         | the same. Although I'd prefer if writing rules put the $ after
         | the number; eg 1$.
        
       | MoD411 wrote:
       | It should recognize a single stroke house :)
        
         | dvh wrote:
         | Doesn't work for 7 bridges problem :(
        
         | ygra wrote:
         | You can add your own shapes.
        
       | davedunkin wrote:
       | I remember porting this to Objective-C for an iPhone project
       | forever ago. That was fun exercise, and the algorithm works
       | surprisingly well for how simple it is.
       | 
       | https://github.com/ddunkin/dollar-touch
        
       | conradev wrote:
       | I implemented the multistroke version of this
       | (https://faculty.washington.edu/wobbrock/pubs/gi-12.03.pdf) in a
       | jailbreak tweak for iPhone: https://youtu.be/35SX6A9fE0g
       | 
       | It was very cool at the time, but I don't think it saved me much
       | time :)
        
       | [deleted]
        
       | Gys wrote:
       | It only works if the starting point of a gesture is as expected.
       | If I start a rectangle in the top right corner then it is
       | characterized as a caret. Only a start in the top left results in
       | a rectangle.
        
         | scotty79 wrote:
         | It's more about not where you start and how rotated is what you
         | are drawing, but rather about if you are drawing it clock-wise
         | or counter clock-wise.
        
         | horsawlarway wrote:
         | This varied a lot for me during testing - It looks like it's
         | actually comparing rotations of the gesture to find a match
         | 
         | 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)
        
         | tyingq wrote:
         | Like my Palm Pilot :)
         | 
         | https://designobserver.com/media/images/Palmsmall_525.jpg
        
           | aidenn0 wrote:
           | Palm apparently had to change graffiti later to use multiple
           | strokes for some letters, as someone had a patent on letter-
           | recognition via single-stroke letters.
        
         | ziml77 wrote:
         | I was disappointed by that at first too, but then remembered
         | that it says it detects gestures. A gesture is a series of
         | motions, not the final shape.
        
         | bobbiechen wrote:
         | Right, this is expected. I would think of a "gesture" as a
         | series of points over time (relative to the starting point) -
         | it is path dependent, so a clockwise circle is recognized
         | differently from a counter-clockwise circle.
         | 
         | 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.
        
         | mkl wrote:
         | Try the point cloud version, which doesn't care at all:
         | https://depts.washington.edu/acelab/proj/dollar/pdollar.html
        
           | thomasahle wrote:
           | The first one recognizes my "five point star" as "delete".
           | The cloud one as an "X"..
        
         | Tuna-Fish wrote:
         | I added a second rectangle as an example starting from a
         | different point, and it never misrecognized any of my
         | rectangles for carets or square brackets again.
        
           | RantyDave wrote:
           | Likewise, I added a circle going the "other way" and it got
           | it every time. Cool piece of code, eh?
        
             | airstrike wrote:
             | Adding left and right parenthesis started messing up with
             | the square brackets, but then I added a couple more of each
             | square and round brackets and it worked perfectly.
             | 
             | Differentiating from lowercase y and g was next to
             | impossible, though...
        
       | NiceWayToDoIT wrote:
       | When drawing circle slow always says it is 'rectangle' ?
        
       | bobbiechen wrote:
       | I'm a big fan of the $1 Unistroke Recognizer - it's just so cool
       | that it works so well with minimal training. I was itching for a
       | reason to use it and threw it into a flag semaphore decoder. Then
       | I realized it was completely the wrong tool for drawings with
       | only (8 choose 2) combinations where rotation does matter, and
       | did something else instead. So, I'm still itching for a good
       | reason to use it.
        
       | W0lf wrote:
       | This breaks pretty easy unfortunately by simply drawing in
       | reverse (e.g. draw circle counter-clockwise instead of clockwise
       | etc.)
        
         | mhandley wrote:
         | That's true, but you can always add the reverse circle as a
         | second example, and then it's happy with either.
        
         | pjc50 wrote:
         | That's a different stroke! Of course it shouldn't match.
        
           | StavrosK wrote:
           | Yeah but you know what they say about different folks.
        
       | belugacat wrote:
       | Very cool! I think the name is a reference to the 1EUR filter?
       | 
       | https://cristal.univ-lille.fr/~casiez/1euro/
        
         | vanderZwan wrote:
         | It's the other way around, says so on the page you linked
        
         | CiTyBear wrote:
         | It is the opposite. As state on the website you liked: > The
         | name "1EUR" is an homage to the $1 recognizer.
        
           | jl6 wrote:
           | Where did the name $1 come from?
        
             | [deleted]
        
             | MawKKe wrote:
             | I believe it is a reference to the US dollar
        
             | tantalor wrote:
             | Because this software cost about dollar to make (it sucks).
        
       | maury91 wrote:
       | They all need to be drawn in the same direction of the demo. If I
       | draw them in the opposite direction ( example the circle instead
       | of counter-clockwise, I draw it clockwise ), another shape is
       | recognised:
       | 
       | 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
        
         | leoedin wrote:
         | When I was a teenager playing Dr Kawashima's Brain Training on
         | DS, I had to completely change how I drew my 9s in order to get
         | it to recognise them (it turned out I started in the wrong
         | place for it to recognise the number).
         | 
         | 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.
        
         | lopis wrote:
         | Well, it's not magic. It probably recognizes direction of
         | strokes. I imagine that you can start from scratch and train
         | both directions to be valid, but then you will find more
         | mismatches.
        
       | occamrazor wrote:
       | Does it work on on iPad? Both using finger and pen it scrolls
       | rather then drawing.
        
       | jzer0cool wrote:
       | Thought "at first" a medical device.
       | 
       | 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.
        
         | jmiskovic wrote:
         | Now I want editor that shows carrot in place of caret.
        
       | skrebbel wrote:
       | It took me long to figure out that this wasn't a one dollar piece
       | of hardware.
        
       | hathym wrote:
       | HN challenge: draw a circle! (no matter how hard I tried, it's
       | always a triangle for me)
        
         | xxs wrote:
         | 1st thing[0]. I didn't seem hard (and I am exceptionally bad at
         | drawing anything, incl. circles with pen and paper):
         | 
         | [0]: https://imgur.com/a/wfyoPLF
        
         | ihalip wrote:
         | For me, it says rectangle when my "circle" looks more like an
         | elipse.
        
       | yread wrote:
       | I wonder if you could make a brain stroke recognizer by filming
       | someone's face and look for one sided paralysis that often comes
       | with it
        
       | shimonabi wrote:
       | I made my unistroke symbol recognizer in Python for my AI class a
       | year ago. It uses the backpropagation algorithm.
       | 
       | You must have the Numpy and Scipy libraries installed.
       | 
       | https://github.com/smnbgn/unistroke
        
       | iamtedd wrote:
       | Is this a joke? A stroke recogniser, and they decided to go with
       | a gesture that looks like a ball-bag?
        
       | chrisxcross wrote:
       | I used it to integrate sketching into a web-based diagram editor
       | ~10 years ago and it was a breeze. OK, I had to train it myself.
       | But it takes only minutes to draw all the shape variants needed.
       | In practice I used 6 shapes and about 5 variants per shape. I
       | conducted a usability test and the $1 recognizer only failed to
       | recognizes the sketches 2-3 times out of ~300 shapes drawn by
       | different users with no additional training.
        
       ___________________________________________________________________
       (page generated 2021-05-05 23:02 UTC)