/// <summary> /// Adds a new example to the list of templates. /// </summary> /// <param name="label">Class name/label for the shape</param> /// <param name="strokes">List of strokes in the shape</param> public virtual BitmapSymbol Add(ShapeType label, List <Substroke> strokes, System.Drawing.Bitmap bitmap) { if (label.Classification != LogicDomain.GATE_CLASS) { return(new BitmapSymbol()); } BitmapSymbol bs = new BitmapSymbol(strokes, label, bitmap); // give the BitmapSymbol a unique name int templateCount = 0; List <string> alreadySeen = new List <string>(); foreach (BitmapSymbol template in _templates) { alreadySeen.Add(template.Name); } while (alreadySeen.Contains(bs.SymbolType + "_" + templateCount)) { ++templateCount; } bs.Name = bs.SymbolType + "_" + templateCount; if (debug) { Console.WriteLine("Adding template " + bs.Name); } _templates.Add(bs); return(bs); }
public ImageResultSubForm(BitmapSymbol unknown, ImageScore template) { InitializeComponent(); ImageScore score = template; labelNames.Text = score.SymbolClass + ": " + score.SymbolType; labelHausdorff.Text += score.HausdorfScore.ToString("#0.000"); labelModifiedHausdorff.Text += score.ModifiedHausdorfScore.ToString("#0.000"); labelTanimoto.Text += score.TanimotoScore.ToString("#0.000"); labelYule.Text += score.YuleScore.ToString("#0.000"); labelUserName.Text += score.UserName; labelCompleteness.Text += score.Completeness.ToString(); labelPlatform.Text += score.Platform.ToString(); InkOverlay ink = new InkOverlay(panelInk); foreach (Point[] pts in unknown.Points) { ink.Ink.CreateStroke(pts); ink.Ink.Strokes[ink.Ink.Strokes.Count - 1].DrawingAttributes.Color = Color.Blue; } ScaleAndMoveInk(ref ink); InkOverlay symbolInk = new InkOverlay(panelInk); List <Point[]> strokes = score.TemplateSymbol.Points; foreach (Point[] points in strokes) { symbolInk.Ink.CreateStroke(points); symbolInk.Ink.Strokes[symbolInk.Ink.Strokes.Count - 1].DrawingAttributes.Color = Color.Red; } ScaleAndMoveInk(ref symbolInk); }
/// <summary> /// Adds a new example to the list of templates. /// </summary> /// <param name="label">Class name/label for the shape</param> /// <param name="strokes">List of strokes in the shape</param> public override BitmapSymbol Add(ShapeType label, List <Substroke> strokes, System.Drawing.Bitmap bitmap) { BitmapSymbol bs = base.Add(label, strokes, bitmap); _templateUsage[bs.SymbolType].Add(bs, 0); // If bs.SymbolType is not in the dictionary, just cry. return(bs); }
/// <summary> /// Recognizes the given strokes. Used by ComboRecognizer. /// </summary> /// <param name="strokes">The list of strokes to recognize</param> /// <returns>A ranked list of possible ShapeType matches</returns> public List <ShapeType> Recognize(List <Substroke> strokes) { BitmapSymbol unknown = new BitmapSymbol(strokes); List <SymbolRank> results = unknown.Recognize(_templates); List <ShapeType> output = new List <ShapeType>(); foreach (SymbolRank sr in results) { output.Add(sr.SymbolType); } return(output); }
/// <summary> /// Update the recognizer to learn from an example shape. /// /// Precondition: shape has a valid type /// </summary> /// <param name="shape">the shape to learn</param> public override void learnFromExample(Sketch.Shape shape) { // If we made a mistake in recognition, make note of that BitmapSymbol bs = base.findTemplate(shape.TemplateName); if (bs != null && bs.SymbolType != shape.Type) { _templateUsage[bs.SymbolType][bs] -= errorSubtraction; } // Update the list of templates accordingly removeExample(shape.Type); Add(shape.Type, shape.SubstrokesL, shape.createBitmap(100, 100, true)); }
private void FillLabels(List <Sketch.Substroke> strokes, Dictionary <string, List <SymbolRank> > SRs) { string name = SRs["Fusio"][0].SymbolName; double distance = SRs["Fusio"][0].Distance; label1.Text = name + " Score: " + distance.ToString("#0.00"); BitmapSymbol bestSymbol = SRs["Fusio"][0].Symbol; BitmapSymbol UnknownSymbol = new BitmapSymbol(strokes); UnknownSymbol.Process(); double[] scores = BitmapSymbol.Compare(bestSymbol, UnknownSymbol); label6.Text += scores[1].ToString("#0.00"); label7.Text += scores[2].ToString("#0.00"); label8.Text += scores[3].ToString("#0.00"); label9.Text += scores[4].ToString("#0.00"); if (SRs["Fusio"].Count > 1) { name = SRs["Fusio"][1].SymbolName; distance = SRs["Fusio"][1].Distance; label2.Text = name + " Score: " + distance.ToString("#0.00"); } if (SRs["Fusio"].Count > 2) { name = SRs["Fusio"][2].SymbolName; distance = SRs["Fusio"][2].Distance; label3.Text = name + " Score: " + distance.ToString("#0.00"); } if (SRs["Fusio"].Count > 3) { name = SRs["Fusio"][3].SymbolName; distance = SRs["Fusio"][3].Distance; label4.Text = name + " Score: " + distance.ToString("#0.00"); } if (SRs["Fusio"].Count > 4) { name = SRs["Fusio"][4].SymbolName; distance = SRs["Fusio"][4].Distance; label5.Text = name + " Score: " + distance.ToString("#0.00"); } }
public virtual void orient(Shape shape, Featurefy.FeatureSketch featureSketch) { ShapeType type = shape.Type; BitmapSymbol defn = new BitmapSymbol(); foreach (BitmapSymbol template in _templates) { if (template.SymbolType == type) { defn = template; break; } } BitmapSymbol unknown = new BitmapSymbol(shape.SubstrokesL); shape.Orientation = unknown.bestOrientation(defn); }
public VisualizeSearch(BitmapSymbol unknown, List <ImageScore> results) { InitializeComponent(); forms = new List <ImageResultSubForm>(); int count = 0; foreach (ImageScore r in results) { count++; ImageResultSubForm subFormChild = new ImageResultSubForm(unknown, r); subFormChild.MdiParent = this; subFormChild.Show(); forms.Add(subFormChild); } //this.LayoutMdi(MdiLayout.Cascade); }
/// <summary> /// Uses the RecognitionInterfaces.Recognizer recognize method /// which recognizes and assigns the type of a shape. This /// implementation allows the use of the learnFromExample /// method in Interface Functions. /// </summary> /// <param name="shape">The shape to recognize</param> /// <param name="featureSketch">The featureSketch to use</param> public override void recognize(Sketch.Shape shape, Featurefy.FeatureSketch featureSketch) { BitmapSymbol unknown = new BitmapSymbol(shape.SubstrokesL); List <SymbolRank> results = unknown.Recognize(_templates); if (results.Count > 0) { // Populate the dictionary of alterateTypes with all of the ShapeTypes in results Dictionary <ShapeType, double> alternateTypes = new Dictionary <ShapeType, double>(); if (debug) { Console.WriteLine("\nRecognition results: "); } foreach (SymbolRank result in results) { if (!alternateTypes.ContainsKey(result.SymbolType)) { alternateTypes.Add(result.SymbolType, getProbability(result.SymbolType, results)); } if (debug) { Console.WriteLine(result.SymbolType + " with template " + result.SymbolName); } } ShapeType type = results[0].SymbolType; // the most likely type float probability = (float)alternateTypes[type]; // grab the probability of our most likely type alternateTypes.Remove(type); // the most likely type is NOT an alternate shape.setRecognitionResults( type, probability, alternateTypes, results[0].BestOrientation, results[0].SymbolName); } }
/// <summary> /// Removes an example from the list of templates based on the values in _templateUsage. /// Only removes an example if there are already at least numTemplatesPerGate templates for /// the specificed ShapeType. /// </summary> /// <param name="type">The ShapeType you want to remove an example of. Must be a gate.</param> public void removeExample(ShapeType type) { // first check that you actually want to remove an example if (_templateUsage[type].Count < numTemplatesPerGate) { return; } // if they're all equally bad, remove the first one of that type in the list BitmapSymbol first = null; foreach (BitmapSymbol template in _templates) { if (template.SymbolType == type) { first = template; } } // lets us keep track of the worst template we've seen so far KeyValuePair <BitmapSymbol, int> worst = new KeyValuePair <BitmapSymbol, int>(first, _templateUsage[type][first]); // replace worst if we find a worse template foreach (BitmapSymbol template in _templateUsage[type].Keys) { if (_templateUsage[type][template] < worst.Value) { worst = new KeyValuePair <BitmapSymbol, int>(template, _templateUsage[type][template]); } } #if DEBUG Console.WriteLine("Removing template " + worst.Key.Name + " which has score " + worst.Value); #endif // actually remove the template from both members that know about it _templates.Remove(worst.Key); _templateUsage[type].Remove(worst.Key); }
public virtual void orient(Shape shape, Featurefy.FeatureSketch featureSketch) { ShapeType type = shape.Type; BitmapSymbol defn = new BitmapSymbol(); // TODO: should we use multiple templates, or just one? foreach (BitmapSymbol template in _templates) { if (template.SymbolType == type) { defn = template; break; } } BitmapSymbol unknown = _shapesToSymbols[shape]; shape.Orientation = unknown.bestOrientation(defn); #if JESSI Console.WriteLine("The final shape orientation is " + shape.Orientation); Console.WriteLine(); #endif }
private void Create2StrokeLR(string name, string leftName, string rightName) { if (m_InkOverlay.Ink.Strokes.Count != 2) { MessageBox.Show("Incorrect # of strokes present"); return; } Rectangle b0 = m_InkOverlay.Ink.Strokes[0].GetBoundingBox(); Rectangle b1 = m_InkOverlay.Ink.Strokes[1].GetBoundingBox(); Rectangle bLeft, bRight; Stroke msLeft, msRight; if (b0.Right < b1.Right) { msLeft = m_InkOverlay.Ink.Strokes[0]; msRight = m_InkOverlay.Ink.Strokes[1]; bLeft = b0; bRight = b1; } else { msLeft = m_InkOverlay.Ink.Strokes[1]; msRight = m_InkOverlay.Ink.Strokes[0]; bLeft = b1; bRight = b0; } Sketch.Substroke Left = m_Sketch.GetSketchSubstrokeByInkId(msLeft.Id); Sketch.Substroke Right = m_Sketch.GetSketchSubstrokeByInkId(msRight.Id); List <Sketch.Substroke> strokes = new List <Sketch.Substroke>(); strokes.Add(Left); strokes.Add(Right); Rectangle shapeBbox = m_InkOverlay.Ink.Strokes.GetBoundingBox(); BitmapSymbol complete = new BitmapSymbol(strokes); BitmapSymbol leftPartial = new BitmapSymbol(Left, shapeBbox); // bLeft); BitmapSymbol rightPartial = new BitmapSymbol(Right, shapeBbox); // bRight); complete.Name = name; complete.SymbolType = name; complete.SymbolClass = "Gate"; complete.Platform = PlatformUsed.TabletPC; complete.DrawTask = DrawingTask.Synthesize; complete.Completeness = SymbolCompleteness.Complete; leftPartial.Name = leftName; leftPartial.SymbolType = leftName; leftPartial.SymbolClass = "Gate"; leftPartial.Platform = PlatformUsed.TabletPC; leftPartial.DrawTask = DrawingTask.Synthesize; leftPartial.Completeness = SymbolCompleteness.Partial; rightPartial.Name = rightName; rightPartial.SymbolType = rightName; rightPartial.SymbolClass = "Gate"; rightPartial.Platform = PlatformUsed.TabletPC; rightPartial.DrawTask = DrawingTask.Synthesize; rightPartial.Completeness = SymbolCompleteness.Partial; m_CompleteSymbols.Add(complete); m_PartialSymbols.Add(leftPartial); m_PartialSymbols.Add(rightPartial); }
private void CreateOR3() { if (m_InkOverlay.Ink.Strokes.Count != 3) { MessageBox.Show("Incorrect # of strokes present"); return; } Rectangle b0 = m_InkOverlay.Ink.Strokes[0].GetBoundingBox(); Rectangle b1 = m_InkOverlay.Ink.Strokes[1].GetBoundingBox(); Rectangle b2 = m_InkOverlay.Ink.Strokes[2].GetBoundingBox(); Stroke msLeft, msTop, msBottom; Rectangle bLeft, bTop, bBottom; if (b0.Right < b1.Right && b0.Right < b2.Right) { msLeft = m_InkOverlay.Ink.Strokes[0]; bLeft = b0; if (b1.Top > b2.Top) { msTop = m_InkOverlay.Ink.Strokes[1]; msBottom = m_InkOverlay.Ink.Strokes[2]; bTop = b1; bBottom = b2; } else { msTop = m_InkOverlay.Ink.Strokes[2]; msBottom = m_InkOverlay.Ink.Strokes[1]; bTop = b2; bBottom = b1; } } else if (b1.Right < b2.Right && b1.Right < b0.Right) { msLeft = m_InkOverlay.Ink.Strokes[1]; bLeft = b1; if (b0.Top > b2.Top) { msTop = m_InkOverlay.Ink.Strokes[0]; msBottom = m_InkOverlay.Ink.Strokes[2]; bTop = b0; bBottom = b2; } else { msTop = m_InkOverlay.Ink.Strokes[2]; msBottom = m_InkOverlay.Ink.Strokes[0]; bTop = b2; bBottom = b0; } } else { msLeft = m_InkOverlay.Ink.Strokes[2]; bLeft = b2; if (b0.Top > b1.Top) { msTop = m_InkOverlay.Ink.Strokes[0]; msBottom = m_InkOverlay.Ink.Strokes[1]; bTop = b0; bBottom = b1; } else { msTop = m_InkOverlay.Ink.Strokes[1]; msBottom = m_InkOverlay.Ink.Strokes[0]; bTop = b1; bBottom = b0; } } Sketch.Substroke Left = m_Sketch.GetSketchSubstrokeByInkId(msLeft.Id); Sketch.Substroke Top = m_Sketch.GetSketchSubstrokeByInkId(msTop.Id); Sketch.Substroke Bottom = m_Sketch.GetSketchSubstrokeByInkId(msBottom.Id); List <Sketch.Substroke> strokes = new List <Sketch.Substroke>(); strokes.Add(Left); strokes.Add(Top); strokes.Add(Bottom); Rectangle shapeBbox = m_InkOverlay.Ink.Strokes.GetBoundingBox(); BitmapSymbol complete = new BitmapSymbol(strokes); BitmapSymbol leftPartial = new BitmapSymbol(Left, shapeBbox); // bLeft); BitmapSymbol topPartial = new BitmapSymbol(Top, shapeBbox); // bTop); BitmapSymbol bottomPartial = new BitmapSymbol(Bottom, shapeBbox); // bBottom); complete.Name = "OR_3"; complete.SymbolType = "OR_3"; complete.SymbolClass = "Gate"; complete.Platform = PlatformUsed.TabletPC; complete.DrawTask = DrawingTask.Synthesize; complete.Completeness = SymbolCompleteness.Complete; leftPartial.Name = "OR_3-Left"; leftPartial.SymbolType = "OR_3-Left"; leftPartial.SymbolClass = "Gate"; leftPartial.Platform = PlatformUsed.TabletPC; leftPartial.DrawTask = DrawingTask.Synthesize; leftPartial.Completeness = SymbolCompleteness.Partial; topPartial.Name = "OR_3-topRight"; topPartial.SymbolType = "OR_3-topRight"; topPartial.SymbolClass = "Gate"; topPartial.Platform = PlatformUsed.TabletPC; topPartial.DrawTask = DrawingTask.Synthesize; topPartial.Completeness = SymbolCompleteness.Partial; bottomPartial.Name = "OR_3-bottomRight"; bottomPartial.SymbolType = "OR_3-bottomRight"; bottomPartial.SymbolClass = "Gate"; bottomPartial.Platform = PlatformUsed.TabletPC; bottomPartial.DrawTask = DrawingTask.Synthesize; bottomPartial.Completeness = SymbolCompleteness.Partial; m_CompleteSymbols.Add(complete); m_PartialSymbols.Add(leftPartial); m_PartialSymbols.Add(topPartial); m_PartialSymbols.Add(bottomPartial); }
public ClusterForm(Strokes strokes, List <Sketch.Substroke> substrokes, Dictionary <string, List <SymbolRank> > SRs, BitmapSymbol Unknown) { InitializeComponent(); InkPanel.Enabled = true; _OverlayInk = new Microsoft.Ink.InkOverlay(); _OverlayInk.AttachedControl = InkPanel; _OverlayInk.Enabled = false; FillInkOverlay(strokes); FillLabels(substrokes, SRs); }
/// <summary> /// Recognize a shape as if it had the given type /// </summary> /// <param name="symbol"></param> /// <param name="types"></param> /// <returns></returns> public Dictionary <ShapeType, RecognitionInterfaces.RecognitionResult> RecognitionResults(BitmapSymbol symbol, IEnumerable <ShapeType> types) { if (_templates.Count == 0) { throw new Exception("Cannot recognize a symbol when there are no available templates"); } var recResults = new Dictionary <ShapeType, RecognitionInterfaces.RecognitionResult>(); RecoResult allResults = symbol.Recognize(_templates); List <SymbolRank> results = allResults.SortedResults(ResultType.FUSION); if (results.Count == 0) { throw new Exception("Image recognition failed on bitmap symbol " + symbol); } Dictionary <ShapeType, double> alternateTypes = new Dictionary <ShapeType, double>(); // Loop through them from most-likely to least-likely. foreach (SymbolRank result in results) { if (!recResults.ContainsKey(result.SymbolType)) { double partialHausdorff = allResults.getSR(ResultType.PARTIAL_HAUSDORFF, result.Symbol).Distance; double modHausdorff = allResults.getSR(ResultType.MOD_HAUSDORFF, result.Symbol).Distance; double yule = allResults.getSR(ResultType.YULE, result.Symbol).Distance; double tanimoto = allResults.getSR(ResultType.TANIMOTO, result.Symbol).Distance; ImageRecognitionResult r = new ImageRecognitionResult( result.SymbolType, partialHausdorff, modHausdorff, yule, tanimoto, getProbabilityFromTotalDistance(result), result.BestOrientation, alternateTypes, result.SymbolName, result.Symbol.toBitmap()); recResults.Add(result.SymbolType, r); } if (!alternateTypes.ContainsKey(result.SymbolType)) { alternateTypes.Add(result.SymbolType, getProbabilityFromTotalDistance(result)); } } foreach (ShapeType type in types) { if (!recResults.ContainsKey(type)) { recResults.Add(type, new ImageRecognitionResult( type, 0, 0, 0, 0, 0, 0, new Dictionary <ShapeType, double>(), "", null)); } } return(recResults); }
/// <summary> /// Recognize a shape. /// </summary> /// <param name="shape"></param> /// <param name="featureSketch"></param> /// <returns>An ImageRecognitionResult. If you know you are dealing with an ImageRecognizer, you can cast the returned /// RecognitionResult to an ImageRecognitionResult safely.</returns> public override RecognitionInterfaces.RecognitionResult recognize(Sketch.Shape shape, Featurefy.FeatureSketch featureSketch) { // Gaaghaghagahga // C# has one flaw, and I found it: // http://www.simple-talk.com/community/blogs/simonc/archive/2010/07/14/93495.aspx // In short, this method must return a generic "RecognitionResult" and cannot return // the better "ImageRecognitionResult," even though doing so would be perfectly // type-safe. =( BitmapSymbol unknown = _shapesToSymbols[shape]; RecoResult allResults = unknown.Recognize(_templates); List <SymbolRank> results = allResults.SortedResults(ResultType.FUSION); if (results.Count > 0) { // Populate the dictionary of alterateTypes with all of the ShapeTypes in results var alternateTypes = new Dictionary <ShapeType, double>(); #if JESSI Console.WriteLine(); Console.WriteLine("\nRecognition results: "); #endif foreach (SymbolRank result in results) { if (!alternateTypes.ContainsKey(result.SymbolType)) { alternateTypes.Add(result.SymbolType, getProbabilityFromTotalDistance(result)); } #if JESSI if (debug) { Console.WriteLine(result.SymbolType + " with template " + result.SymbolName); } #endif } ShapeType type = results[0].SymbolType; // the most likely type float probability = (float)alternateTypes[type]; // grab the probability of our most likely type alternateTypes.Remove(type); // the most likely type is NOT an alternate double confidence = getProbabilityFromTotalDistance(results[0]); double orientation = results[0].BestOrientation; string templateName = results[0].SymbolName; System.Drawing.Bitmap templateBitmap = results[0].Symbol.toBitmap(); double partialHausdorff = allResults.getSR(ResultType.PARTIAL_HAUSDORFF, results[0].Symbol).Distance; double modHausdorff = allResults.getSR(ResultType.MOD_HAUSDORFF, results[0].Symbol).Distance; double yule = allResults.getSR(ResultType.YULE, results[0].Symbol).Distance; double tanimoto = allResults.getSR(ResultType.TANIMOTO, results[0].Symbol).Distance; return(new ImageRecognitionResult( type, partialHausdorff, modHausdorff, yule, tanimoto, confidence, orientation, alternateTypes, templateName, templateBitmap)); } throw new Exception("Image recognition failed on shape " + shape); }