/// <summary>
        /// Connects all shapes in a sketch as well as possible.
        ///
        /// Precondition: the shapes of the sketch have identified types.
        ///
        /// Postconditions:
        ///    - the shapes are connected and oriented according to the context domain.
        ///    - no wires are connected to each other; connected wires are a single shape
        /// </summary>
        /// <param name="featureSketch">the sketch to connect</param>
        public virtual void process(Featurefy.FeatureSketch featureSketch)
        {
            recomputeConnectedShapes(featureSketch.Sketch.Shapes, featureSketch.Sketch);

            //foreach (Sketch.Shape shape in featureSketch.Sketch.ShapesL)
            //_domain.OrientShape(shape, featureSketch.Sketch);
        }
Exemple #2
0
        /// <summary>
        /// Uses WEKA to decide if each pair of strokes should be joined, then merges the paired strokes into shapes.
        /// </summary>
        public override void group(Featurefy.FeatureSketch featureSketch)
        {
            // Compile the substroke classification dictionary.
            Dictionary <Substroke, string> strokeClassifications = new Dictionary <Substroke, string>();

            foreach (Substroke s in featureSketch.Sketch.Substrokes)
            {
                strokeClassifications.Add(s, s.Classification);
            }

            // Calculate pairwise feature values.
            Dictionary <string, Dictionary <FeatureStrokePair, double[]> > pairwiseValuesPerClass = featureSketch.GetValuesPairwise(strokeClassifications);

            List <StrokePair> pairsToJoin = groupWithWeka(pairwiseValuesPerClass);

            // Using the results from the StrokeGrouper,
            // make shapes by combining joined strokes.
            try
            {
                makeShapes(pairsToJoin, featureSketch.Sketch);
            }
            catch (NullReferenceException nre)
            {
                Console.WriteLine("Cannot call makeShapes(). \n" + nre.Message);
            }
        }
Exemple #3
0
 /// <summary>
 /// Sets up the caches for a given featureSketch. This step is very important, since without caching
 /// the search refiner is intolerably slow.
 /// </summary>
 /// <param name="featureSketch"></param>
 public virtual void Start(Featurefy.FeatureSketch featureSketch)
 {
     _classifications = new SmartCache <Substroke, string>(
         s => {
         return(_classifier.classify(s, featureSketch));
     });
     _identificationResults = new Dictionary <SubstrokeCollection, Dictionary <ShapeType, RecognitionResult> >();
 }
Exemple #4
0
        /// <summary>
        /// Loads a Sketch into the InkSketch
        /// </summary>
        /// <param name="sketch">The sketch to load</param>
        /// Precondition: The InkSketch is clean (all dictionaries cleared etc)
        /// Postcondition: The InkSketch has the proper data members
        public StrokeCollection LoadSketch(Sketch.Sketch sketch)
        {
            project.sketch = sketch;
            featureSketch  = FeatureSketch.MakeFeatureSketch(project);
            setUserSpecified();

            return(CreateInkStrokesFromSketch());
        }
Exemple #5
0
        /// <summary>
        /// Clears out the internal data structures for loading
        /// </summary>
        public void Clear()
        {
            createEmptySketch();
            featureSketch = FeatureSketch.MakeFeatureSketch(project);

            ink2sketchStr.Clear();
            sketchStr2ink.Clear();
            substrokeIdMap.Clear();
        }
Exemple #6
0
        /// <summary>
        /// Suppose that the given substrokes form a shape. What is the most likely type for it?
        /// </summary>
        /// <param name="substrokes"></param>
        /// <param name="featureSketch"></param>
        /// <returns></returns>
        private RecognitionResult Identify(SubstrokeCollection substrokes, Featurefy.FeatureSketch featureSketch)
        {
            RecognitionResult best = null;

            foreach (ShapeType type in LogicDomain.Types)
            {
                RecognitionResult result = RecognizeAsType(substrokes, type, featureSketch);
                double            prob   = result.Confidence;
                if (best == null || prob > best.Confidence)
                {
                    best = result;
                }
            }
            return(best);
        }
