OCR with Tessaract

.Net
Admin
Site Admin
Posts: 955
Joined: Thu Aug 23, 2007 10:35 am

OCR with Tessaract

Postby Admin » Wed Jan 11, 2017 7:21 pm

Form1.vb

Code: Select all

Imports Tesseract
Imports System.Threading
Imports System.Runtime.InteropServices

Public Class Form1
    Const IDC_ARROW As Integer = 32512
    Const IDC_CROSS As Integer = 32515
    <DllImport("user32.dll")> Private Shared Function SetSystemCursor(ByVal hCursor As IntPtr, ByVal id As Integer) As Boolean
    End Function
    <DllImport("user32.dll")> Private Shared Function LoadCursor(ByVal hInstance As IntPtr, ByVal id As Integer) As IntPtr
    End Function

    Public Const MOD_ALT As Integer = &H1 'Alt key
    Public Const WM_HOTKEY As Integer = &H312

    <DllImport("User32.dll")> _
    Public Shared Function RegisterHotKey(ByVal hwnd As IntPtr, _
                        ByVal id As Integer, ByVal fsModifiers As Integer, _
                        ByVal vk As Integer) As Integer
    End Function

    <DllImport("User32.dll")> _
    Public Shared Function UnregisterHotKey(ByVal hwnd As IntPtr, _
                        ByVal id As Integer) As Integer
    End Function

    <DllImport("dwmapi.dll", PreserveSig:=False)> _
    Public Shared Function DwmIsCompositionEnabled() As Boolean
    End Function

    <DllImport("dwmapi.dll", PreserveSig:=False)> _
    Public Shared Sub DwmEnableComposition(ByVal bEnable As Boolean)
    End Sub

    <DllImport("user32.dll", EntryPoint:="GetCursorInfo")> _
    Public Shared Function GetCursorInfo(ByRef pci As CURSORINFO) As Boolean
    End Function

    <DllImport("user32.dll", EntryPoint:="CopyIcon")> _
    Public Shared Function CopyIcon(ByVal hIcon As IntPtr) As IntPtr
    End Function

    <DllImport("user32.dll", EntryPoint:="GetIconInfo")> _
    Public Shared Function GetIconInfo(ByVal hIcon As IntPtr, ByRef piconinfo As ICONINFO) As Boolean
    End Function

    Dim aeroIsEnabled As Boolean
    Dim b As Bitmap
    Dim graphics As Graphics

    Dim StartPoint As New Point(0, 0)
    Dim ScreenShotSize As Drawing.Size

    Dim Page As Integer = 1
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg = WM_HOTKEY Then
            Dim id As IntPtr = m.WParam
            Select Case (id.ToString)
                Case "100"
                    CaptureAndRender()
                Case "200"
                    TextBox1.Text &= vbCrLf & vbCrLf & "--------- Page " & Page & " ---------" & vbCrLf & vbCrLf
            End Select
        End If
        MyBase.WndProc(m)
    End Sub

    Private Function CaptureAndRender()
        Debug.WriteLine("You pressed ALT+S key combination")
        If StartPoint.IsEmpty Then
            StartPoint = GetCursorPosition()
            Debug.WriteLine(StartPoint)
        Else
            Dim MyEndPoint As Point = GetCursorPosition()
            Debug.WriteLine(MyEndPoint)
            Dim MyTwoPoints As New Point(MyEndPoint.X - StartPoint.X, MyEndPoint.Y - StartPoint.Y)
            ScreenShotSize = New Size(MyTwoPoints)
            Debug.WriteLine(ScreenShotSize)
            'CaptureScreenshot(New Point(0, 0), PictureBox1.Size)
            'This resizes the Background of the image to scale
            If True Then
                b = New Bitmap(PictureBox1.Size.Width, PictureBox1.Size.Height)
            Else
                'b = New Bitmap(MyEndPoint.X - StartPoint.X, MyEndPoint.Y - StartPoint.Y)
                b = New Bitmap(ScreenShotSize.Width * 2, ScreenShotSize.Height * 2)
            End If
            'ResizeImage(b, b.Width * 3, b.Height * 3)

            PictureBox1.Image = b
            graphics = Graphics.FromImage(b)
            '
            graphics.Clear(Color.Transparent)
            graphics.CopyFromScreen(StartPoint, New Point(0, 0), ScreenShotSize)

            If True Then
                Dim output As New Bitmap(ScreenShotSize.Width * 2, ScreenShotSize.Height * 2)
                Using g As Graphics = Graphics.FromImage(output)
                    g.DrawImage(b, 0, 0, PictureBox1.Size.Width * 2, PictureBox1.Size.Height * 2)
                End Using
                PictureBox1.Image = b
                translateFromMemory(ConvertToByteArray(output))
            Else
                translateFromMemory(ConvertToByteArray(b))
            End If

            'PictureBox1.Image = output
            'PictureBox1.Image.Save("./saved.tiff", System.Drawing.Imaging.ImageFormat.Tiff)
            'ResizeImage(b, b.Width * 3, b.Height * 3)
            '
            StartPoint = New Point(0, 0)
            My.Computer.Audio.Play("c:\Windows\Media\ding.wav")
            Application.DoEvents()

            'translateFromFile("./saved.tiff")
            'translateFromMemory(ConvertToByteArray(New Bitmap(ScreenShotSize.Width, ScreenShotSize.Height, graphics)))
        End If
    End Function

    Public Shared Function ConvertToByteArray(ByVal value As Bitmap) As Byte()
        Dim ms = New System.IO.MemoryStream
        value.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff) ' Use appropriate format here
        Dim bytes = ms.ToArray()
        Return bytes
    End Function

