Dela via


Exempel på inkavgränsare

Det här exemplet baseras på Ink Collection Sample. Det visar hur du använder objektet Divider för att analysera bläckinmatning.

Detaljerad konceptuell information om Dividerfinns i The Divider Object.

När formuläret uppdateras ritar exemplet en avgränsningsrektangel runt varje analyserad enhet, uppdelad i ord, linjer, stycken och ritningar. Förutom att använda olika färger förstoras dessa rektanglar med olika mängder för att säkerställa att ingen av rektanglarna skyms av andra. I följande tabell anges färg och förstoring för varje analyserad enhet.

analyserad enhet Färg Pixelförstoring
Ord
Grön
1
Linje
Magenta
3
Paragraf
Blå
5
Teckning
Röd
1

Konfigurera formuläret

När formuläret läses in skapas ett Divider- objekt. Ett InkOverlay- objekt skapas och associeras med en panel i formuläret. Sedan kopplas händelsehanterare till InkOverlay-objektet för att spåra när linjer läggs till och tas bort. Om identifierare sedan är tillgängliga tilldelas ett RecognizerContext-objekt för standardigenkänningen till dividern. Sedan anges Divider-objektets egenskap LineHeight och Strokes-samlingen från InkOverlay-objektet tilldelas Divider-objektet. Slutligen är InkOverlay-objektet aktiverat.

// Create the ink overlay and associate it with the form
myInkOverlay = new Microsoft.Ink.InkOverlay(DrawArea.Handle);

// Set the erasing mode to stroke erase.
myInkOverlay.EraserMode = InkOverlayEraserMode.StrokeErase;

// Hook event handler for the Stroke event to myInkOverlay_Stroke.
// This is necessary since the application needs to pass the strokes 
// to the ink divider.
myInkOverlay.Stroke += new InkCollectorStrokeEventHandler(myInkOverlay_Stroke); 

// Hook the event handler for StrokeDeleting event to myInkOverlay_StrokeDeleting.
// This is necessary as the application needs to remove the strokes from 
// ink divider object as well.
myInkOverlay.StrokesDeleting += new InkOverlayStrokesDeletingEventHandler(myInkOverlay_StrokeDeleting);

// Hook the event handler for StrokeDeleted event to myInkOverlay_StrokeDeleted.
// This is necessary to update the layout analysis result when automatic layout analysis
// option is selected.
myInkOverlay.StrokesDeleted += new InkOverlayStrokesDeletedEventHandler(myInkOverlay_StrokeDeleted);

// Create the ink divider object
myInkDivider = new Divider();

// Add a default recognizer context to the divider object
// without adding the recognizer context, the divider would
// not use a recognizer to do its word segmentation and would
// have less accurate results.
// Adding the recognizer context slows down the call to 
// myInkDivider.Divide though.
// It is possible that there is no recognizer installed on the
// machine for this language. In that case the divider does
// not use a recognizer to improve its accuracy.
// Get the default recognizer if any
try
{
    Recognizers recognizers = new Recognizers();
     myInkDivider.RecognizerContext = recognizers.GetDefaultRecognizer().CreateRecognizerContext();
}
catch (InvalidOperationException)
{
     //We are in the case where no default recognizers can be found
}

    // The LineHeight property helps the InkDivider distinguish between 
    // drawing and handwriting. The value should be the expected height 
    // of the user's handwriting in ink space units (0.01mm).
    // Here we set the LineHeight to 840, which is about 1/3 of an inch.
    myInkDivider.LineHeight = 840;

// Assign ink overlay's strokes collection to the ink divider
// This strokes collection is updated in the event handler
myInkDivider.Strokes = myInkOverlay.Ink.Strokes;

// Enable ink collection
myInkOverlay.Enabled = true;

Samlingen av Divider-objektets Strokes måste hållas synkroniserad med samlingen av InkOverlay-objektets Strokes (som nås genom egenskapen Ink hos InkOverlay-objektet). För att säkerställa att detta sker skrivs händelsehanteraren stroke för InkOverlay-objektet på följande sätt. Observera att händelsehanteraren först testar om EditingMode är inställd på Ink för att filtrera bort raderingsstreck. Om användaren har begärt automatisk layoutanalys anropar programmet formulärets DivideInk-metod och uppdaterar ritningsområdet.

