/// <summary> /// Computes the total Euclidean Distance between two templates at a specified angle /// </summary> /// <param name="avgPoints"></param> /// <param name="T"></param> /// <param name="theta"></param> /// <returns></returns> private double EuclideanDistanceAtAngle(List <AveragePoint> avgPoints, DollarTemplateAverage T, double theta) { List <Point> points = GetPoints(avgPoints); List <Point> newPoints = rotateBy(points, theta); return(EuclideanDistance(newPoints, T.m_AveragePoints) / (double)points.Count); }
/// <summary> /// Find the optimal angle and compute the distance at this angle. Uses the Golden Section Search. /// </summary> /// <param name="points">Points trying to be matched to template</param> /// <param name="T">Template being matched to</param> /// <param name="thetaA">Initial lowest angle</param> /// <param name="thetaB">Initial highest angle</param> /// <param name="thetaDelta">Threshold below which to stop searching</param> /// <returns>Distance at best angle</returns> private double distanceAtBestAngle(List <AveragePoint> points, DollarTemplateAverage T, double thetaA, double thetaB, double thetaDelta, ref double theta) { double f1 = distanceAtAngle(points, T, thetaA); double f2 = distanceAtAngle(points, T, thetaB); while (Math.Abs(thetaB - thetaA) > thetaDelta) { if (f1 < f2) { thetaB = (1 - PHI) * thetaA + PHI * thetaB; f2 = distanceAtAngle(points, T, thetaB); } else { thetaA = PHI * thetaA + (1 - PHI) * thetaB; f1 = distanceAtAngle(points, T, thetaA); } } if (f1 < f2) { theta = thetaB; return(f1); } else { theta = thetaA; return(f2); } }
public string Recognize(List <DollarTemplateAverage> templates) { double score = 0.0; DollarTemplateAverage best = RecognizeSymbol(templates, ref score); if (score < SCORE_THRESHOLD) { return("Unknown"); } return(best.Name); }
/// <summary> /// Match this symbol to the best Template in templates. /// </summary> /// <param name="templates">Existing templates with which to match</param> /// <param name="score">Score of best matching template</param> public DollarTemplateAverage RecognizeSymbol(List <DollarTemplateAverage> templates, ref double score) { if (templates.Count == 0) { return(null); } DollarTemplateAverage Tbest = templates[0]; double bestD = double.MaxValue; double bestTheta = 0.0; double d = 0.0; for (int i = 0; i < templates.Count; i++) { double theta = 0.0; d = EuclideanDistanceAtBestAngle(m_AveragePoints, templates[i], -THETA_MAX, THETA_MAX, THETA_DELTA, ref theta); //d = distanceAtBestAngle(m_AveragePoints, templates[i], -THETA_MAX, THETA_MAX, THETA_DELTA, ref theta); if (d < bestD) { bestD = d; bestTheta = theta; Tbest = templates[i]; } } //double bestDistance = EuclideanDistanceAtAngle(m_AveragePoints, Tbest, bestTheta); double bestDistance = distanceAtAngle(m_AveragePoints, Tbest, bestTheta); bestDistance /= 10.0; double score1 = 1 - bestD / (0.5 * Math.Sqrt(Math.Pow(SIZE, 2.0) * 2)); double score2 = Math.Exp(-bestDistance); //Console.WriteLine("BestDistance = {0}, SDscore = {1} ||| EuclDistance = {2}, Escore = {3}", bestDistance, score2, bestD, score1); score = Math.Max(score1, score2); return(Tbest); }
/// <summary> /// Gets the result for the best matching "Average" template /// </summary> /// <param name="stroke">Stroke to be recognized</param> /// <returns>Class name of the best match</returns> public string RecognizeAverage(Substroke stroke) { DollarTemplateAverage unknown = new DollarTemplateAverage(stroke.PointsL); return(unknown.Recognize(_averageTemplates)); }