#Region " ResizeImage "
    Public Overloads Shared Function ResizeImage(SourceImage As Drawing.Image, TargetWidth As Int32, TargetHeight As Int32) As Drawing.Bitmap
        Dim bmSource = New Drawing.Bitmap(SourceImage)

        Return ResizeImage(bmSource, TargetWidth, TargetHeight)
    End Function

    Public Overloads Shared Function ResizeImage(bmSource As Drawing.Bitmap, TargetWidth As Int32, TargetHeight As Int32) As Drawing.Bitmap
        Dim bmDest As New Drawing.Bitmap(TargetWidth, TargetHeight, Drawing.Imaging.PixelFormat.Format32bppArgb)

        Dim nSourceAspectRatio = bmSource.Width / bmSource.Height
        Dim nDestAspectRatio = bmDest.Width / bmDest.Height

        Dim NewX = 0
        Dim NewY = 0
        Dim NewWidth = bmDest.Width
        Dim NewHeight = bmDest.Height

        If nDestAspectRatio = nSourceAspectRatio Then
            'same ratio
        ElseIf nDestAspectRatio > nSourceAspectRatio Then
            'Source is taller
            NewWidth = Convert.ToInt32(Math.Floor(nSourceAspectRatio * NewHeight))
            NewX = Convert.ToInt32(Math.Floor((bmDest.Width - NewWidth) / 2))
        Else
            'Source is wider
            NewHeight = Convert.ToInt32(Math.Floor((1 / nSourceAspectRatio) * NewWidth))
            NewY = Convert.ToInt32(Math.Floor((bmDest.Height - NewHeight) / 2))
        End If

        Using grDest = Drawing.Graphics.FromImage(bmDest)
            With grDest
                .CompositingQuality = Drawing.Drawing2D.CompositingQuality.HighQuality
                .InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
                .PixelOffsetMode = Drawing.Drawing2D.PixelOffsetMode.HighQuality
                .SmoothingMode = Drawing.Drawing2D.SmoothingMode.AntiAlias
                .CompositingMode = Drawing.Drawing2D.CompositingMode.SourceOver

                .DrawImage(bmSource, NewX, NewY, NewWidth, NewHeight)
            End With
        End Using

        Return bmDest
    End Function
