CUGL 2.5
Cornell University Game Library
|
#include <CUGestureRecognizer.h>
Public Types | |
enum class | Algorithm { ONEDOLLAR , PROTRACTOR } |
Public Member Functions | |
GestureRecognizer () | |
~GestureRecognizer () | |
bool | init () |
bool | init (size_t samples, Size bounds) |
bool | initWithJson (const std::shared_ptr< JsonValue > &json) |
void | dispose () |
float | getSampleSize () const |
Size | getNormalizedBounds () const |
Algorithm | getAlgorithm () const |
void | setAlgorithm (Algorithm algorithm) |
float | getSimilarityThreshold () const |
void | setSimilarityThreshold (float accuracy) |
float | getOrientationTolerance () const |
void | setOrientationTolerance (float tolerance) |
const std::string | match (const std::vector< Vec2 > points) |
const std::string | match (const Vec2 *points, size_t psize) |
const std::string | match (const Path2 &path) |
const std::string | match (const std::vector< Vec2 > points, float &similarity) |
const std::string | match (const Vec2 *points, size_t psize, float &similarity) |
const std::string | match (const Path2 &path, float &similarity) |
float | similarity (const std::string name, const std::vector< Vec2 > &points, bool invariant=true) |
float | similarity (const std::string name, const Vec2 *points, size_t psize, bool invariant=true) |
float | similarity (const std::string name, const Path2 &path, bool invariant=true) |
bool | addGesture (const std::string name, const std::vector< Vec2 > &points, bool unique=false) |
bool | addGesture (const std::string name, const Vec2 *points, size_t psize, bool unique=false) |
bool | addGesture (const std::string name, const Path2 &path, bool unique=false) |
void | addGestures (const std::shared_ptr< JsonValue > &json, bool unique=false) |
void | removeGesture (const std::string name) |
void | clearGestures () |
bool | hasGesture (const std::string name) const |
const UnistrokeGesture | getGesture (const std::string name) const |
std::vector< std::string > | getGestureNames () const |
std::vector< UnistrokeGesture > | getGestures () const |
Static Public Member Functions | |
static std::shared_ptr< GestureRecognizer > | alloc () |
static std::shared_ptr< GestureRecognizer > | alloc (size_t samples, Size bounds) |
static std::shared_ptr< GestureRecognizer > | allocWithJson (const std::shared_ptr< JsonValue > &json) |
A class representing the gesture recognition engine.
This class contains all the required funtionality needed for recognizing user defined gestures. It's major responsibilities are to store a collection of template gestures (for comparison), and normalize a gesture to a grid of fixed size. Gesture matches are determined by computing a similarity score between normalized instances.
Normalization involves resampling the gesture to a fixed number of points, as defined by getSampleSize
. In addition, the gesture is rescaled to a box defined by getNormalizedBounds
.
The recognition algorithm can use either the traditional $1 algorithm algorithm or the PROTACTOR method, depending on what suits you and what gives you the best results for your application. For more information on these algorithms, see
https ://dl.acm.org/citation.cfm?id=1294238 https ://dl.acm.org/citation.cfm?id=1753654/
Both of these algorithms are rotationally oblivious, meaning that they can recognize the gestures at any orientation. Typically this is not what we want in game development, however. Therfore, this recognizer includes the option to reject any matches whose angles of rotation exceed a certain threshold. See getOrientationTolerance
for more information.
Similarity is determined on a scale of 0 to 1 where 1 is a complete match and 0 is no match at all. A pure 0 is difficult to achieve. By default, we consider any gesture a possible match if it has a similarity of at least 0.8.
|
strong |
An enumeration listing the type of matching algorithms
cugl::GestureRecognizer::GestureRecognizer | ( | ) |
Creates an uninitialized Gesture Recognizer.
NEVER USE A CONSTRUCTOR WITH NEW. If you want to allocate an object on the heap, use one of the static constructors instead.
|
inline |
Deletes this recognizer and all of its resources.
|
inline |
Adds the given gesture to this recognizer using the given name.
The gesture will be normalized before storing it. If the gesture has the same name as an existing one, the previous gesture will be replaced.
If the optional parameter unique is set to true, this method will first check that the gesture is unique (e.g. it does not exceed the similarity threshold when compared to any existing gestures) before adding it. If the gesture is too close to an existing one, this method will return false.
Note that uniqueness is determined according the current algorithm, similarity threshold, and orientation tolerance. If any of these values change, then uniqueness is no longer guaranteed.
When converting to a gesture, the path will be treated as a linear sequence of points. Corner classifications and whether the path is closed will be ignored.
name | the name of the gesture to compare |
path | a path representing a candidate gesture |
unique | whether to enforce gesture uniqueness |
|
inline |
Adds the given gesture to this recognizer using the given name.
The gesture will be normalized before storing it. If the gesture has the same name as an existing one, the previous gesture will be replaced.
If the optional parameter unique is set to true, this method will first check that the gesture is unique (e.g. it does not exceed the similarity threshold when compared to any existing gestures) before adding it. If the gesture is too close to an existing one, this method will return false.
Note that uniqueness is determined according the current algorithm, similarity threshold, and orientation tolerance. If any of these values change, then uniqueness is no longer guaranteed.
name | the gesture name |
points | a vector of points representing a gesture |
unique | whether to enforce gesture uniqueness |
bool cugl::GestureRecognizer::addGesture | ( | const std::string | name, |
const Vec2 * | points, | ||
size_t | psize, | ||
bool | unique = false |
||
) |
Adds the given gesture to this recognizer using the given name.
The gesture will be normalized before storing it. If the gesture has the same name as an existing one, the previous gesture will be replaced.
If the optional parameter unique is set to true, this method will first check that the gesture is unique (e.g. it does not exceed the similarity threshold when compared to any existing gestures) before adding it. If the gesture is too close to an existing one, this method will return false.
Note that uniqueness is determined according the current algorithm, similarity threshold, and orientation tolerance. If any of these values change, then uniqueness is no longer guaranteed.
name | the gesture name |
points | an array of points representing a gesture |
psize | the number of points in the gesture |
unique | whether to enforce gesture uniqueness |
void cugl::GestureRecognizer::addGestures | ( | const std::shared_ptr< JsonValue > & | json, |
bool | unique = false |
||
) |
Adds all of the gestures in the given JSON specification
The JSON value should be a list of entries that all follow the format used by the Path2
class.
If the optional parameter unique is set to true, this method will first check that each gesture is unique (e.g. it does not exceed the similarity threshold when compared to any existing gestures) before adding it. Any gesture that matches one that came previously in the list will be dropped.
Note that uniqueness is determined according the current algorithm, similarity threshold, and orientation tolerance. If any of these values change, then uniqueness is no longer guaranteed.
json | The JSON object specifying the recognizer |
unique | whether to enforce gesture uniqueness |
|
inlinestatic |
Returns a newly allocated gesture recognizer with the default settings.
The sample rate and normalization bounds will be set the default values. The recognier will be empty, and therefore will not match any gestures until some are added via addGesture
.
|
inlinestatic |
Returns a newly allocated gesture recognizer with the given accuracy.
The recognier will be empty, and therefore will not match any gestures until some are added via addGesture
.
samples | The number of samples to use in a normalized gesture |
bounds | The bounding box for normalized gestures |
|
inlinestatic |
Returns a newly allocated gesture recognizer with the given JSON entry
The JSON entry supports the following attribute values:
"algorithm": One of "onedollar" or "protractor" "accuracy": A float with the similarity threshold "tolerance": A float with the rotational tolerance "samples": An int for the number of sample points "bounds": A two-element list of floats representing the bounding box for normalized gestures "gestures": A list of path entries
The path entries should all follow the format used by the Path2
class.
json | The JSON object specifying the recognizer |
|
inline |
Removes all gestures from this recognizer
void cugl::GestureRecognizer::dispose | ( | ) |
Empties the recongizer of all gestures and resets all attributes.
This will set the sample size to 0, meaning no future matches are possible. You must reinitialize the object to use it.
|
inline |
Returns the current matching algorithm
This gesture recognizer can use either the classic $1 algorithm or the PROTRACTOR algorithm. The PROTRACTOR is faster with less accuracy. However the need for speed really depends on the number of gestures stored in this recognizer. Determining which algorithm is best is typically a matter of experiementation.
Note that changing this value can possible invalidate any uniqueness constraints previously applied to the gestures. That is because uniqueness is determined using the active algorithm. If uniqueness is important, we recommend that you clear the existing gestures and add them back.
|
inline |
Returns (a copy of) gesture of the given name
If there is no gesture of that name, it will return an empty gesture.
name | the name of the gesture to query |
std::vector< std::string > cugl::GestureRecognizer::getGestureNames | ( | ) | const |
Returns a vector of all the gesture names
std::vector< UnistrokeGesture > cugl::GestureRecognizer::getGestures | ( | ) | const |
Returns all the (normalized) gestures stored in this recognizer
|
inline |
Returns the bounding box of the normalization space
When a gesture is normalized, it is resized to so that its bounding box matches that of all other gestures. This value is the size of the box. By default it is 250x250.
This value is set when the gesture recognizer is allocated and cannot be changed. Changing this value would require the reintialization of all gestures.
|
inline |
Returns the rotational tolerance for gesture matching.
The matching algorithms are rotationally oblivious, meaning that they can recognize the gestures at any orientation. Typically this is not what we want in game development, however. If a gesture is rotated too far, we want to reject it.
The tolerance is the maximum allowable angle (in radians) of rotation for a gesture to be recognized. The angle of a gesture is measured using the vector from its first point to the (normalized) centroid. If θ is the angle between the gesture and potential match, it will be rejected if it is greater than +/- the tolerance.
By default this value is 20°. Setting this to a negative value will allow free rotation of gestures.
Note that changing this value can possible invalidate any uniqueness constraints previously applied to the gestures. That is because uniqueness is determined using the current rotational tolerance. If uniqueness is important, we recommend that you clear the existing gestures and add them back.
|
inline |
Returns the sample rate of a normalized gesture
When a gesture is either added to the recognizer or posed as a candidate for matching, it will first be normalized. All normalized gestures will have this many points (the the PROCTRACTOR algorithm will only use 1/4 this many points).
Increasing this number will hurt performance, while decreasing this value will hurt accuracy. Ideally it should be between 30-128. By default this value is 64 (and hence 16 for the PROTRACTOR algorithm).
This value is set when the gesture recognizer is allocated and cannot be changed. Changing this value would require the reintialization of all gestures.
|
inline |
Returns the similarity threshold
When matching a candidate gesture against the stored values, we only consider matches whose similarity value is above this threshold. If this value is non-zero, it is possible that a candidate gesture will have no matches. By default this value is 0.8.
Note that changing this value can possible invalidate any uniqueness constraints previously applied to the gestures. That is because uniqueness is determined using the current similarity threshold. If uniqueness is important, we recommend that you clear the existing gestures and add them back.
|
inline |
Returns true if this recognizer has a gesture of the given name
name | the name of the gesture to query |
bool cugl::GestureRecognizer::init | ( | ) |
Initializes an empty gesture recognizer with the default settings.
Calling this method initializes the sample rate and the bounding box for normalization. These values will be set to the defaults. The recognizer will be empty, and therefore will not match any gestures until some are added via addGesture
.
bool cugl::GestureRecognizer::init | ( | size_t | samples, |
Size | bounds | ||
) |
Initializes an empty gesture recognizer with the given settings.
The recognier will be empty, and therefore will not match any gestures until some are added via addGesture
.
samples | The number of samples to use in a normalized gesture |
bounds | The bounding box for normalized gestures |
bool cugl::GestureRecognizer::initWithJson | ( | const std::shared_ptr< JsonValue > & | json | ) |
Initializes the gesture recognizer with the given JSON entry
The JSON entry supports the following attribute values:
"algorithm": One of "onedollar" or "protractor" "accuracy": A float with the similarity threshold "tolerance": A float with the rotational tolerance "samples": An int for the number of sample points "bounds": A two-element list of floats representing the bounding box for normalized gestures "gestures": A list of path entries
The path entries should all follow the format used by the Path2
class.
json | The JSON object specifying the recognizer |
|
inline |
Returns the name of the gesture with the closest match to the given one.
The match will be performed using the current active algorithm. If there is no match within the similarity threshold or orientation tolerance, this method will return the empty string. A gesture must consist of at least two points.
When matching as a gesture, the path will be treated as a linear sequence of points. Corner classifications and whether the path is closed will be ignored.
path | a path representing a candidate gesture. |
|
inline |
Returns the name of the gesture with the closest match to the given one.
The match will be performed using the current active algorithm, with the (rotationally invariant) similarity score stored in the reference parameter. If there is no match within the similarity threshold, or orientation tolerance, this method will return the empty string (though it will still report the rotationally invariant similarity. A gesture must consist of at least two points.
When matching as a gesture, the path will be treated as a linear sequence of points. Corner classifications and whether the path is closed will be ignored.
path | a path representing a candidate gesture. |
similarity | parameter to store the similarity value |
|
inline |
Returns the name of the gesture with the closest match to the given one.
The match will be performed using the current active algorithm. If there is no match within the similarity threshold or orientation tolerance, this method will return the empty string. A gesture must consist of at least two points.
points | a vector of points representing a candidate gesture. |
|
inline |
Returns the name of the gesture with the closest match to the given one.
The match will be performed using the current active algorithm, with the (rotationally invariant) similarity score stored in the reference parameter. If there is no match within the similarity threshold, or orientation tolerance, this method will return the empty string (though it will still report the rotationally invariant similarity. A gesture must consist of at least two points.
points | a vector of points representing a candidate gesture. |
similarity | parameter to store the similarity score |
|
inline |
Returns the name of the gesture with the closest match to the given one.
The match will be performed using the current active algorithm. If there is no match within the similarity threshold or orientation tolerance, this method will return the empty string. A gesture must consist of at least two points.
points | an array of points representing a candidate gesture. |
psize | the number of points in the candidate gesture. |
const std::string cugl::GestureRecognizer::match | ( | const Vec2 * | points, |
size_t | psize, | ||
float & | similarity | ||
) |
Returns the name of the gesture with the closest match to the given one.
The match will be performed using the current active algorithm, with the (rotationally invariant) similarity score stored in the reference parameter. If there is no match within the similarity threshold, or orientation tolerance, this method will return the empty string (though it will still report the rotationally invariant similarity. A gesture must consist of at least two points.
points | an array of points representing a candidate gesture. |
psize | the number of points in the candidate gesture. |
similarity | parameter to store the similarity value |
void cugl::GestureRecognizer::removeGesture | ( | const std::string | name | ) |
Removes the gesture with the given name from the recongizer
name | The name of the gesture to remove |
|
inline |
Sets the current matching algorithm
This gesture recognizer can use either the classic $1 algorithm or the PROTRACTOR algorithm. The PROTRACTOR is faster with less accuracy. However the need for speed really depends on the number of gestures stored in this recognizer. Determining which algorithm is best is typically a matter of experiementation.
Note that changing this value can possible invalidate any uniqueness constraints previously applied to the gestures. That is because uniqueness is determined using the active algorithm. If uniqueness is important, we recommend that you clear the existing gestures and add them back.
algorithm | the matching algorithm |
|
inline |
Sets the rotational tolerance for gesture matching.
The matching algorithms are rotationally oblivious, meaning that they can recognize the gestures at any orientation. Typically this is not what we want in game development, however. If a gesture is rotated too far, we want to reject it.
The tolerance is the maximum allowable angle (in radians) of rotation for a gesture to be recognized. The angle of a gesture is measured using the vector from its first point to the (normalized) centroid. If θ is the angle between the gesture and potential match, it will be rejected if it is greater than +/- the tolerance.
By default this value is 20°. Setting this to a negative value will allow free rotation of gestures.
Note that changing this value can possible invalidate any uniqueness constraints previously applied to the gestures. That is because uniqueness is determined using the current rotational tolerance. If uniqueness is important, we recommend that you clear the existing gestures and add them back.
tolerance | the rotational tolerance for gesture matching. |
|
inline |
Sets the similarity threshold
When matching a candidate gesture against the stored values, we only consider matches whose similarity value is above this threshold. If this value is non-zero, it is possible that a candidate gesture will have no matches. By default this value is 0.3.
Note that changing this value can possible invalidate any uniqueness constraints previously applied to the gestures. That is because uniqueness is determined using the current similarity threshold. If uniqueness is important, we recommend that you clear the existing gestures and add them back.
accuracy | the similarity threshold |
|
inline |
Returns the similarity measure of the named gesture to this one.
The similarity measure will be computed using the active algorithm. As those algorithms are rotationally invariant, it will ignore the rotation when computing that value. However, if the parameter invariant is set to false, this method will return 0 for gestures not within the orientation tolerance.
If there is no gesture of the given name, this method will return 0. A gesture must consist of at least two points.
When matching as a gesture, the path will be treated as a linear sequence of points. Corner classifications and whether the path is closed will be ignored.
name | the name of the gesture to compare |
path | a path representing a candidate gesture |
invariant | whether to ignore rotation when computing similarity |
|
inline |
Returns the similarity measure of the named gesture to this one.
The similarity measure will be computed using the active algorithm. As those algorithms are rotationally invariant, it will ignore the rotation when computing that value. However, if the parameter invariant is set to false, this method will return 0 for gestures not within the orientation tolerance.
If there is no gesture of the given name, this method will return 0. A gesture must consist of at least two points.
name | the name of the gesture to compare |
points | a vector of points representing a candidate gesture |
invariant | whether to ignore rotation when computing similarity |
float cugl::GestureRecognizer::similarity | ( | const std::string | name, |
const Vec2 * | points, | ||
size_t | psize, | ||
bool | invariant = true |
||
) |
Returns the similarity measure of the named gesture to this one.
The similarity measure will be computed using the active algorithm. As those algorithms are rotationally invariant, it will ignore the rotation when computing that value. However, if the parameter invariant is set to false, this method will return 0 for gestures not within the orientation tolerance.
If there is no gesture of the given name, this method will return 0. A gesture must consist of at least two points.
name | the name of the gesture to compare |
points | an array of points representing a candidate gesture |
psize | the number of points in the candidate gesture |
invariant | whether to ignore rotation when computing similarity |