Exemple #7
0
        /// <summary>
        /// Constructor for testing (where we pass in an initialized featureSketch)
        /// </summary>
        /// <param name="inkCanvas"></param>
        /// <param name="featureSketch"></param>
        public InkCanvasSketch(InkCanvas inkCanvas, FeatureSketch featureSketch)
        {
            this.inkCanvas     = inkCanvas;
            this.featureSketch = featureSketch;

            // Don't have a circuit yet
            this.circuit  = null;
            alreadyLoaded = new List <string>();

            project = new Sketch.Project();
            // Comply with XML format requirements
            dtGuid       = new Guid(dtGuidString);
            idGuid       = new Guid(idGuidString);
            Sketch.Units = DefaultSketchUnits;

            // Intialize other fields
            ink2sketchStr  = new Dictionary <String, Guid?>();
            sketchStr2ink  = new Dictionary <Guid?, String>();
            substrokeIdMap = new Dictionary <Guid?, Substroke>();
        }
Exemple #8
0
        public strokeInfoForm(Featurefy.FeatureStroke strokeFeatures, Featurefy.FeatureSketch sketchFeatures, Microsoft.Ink.Stroke inkStroke, Substroke ss)
        {
            InitializeComponent();
            this.inkMovedX = 0.0f;
            this.inkMovedY = 0.0f;
            this.scale     = 2.0f;

            pictureInk        = new InkPicture();
            pictureInk.Bounds = new Rectangle(0, 0, this.Width - dataView.Width, this.Height);
            Controls.Add(pictureInk);
            r = new Renderer();
            g = this.pictureInk.CreateGraphics();
            pictureInk.Painted += new InkOverlayPaintedEventHandler(pictureInk_Painted);

            _sketchFeatures = sketchFeatures;
            _strokeFeatures = strokeFeatures;
            _inkStroke      = inkStroke;
            _substroke      = ss;

            this.pictureInk.Ink.CreateStroke(_inkStroke.GetPoints());
            this.pictureInk.Ink.Strokes[0].DrawingAttributes.Color = Color.Red;
            populateListView();
            //drawPrimitives(this.features);
        }
