Merge change I4758f121 into eclair-mr2
* changes: Added the Protractor algorithm for calculating the minimum cosine distance between gestures
This commit is contained in:
@@ -65,7 +65,12 @@ public class GestureStore {
|
||||
|
||||
// ORIENTATION_SENSITIVE and ORIENTATION_INVARIANT are only for SEQUENCE_SENSITIVE gestures
|
||||
public static final int ORIENTATION_INVARIANT = 1;
|
||||
// at most 2 directions can be recognized
|
||||
public static final int ORIENTATION_SENSITIVE = 2;
|
||||
// at most 4 directions can be recognized
|
||||
static final int ORIENTATION_SENSITIVE_4 = 4;
|
||||
// at most 8 directions can be recognized
|
||||
static final int ORIENTATION_SENSITIVE_8 = 8;
|
||||
|
||||
private static final short FILE_FORMAT_VERSION = 1;
|
||||
|
||||
@@ -131,7 +136,7 @@ public class GestureStore {
|
||||
public ArrayList<Prediction> recognize(Gesture gesture) {
|
||||
Instance instance = Instance.createInstance(mSequenceType,
|
||||
mOrientationStyle, gesture, null);
|
||||
return mClassifier.classify(mSequenceType, instance.vector);
|
||||
return mClassifier.classify(mSequenceType, mOrientationStyle, instance.vector);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -366,6 +366,38 @@ final class GestureUtilities {
|
||||
}
|
||||
return Math.acos(sum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the "minimum" cosine distance between two instances
|
||||
*
|
||||
* @param vector1
|
||||
* @param vector2
|
||||
* @param numOrientations the maximum number of orientation allowed
|
||||
* @return the distance between the two instances (between 0 and Math.PI)
|
||||
*/
|
||||
static double minimumCosineDistance(float[] vector1, float[] vector2, int numOrientations) {
|
||||
final int len = vector1.length;
|
||||
double a = 0;
|
||||
double b = 0;
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
a += vector1[i] * vector2[i] + vector1[i + 1] * vector2[i + 1];
|
||||
b += vector1[i] * vector2[i + 1] - vector1[i + 1] * vector2[i];
|
||||
}
|
||||
if (a != 0) {
|
||||
final double tan = b/a;
|
||||
final double angle = Math.atan(tan);
|
||||
if (numOrientations > 2 && Math.abs(angle) >= Math.PI / numOrientations) {
|
||||
return Math.acos(a);
|
||||
} else {
|
||||
final double cosine = Math.cos(angle);
|
||||
final double sine = cosine * tan;
|
||||
return Math.acos(a * cosine + b * sine);
|
||||
}
|
||||
} else {
|
||||
return Math.PI / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static OrientedBoundingBox computeOrientedBoundingBox(ArrayList<GesturePoint> pts) {
|
||||
GestureStroke stroke = new GestureStroke(pts);
|
||||
|
||||
@@ -94,7 +94,7 @@ class Instance {
|
||||
float orientation = (float)Math.atan2(pts[1] - center[1], pts[0] - center[0]);
|
||||
|
||||
float adjustment = -orientation;
|
||||
if (orientationType == GestureStore.ORIENTATION_SENSITIVE) {
|
||||
if (orientationType != GestureStore.ORIENTATION_INVARIANT) {
|
||||
int count = ORIENTATIONS.length;
|
||||
for (int i = 0; i < count; i++) {
|
||||
float delta = ORIENTATIONS[i] - orientation;
|
||||
|
||||
@@ -41,7 +41,7 @@ class InstanceLearner extends Learner {
|
||||
};
|
||||
|
||||
@Override
|
||||
ArrayList<Prediction> classify(int sequenceType, float[] vector) {
|
||||
ArrayList<Prediction> classify(int sequenceType, int orientationType, float[] vector) {
|
||||
ArrayList<Prediction> predictions = new ArrayList<Prediction>();
|
||||
ArrayList<Instance> instances = getInstances();
|
||||
int count = instances.size();
|
||||
@@ -53,7 +53,7 @@ class InstanceLearner extends Learner {
|
||||
}
|
||||
double distance;
|
||||
if (sequenceType == GestureStore.SEQUENCE_SENSITIVE) {
|
||||
distance = GestureUtilities.cosineDistance(sample.vector, vector);
|
||||
distance = GestureUtilities.minimumCosineDistance(sample.vector, vector, orientationType);
|
||||
} else {
|
||||
distance = GestureUtilities.squaredEuclideanDistance(sample.vector, vector);
|
||||
}
|
||||
|
||||
@@ -79,5 +79,5 @@ abstract class Learner {
|
||||
instances.removeAll(toDelete);
|
||||
}
|
||||
|
||||
abstract ArrayList<Prediction> classify(int gestureType, float[] vector);
|
||||
abstract ArrayList<Prediction> classify(int sequenceType, int orientationType, float[] vector);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user