Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ten przykład opiera się na próbce z kolekcji Ink Collection. Pokazuje, jak używać obiektu Divider do analizowania wejścia atramentu.
Aby uzyskać szczegółowe informacje koncepcyjne na temat dzielenia, zobacz obiekt dzielenia.
Po zaktualizowaniu formularza przykład rysuje prostokąt ograniczenia wokół każdej analizowanej jednostki, podzielony na wyrazy, wiersze, akapity i rysunki. Oprócz używania różnych kolorów, prostokąty te są powiększane o różne ilości, aby upewnić się, że żaden z prostokątów nie jest zasłonięty przez inne. W poniższej tabeli przedstawiono kolor i rozszerzenie dla każdej przeanalizowanej jednostki.
| przeanalizowana jednostka | Kolor | Powiększenie pikseli |
|---|---|---|
| Słowo |
Zielony |
1 |
| Linia |
Magenta |
3 |
| Akapit |
Niebieski |
5 |
| Rysunek |
Czerwony |
1 |
Konfigurowanie formularza
Podczas ładowania formularza tworzony jest obiekt Divider. Obiekt InkOverlay jest tworzony i skojarzony z panelem w formularzu. Następnie programy obsługi zdarzeń są dołączone do obiektu InkOverlay w celu śledzenia, gdy pociągnięcia są dodawane i usuwane. Następnie, jeśli rozpoznawacze są dostępne, obiekt RecognizerContext dla domyślnego rozpoznawacza jest przypisywany do rozdzielacza. Następnie właściwość LineHeight obiektu Divider jest ustawiona, a kolekcja Strokes z obiektu InkOverlay jest przypisywana do obiektu Divider. Na koniec jest włączony obiekt InkOverlay.
// 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;
Kolekcja Strokes obiektu Divider musi być zsynchronizowana z kolekcją Strokes obiektu InkOverlay (dostęp za pośrednictwem właściwości Ink obiektu InkOverlay). Aby upewnić się, że tak się stanie, obsługiwacz zdarzeń Stroke dla obiektu InkOverlay jest napisany następująco. Należy pamiętać, że program obsługi zdarzeń najpierw testuje, czy EditingMode jest ustawiony na pismo odręczne w celu odfiltrowania pociągnięć gumki. Jeśli użytkownik zażądał automatycznej analizy układu, aplikacja wywołuje metodę DivideInk formularza i odświeża obszar rysunku.
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();
}
}
}
Podział atramentu
Gdy użytkownik kliknie pozycję Podziel w menu Plik, metoda Divide jest wywoływana dla obiektu Divider. Jest używany domyślny program rozpoznawania, jeśli jest dostępny.
DivisionResult divResult = myInkDivider.Divide();
Wynikowy obiekt DivisionResult, do którego odwołuje się zmienna divResult, jest przekazywany do funkcji narzędziowej getUnitBBBoxes(). Funkcja narzędzia zwraca tablicę prostokątów dla dowolnego żądanego typu dzielenia: segmenty, linie, akapity lub rysunki.
myWordBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Segment, 1);
myLineBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Line, 3);
myParagraphBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Paragraph, 5);
myDrawingBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Drawing, 1);
Na koniec panel formularza musi być narysowany ponownie, aby pojawiły się prostokąty ograniczające.
DrawArea.Refresh();
Wyniki analizy tuszu
W funkcji użytkowej obiekt DivisionResult jest przepytywany o wyniki przy użyciu metody ResultByType, na podstawie typu dzielenia żądanego przez wywołującego. Metoda ResultByType zwraca kolekcję DivisionUnits. Każda DivisionUnit w kolekcji reprezentuje rysunek, pojedynczy segment rozpoznawania pisma ręcznego, wiersz pisma ręcznego lub blok pisma ręcznego, w zależności od tego, co zostało określone w momencie wywołania funkcji użytkowej.
DivisionUnits units = divResult.ResultByType(divType);
Jeśli istnieje co najmniej jeden DivisionUnit, zostanie utworzona tablica prostokątów zawierająca jeden prostokąt ograniczenia na jednostkę. Prostokąty są powiększone o różne wartości w zależności od rodzaju jednostki, co jest przechowywane w zmiennej powiększenia, aby zapobiec nakładaniu się.
// 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
}
Ponowne rysowanie formularza
Po wymuszeniu powyżej ponownego przerysowania, poniższy kod jest wykonywany w celu malowania ramek ograniczających dla każdego DivisionUnit na formularzu wokół atramentu.
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);
}
}
Zamykanie formularza
Metoda Dispose formularza usuwa obiekty InkOverlay, Divider, RecognizerContext oraz kolekcję Strokes używaną w przykładzie.