Exemple #9
0
        public List <SketchModification> SketchModifications(Featurefy.FeatureSketch featureSketch)
        {
            Sketch.Sketch sketch = featureSketch.Sketch;

            if (debug)
            {
                Console.WriteLine("Sketch Modifications:");
            }

            // Used to assemble the list of results
            List <SketchModification> results = new List <SketchModification>();

            // Precompute closest contexts for each shape
            Dictionary <Shape, Tuple <double, ConnectionContext> > closestContexts = new Dictionary <Shape, Tuple <double, ConnectionContext> >();

            foreach (Shape shape in sketch.Shapes)
            {
                closestContexts.Add(shape, _domain.ClosestContext(shape));
            }

            // ==========================================================================================================

            /*
             * Operation zero: running the connector is ALWAYS an option.
             */

            //results.Add(new SketchModification(sketch, new RunConnectorOperation(featureSketch, _connector), computeEnergy));

            // ==========================================================================================================

            /*
             * First things first: missing connections
             * This takes care of obvious connector problems. If there is a wire with a dangling endpoint and a
             * shape that would be better off connected to a wire, we make that connection. The benefit is:
             *    benefit = 1 / distance
             * where "distance" is the minimum distance from the dangling endpoint to the shape. This will favor
             * close connections over distant ones.
             */

            List <EndPoint> wiresMissingConnections        = findWireEndpointsMissingConnections(sketch);
            List <Shape>    nonWiresMissingWireConnections = findNonWiresMissingConnections(sketch, closestContexts);

            foreach (EndPoint wireEndpoint in wiresMissingConnections)
            {
                foreach (Shape shape in nonWiresMissingWireConnections)
                {
                    Shape wire = wireEndpoint.ParentShape;
                    if (debug)
                    {
                        Console.WriteLine("ACTION (connect wire endpoint): " + sketch + ", " + wire + ", " + wireEndpoint + ", " + shape);
                    }
                    var op           = new ConnectEndpointOperation(sketch, wireEndpoint, shape);
                    var modification = new SketchModification(featureSketch, op, computeEnergy);
                    results.Add(modification);
                }
            }

            // ==========================================================================================================

            /*
             * Second: relabeling
             * Now we go through every shape and see if its context would be better matched as a different shape.
             * If so, we can change the shape. The benefit is the % improvement in context score plus the %
             * improvement in recognition quality.
             */

            foreach (Shape shape in sketch.Shapes)
            {
                if (shape.AlreadyLabeled)
                {
                    continue;
                }

                Tuple <double, ConnectionContext> currentContext = closestContexts[shape];
                List <ShapeType> allTypes = LogicDomain.Types;

                foreach (ShapeType otherType in AlternateTypes(shape.Type))
                {
                    if (debug)
                    {
                        Console.WriteLine("ACTION (relabel shape): " + shape + ", " + otherType);
                    }
                    var op           = new RelabelShapeOperation(sketch, shape, RecognizeAsType(shape, otherType, featureSketch));
                    var modification = new SketchModification(featureSketch, op, computeEnergy);
                    results.Add(modification);
                }
            }

            // ==========================================================================================================

            /*
             * Third: stroke steal
             * This works as follows:
             *
             * For every shape, get the set of closeSubstrokes (within a certain threshold).
             *     For every substroke in closeSubstrokes
             *         generate a steal modification (substroke --> shape)
             *
             * The steal modifications should have their benefit based on
             *    (1) connection contexts
             *    (2) recognition quality
             */

            foreach (Shape thief in sketch.Shapes)
            {
                if (thief.AlreadyLabeled)
                {
                    continue;
                }

                List <Substroke> closeSubstrokes = findSubstrokesCloseTo(thief, sketch, STROKE_STEAL_THRESHOLD);

                foreach (Substroke gem in closeSubstrokes) // thiefs steal gems
                {
                    Shape victim = gem.ParentShape;        // thiefs steal from victims

                    if (victim.AlreadyLabeled)
                    {
                        continue;
                    }

                    // find the thief's new type
                    var newThiefSubstrokes = new List <Substroke>(thief.SubstrokesL);
                    newThiefSubstrokes.Add(gem);
                    RecognitionResult newThiefRecognition = Identify(newThiefSubstrokes, featureSketch);

                    if (debug)
                    {
                        Console.WriteLine("ACTION (steal stroke): " + thief + ", " + victim + ", " + gem);
                    }
                    var stealOp        = new StrokeStealOperation(sketch, thief, gem);
                    var relabelThiefOp = new RelabelShapeOperation(sketch, thief, newThiefRecognition);
                    var runConnectorOp = new RunConnectorOperation(featureSketch, _connector);
                    ISketchOperation op;

                    // if the victim will still be around after the steal
                    if (victim.Substrokes.Length > 1)
                    {
                        var newVictimSubstrokes = new List <Substroke>(victim.SubstrokesL);
                        newVictimSubstrokes.Remove(gem);
                        RecognitionResult newVictimRecognition = Identify(newVictimSubstrokes, featureSketch);

                        var relabelVictimOp = new RelabelShapeOperation(sketch, victim, newVictimRecognition);

                        op = new CompoundSketchOperation(stealOp, relabelThiefOp, relabelVictimOp, runConnectorOp);
                    }
                    else
                    {
                        op = new CompoundSketchOperation(stealOp, relabelThiefOp, runConnectorOp);
                    }
                    var modification = new SketchModification(featureSketch, op, computeEnergy);
                    results.Add(modification);
                }
            }

            if (debug && results.Count == 0)
            {
                Console.WriteLine("(none)");
            }

            // Keep only the ones greater than the cutoff
            results = results.FindAll(r => { return(r.benefit() > BENEFIT_CUTOFF); });

            return(results);
        }
Exemple #10
0
 /// <summary>
 /// Connects all shapes in a sketch as well as possible.
 ///
 /// Precondition: the shapes of the sketch have identified types.
 ///
 /// Postconditions:
 ///    - the shapes are connected and oriented according to the context domain.
 ///    - no wires are connected to each other; connected wires are a single shape
 /// </summary>
 /// <param name="featureSketch">the sketch to connect</param>
 public virtual void process(Featurefy.FeatureSketch featureSketch)
 {
     recomputeConnectedShapes(featureSketch.Sketch.Shapes, featureSketch.Sketch);
 }