private void myInkOverlay_Stroke(object sender, InkCollectorStrokeEventArgs e )
{
    // Filter out the eraser stroke.
    if(InkOverlayEditingMode.Ink == myInkOverlay.EditingMode)
    {
        // Add the new stroke to the ink divider's strokes collection
        myInkDivider.Strokes.Add(e.Stroke);
        
        if(miAutomaticLayoutAnalysis.Checked)
        {
            // Call DivideInk
            DivideInk();

            // Repaint the screen to reflect the change
            DrawArea.Refresh();
        }
    }
}

Dela upp bläcket

När användaren klickar på Dela på menyn Arkiv anropas metoden Divide på objektet Divider. Standardigenkänningen används, om den är tillgänglig.

DivisionResult divResult = myInkDivider.Divide();

Det resulterande DivisionResult--objektet, som refereras av variabeln divResult, skickas till en verktygsfunktion getUnitBBBoxes(). Verktygsfunktionen returnerar en matris med rektanglar för den divisionstyp som begärs: segment, linjer, stycken eller ritningar.

myWordBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Segment, 1);
myLineBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Line, 3);
myParagraphBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Paragraph, 5);
myDrawingBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Drawing, 1);

Slutligen tvingas formulärpanelen att rita om så att avgränsningsrektanglarna visas.

DrawArea.Refresh();

Resultat av bläckanalys

I verktygsfunktionen efterfrågas DivisionResult-objektet för dess resultat med hjälp av metoden ResultByType, baserat på den divisionstyp som anroparen begär. Metoden ResultByType returnerar en DivisionUnits- samling. Varje DivisionUnit- i samlingen representerar en ritning, ett enda igenkänningssegment med handskrift, en handskriftsrad eller ett handskriftsblock, beroende på vad som angavs när verktygsfunktionen anropades.

DivisionUnits units = divResult.ResultByType(divType);

Om det finns minst en DivisionUnitskapas en matris med rektanglar som innehåller en avgränsningsrektangel för varje enhet. (Rektanglarna blåses upp med olika mängder för varje typ av enhet, som anges i variabeln "inflate", för att förhindra överlappning.)

// If there is at least one unit, we construct the rectangles
if((null != units) && (0 < units.Count))
{
    // We need to convert rectangles from ink units to
    // pixel units. For that, we need Graphics object
    // to pass to InkRenderer.InkSpaceToPixel method
    using (Graphics g = DrawArea.CreateGraphics())
    {

    // InkSpace to Pixel Space conversion setup done here. 
    // Not shown for brevity.

        // Iterate through the collection of division units to obtain the bounding boxes
        foreach(DivisionUnit unit in units)
        {
            // Get the bounding box of the strokes of the division unit
            divRects[i] = unit.Strokes.GetBoundingBox();

            // Div unit rect Ink space to Pixel space conversion done here. 
            // Not shown for brevity.

            // Inflate the rectangle by inflate pixels in both directions
            divRects[i].Inflate(inflate, inflate);

            // Increment the index
            ++i;
        }

    } // Relinquish the Graphics object
}

Rita om formuläret

När omritning tvingas ovan körs följande kod för att måla avgränsningsrutorna för varje DivisionUnit på formuläret runt bläcket.

private void DrawArea_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            // Create the Pen used to draw bounding boxes.
            // First set of bounding boxes drawn here are 
            // the bounding boxes of paragraphs.
            // These boxes are drawn with Blue pen.
            Pen penBox = new Pen(Color.Blue, 2);

            // First, draw the bounding boxes for Paragraphs
            if(null != myParagraphBoundingBoxes)
            {
                // Draw bounding boxes for Paragraphs
                e.Graphics.DrawRectangles(penBox, myParagraphBoundingBoxes);
            }

            // Next, draw the bounding boxes for Lines
            if(null != myLineBoundingBoxes)
            {
                // Color is Magenta pen
                penBox.Color = Color.Magenta;
                // Draw the bounding boxes for Lines
                e.Graphics.DrawRectangles(penBox, myLineBoundingBoxes);
            }
            
            // Then, draw the bounding boxes for Words
            if(null != myWordBoundingBoxes)
            {
                // Color is Green
                penBox.Color = Color.Green;
                // Draw bounding boxes for Words
                e.Graphics.DrawRectangles(penBox, myWordBoundingBoxes);
            }
            
            // Finally, draw the boxes for Drawings
            if(null != myDrawingBoundingBoxes)
            {
                // Color is Red pen
                penBox.Color = Color.Red;
                // Draw bounding boxes for Drawings
                e.Graphics.DrawRectangles(penBox, myDrawingBoundingBoxes);
            }
        }

Stänga formuläret

Formulärets metod Dispose disponerar InkOverlay-, Divider-, RecognizerContext-objekten och samlingen Strokes som används i exemplet.