public BoponotoClassifier(int n, double size, SketchPoint point, Dictionary <string, Sketch> templates) { this.N = n; this.Size = size; this.Origin = point; this.Templates = templates; }
public bool Contains(SketchPoint point) { double x = point.X; double y = point.Y; return(x < MaxX && x > MinX && y < MaxX && y > MinY); }
private static bool IsLine(SketchStroke stroke, int i1, int i2) { SketchPoint p1 = stroke.Points[i1]; SketchPoint p2 = stroke.Points[i2]; return(MathHelpers.EuclideanDistance(p1, p2) / SketchStrokeFeatureExtraction.PathLength(stroke, i1, i2) > LineValidationThreshold); }
public static SketchPoint Intersection(SketchStroke sketchStroke1, SketchStroke sketchStroke2) { double minDistance = double.MaxValue; int minDisIndex1 = 0; int minDisIndex2 = 0; List <SketchPoint> points1 = sketchStroke1.Points; List <SketchPoint> points2 = sketchStroke2.Points; for (int i = 0; i < points1.Count; i++) { SketchPoint point1 = points1[i]; for (int j = 0; j < points2.Count; j++) { SketchPoint point2 = points2[j]; double distance = MathHelpers.EuclideanDistance(point1, point2); if (distance < minDistance) { minDistance = distance; minDisIndex1 = i; minDisIndex2 = j; } } } if (minDistance > 30) { return(null); } return(new SketchPoint((points1[minDisIndex1].X + points2[minDisIndex2].X) / 2.0, (points1[minDisIndex1].Y + points2[minDisIndex2].Y) / 2.0)); }
public static List <SketchStroke> ScaleToFrame(Sketch sketch, double frameLength) { List <SketchStroke> result = new List <SketchStroke>(); double templateFrameWidth = sketch.FrameMaxX - sketch.FrameMinX; double templateFrameHeight = sketch.FrameMaxY - sketch.FrameMinY; foreach (SketchStroke origStroke in sketch.Strokes) { List <SketchPoint> origPoints = origStroke.Points; List <SketchPoint> scaledPoints = new List <SketchPoint>(); foreach (SketchPoint origPoint in origPoints) { double scaledX = origPoint.X / templateFrameWidth * frameLength; double scaledY = origPoint.Y / templateFrameHeight * frameLength; SketchPoint scaledPoint = new SketchPoint(scaledX, scaledY); scaledPoints.Add(scaledPoint); } SketchStroke scaledStroke = new SketchStroke(scaledPoints, origStroke.TimeStamp); result.Add(scaledStroke); } return(result); }
public static SketchStroke ResampleStroke(SketchStroke stroke, int n) { SketchStroke resampledStroke = new SketchStroke(); List <SketchPoint> points = new List <SketchPoint>(); List <long> timeStamp = new List <long>(); // Copies the points and timeStamps list of the initial stroke foreach (SketchPoint p in stroke.Points) { points.Add(p); } foreach (long t in stroke.TimeStamp) { timeStamp.Add(t); } double totalLength = SketchStrokeFeatureExtraction.PathLength(stroke); double increment = totalLength / (n - 1); double dist = 0; resampledStroke.AppendPoint(points[0]); for (int i = 1; i < points.Count; i++) { SketchPoint cur = points[i]; SketchPoint pre = points[i - 1]; double d = MathHelpers.EuclideanDistance(cur, pre); if (dist + d >= increment) { double qx = pre.X + ((increment - dist) / d) * (cur.X - pre.X); double qy = pre.Y + ((increment - dist) / d) * (cur.Y - pre.Y); SketchPoint q = new SketchPoint(qx, qy); resampledStroke.AppendPoint(q); points.Insert(i, q); dist = 0.0; } else { dist = dist + d; } } int oldTimeCount = timeStamp.Count; int newTimeCount = resampledStroke.Points.Count; for (int j = 0; j < newTimeCount; ++j) { int index = (int)((double)j / newTimeCount * oldTimeCount); resampledStroke.AppendTime(timeStamp[index]); } return(resampledStroke); }
private void StrokeIntersectionPlayButton_Click(object sender, RoutedEventArgs e) { if (!this.techAssessor.IsCorrectStrokeCount) { return; } this.AnimationCanvas.Children.Clear(); int[] correspondance = this.techAssessor.StrokeToStrokeCorrespondenceSameCount; string[,] sampleIntersections = this.techAssessor.SampleIntersectionMatrix; string[,] templateIntersections = this.techAssessor.TemplateIntersectionMatrix; for (int i = 0; i < sampleIntersections.GetLength(0); i++) { for (int j = 0; j < sampleIntersections.GetLength(0); j++) { if (i == j) { continue; } if (sampleIntersections[i, j] != templateIntersections[i, j]) { int realI = 0; int realJ = 0; for (int index = 0; index < correspondance.GetLength(0); index++) { if (correspondance[index] == i) { realI = index; } if (correspondance[index] == j) { realJ = index; } } SketchPoint intersection = SketchStrokeFeatureExtraction.Intersection(this.sketchStrokes[realI], this.sketchStrokes[realJ]); if (intersection != null) { InteractionTools.HighlightWrongIntersection(this.AnimationCanvas, intersection); } else { InteractionTools.HighlightStrokes(this.AnimationCanvas, this.WritingInkCanvas, realI, realJ); } } } } }
public static double TrioDistance(SketchStroke strokeA, SketchStroke strokeB) { SketchPoint startA = strokeA.StartPoint; SketchPoint startB = strokeB.StartPoint; SketchPoint midA = strokeA.MidPoint; SketchPoint midB = strokeB.MidPoint; SketchPoint endA = strokeA.EndPoint; SketchPoint endB = strokeB.EndPoint; return(MathHelpers.EuclideanDistance(startA, startB) + MathHelpers.EuclideanDistance(midA, midB) + MathHelpers.EuclideanDistance(endA, endB)); }
public static void HighlightWrongIntersection(Canvas animationCanvas, SketchPoint intersection) { Ellipse circle = new Ellipse() { Height = 50, Width = 50, Stroke = new SolidColorBrush(Colors.Red), StrokeThickness = 10, }; Canvas.SetLeft(circle, intersection.X - circle.Width / 2); Canvas.SetTop(circle, intersection.Y - circle.Height / 2); animationCanvas.Children.Add(circle); }
public static List <SketchStroke> Translate(List <SketchStroke> strokes, SketchPoint origin, SketchPoint centroid) { List <SketchStroke> newStrokes = new List <SketchStroke>(); foreach (SketchStroke stroke in strokes) { List <SketchPoint> newPoints = new List <SketchPoint>(); foreach (SketchPoint point in stroke.Points) { newPoints.Add(new SketchPoint(point.X + origin.X - centroid.X, point.Y + origin.Y - centroid.Y)); } SketchStroke newStroke = new SketchStroke(newPoints, stroke.TimeStamp); newStrokes.Add(newStroke); } return(newStrokes); }
public static string IntersectionRelationship(SketchStroke sketchStroke1, SketchStroke sketchStroke2) { SketchPoint closestPoint = Intersection(sketchStroke1, sketchStroke2); if (closestPoint == null) { return("none"); } if (MathHelpers.EuclideanDistance(closestPoint, sketchStroke1.StartPoint) < 40) { return("touch head"); } if (MathHelpers.EuclideanDistance(closestPoint, sketchStroke1.EndPoint) < 40) { return("touch tail"); } return("cross"); }
public static double Distance(List <SketchPoint> alphaPoints, List <SketchPoint> betaPoints) { double distances = 0.0; var pairs = new List <Tuple <SketchPoint, SketchPoint> >(); double minDistance, weight, distance; int index; SketchPoint minPoint = betaPoints[0]; foreach (SketchPoint alphaPoint in alphaPoints) { minDistance = Double.MaxValue; // iterate through each beta point to find the min beta point to the alpha point index = 1; foreach (SketchPoint betaPoint in betaPoints) { distance = MathHelpers.EuclideanDistance(alphaPoint, betaPoint); // update the min distance and min point if (minDistance > distance) { minDistance = distance; minPoint = betaPoint; } } // update distance between alpha and beta point lists weight = 1 - ((index - 1) / alphaPoints.Count); distances += minDistance * weight; // pair the alpha point to the min beta point and remove min beta point from list of beta points pairs.Add(new Tuple <SketchPoint, SketchPoint>(alphaPoint, minPoint)); betaPoints.Remove(minPoint); } return(distances); }
public static double StartToEndSlope(SketchStroke stroke) { SketchPoint start = stroke.StartPoint; SketchPoint end = stroke.EndPoint; if (start.X == end.X) { if (end.Y >= start.Y) { return(double.PositiveInfinity); } else { return(double.NegativeInfinity); } } else { return((end.Y - start.Y) / (end.X - start.X)); } }
public static async Task <Sketch> XMLToSketch(StorageFile file) { string text = await FileIO.ReadTextAsync(file); XDocument document = XDocument.Parse(text); int minX = Int32.Parse(document.Root.Attribute("frameMinX").Value); int maxX = Int32.Parse(document.Root.Attribute("frameMaxX").Value); int minY = Int32.Parse(document.Root.Attribute("frameMinY").Value); int maxY = Int32.Parse(document.Root.Attribute("frameMaxY").Value); string label = document.Root.Attribute("label").Value; List <SketchStroke> strokes = new List <SketchStroke>(); // Itereates through each stroke element foreach (XElement element in document.Root.Elements()) { // Initializes the stroke SketchStroke stroke = new SketchStroke(); // Iterates through each point element double x, y; long t; foreach (XElement pointElement in element.Elements()) { x = Double.Parse(pointElement.Attribute("x").Value); y = Double.Parse(pointElement.Attribute("y").Value); t = Int64.Parse(pointElement.Attribute("time").Value); SketchPoint point = new SketchPoint(x, y); stroke.AppendPoint(point); stroke.AppendTime(t); } strokes.Add(stroke); } return(new Sketch(minX, maxX, minY, maxY, label, strokes)); }
public static double EuclideanDistance(SketchPoint p1, SketchPoint p2) { return(Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2))); }
public static List <SketchStroke> TranslateCentroid(List <SketchStroke> strokes, SketchPoint origin) { return(Translate(strokes, origin, SketchFeatureExtraction.Centroid(strokes))); }
private static bool IsInsideBoard(SketchPoint point, int length) { return(IsInsideBoard((int)point.X, (int)point.Y, length)); }
public void AppendPoint(SketchPoint p) { this.points.Add(p); }
public static List <SketchStroke> Normalize(List <SketchStroke> strokes, int n, double size, SketchPoint origin) { List <SketchStroke> sampleCopy = new List <SketchStroke>(); foreach (SketchStroke orig in strokes) { sampleCopy.Add(SketchStroke.Copy(orig)); } List <SketchStroke> resampled = Resample(sampleCopy, n); List <SketchStroke> scaled = ScaleSquare(resampled, size); List <SketchStroke> translated = TranslateCentroid(scaled, origin); return(translated); }
public static async void SketchToXml(StorageFile file, string label, string userName, string userMotherLanguage, string userFluency, double frameMinX, double frameMinY, double frameMaxX, double frameMaxY, List <SketchStroke> strokes) { // create the string writer as the streaming source of the XML data string output = ""; using (StringWriter stringWriter = new StringWriter()) { // set the string writer as the streaming source for the XML writer using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter)) { // <xml> xmlWriter.WriteStartDocument(); // <sketch> xmlWriter.WriteStartElement("sketch"); xmlWriter.WriteAttributeString("label", label); xmlWriter.WriteAttributeString("name", userName); xmlWriter.WriteAttributeString("motherlanguage", userMotherLanguage); xmlWriter.WriteAttributeString("fluency", userFluency); xmlWriter.WriteAttributeString("frameMinX", "" + frameMinX); xmlWriter.WriteAttributeString("frameMinY", "" + frameMinY); xmlWriter.WriteAttributeString("frameMaxX", "" + frameMaxX); xmlWriter.WriteAttributeString("frameMaxY", "" + frameMaxY); // iterate through each stroke for (int i = 0; i < strokes.Count; i++) { // <stroke> xmlWriter.WriteStartElement("stroke"); // get the current stroke's points and times List <SketchPoint> points = strokes[i].Points; List <long> times = strokes[i].TimeStamp; // for (int j = 0; j < points.Count; ++j) { SketchPoint point = points[j]; long time = times[j]; // TODO: FIX! // <point> xmlWriter.WriteStartElement("point"); xmlWriter.WriteAttributeString("x", "" + point.X); xmlWriter.WriteAttributeString("y", "" + point.Y); xmlWriter.WriteAttributeString("time", "" + times[j]); // </point> xmlWriter.WriteEndElement(); } // </stroke> xmlWriter.WriteEndElement(); } // </sketch> xmlWriter.WriteEndElement(); // </xml> xmlWriter.WriteEndDocument(); } output = stringWriter.ToString(); } await FileIO.WriteTextAsync(file, output); }
public VisionAssessor(List <SketchStroke> sample, int sampleFrameLength, List <SketchStroke> template, int templateFrameLength) { bool[,] sampleArray = VisionFeatureExtraction.SketchToArray(sample, sampleFrameLength); bool[,] templateArray = VisionFeatureExtraction.SketchToArray(template, templateFrameLength); bool[,] sampleArrayScaled = VisionFeatureExtraction.Scale(sampleArray, ScaledFrameSize); bool[,] templateArrayScaled = VisionFeatureExtraction.Scale(templateArray, ScaledFrameSize); SketchPoint sampleCentroid = VisionFeatureExtraction.Centroid(sampleArrayScaled); SketchPoint templateCentroid = VisionFeatureExtraction.Centroid(templateArrayScaled); BoundingBox sampleBoundingBox = VisionFeatureExtraction.BoundingRectangle(sampleArrayScaled); BoundingBox templateBoundingBox = VisionFeatureExtraction.BoundingRectangle(templateArrayScaled); double sampleHeight = sampleBoundingBox.Height; double templateHeight = templateBoundingBox.Height; double sampleWidth = sampleBoundingBox.Width; double templateWidth = templateBoundingBox.Width; int[] sampleProjectionX = VisionFeatureExtraction.VerticalProjection(sampleArrayScaled); int[] sampleProjectionY = VisionFeatureExtraction.HorizontalProjection(sampleArrayScaled); int[] templateProjectionX = VisionFeatureExtraction.VerticalProjection(templateArrayScaled); int[] templateProjectionY = VisionFeatureExtraction.HorizontalProjection(templateArrayScaled); double fc = Math.Sqrt(Math.Pow(sampleCentroid.X - templateCentroid.X, 2) + Math.Pow(sampleCentroid.Y - templateCentroid.Y, 2)) / (0.5 * sampleArrayScaled.GetLength(1)); double fa = (sampleWidth * sampleHeight - templateWidth * templateHeight) / (templateWidth * templateHeight); double fr = (sampleWidth / sampleHeight - templateWidth / templateHeight); double dx = VisionFeatureExtraction.ProjectionDifference(sampleProjectionX, templateProjectionX); double dy = VisionFeatureExtraction.ProjectionDifference(sampleProjectionY, templateProjectionY); double fs = VisionFeatureExtraction.SymmetryFeature(sampleProjectionX, templateProjectionX); double muonNear = Fuzzy.Gamma(fc, 0.1, 0.9); double muonFar = Fuzzy.Lambda(fc, 0.1, 0.9); double muonSmall = Fuzzy.Gamma(fa, -1, 0); double muonProperSize = Fuzzy.Delta(fa, -0.4, 0, 0.4); double muonLarge = Fuzzy.Lambda(fa, 0, 1); double muonTall = Fuzzy.Gamma(fr, -0.5, 0); double muonProperRatio = Fuzzy.Delta(fr, -0.166667, 0, 0.166667); double muonShort = Fuzzy.Lambda(fr, 0, 0.5); double muonLessX = Fuzzy.Gamma(dx, 0.1, 0.9); double muonMuchX = Fuzzy.Lambda(dx, 0.1, 0.9); double muonLessY = Fuzzy.Gamma(dy, 0.1, 0.9); double muonMuchY = Fuzzy.Lambda(dy, 0.1, 0.9); double muonLeft = Fuzzy.Gamma(fs, -1, 0); double muonProperSymmetry = Fuzzy.Delta(fs, -0.4, 0, 0.4); double muonRight = Fuzzy.Lambda(fs, 0, 1); double sc = muonNear > muonFar?Fuzzy.CenterOfAreaHigh(0.1, 0.9, muonNear) : Fuzzy.CenterOfAreaLow(0.1, 0.9, muonFar); double sa = muonProperSize > Math.Max(muonSmall, muonLarge) ? Fuzzy.CenterOfAreaHigh(0.6, 0.9, muonProperSize) : Fuzzy.CenterOfAreaLow(0.1, 0.9, Math.Max(muonSmall, muonLarge)); double sr = muonProperRatio > Math.Max(muonTall, muonShort) ? Fuzzy.CenterOfAreaHigh(0.8, 0.9, muonProperRatio) : Fuzzy.CenterOfAreaLow(0.5, 0.9, Math.Max(muonTall, muonShort)); double sdx = muonLessX > muonMuchX?Fuzzy.CenterOfAreaHigh(0.1, 0.9, muonLessX) : Fuzzy.CenterOfAreaLow(0.1, 0.9, muonMuchX); double sdy = muonLessY > muonMuchY?Fuzzy.CenterOfAreaHigh(0.1, 0.9, muonMuchY) : Fuzzy.CenterOfAreaLow(0.1, 0.9, muonMuchY); double ss = muonProperSymmetry > Math.Max(muonLeft, muonRight) ? Fuzzy.CenterOfAreaHigh(0.6, 0.9, muonProperSymmetry) : Fuzzy.CenterOfAreaLow(0.1, 0.9, Math.Max(muonLeft, muonRight)); double s1 = sc; double s2 = (sa + sr) / 2.0; double s3 = (sdx + sdy) / 2.0; double muonLocationVeryLow = Fuzzy.Gamma(s1, 0.3, 0.4); double muonLocationLow = Fuzzy.Delta(s1, 0.3, 0.4, 0.5); double muonLocationAverage = Fuzzy.Delta(s1, 0.4, 0.5, 0.6); double muonLocationHigh = Fuzzy.Delta(s1, 0.5, 0.6, 0.7); double muonLocationVeryHigh = Fuzzy.Lambda(s1, 0.6, 0.7); double muonShapeVeryLow = Fuzzy.Gamma(s2, 0.3, 0.4); double muonShapeLow = Fuzzy.Delta(s2, 0.3, 0.4, 0.5); double muonShapeAverage = Fuzzy.Delta(s2, 0.4, 0.5, 0.6); double muonShapeHigh = Fuzzy.Delta(s2, 0.5, 0.6, 0.7); double muonShapeVeryHigh = Fuzzy.Lambda(s2, 0.6, 0.7); double muonProjectionVeryLow = Fuzzy.Gamma(s2, 0.3, 0.4); double muonProjectionLow = Fuzzy.Delta(s2, 0.3, 0.4, 0.5); double muonProjectionAverage = Fuzzy.Delta(s2, 0.4, 0.5, 0.6); double muonProjectionHigh = Fuzzy.Delta(s2, 0.5, 0.6, 0.7); double muonProjectionVeryHigh = Fuzzy.Lambda(s2, 0.6, 0.7); LocationFeedback = getFeedback(muonLocationVeryLow, muonLocationLow, muonLocationAverage, muonLocationHigh, muonLocationVeryHigh); ShapeFeedback = getFeedback(muonShapeVeryLow, muonShapeLow, muonShapeAverage, muonShapeHigh, muonShapeVeryHigh); ProjectionFeedback = getFeedback(muonProjectionVeryLow, muonProjectionLow, muonProjectionAverage, muonProjectionHigh, muonProjectionVeryHigh); }