From 455a49de9c6a43db3a0aae69a28673a627008e5e Mon Sep 17 00:00:00 2001 From: Martin Enzelsberger Date: Fri, 10 Jun 2011 12:13:18 +0200 Subject: [PATCH] GestureRecognizer2D and Test application --- .../.classpath | 3 +- GestureDetectionApp/GestureRecognition/.project | 17 ++ .../.settings/org.eclipse.jdt.core.prefs | 12 ++ .../org.eclipse.ltk.core.refactoring.prefs | 3 + .../src/at/mus/recognition/Acceleration.java | 49 +++++ .../src/at/mus/recognition/Point.java | 26 +++ .../src/at/mus/recognition/Recognizer2D.java | 214 ++++++++++++++++++++ .../src/at/mus/recognition/Rectangle.java | 12 ++ .../src/at/mus/recognition/Template.java | 13 ++ .../src/at/mus/recognition/Templates.java | 52 +++++ .../GestureRecognizerTest/.classpath | 7 + GestureDetectionApp/GestureRecognizerTest/.project | 17 ++ .../.settings/org.eclipse.jdt.core.prefs | 12 ++ .../GestureRecognizerTest/src/gui/MainFrame.java | 220 +++++++++++++++++++++ .../GestureRecognizerTest/src/gui/PointsPanel.java | 58 ++++++ .../GestureSensitiveControl/.classpath | 1 + .../GestureSensitiveControl/GestureActivity.java | 8 +- .../GestureSensitiveControl/PositionRecorder.java | 28 +++ 18 files changed, 749 insertions(+), 3 deletions(-) copy GestureDetectionApp/{GestureSensitiveControl => GestureRecognition}/.classpath (50%) create mode 100644 GestureDetectionApp/GestureRecognition/.project create mode 100644 GestureDetectionApp/GestureRecognition/.settings/org.eclipse.jdt.core.prefs create mode 100644 GestureDetectionApp/GestureRecognition/.settings/org.eclipse.ltk.core.refactoring.prefs create mode 100644 GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Acceleration.java create mode 100644 GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Point.java create mode 100644 GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Recognizer2D.java create mode 100644 GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Rectangle.java create mode 100644 GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Template.java create mode 100644 GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Templates.java create mode 100644 GestureDetectionApp/GestureRecognizerTest/.classpath create mode 100644 GestureDetectionApp/GestureRecognizerTest/.project create mode 100644 GestureDetectionApp/GestureRecognizerTest/.settings/org.eclipse.jdt.core.prefs create mode 100644 GestureDetectionApp/GestureRecognizerTest/src/gui/MainFrame.java create mode 100644 GestureDetectionApp/GestureRecognizerTest/src/gui/PointsPanel.java create mode 100644 GestureDetectionApp/GestureSensitiveControl/src/at/mus/GestureSensitiveControl/PositionRecorder.java diff --git a/GestureDetectionApp/GestureSensitiveControl/.classpath b/GestureDetectionApp/GestureRecognition/.classpath similarity index 50% copy from GestureDetectionApp/GestureSensitiveControl/.classpath copy to GestureDetectionApp/GestureRecognition/.classpath index 609aa00..18d70f0 100644 --- a/GestureDetectionApp/GestureSensitiveControl/.classpath +++ b/GestureDetectionApp/GestureRecognition/.classpath @@ -1,7 +1,6 @@ - - + diff --git a/GestureDetectionApp/GestureRecognition/.project b/GestureDetectionApp/GestureRecognition/.project new file mode 100644 index 0000000..78858f1 --- /dev/null +++ b/GestureDetectionApp/GestureRecognition/.project @@ -0,0 +1,17 @@ + + + GestureRecognition + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/GestureDetectionApp/GestureRecognition/.settings/org.eclipse.jdt.core.prefs b/GestureDetectionApp/GestureRecognition/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..08908ea --- /dev/null +++ b/GestureDetectionApp/GestureRecognition/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Fri Jun 03 15:05:57 CEST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/GestureDetectionApp/GestureRecognition/.settings/org.eclipse.ltk.core.refactoring.prefs b/GestureDetectionApp/GestureRecognition/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 0000000..4272109 --- /dev/null +++ b/GestureDetectionApp/GestureRecognition/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,3 @@ +#Fri Jun 03 19:22:01 CEST 2011 +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Acceleration.java b/GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Acceleration.java new file mode 100644 index 0000000..34875e7 --- /dev/null +++ b/GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Acceleration.java @@ -0,0 +1,49 @@ +package at.mus.recognition; + +public class Acceleration { + public float x, y, z; + + public Acceleration(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + + public Acceleration(float[] value) { + this(value[0], value[1], value[2]); + } + + /** + * Returns distance between 2 vectors + * @param acc + * @return + */ + public float distance(Acceleration acc) { + return (float) Math.sqrt((x - acc.x) * (x - acc.x) + (y - acc.y) * (y - acc.y) + (z - acc.z) * (z - acc.z)); + } + + /** + * Returns length of the vector + * @return + */ + public float length() { + return (float)Math.sqrt(x*x + y*y + z*z); + } + + /** + * Returns unit vector + * @return + */ + public Acceleration unit() { + float norm = (float)(1.0 / length()); + return new Acceleration(norm * x, norm * y, norm * z); + } + + /** + * Returns difference between 2 vectors + * @return + */ + public Acceleration difference(Acceleration acc) { + return new Acceleration(x - acc.x, y - acc.y, z - acc.z); + } +} diff --git a/GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Point.java b/GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Point.java new file mode 100644 index 0000000..d0b34da --- /dev/null +++ b/GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Point.java @@ -0,0 +1,26 @@ +package at.mus.recognition; + +public class Point { + public double x, y; + + public Point() { + this.x = 0.0; + this.y = 0.0; + } + + public Point(double x, double y) { + this.x = x; + this.y = y; + } + + public Point(Point p) { + this.x = p.x; + this.y = p.y; + } + + public double distance(Point p){ + double dx = p.x - x; + double dy = p.y - y; + return Math.sqrt(dx * dx + dy * dy); + } +} diff --git a/GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Recognizer2D.java b/GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Recognizer2D.java new file mode 100644 index 0000000..5e0a95d --- /dev/null +++ b/GestureDetectionApp/GestureRecognition/src/at/mus/recognition/Recognizer2D.java @@ -0,0 +1,214 @@ +package at.mus.recognition; + +import java.util.*; + +public class Recognizer2D { + private static final double Phi = 0.5 * (-1.0 + Math.sqrt(5.0)); // Golden Ratio + private static final double AngleRange = deg2Rad(45.0); + private static final double AnglePrecision = deg2Rad(2.0); + + /* Step 1: Resample */ + + public List resample(List points, int n) { + List newPoints = new ArrayList(); + double I = pathLength(points) / (n - 1); + double D = 0.0; + + newPoints.add(points.get(0)); + for (int i = 1; i < points.size(); i++) { + Point pi_1 = points.get(i - 1); + Point pi = points.get(i); + double d = pi_1.distance(pi); + if (D + d >= I) { + Point q = new Point(pi_1.x + ((I - D) / d) * (pi.x - pi_1.x), + pi_1.y + ((I - D) / d) * (pi.y - pi_1.y)); + newPoints.add(q); + points.add(i, q); + D = 0.0; + } else + D += d; + } + // somtimes we fall a rounding-error short of adding the last point, so + // add it if so + if (newPoints.size() == (n - 1)) { + Point last = points.get(points.size() - 1); + newPoints.add(new Point(last.x, last.y)); + } + return newPoints; + } + + private double pathLength(List points) { + double d = 0.0; + for (int i = 1; i < points.size(); i++) + d += points.get(i - 1).distance(points.get(i)); + return d; + } + + /* Step 2: Rotate */ + + public List rotateToZero(List points) { + Point c = centroid(points); + Point p0 = points.get(0); + double radians = Math.atan2(c.y - p0.y, c.x - p0.x); // indicative angle + return rotateBy(points, c, radians); + } + + private List rotateBy(List points, Point c, double radians) { + double cos = Math.cos(radians); + double sin = Math.sin(radians); + + List newPoints = new ArrayList(); + for (Point p : points) { + newPoints.add(new Point( + (p.x - c.x) * cos - (p.y - c.y) * sin + c.x, (p.x - c.x) + * sin + (p.y - c.y) * cos + c.y)); + } + return newPoints; + } + + private Point centroid(List points) { + double cx = 0.0, cy = 0.0; + for (Point p : points) { + cx += p.x; + cy += p.y; + } + cx /= points.size(); + cy /= points.size(); + return new Point(cx, cy); + } + + /* Step 3: Scale */ + + public List scaleAndTranslateTo(List points, double size, Point pt) { + List newPoints = new ArrayList(); + + // scale + Rectangle rect = boundingBox(points); + for (Point p : points) { + newPoints.add(new Point(p.x * (size / rect.width), p.y + * (size / rect.height))); + } + + // translate + Point c = centroid(newPoints); + for (Point p : newPoints) { + p.x = p.x + pt.x - c.x; + p.y = p.y + pt.y - c.y; + } + return newPoints; + } + + private Rectangle boundingBox(List points) { + double minX = Double.MAX_VALUE, maxX = Double.MIN_VALUE; + double minY = Double.MAX_VALUE, maxY = Double.MIN_VALUE; + for (Point p : points) { + if (p.x < minX) + minX = p.x; + if (p.y < minY) + minY = p.y; + if (p.x > maxX) + maxX = p.x; + if (p.y > maxY) + maxY = p.y; + } + return new Rectangle(minX, minY, maxX - minX, maxY - minY); + } + + /* Step 4: Recognition */ + + /** + * @param rawPoints list of points to recognize + * @param templates pre-defined list of templates + * @param n number of points (resample) + * @param size square size (scaleAndTranslateTo) + * @param origin desired origin (scaleAndTranslateTo) + */ + public Result recognize(List rawPoints, List