one_dollar_unistroke_recognizer 0.6.0 copy "one_dollar_unistroke_recognizer: ^0.6.0" to clipboard
one_dollar_unistroke_recognizer: ^0.6.0 copied to clipboard

The $1 Unistroke Recognizer, a 2D single-stroke recognizer. This is a Dart port of the original JavaScript implementation.

A Dart port of the $1 Unistroke Recognizer, with some additional features planned.

Pub

Usage #

Basic usage

final points = <Offset>[...];
final recognized = recognizeUnistroke(points);
if (recognized == null) {
  print('No match found');
} else {
  // e.g. DefaultUnistrokeNames.circle
  print('Stroke recognized as ${recognized.name}');
}

Protractor enhancement

The Protractor enhancement is enabled by default. You can disable it by setting useProtractor to false.

final recognized = recognizeUnistroke(
  points,
  useProtractor: false,
);

Getting the "perfect" (canonical) shape

You can get a "perfect" shape from the user's stroke by calling one of the following methods on the RecognizedUnistroke object:

  • convertToCanonicalPolygon(): Returns the closest template match, scaled and translated to match the input gesture. Note that this method returns a list of points, instead of a perfect circle or rectangle like the other methods. (Shown in 🔴red in the examples below.)
  • convertToLine(): Returns the first and last input points. (Shown in 🟠orange in the examples below.)
  • convertToCircle(): Returns the radius and center of the best-fit circle. (Shown in 🔵blue in the examples below.)
  • convertToOval(): The same as convertToCircle() but doesn't take the average of the width and height. (Not shown in the examples below.)
  • convertToRect(): Returns the Rect of the best-fit (bounding box) rectangle. Tip: you can round the corners of the Rect with RRect.fromRectAndRadius. (Shown in 🟢green in the examples below.)
Line Circle Rectangle Triangle
Line Circle Rectangle Triangle
final recognized = recognizeUnistroke(points);
switch (recognized?.name) {
  case null:
    break;
  case DefaultUnistrokeNames.line:
    final (start, end) = recognized!.convertToLine();
    canvas.drawLine(start, end, paint);
    break;
  case DefaultUnistrokeNames.circle:
    final (center, radius) = recognized!.convertToCircle();
    canvas.drawCircle(center, radius, paint);
    break;
  case DefaultUnistrokeNames.rectangle:
    final rect = recognized!.convertToRect();
    if (youWantARoundedRectangle) {
      canvas.drawRRect(
        RRect.fromRectAndRadius(rect, Radius.circular(10)),
        paint,
      );
    } else {
      canvas.drawRect(rect, paint);
    }
    break;
  case DefaultUnistrokeNames.triangle:
    final polygon = recognized!.convertToCanonicalPolygon();
    canvas.drawPoints(PointMode.polygon, polygon, paint);
    break;
}

Using custom unistroke templates

You can recognize custom unistrokes by setting the referenceUnistrokes list.

Note that this will disable the default unistroke templates defined in default$1Unistrokes.

If your key type isn't DefaultUnistrokeNames, you'll need to call recognizeUnistrokeOfType<MyKey>(...) instead of recognizeUnistroke().

referenceUnistrokes = <Unistroke<MyUnistrokeNames>>[
  Unistroke(MyUnistrokeNames.circle, [...]),
  Unistroke(MyUnistrokeNames.rectangle, [...]),
  Unistroke(MyUnistrokeNames.triangle, [...]),
  Unistroke(MyUnistrokeNames.leaf, [...]),
];

enum MyUnistrokeNames {
  circle,
  rectangle,
  triangle,
  leaf,
}

final recognized = recognizeUnistrokeOfType<MyUnistrokeNames>(points);

Alternatively, you can temporarily override the referenceUnistrokes list for a single call to recognizeUnistroke by setting the overrideReferenceUnistrokes list.

final recognized = recognizeUnistrokeOfType<MyUnistrokeNames>(
  points,
  overrideReferenceUnistrokes: [...],
);

You could also set referenceUnistrokes to example$1Unistrokes to use the templates that were originally defined in the paper, though they're not very pretty and were probably intended to just be a proof-of-concept. (The key type for example$1Unistrokes is String.)

About the $1 Unistroke Recognizer #

The $1 Unistroke Recognizer is a 2-D single-stroke recognizer designed for rapid prototyping of gesture-based user interfaces. In machine learning terms, $1 is an instance-based nearest-neighbor classifier with a 2-D Euclidean distance function, i.e., a geometric template matcher. $1 is a significant extension of the proportional shape matching approach used in SHARK2, which itself is an adaptation of Tappert's elastic matching approach with zero look-ahead. Despite its simplicity, $1 requires very few templates to perform well and is only about 100 lines of code, making it easy to deploy. An optional enhancement called Protractor improves $1's speed.

You can read more about the $1 Unistroke Recognizer at depts.washington.edu/acelab/proj/dollar.

This Dart package is a port of the JavaScript version of the $1 Unistroke Recognizer, which you can find at depts.washington.edu/acelab/proj/dollar/dollar.js.

2
likes
0
pub points
84%
popularity

Publisher

verified publisheradil.hanney.org

The $1 Unistroke Recognizer, a 2D single-stroke recognizer. This is a Dart port of the original JavaScript implementation.

Homepage
Repository (GitHub)
View/report issues

Topics

#one-dollar #unistrokes #shape-recognition #gesture-recognition

License

unknown (license)

Dependencies

flutter, vector_math

More

Packages that depend on one_dollar_unistroke_recognizer