Can anyone implement a simple tesseract dllcall example? Topic is solved
-
- Posts: 502
- Joined: 03 Dec 2018, 20:02
Can anyone implement a simple tesseract dllcall example?
I tried Vis2 but it's quite slow because each time it runs tesseract cli binary. The UWP OCR is fast but it won't recognize certain texts and is less accurate than tesseract. It would be great if ahk can directly interop with the tesseract library.
There is a C++ example here but unfortunately I don't know much C++
It will be a big step forward if this is implemented (accurate and fast OCR library).
There is a C++ example here but unfortunately I don't know much C++
It will be a big step forward if this is implemented (accurate and fast OCR library).
Re: Can anyone implement a simple tesseract dllcall example?
in a folder, download and put:
- https://github.com/tesseract-ocr/tessdata/blob/master/eng.traineddata
- https://github.com/nguyenq/tess4j/blob/master/src/main/resources/win32-x86-64/libtesseract500.dll (dont forget to Unblock) (yes, the links will break over time. use common sense or compile the dlls from source urself)
- https://github.com/nguyenq/lept4j/blob/master/src/main/resources/win32-x86-64/liblept1811.dll (same) (yes, the links will break over time. use common sense or compile the dlls from source urself)
- https://github.com/tesseract-ocr/test/blob/master/testing/phototest.tif
Code: Select all
DllCall("LoadLibrary", "Str", "libtesseract500.dll", "Ptr") MsgBox % "Version: " DllCall("libtesseract500\TessVersion", "AStr") hAPI := DllCall("libtesseract500\TessBaseAPICreate", "Ptr") DllCall("libtesseract500\TessBaseAPIInit3", "Ptr", hAPI, "AStr", A_ScriptDir, "AStr", "eng") hPix := DllCall("liblept1811\pixRead", "AStr", A_ScriptDir "\phototest.tif", "Ptr") DllCall("libtesseract500\TessBaseAPISetImage2", "Ptr", hAPI, "Ptr", hPix) MsgBox % DllCall("libtesseract500\TessBaseAPIGetUTF8Text", "Ptr", hAPI, "AStr")
Last edited by swagfag on 17 Apr 2023, 02:25, edited 1 time in total.
-
- Posts: 502
- Joined: 03 Dec 2018, 20:02
Re: Can anyone implement a simple tesseract dllcall example?
@swagfag Thank you so much!
-
- Posts: 502
- Joined: 03 Dec 2018, 20:02
Re: Can anyone implement a simple tesseract dllcall example?
@swagfag Is it possible to pass an image from memory to pixRead? That way we can recognize texts on screen directly without saving the screenshot as a file. Looks like there is a pixReadMem function in the leptonica library.
Re: Can anyone implement a simple tesseract dllcall example?
pixReadMem - reads bitmap file from memory.
So You need create BITMAPFILEHEADER and BITMAPINFOHEADER structures and combine with bitmap data by Yourself.
So You need create BITMAPFILEHEADER and BITMAPINFOHEADER structures and combine with bitmap data by Yourself.
Re: Can anyone implement a simple tesseract dllcall example?
if u already got it in memory might as well invoke one of the overloads directly
https://github.com/tesseract-ocr/tesseract/blob/master/src/api/capi.cpp#L295-L296
https://tesseract-ocr.github.io/tessapi/5.x/a02438.html#aa463622111f3b11d8fca5863709cc699
https://github.com/tesseract-ocr/tesseract/blob/master/src/api/capi.cpp#L295-L296
https://tesseract-ocr.github.io/tessapi/5.x/a02438.html#aa463622111f3b11d8fca5863709cc699
-
- Posts: 502
- Joined: 03 Dec 2018, 20:02
Re: Can anyone implement a simple tesseract dllcall example?
Thanks! Should I pass the image as a buffer? How do I get bytes_per_pixel, bytes_per_line for the image?
Code: Select all
DllCall("libtesseract500\TessBaseAPISetImage", "Ptr", hAPI, "Ptr", hImg, "Int", image_width, "Int", image_height, "Int", , "Int", )
Re: Can anyone implement a simple tesseract dllcall example?
u loaded the image. either u know these properties ahead of time, or if theyre encoded in the image's metadata u can read them off, or u could derive them according to the image's format specification or u use whatever image introspection functions are available to u(if any, and presumably from the same set of APIs that allowed u to load the image in the first place)
Re: Can anyone implement a simple tesseract dllcall example?
You should pass pointer to a bit array of Your bitmap.Should I pass the image as a buffer?
Code: Select all
bytes_per_pixel := bits_per_pixel/8
bytes_per_line := bytes_per_pixel*image_width
Re: Can anyone implement a simple tesseract dllcall example? Topic is solved
Thanks to swagfag I made sample script below to demonstrate use of using Tesseract to ocr a file and screenshot using pixReadMemBmp / TessBaseAPISetImage. Uncomment the line with out.bmp to see output of screenshot
Code: Select all
#NoEnv ; Don't check empty variables to see if they are environment variables (significantly improves performance)
; https://www.autohotkey.com/boards/viewtopic.php?f=76&t=93120
; download to same folder
; https://github.com/tesseract-ocr/tessdata/blob/master/eng.traineddata
; https://github.com/nguyenq/tess4j/blob/master/src/main/resources/win32-x86-64/libtesseract500.dll (dont forget to Unblock)
; https://github.com/nguyenq/lept4j/blob/master/src/main/resources/win32-x86-64/liblept1820.dll (same)
; https://github.com/tesseract-ocr/test/blob/master/testing/phototest.tif
msgbox % ocr("phototest.tif") ; ocr file
msgbox % ocr() ; ocr screen
return
ocr(win_id="",x1=0,y1=0,x2="",y2="",whitelist="",bw="",v=20,leptonica=0)
{
static hAPI, header
if !hAPI
LoadLibrary("libtesseract500.dll")
, LoadLibrary("liblept1820.dll")
, hAPI := DllCall("libtesseract500\TessBaseAPICreate", "Ptr")
, DllCall("libtesseract500\TessBaseAPIInit3", "Ptr", hAPI, "AStr", A_ScriptDir, "AStr", "eng")
, VarSetCapacity(header, 54, 0)
, NumPut(0x360000, NumPut(1, NumPut(0x5FC64D42, header, "UInt"), "UInt"), "UInt") ; Bitmap file header (14 bytes)
if whitelist
DllCall("libtesseract500\TessBaseAPISetVariable", "Ptr", hAPI, "Str", "tessedit_char_whitelist", "Str", whitelist)
if (win_id<>"") && FileExist(win_id)
hPix := DllCall("liblept1820\pixRead", "AStr", win_id, "Ptr")
, DllCall("libtesseract500\TessBaseAPISetImage2", "Ptr", hAPI, "Ptr", hPix)
, str:= DllCall("libtesseract500\TessBaseAPIGetUTF8Text", "Ptr", hAPI, "AStr")
else {
if (win_id=="")
win_id:=WinExist("A")
if (x2=="")
WinGetPos,,,x2,,ahk_id %win_id%
if (y2=="")
WinGetPos,,,,y2,ahk_id %win_id%
x:=min(x1,x2), y:=min(y1,y2), w:=abs(x2-x1)+1, h:=abs(y2-y1)+1
, bh := -h ; must be -h for Tesseract
, NumPut(32, NumPut(1, NumPut(bh, NumPut(w, NumPut(40, header, 14, "uint"), "int"), "int"), "UShort"), 0, "UShort") ; bitmap info for CreateDIB (40 bytes) positive h for Capture2Text to work
, src := DllCall("user32.dll\GetDCEx", "Ptr", win_id, "Ptr", 0, "UInt", 3, "Ptr")
, dst := DllCall("CreateCompatibleDC", "Ptr", src, "Ptr")
, DIB := DllCall("CreateDIBSection", "Ptr", dst, "Ptr", &header+14, "UInt", 0, "Ptr*", pbits, "Ptr", 0, "UInt", 0, "Ptr")
, DllCall("SelectObject", "Ptr", dst, "Ptr", DIB, "Ptr")
, DllCall("BitBlt", "ptr", dst, "int", 0, "int", 0, "int", w, "int", h, "ptr", src, "int", x, "int", y, "Uint", 0xCC0020)
if (bw<>"")
{
b:=(bw>>16)&x0xFF, g:=(bw>>8)&0xFF, r:=bw&0xFF
Loop % w*h
{
Addr := pbits + A_Index*4
if (abs(r - NumGet(Addr+2, 0, "UChar"))<=v)
&& (abs(g - NumGet(Addr+1, 0, "UChar"))<=v)
&& (abs(b - NumGet(Addr+0, 0, "UChar"))<=v)
Numput(0, Addr+0, "UInt")
else Numput(0xFFFFFF, Addr+0, "UInt")
}
}
if leptonica
{
hData := DllCall("GlobalAlloc", "uint", 0x2, "uint", 54 + w*h*4, "ptr")
, pData := DllCall("GlobalLock", "ptr", hData, "ptr")
, DllCall("RtlMoveMemory", "ptr", pData + 0, "ptr", &header, "UInt", 54) ; destination, source, length
, DllCall("RtlMoveMemory", "ptr", pData + 54, "ptr", pbits, "UInt", w*h*4)
, hPix := DllCall("liblept1820\pixReadMemBmp", "Ptr", pData, "UInt", 54+w*h*4, "Ptr")
, DllCall("libtesseract500\TessBaseAPISetImage2", "Ptr", hAPI, "Ptr", hPix)
; , out := FileOpen("out.bmp", "w"), out.Rawwrite(pData+0,54+w*h*4), out.Close()
, DllCall("GlobalUnlock", "ptr", hData) ; don't unlock immediately after rtlmovememory, wait a little bit
} else DllCall("libtesseract500\TessBaseAPISetImage", "Ptr", hAPI, "Ptr", pbits, "UInt", w, "UInt", h, "UInt", bytes_per_pixel := 4, "UInt", bytes_per_line := 4*w)
str := DllCall("libtesseract500\TessBaseAPIGetUTF8Text", "Ptr", hAPI, "AStr")
DllCall("DeleteDC", "ptr", dst)
, DllCall("DeleteObject", "ptr", dib)
, DllCall("ReleaseDC", "ptr", win_id, "ptr", src)
}
return str
}
LoadLibrary(dll)
{
if !hModule:=DllCall("LoadLibrary", "Str", dll, "Ptr")
msgbox % "LoadLibrary(" dll "): " GetLastError(A_LastError)
return hModule
}
GetLastError(Error=0)
{
VarSetCapacity(ErrorString, 1024)
IfEqual, Error, 0, SetEnv, Error, %A_LastError%
if DllCall("FormatMessage"
, "UINT", 0x1000 ; FORMAT_MESSAGE_FROM_SYSTEM: The function should search the system message-table resource(s) for the requested message.
, "PTR", 0 ; A handle to the module that contains the message table to search.
, "UINT", Error
, "UINT", 0 ; Language-ID is automatically retreived
, "Str", ErrorString
, "UINT", 1024 ; Buffer-Length
, "STR", "") ; "str", "") ;An array of values that are used as insert values in the formatted message. (not used)
return ErrorString
}
-
- Posts: 4393
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Can anyone implement a simple tesseract dllcall example?
This is most likely incorrect, should be
Code: Select all
pStr := DllCall("libtesseract500\TessBaseAPIGetUTF8Text", "Ptr", hAPI, "Ptr")
MsgBox, % StrGet(pStr, "UTF-8")
-
- Posts: 2
- Joined: 30 Nov 2022, 22:51
Re: Can anyone implement a simple tesseract dllcall example?
Can somebody help me,
1. Where to get liplept dll ?
2. i cant load tesseract dll and always got error code 126, how to resolve that ?
1. Where to get liplept dll ?
2. i cant load tesseract dll and always got error code 126, how to resolve that ?
-
- Posts: 2
- Joined: 30 Nov 2022, 22:51
Re: Can anyone implement a simple tesseract dllcall example?
Thanks @malcev now its working,
Re: Can anyone implement a simple tesseract dllcall example?
wasnt really the point of the example, but yes its incorrect. should be freed with:teadrinker wrote: ↑19 Oct 2021, 16:22This is most likely incorrect, should beCode: Select all
pStr := DllCall("libtesseract500\TessBaseAPIGetUTF8Text", "Ptr", hAPI, "Ptr") MsgBox, % StrGet(pStr, "UTF-8")
Code: Select all
DllCall("libtesseract500\TessDeleteText", "Ptr", pStr)
-
- Posts: 188
- Joined: 08 Jul 2019, 05:37
- Contact:
Re: Can anyone implement a simple tesseract dllcall example?
Code: Select all
~ObjectCache(): WARNING! LEAK! object 00000000009AE440 still has count 1
Code: Select all
DllCall("libtesseract531\TessBaseAPIDelete","Ptr", hAPI)
Re: Can anyone implement a simple tesseract dllcall example?
I free like this:
Code: Select all
DllCall("libtesseract500\TessDeleteText", "ptr", pStr)
DllCall("libtesseract500\TessBaseAPIClear", "ptr", hApi)
DllCall("libtesseract500\TessBaseAPIEnd", "ptr", hApi)
DllCall("libtesseract500\TessBaseAPIDelete", "ptr", hApi)