#End Region

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' Add any initialization after the InitializeComponent() call.
        'b = New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
        b = New Bitmap(PictureBox1.Size.Width, PictureBox1.Size.Height)
        PictureBox1.Image = b
        graphics = graphics.FromImage(b)

        Me.DisableAero()

        RegisterHotKey(Me.Handle, 100, MOD_ALT, Keys.S)
        RegisterHotKey(Me.Handle, 100, MOD_ALT, Keys.A)

        'PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
        'translateFromFile("./saved.tiff")
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As System.Object, _
                        ByVal e As System.Windows.Forms.FormClosingEventArgs) _
                        Handles MyBase.FormClosing
        UnregisterHotKey(Me.Handle, 100)
        UnregisterHotKey(Me.Handle, 200)
    End Sub

    Private Sub DisableAero()
        Try
            aeroIsEnabled = DwmIsCompositionEnabled()
            If aeroIsEnabled = True Then
                DwmEnableComposition(False)
            End If
        Catch ex As Exception
        End Try

    End Sub

    Dim sFrm As Form
    Dim sPoint As Point
    Dim selsize As Size
    Dim selstrt As Boolean = False
    Dim selmade As Boolean = False
    Dim mDown As Boolean = False

    Private Sub StartScreenSelect()
        If selmade = True Then
            selmade = False
            sFrm.Close()
        End If
        Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        'Timer1.Stop()
        'CaptureScreenshot(New Point(0, 0), PictureBox1.Size)
        'Timer1.Start()
        If MouseButtons = Windows.Forms.MouseButtons.Left Then
            If mDown = False Then
                sPoint = New Point(MousePosition.X, MousePosition.Y)
                mDown = True
            Else
                selsize = New Size(Math.Abs(MousePosition.X - sPoint.X), Math.Abs(MousePosition.Y - sPoint.Y))
                Dim x As Integer = sPoint.X
                If sPoint.X > MousePosition.X Then x = MousePosition.X
                Dim y As Integer = sPoint.Y
                If sPoint.Y > MousePosition.Y Then y = MousePosition.Y
                If selsize.Width > 0 And selsize.Height > 0 And selstrt = False Then
                    selstrt = True
                    sFrm = New Form2
                    sFrm.Show()
                ElseIf selstrt = True Then
                    sFrm.Size = selsize
                    sFrm.Location = New Point(x, y)
                End If
            End If
        End If
        If MouseButtons = Windows.Forms.MouseButtons.None And selsize.Width > 0 And selsize.Height > 0 Then
            Timer1.Stop()
            selmade = True
            mDown = False
            selstrt = False
            selsize = New Size(0, 0)
            Dim sSize As Size = sFrm.ClientSize
            Dim sLoc As Point = sFrm.Location
            Debug.WriteLine("X=" & sLoc.X.ToString & ", Y=" & sLoc.Y.ToString & ", Width=" & sSize.Width.ToString & ", Height=" & sSize.Height.ToString)
            CaptureScreenshot(sLoc, sSize)
        End If
    End Sub

    Private Function CaptureScreenshot(startPoint As Point, DrawingSize As Size) As Boolean
        Try
            If b IsNot Nothing Then
               
                'graphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.Location, New Point(0, 0), Screen.PrimaryScreen.Bounds.Size)
                'Dim newDrawingSize As New System.Drawing.Size(PictureBox1.Size)
                'graphics.CopyFromScreen(New Point(x, y), startPoint, DrawingSize)
                'graphics.CopyFromScreen(startPoint, New Point(0, 0), DrawingSize, CopyPixelOperation.SourceAnd)
                graphics.CopyFromScreen(startPoint, New Point(0, 0), DrawingSize)
                If False Then
                    Dim x As Integer
                    Dim y As Integer
                    Dim cursorBmp As Bitmap = CaptureCursor(x, y)
                    'Draws Cursor on picture
                    graphics.DrawImage(cursorBmp, x, y)
                    cursorBmp.Dispose()
                    'Cursor.Draw(graphics, New Rectangle(Cursor.Position, Cursor.Size))
                End If

                Me.Refresh()
            End If
        Catch ex As Exception

        End Try
    End Function

    Private Shared Function CaptureCursor(ByRef x As Integer, ByRef y As Integer) As Bitmap
        Dim bmp As Bitmap
        Dim hicon As IntPtr
        Dim ci As New CURSORINFO()
        Dim icInfo As ICONINFO
        ci.cbSize = Marshal.SizeOf(ci)
        If GetCursorInfo(ci) Then
            hicon = CopyIcon(ci.hCursor)
            If GetIconInfo(hicon, icInfo) Then
                x = ci.ptScreenPos.X - CInt(icInfo.xHotspot)
                y = ci.ptScreenPos.Y - CInt(icInfo.yHotspot)
                Dim ic As Icon = Icon.FromHandle(hicon)
                bmp = ic.ToBitmap()
                ic.Dispose()
                Return bmp
            End If
        End If
        Return Nothing
    End Function

    Private Shared Function GetCursorPosition() As Point
        Dim hicon As IntPtr
        Dim ci As New CURSORINFO()
        Dim icInfo As ICONINFO
        Dim x, y As Integer
        ci.cbSize = Marshal.SizeOf(ci)
        If GetCursorInfo(ci) Then
            hicon = CopyIcon(ci.hCursor)
            If GetIconInfo(hicon, icInfo) Then
                x = ci.ptScreenPos.X - CInt(icInfo.xHotspot)
                y = ci.ptScreenPos.Y - CInt(icInfo.yHotspot)
                Return New Point(x, y)
            End If
        End If
        Return Nothing
    End Function


    <StructLayout(LayoutKind.Sequential)> _
    Public Structure CURSORINFO
        Public cbSize As Int32
        Public flags As Int32
        Public hCursor As IntPtr
        Public ptScreenPos As Point
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Public Structure ICONINFO
        Public fIcon As Boolean
        Public xHotspot As Int32
        Public yHotspot As Int32
        Public hbmMask As IntPtr
        Public hbmColor As IntPtr
    End Structure

    Private Sub translateFromMemory(ByteArray As Byte())
        Me.ForeColor = Color.Red
        Application.DoEvents()

        'Dim testImagePath = "./phototest.tif"
        Dim testImagePath = "./page1b.png"

        Try
            Using engine = New TesseractEngine("./tessdata", "eng", EngineMode.Default)
                'Using img = Pix.LoadFromFile(testImagePath)
                Using img = Pix.LoadTiffFromMemory(ByteArray)
                    Using page = engine.Process(img)
                        Dim text = page.GetText()
                        Console.WriteLine("Mean confidence: {0}", page.GetMeanConfidence())

                        Console.WriteLine("Text (GetText): " & vbCr & vbLf & "{0}", text)
                        Console.WriteLine("Text (iterator):")
                        Using iter = page.GetIterator()
                            iter.Begin()

                            Do
                                Do
                                    Do
                                        Do
                                            If iter.IsAtBeginningOf(PageIteratorLevel.Block) Then
                                                Console.WriteLine("<BLOCK>")
                                            End If

                                            TextBox1.Text &= (iter.GetText(PageIteratorLevel.Word))
                                            TextBox1.Text &= (" ")

                                            If iter.IsAtFinalOf(PageIteratorLevel.TextLine, PageIteratorLevel.Word) Then
                                                TextBox1.Text &= vbCrLf
                                            End If
                                        Loop While iter.[Next](PageIteratorLevel.TextLine, PageIteratorLevel.Word)

                                        If iter.IsAtFinalOf(PageIteratorLevel.Para, PageIteratorLevel.TextLine) Then
                                            Console.WriteLine()
                                        End If
                                    Loop While iter.[Next](PageIteratorLevel.Para, PageIteratorLevel.TextLine)
                                Loop While iter.[Next](PageIteratorLevel.Block, PageIteratorLevel.Para)
                            Loop While iter.[Next](PageIteratorLevel.Block)
                        End Using
                    End Using
                End Using
            End Using
        Catch ex As Exception
            Trace.TraceError(ex.ToString())
            Console.WriteLine("Unexpected Error: " + ex.Message)
            Console.WriteLine("Details: ")
            Console.WriteLine(ex.ToString())
        End Try
        TextBox1.Select(TextBox1.Text.Length, 0)
        TextBox1.ScrollToCaret()
    End Sub

    Private Sub translateFromFile(testImagePath As String)
        Try
            Using engine = New TesseractEngine("./tessdata", "eng", EngineMode.Default)
                Using img = Pix.LoadFromFile(testImagePath)
                    Using page = engine.Process(img)
                        Dim text = page.GetText()
                        Console.WriteLine("Mean confidence: {0}", page.GetMeanConfidence())

                        Console.WriteLine("Text (GetText): " & vbCr & vbLf & "{0}", text)
                        Console.WriteLine("Text (iterator):")
                        Using iter = page.GetIterator()
                            iter.Begin()

                            Do
                                Do
                                    Do
                                        Do
                                            If iter.IsAtBeginningOf(PageIteratorLevel.Block) Then
                                                Console.WriteLine("<BLOCK>")
                                            End If

                                            TextBox1.Text &= (iter.GetText(PageIteratorLevel.Word))
                                            TextBox1.Text &= (" ")

                                            If iter.IsAtFinalOf(PageIteratorLevel.TextLine, PageIteratorLevel.Word) Then
                                                TextBox1.Text &= vbCrLf
                                            End If
                                        Loop While iter.[Next](PageIteratorLevel.TextLine, PageIteratorLevel.Word)

                                        If iter.IsAtFinalOf(PageIteratorLevel.Para, PageIteratorLevel.TextLine) Then
                                            Console.WriteLine()
                                        End If
                                    Loop While iter.[Next](PageIteratorLevel.Para, PageIteratorLevel.TextLine)
                                Loop While iter.[Next](PageIteratorLevel.Block, PageIteratorLevel.Para)
                            Loop While iter.[Next](PageIteratorLevel.Block)
                        End Using
                    End Using
                End Using
            End Using
        Catch ex As Exception
            Trace.TraceError(ex.ToString())
            Console.WriteLine("Unexpected Error: " + ex.Message)
            Console.WriteLine("Details: ")
            Console.WriteLine(ex.ToString())
        End Try
        Console.Write("Press any key to continue . . . ")
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'Timer1.Interval = 1000
        'Timer1.Enabled = True
        StartScreenSelect()
    End Sub
End Class


Form2.vb

Code: Select all

Public Class Form2
    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Size = New Size(0, 0)
        Me.Location = New Point(MousePosition.X, MousePosition.Y)
        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
        Me.BackColor = Color.Blue
        Me.TransparencyKey = Color.Blue
        Me.TopMost = True
    End Sub
    Private Sub Form2_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        e.Graphics.DrawRectangle(New Pen(Color.Red, 2), Me.ClientRectangle)
    End Sub
End Class

Return to “Visual Basic .NET”

Who is online

Users browsing this forum: No registered users and 1 guest