#include "GeometricRecognizer.h"
#define MAX_DOUBLE std::numeric_limits<double>::max();
namespace DollarRecognizer
{
GeometricRecognizer::GeometricRecognizer()
{
//--- How many templates do we have to compare the user's gesture against?
//--- Can get ~97% accuracy with just one template per symbol to recognize
//numTemplates = 16;
//--- How many points do we use to represent a gesture
//--- Best results between 32-256
numPointsInGesture = 128;
//--- Before matching, we stretch the symbol across a square
//--- That way we don't have to worry about the symbol the user drew
//--- being smaller or larger than the one in the template
squareSize = 250;
//--- 1/2 max distance across a square, which is the maximum distance
//--- a point can be from the center of the gesture
halfDiagonal = 0.5 * sqrt((250.0 * 250.0) + (250.0 * 250.0));
//--- Before matching, we rotate the symbol the user drew so that the
//--- start point is at degree 0 (right side of symbol). That's how
//--- the templates are rotated so it makes matching easier
//--- Note: this assumes we want symbols to be rotation-invariant,
//--- which we might not want. Using this, we can't tell the difference
//--- between squares and diamonds (which is just a rotated square)
setRotationInvariance(false);
anglePrecision = 2.0;
//--- A magic number used in pre-processing the symbols
goldenRatio = 0.5 * (-1.0 + sqrt(5.0));
}
void GeometricRecognizer::loadTemplates()
{
SampleGestures samples;
addTemplate("Arrow", samples.getGestureArrow());
addTemplate("Caret", samples.getGestureCaret());
addTemplate("CheckMark", samples.getGestureCheckMark());
addTemplate("Circle", samples.getGestureCircle());
addTemplate("Delete", samples.getGestureDelete());
addTemplate("Diamond", samples.getGestureDiamond());
//addTemplate("LeftCurlyBrace", samples.getGestureLeftCurlyBrace());
addTemplate("LeftSquareBracket", samples.getGestureLeftSquareBracket());
addTemplate("LeftToRightLine", samples.getGestureLeftToRightLine());
addTemplate("LineDownDiagonal", samples.getGestureLineDownDiagonal());
addTemplate("Pigtail", samples.getGesturePigtail());
addTemplate("QuestionMark", samples.getGestureQuestionMark());
addTemplate("Rectangle", samples.getGestureRectangle());
//addTemplate("RightCurlyBrace", samples.getGestureRightCurlyBrace());
addTemplate("RightSquareBracket", samples.getGestureRightSquareBracket());
addTemplate("RightToLeftLine", samples.getGestureRightToLeftLine());
addTemplate("RightToLeftLine2", samples.getGestureRightToLeftLine2());
addTemplate("RightToLeftSlashDown", samples.getGestureRightToLeftSlashDown());
addTemplate("Spiral", samples.getGestureSpiral());
addTemplate("Star", samples.getGestureStar());
addTemplate("Triangle", samples.getGestureTriangle());
addTemplate("V", samples.getGestureV());
addTemplate("X", samples.getGestureX());
}
int GeometricRecognizer::addTemplate(string name, Path2D points)
{
points = normalizePath(points);
templates.push_back(GestureTemplate(name, points));
//--- Let them know how many examples of this template we have now
int numInstancesOfGesture = 0;
// You know, i don't care so i'm just going to ignore this
//for (var i = 0; i < templates.size(); i++)
//{
// if (templates[i].Name == name)
// numInstancesOfGesture++;
//}
return numInstancesOfGesture;
}
Rectangle GeometricRecognizer::boundingBox(Path2D points)
{
double minX = MAX_DOUBLE;
double maxX = -MAX_DOUBLE;
double minY = MAX_DOUBLE;
double maxY = -MAX_DOUBLE;
for (Path2DIterator i = points.begin(); i != points.end(); i++)
{
Point2D point = *i;
if (point.x < minX)
minX = point.x;
if (point.x > maxX)
maxX = point.x;
if (point.y < minY)
minY = point.y;
if (point.y > maxY)
maxY = point.y;
}
Rectangle bounds(minX, minY, (maxX - minX), (maxY - minY));
return bounds;
}
Point2D GeometricRecognizer::centroid(Path2D points)
{
double x = 0.0, y = 0.0;
for (Path2DIterator i = points.begin(); i != points.end(); i++)
{
Point2D point = *i;
x += point.x;
y += point.y;
}
x /= points.size();
y /= points.size();
return Point2D(x, y);
}
double GeometricRecognizer::getDistance(Point2D p1, Point2D p2)
{
double dx = p2.x - p1.x;
double dy = p2.y - p1.y;
double distance = sqrt((dx * dx) + (dy * dy));
return distance;
}
double GeometricRecognizer::distanceAtAngle(
Path2D points, GestureTemplate aTemplate, double rotation)
{
Path2D newPoints = rotateBy(points, rotation);
return pathDistance(newPoints, aTemplate.points);
}
double GeometricRecognizer::distanceAtBestAngle(
Path2D points, GestureTemplate aTemplate)
{
double startRange = -angleRange;
double endRange = angleRange;
double x1 = goldenRatio * startRange + (1.0 - goldenRatio) * endRange;
double f1 = distanceAtAngle(points, aTemplate, x1);
double x2 = (1.0 - goldenRatio) * startRange + goldenRatio * endRange;
double f2 = distanceAtAngle(points, aTemplate, x2);
while (abs(endRange - startRange) > anglePrecision)
{
if (f1 < f2)
{
endRange = x2;
x2 = x1;
f2 = f1;
x1 = goldenRatio * startRange + (1.0 - goldenRatio) * endRange;
f1 = distanceAtAngle(points, aTemplate, x1);
}
else
{
startRange = x1;
x1 = x2;
f1 = f2;
x2 = (1.0 - goldenRatio) * startRange + goldenRatio * endRange;
f2 = distanceAtAngle(points, aTemplate, x2);
}
}
return min(f1, f2);
}
Path2D GeometricRecognizer::normalizePath(Path2D points)
{
/* Recognition algorithm from
http://faculty.washington.edu/wobbrock/pubs/uist-07.1.pdf
Step 1: Resample the Point Path
Step 2: Rotate Once Based on the "Indicative Angle"
Step 3: Scale and Translate
Step 4: Find the Optimal Angle for the Best Score
*/
// TODO: Switch to $N algorithm so can handle 1D shapes
//--- Make everyone have the same number of points (anchor points)
points = resample(points);
//--- Pretend that all gestures began moving from right hand side
//--- (degree 0). Makes matching two items easier if they're
//--- rotated the same
if (getRotationInvariance())
points = rotateToZero(points);
//--- Pretend all shapes are the same size.
//--- Note that since this is a square, our new shape probably
//--- won't be the same aspect ratio
points = scaleToSquare(points);
//--- Move the shape until its center is at 0,0 so that everyone
//--- is in the same coordinate system
points = translateToOrigin(points);
return points;
}
double GeometricRecognizer::pathDistance(Path2D pts1, Path2D pts2)
{
// assumes pts1.size == pts2.size
double distance = 0.0;
for (int i = 0; i < (int)pts1.size(); i++)
distance += getDistance(pts1[i], pts2[i]);
return (distance / pts1.size());
}
double GeometricRecognizer::pathLength(Path2D points)
{
double distance = 0;
for (int i = 1; i < (int)points.size(); i++)
distance += getDistance(points[i - 1], points[i]);
return distance;
}
RecognitionResult GeometricRecognizer::recognize(Path2D points)
{
//--- Make sure we have some templates to compare this to
//--- or else recognition will be impossible
if (templates.empty())
{
std::cout << "No templates loaded so no symbols to match." << std::endl;
return RecognitionResult("Unknown", NULL);
}
points = normalizePath(points);
//--- Initialize best distance to the largest possible number
//--- That way everything will be better than that
double bestDistance = MAX_DOUBLE;
//--- We haven't found a good match yet
int indexOfBestMatch = -1;
//--- Check the shape passed in against every shape in our database
for (int i = 0; i < (int)templa
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
.rar (88个子文件)
源码素材
Resources
Ground01.png 40KB
parkour.png 68KB
crouch.ogg 12KB
res
map00.tmx 623B
Ground01.png 23KB
parkour.png 68KB
crouch.ogg 12KB
stars.png 1KB
Map01.PNG 117KB
pickup_coin.ogg 9KB
map01.tmx 627B
map.png 14KB
background.ogg 213KB
start_s.png 18KB
restart_n.png 17KB
restart_s.png 21KB
parkour.plist 12KB
Map00.png 98KB
Thumbs.db 42KB
res.rar 145KB
jump.ogg 8KB
helloBG.png 272KB
start_n.png 15KB
favicon.ico 1KB
Ground00.png 18KB
stars.png 1KB
pickup_coin.ogg 9KB
CloseSelected.png 5KB
background.ogg 213KB
fonts
arial.ttf 760KB
Marker Felt.ttf 25KB
CloseNormal.png 6KB
HelloWorld.png 136KB
start_s.png 18KB
restart_n.png 17KB
restart_s.png 21KB
Map01.png 175KB
parkour.plist 12KB
Map00.png 170KB
Thumbs.db 35KB
jump.ogg 8KB
helloBG.png 272KB
start_n.png 15KB
favicon.ico 1KB
Ground00.png 27KB
proj.win32
Parkour.vcxproj 12KB
Parkour.sln 4KB
main.cpp 591B
main.h 267B
Classes
Coin.h 1KB
GeometricRecognizer.cpp 13KB
AppMacros.h 3KB
Map.cpp 4KB
PlayScene.h 2KB
ObjectManager.h 833B
StatusLayer.cpp 2KB
Rock.h 996B
Dollar.h 625B
AppDelegate.cpp 4KB
Dollar.cpp 3KB
HelloWorldScene.h 604B
AppDelegate.h 955B
HelloWorldScene.cpp 3KB
BackgroundLayer.h 381B
cpp.bw.zip 12KB
SimpleRecognizer.cpp 2KB
MainScene.cpp 3KB
Runner.cpp 11KB
SimpleRecognizer.h 1KB
GameOverLayer.cpp 1KB
BackgroundLayer.cpp 979B
GeometricRecognizer.h 2KB
ObjectManager.cpp 6KB
MainScene.h 600B
Map.h 526B
resource.h 1KB
Utils.h 423B
Utils.cpp 334B
GameOverLayer.h 376B
GestureTemplate.h 390B
PathWriter.h 929B
StatusLayer.h 539B
Coin.cpp 3KB
PlayScene.cpp 10KB
GeometricRecognizerTypes.h 2KB
SampleGestures.h 56KB
Rock.cpp 2KB
Runner.h 2KB
共 88 条
- 1
这是一个神秘的博客
- 粉丝: 529
- 资源: 20
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
- 4
- 5
- 6
前往页