Gets the zero-based index of the zone under a certain point.
- (NSUInteger)hitTestZone:(LeadPoint)point
public int hitTestZone(LeadPoint point)
point
The test point in pixels.
The zero-based index of the zone under point, if no zone is under the test point, this method will return -1.
You can use this method to check whether a zone (either added manually or automatically) is under a given test point. For example, if you have a Windows Forms based application with the current IOcrPage in a ImageViewer control. You might want to draw the zones on the surface of the viewer. For this, you can use the GetZoneBoundsInPixels methods. If you want to allow the user to click with the mouse on the viewer to select and de-select zones, you can use HitTestZone.
This example will view the OCR Page and its zones in a ImageViewer control. It will then allow the user to select/deselect zones with the mouse.
using Leadtools;
using Leadtools.Codecs;
using Leadtools.Ocr;
using Leadtools.Forms.Common;
using Leadtools.Document.Writer;
using Leadtools.WinForms;
using Leadtools.Drawing;
using Leadtools.ImageProcessing;
using Leadtools.ImageProcessing.Color;
// Assume Form1 is a Windows.Forms form in your application
// The OCR engine we are using
private IOcrEngine _ocrEngine;
// The OCR page we are using
private IOcrPage _ocrPage;
// Our raster image viewer instance
private RasterImageViewer _viewer;
public Form1()
{
InitializeComponent();
// Initialize the raster image viewer
// Turn on use DPI, center the image, add border padding and frame shadow to show that our calculations will be
// independent on all of those extra options
_viewer = new RasterImageViewer();
_viewer.Dock = DockStyle.Fill;
_viewer.BackColor = SystemColors.AppWorkspace;
_viewer.UseDpi = true;
_viewer.BorderPadding.All = 8;
_viewer.FrameSize = new SizeF(1, 1);
_viewer.FrameShadowSize = new SizeF(2, 2);
_viewer.SizeMode = RasterPaintSizeMode.Normal;
_viewer.HorizontalAlignMode = RasterPaintAlignMode.Center;
_viewer.VerticalAlignMode = RasterPaintAlignMode.Center;
_viewer.AutoDisposeImages = true;
_viewer.InteractiveMode = RasterViewerInteractiveMode.None;
// Turn on scale to gray painting in the viewer
RasterPaintProperties props = _viewer.PaintProperties;
props.PaintDisplayMode |= RasterPaintDisplayModeFlags.ScaleToGray;
_viewer.PaintProperties = props;
// Subscribe to the viewer events we need
_viewer.KeyDown += new KeyEventHandler(_viewer_KeyDown);
_viewer.MouseDown += new MouseEventHandler(_viewer_MouseDown);
_viewer.PostImagePaint += new PaintEventHandler(_viewer_PostImagePaint);
Controls.Add(_viewer);
_viewer.BringToFront();
// Create and startup the OCR engine
_ocrEngine = OcrEngineManager.CreateEngine(OcrEngineType.LEAD, false);
_ocrEngine.Startup(null, null, null, LEAD_VARS.OcrLEADRuntimeDir);
// Load an image into the OCR document
string tifFileName = Path.Combine(LEAD_VARS.ImagesDir, "Ocr1.tif");
_ocrPage = _ocrEngine.CreatePage(_ocrEngine.RasterCodecsInstance.Load(tifFileName, 1), OcrImageSharingMode.AutoDispose);
// Do auto zone
_ocrPage.AutoZone(null);
// AutoZone does not specify a name for the zones, so loop through all the zones and set their names
// to a unique value. We will use the name in the paint code later
IOcrZoneCollection ocrZones = _ocrPage.Zones;
for (int i = 0; i < ocrZones.Count; i++)
{
OcrZone ocrZone = ocrZones[i];
// Construct the name from the ID
ocrZone.Name = string.Format("Zone {0}", ocrZone.Id);
ocrZones[i] = ocrZone;
}
// Show the same image in the viewer
_viewer.Image = _ocrPage.GetRasterImage();
// Note, the image we got from GetRasterImage is a copy of the image in the engine
// Since we set the AutoDisposeImages of the viewer to "true", the image will be disposed
// when the viewer is disposed at application termination
Text = "+ to zoom in, - to zoom out, enter to return to 100%. Select the zones with the mouse";
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
// Dispose the page
_ocrPage.Dispose();
// Shutdown the OCR engine
_ocrEngine.Dispose();
base.OnFormClosed(e);
}
private void _viewer_KeyDown(object sender, KeyEventArgs e)
{
const double zoomRatio = 1.2;
double scaleFactor = _viewer.ScaleFactor;
switch (e.KeyCode)
{
case Keys.Add:
case Keys.Oemplus:
// Zoom in
scaleFactor *= zoomRatio;
e.Handled = true;
break;
case Keys.Subtract:
case Keys.OemMinus:
// Zone out
scaleFactor /= zoomRatio;
e.Handled = true;
break;
case Keys.Enter:
scaleFactor = 1;
e.Handled = true;
break;
}
const double minimumScaleFactor = 0.05;
const double maximumScaleFactor = 11;
scaleFactor = Math.Max(minimumScaleFactor, Math.Min(maximumScaleFactor, scaleFactor));
// Check if scale factor has changed
if (scaleFactor != _viewer.ScaleFactor)
{
_viewer.BeginUpdate();
// Yes, zoom keeping the center of the image
// Get what you see in physical coordinates
Rectangle rc = Rectangle.Intersect(_viewer.PhysicalViewRectangle, _viewer.ClientRectangle);
// Get the center of what you see in physical coordinates
PointF center = new PointF(rc.Left + rc.Width / 2, rc.Top + rc.Height / 2);
Transformer t = new Transformer(_viewer.Transform);
// Get the center of what you see in logical coordinates
center = t.PointToLogical(center);
_viewer.ScaleFactor = scaleFactor;
// Bring the original center into the view center
t = new Transformer(_viewer.Transform);
// Get the center of what you saw before the zoom in physical coordinates
center = t.PointToPhysical(center);
// Bring the old center into the center of the view
_viewer.CenterAtPoint(Point.Round(center));
_viewer.EndUpdate();
}
}
private void _viewer_MouseDown(object sender, MouseEventArgs e)
{
// Perform hit-testing on the zones
if (_ocrEngine != null && _ocrEngine.IsStarted && _ocrPage != null && e.Button == MouseButtons.Left)
{
// Get the transform of the viewer
// Use the transform that takes the DPI into consideration since we turned that on
using (Matrix matrix = _viewer.GetTransformWithDpi())
{
Transformer t = new Transformer(matrix);
// Convert the mouse click coordinates from physical (viewer) to logical (image)
PointF point = new PointF(e.X, e.Y);
point = t.PointToLogical(point);
// Hit test the zones
// An alternative to calling HitTestZone is to loop through all the zones
// and get the value of .Bounds in pixels, then check if the point is inside
// the boundaries.
LeadPoint lPoint = new LeadPoint((int)point.X, (int)point.Y);
int zoneIndex = _ocrPage.HitTestZone(lPoint);
if (zoneIndex != -1)
{
// We hit a zone, loop through all the zones, unselect all but the hit tested zone
for (int index = 0; index < _ocrPage.Zones.Count; index++)
{
// Since OcrZone is a structure, we cannot simply do
// ocrZone.Zones[index].Name = value
// We have to get a copy of the structure, modify it and set it back
OcrZone ocrZone = _ocrPage.Zones[index];
if (index != zoneIndex)
ocrZone.Name = null;
else
ocrZone.Name = "Selected";
_ocrPage.Zones[index] = ocrZone;
}
// Re-paint the viewer to show the new zones
_viewer.Invalidate();
}
}
}
}
private void _viewer_PostImagePaint(object sender, PaintEventArgs e)
{
// Draw the zones on the viewer in their correct location
if (_ocrEngine != null && _ocrEngine.IsStarted && _ocrPage != null)
{
// Get the transform of the viewer
// Use the transform that takes the DPI into consideration since we turned that on
using (Matrix matrix = _viewer.GetTransformWithDpi())
{
Transformer t = new Transformer(matrix);
Pen normalPen = new Pen(Color.Blue, 1);
Pen selectedPen = new Pen(Color.Red, 2);
selectedPen.DashStyle = DashStyle.Dash;
foreach (OcrZone ocrZone in _ocrPage.Zones)
{
// Get the zone bounds in pixels
// You can also use _ocrPage.GetZoneBoundsInPixels here
RectangleF zoneBounds = new RectangleF(ocrZone.Bounds.Left, ocrZone.Bounds.Top, ocrZone.Bounds.Width, ocrZone.Bounds.Height);
// This rectangle is in image (logical) coordinates with top-left view perspective
// Convert to the physical coordinates of the viewer
zoneBounds = t.RectangleToPhysical(zoneBounds);
// Now draw this zone on the viewer surface
if (ocrZone.Name == "Selected")
e.Graphics.DrawRectangle(selectedPen, zoneBounds.X, zoneBounds.Y, zoneBounds.Width - 1, zoneBounds.Height - 1);
else
e.Graphics.DrawRectangle(normalPen, zoneBounds.X, zoneBounds.Y, zoneBounds.Width - 1, zoneBounds.Height - 1);
// Draw the zone name on the left hand corner of the zone
// Note, in a real application you might want to have an option to show/hide the zone names (labels)
SizeF labelSize = e.Graphics.MeasureString(ocrZone.Name, Font);
RectangleF labelRectangle = new RectangleF(zoneBounds.X, zoneBounds.Y - labelSize.Height, labelSize.Width, labelSize.Height);
e.Graphics.FillRectangle(Brushes.Yellow, labelRectangle);
e.Graphics.DrawString(ocrZone.Name, Font, Brushes.Black, labelRectangle.X, labelRectangle.Y);
}
}
}
}
static class LEAD_VARS
{
public const string ImagesDir = @"C:\Users\Public\Documents\LEADTOOLS Images";
public const string OcrLEADRuntimeDir = @"C:\LEADTOOLS 20\Bin\Common\OcrLEADRuntime";
}
Imports Leadtools
Imports Leadtools.Codecs
Imports Leadtools.Ocr
Imports Leadtools.Forms
Imports Leadtools.Document.Writer
Imports Leadtools.WinForms
Imports Leadtools.Drawing
Imports Leadtools.ImageProcessing
Imports Leadtools.ImageProcessing.Color
' Assume Form1 is a Windows.Forms form in your application
' The OCR engine we are using
Private _ocrEngine As IOcrEngine
' The OCR page we are using
Private _ocrPage As IOcrPage
' Our raster image viewer instance
Private _viewer As RasterImageViewer
Public Sub New()
InitializeComponent()
' Initialize the raster image viewer
' Turn on use DPI, center the image, add border padding and frame shadow to show that our calculations will be
' independent on all of those extra options
_viewer = New RasterImageViewer()
_viewer.Dock = DockStyle.Fill
_viewer.BackColor = SystemColors.AppWorkspace
_viewer.UseDpi = True
_viewer.BorderPadding.All = 8
_viewer.FrameSize = New SizeF(1, 1)
_viewer.FrameShadowSize = New SizeF(2, 2)
_viewer.SizeMode = RasterPaintSizeMode.Normal
_viewer.HorizontalAlignMode = RasterPaintAlignMode.Center
_viewer.VerticalAlignMode = RasterPaintAlignMode.Center
_viewer.AutoDisposeImages = True
_viewer.InteractiveMode = RasterViewerInteractiveMode.None
' Turn on scale to gray painting in the viewer
Dim props As RasterPaintProperties = _viewer.PaintProperties
props.PaintDisplayMode = props.PaintDisplayMode Or RasterPaintDisplayModeFlags.ScaleToGray
_viewer.PaintProperties = props
' Subscribe to the viewer events we need
AddHandler _viewer.KeyDown, AddressOf _viewer_KeyDown
AddHandler _viewer.MouseDown, AddressOf _viewer_MouseDown
AddHandler _viewer.PostImagePaint, AddressOf _viewer_PostImagePaint
Controls.Add(_viewer)
_viewer.BringToFront()
' Create and startup the OCR engine
_ocrEngine = OcrEngineManager.CreateEngine(OcrEngineType.LEAD, False)
_ocrEngine.Startup(Nothing, Nothing, Nothing, LEAD_VARS.OcrLEADRuntimeDir)
' Load an image into the OCR document
Dim tifFileName As String = Path.Combine(LEAD_VARS.ImagesDir, "Ocr1.tif")
_ocrPage = _ocrEngine.CreatePage(_ocrEngine.RasterCodecsInstance.Load(tifFileName, 1), OcrImageSharingMode.AutoDispose)
' Do auto zone
_ocrPage.AutoZone(Nothing)
' AutoZone does not specify a name for the zones, so loop through all the zones and set their names
' to a unique value. We will use the name in the paint code later
Dim ocrZones As IOcrZoneCollection = _ocrPage.Zones
For i As Integer = 0 To ocrZones.Count - 1
Dim ocrZone As OcrZone = ocrZones(i)
' Construct the name from the ID
ocrZone.Name = String.Format("Zone {0}", ocrZone.Id)
ocrZones(i) = ocrZone
Next
' Show the same image in the viewer
_viewer.Image = _ocrPage.GetRasterImage()
' Note, the image we got from GetRasterImage is a copy of the image in the engine
' Since we set the AutoDisposeImages of the viewer to "true", the image will be disposed
' when the viewer is disposed at application termination
Text = "+ to zoom in, - to zoom out, enter to return to 100%. Select the zones with the mouse"
End Sub
Protected Overrides Sub OnFormClosed(e As FormClosedEventArgs)
' Dispose the page
_ocrPage.Dispose()
' Shutdown the OCR engine
_ocrEngine.Dispose()
MyBase.OnFormClosed(e)
End Sub
Private Sub _viewer_KeyDown(sender As Object, e As KeyEventArgs)
Const zoomRatio As Double = 1.2
Dim scaleFactor As Double = _viewer.ScaleFactor
Select Case e.KeyCode
Case Keys.Add, Keys.Oemplus
' Zoom in
scaleFactor *= zoomRatio
e.Handled = True
Exit Select
Case Keys.Subtract, Keys.OemMinus
' Zoom out
scaleFactor /= zoomRatio
e.Handled = True
Exit Select
Case Keys.Enter
scaleFactor = 1
e.Handled = True
Exit Select
End Select
Const minimumScaleFactor As Double = 0.05
Const maximumScaleFactor As Double = 11
scaleFactor = Math.Max(minimumScaleFactor, Math.Min(maximumScaleFactor, scaleFactor))
' Check if scale factor has changed
If scaleFactor <> _viewer.ScaleFactor Then
_viewer.BeginUpdate()
' Yes, zoom keeping the center of the image
' Get what you see in physical coordinates
Dim rc As Rectangle = Rectangle.Intersect(_viewer.PhysicalViewRectangle, _viewer.ClientRectangle)
' Get the center of what you see in physical coordinates
Dim center As New PointF(rc.Left + rc.Width \ 2, rc.Top + rc.Height \ 2)
Dim t As New Transformer(_viewer.Transform)
' Get the center of what you see in logical coordinates
center = t.PointToLogical(center)
_viewer.ScaleFactor = scaleFactor
' Bring the original center into the view center
t = New Transformer(_viewer.Transform)
' Get the center of what you saw before the zoom in physical coordinates
center = t.PointToPhysical(center)
' Bring the old center into the center of the view
_viewer.CenterAtPoint(Point.Round(center))
_viewer.EndUpdate()
End If
End Sub
Private Sub _viewer_MouseDown(sender As Object, e As MouseEventArgs)
' Perform hit-testing on the zones
If _ocrEngine IsNot Nothing AndAlso _ocrEngine.IsStarted AndAlso _ocrPage IsNot Nothing AndAlso e.Button = MouseButtons.Left Then
' Get the transform of the viewer
' Use the transform that takes the DPI into consideration since we turned that on
Using matrix As Matrix = _viewer.GetTransformWithDpi()
Dim t As New Transformer(matrix)
' Convert the mouse click coordinates from physical (viewer) to logical (image)
Dim point As New PointF(e.X, e.Y)
point = t.PointToLogical(point)
' Hit test the zones
' An alternative to calling HitTestZone is to loop through all the zones
' and get the value of .Bounds in pixels, then check if the point is inside
' the boundaries.
Dim lPoint As New LeadPoint(CInt(Math.Truncate(point.X)), CInt(Math.Truncate(point.Y)))
Dim zoneIndex As Integer = _ocrPage.HitTestZone(lPoint)
If zoneIndex <> -1 Then
' We hit a zone, loop through all the zones, unselect all but the hit tested zone
For index As Integer = 0 To _ocrPage.Zones.Count - 1
' Since OcrZone is a structure, we cannot simply do
' ocrZone.Zones[index].Name = value
' We have to get a copy of the structure, modify it and set it back
Dim ocrZone As OcrZone = _ocrPage.Zones(index)
If index <> zoneIndex Then
ocrZone.Name = Nothing
Else
ocrZone.Name = "Selected"
End If
_ocrPage.Zones(index) = ocrZone
Next
' Re-paint the viewer to show the new zones
_viewer.Invalidate()
End If
End Using
End If
End Sub
Private Sub _viewer_PostImagePaint(sender As Object, e As PaintEventArgs)
' Draw the zones on the viewer in their correct location
If _ocrEngine IsNot Nothing AndAlso _ocrEngine.IsStarted AndAlso _ocrPage IsNot Nothing Then
' Get the transform of the viewer
' Use the transform that takes the DPI into consideration since we turned that on
Using matrix As Matrix = _viewer.GetTransformWithDpi()
Dim t As New Transformer(matrix)
Dim normalPen As New Pen(Color.Blue, 1)
Dim selectedPen As New Pen(Color.Red, 2)
selectedPen.DashStyle = DashStyle.Dash
For Each ocrZone As OcrZone In _ocrPage.Zones
' Get the zone bounds in pixels
' You can also use _ocrPage.GetZoneBoundsInPixels here
Dim ltzoneBounds As LeadRect = ocrZone.Bounds
Dim zoneBounds As New RectangleF(ltzoneBounds.Left, ltzoneBounds.Top, ltzoneBounds.Width, ltzoneBounds.Height)
' This rectangle is in image (logical) coordinates with top-left view perspective
' Convert to the physical coordinates of the viewer
zoneBounds = t.RectangleToPhysical(zoneBounds)
' Now draw this zone on the viewer surface
If ocrZone.Name = "Selected" Then
e.Graphics.DrawRectangle(selectedPen, zoneBounds.X, zoneBounds.Y, zoneBounds.Width - 1, zoneBounds.Height - 1)
Else
e.Graphics.DrawRectangle(normalPen, zoneBounds.X, zoneBounds.Y, zoneBounds.Width - 1, zoneBounds.Height - 1)
End If
' Draw the zone name on the left hand corner of the zone
' Note, in a real application you might want to have an option to show/hide the zone names (labels)
Dim labelSize As SizeF = e.Graphics.MeasureString(ocrZone.Name, Font)
Dim labelRectangle As New RectangleF(zoneBounds.X, zoneBounds.Y - labelSize.Height, labelSize.Width, labelSize.Height)
e.Graphics.FillRectangle(Brushes.Yellow, labelRectangle)
e.Graphics.DrawString(ocrZone.Name, Font, Brushes.Black, labelRectangle.X, labelRectangle.Y)
Next
End Using
End If
End Sub
Public NotInheritable Class LEAD_VARS
Public Const ImagesDir As String = "C:\Users\Public\Documents\LEADTOOLS Images"
Public Const OcrLEADRuntimeDir As String = "C:\LEADTOOLS 20\Bin\Common\OcrLEADRuntime"
End Class
Help Collections
Raster .NET | C API | C++ Class Library | HTML5 JavaScript
Document .NET | C API | C++ Class Library | HTML5 JavaScript
Medical .NET | C API | C++ Class Library | HTML5 JavaScript
Medical Web Viewer .NET
Multimedia
Direct Show .NET | C API | Filters
Media Foundation .NET | C API | Transforms
Supported Platforms
.NET, Java, Android, and iOS/macOS Assemblies
Imaging, Medical, and Document
C API/C++ Class Libraries
Imaging, Medical, and Document
HTML5 JavaScript Libraries
Imaging, Medical, and Document