3

I am trying to call this cpp function from python:

TESS_API BOOL TESS_CALL TessBaseAPIProcessPages(TessBaseAPI* handle, const char* filename, 
  const char* retry_config, int timeout_millisec, TessResultRenderer* renderer)
{
    if (handle->ProcessPages(filename, retry_config, timeout_millisec, renderer))
        return TRUE;
    else
        return FALSE;
}

The last parameter of this function is TessResultRenderer. There is another cpp function for creating TessResultRenderer

TESS_API TessResultRenderer* TESS_CALL TessTextRendererCreate(const char* outputbase)
{
    return new TessTextRenderer(outputbase);
}

Now while calling this from my python, I did the following:

outputbase = "stdout"
renderer = tesseract.TessTextRendererCreate(outputbase)
text_out = tesseract.TessBaseAPIProcessPages(api, 
     ctypes.create_string_buffer(path), 
     None, 0, renderer) //Segmentation fault (core dumped) error on this line

but I keep getting Segmentation fault error.

My question is how can I called TessBaseAPIProcessPages from Python?

Some more reference links into the codebase:

referer api

Implementation of processPages(...)

Edit

After trying the commented suggestions, I did the following but I get an error: item 1 in _argtypes_ has no from_param method

PTessResultRenderer = ctypes.POINTER(TessResultRenderer)
self.tesseract.TessTextRendererCreate.restype = PTessResultRenderer
outputbase = "stdout"
self.tesseract.TessTextRendererCreate.argtypes = [outputbase] #error here
self.tesseract.TessTextRendererCreate

ReturnVal = ctypes.c_bool
self.tesseract.TessBaseAPIProcessPages.argtypes = [self.api, path, None, 0, PTessResultRenderer]
self.tesseract.TessBaseAPIProcessPages.restype = ReturnVal
self.tesseracto.TessBaseAPIProcessPages

class TessResultRenderer(ctypes.Structure):
    pass
6
  • 1
    The default result type is c_int. It's also the default conversion type for integer arguments. Learn how to set restype and argtypes. Commented Apr 26, 2016 at 18:43
  • @eryksun the result type of TessTextRendererCreate is new TessTextRenderer. I'm aware of the argtypes but not sure how to apply it here. Commented Apr 26, 2016 at 20:45
  • 1
    Use an opaque type: class TessResultRenderer(ctypes.Structure): pass. Create a pointer type for it: PTessResultRenderer = ctypes.POINTER(TessResultRenderer). Then set tesseract.TessTextRendererCreate.restype = PTessResultRenderer. Commented Apr 26, 2016 at 21:00
  • 1
    @eryksun I've edited the question with what I've tried based on your kind help. Could you please take a look...I still get an error. Commented Apr 26, 2016 at 21:56
  • 1
    argtypes is to specify the types of the parameters, not for calling the function. For example: tesseract.TessTextRendererCreate.argtypes = [ctypes.c_char_p] and tesseract.TessBaseAPIProcessPages.argtypes = [PTessBaseAPI, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int, PTessResultRenderer]. Commented Apr 26, 2016 at 22:10

2 Answers 2

4

There is an example of using the tesseract C-API from ctypes in the contrib folder. However it seems to be a little out of date. contrib/tesseract-c_api-demo.py

You need to set the restype and argtypes for a few methods. Also, don't forget to call the init function on the handler. The following example works for me. It reads the text from a file called "test.bmp" in English into the text variable.

from ctypes import *
from ctypes.util import find_library

lang = b"eng"
filename = b"test.bmp"
TESSDATA_PREFIX = b"/usr/local/Cellar/tesseract/3.04.01_1/share/tessdata"

path = find_library("libtesseract.dylib")
tesseract = CDLL(path)

class TessBaseAPI(Structure):
    pass
class TessResultRenderer(Structure):
    pass

tesseract.TessBaseAPICreate.restype = POINTER(TessBaseAPI)
tesseract.TessBaseAPIInit3.argtypes = [POINTER(TessBaseAPI), c_char_p, c_char_p]
tesseract.TessBaseAPIInit3.restype = c_bool
tesseract.TessBaseAPIProcessPages.argtypes = [POINTER(TessBaseAPI), c_char_p, c_char_p, c_int, POINTER(TessResultRenderer)]
tesseract.TessBaseAPIProcessPages.restype = c_bool
tesseract.TessBaseAPIGetUTF8Text.argtypes = [POINTER(TessBaseAPI)]
tesseract.TessBaseAPIGetUTF8Text.restype = c_char_p

api = tesseract.TessBaseAPICreate()
rc = tesseract.TessBaseAPIInit3(api, TESSDATA_PREFIX, lang);
if (rc):
    tesseract.TessBaseAPIDelete(api)
    print("Could not initialize tesseract.\n")
    exit(3)

success = tesseract.TessBaseAPIProcessPages(api, filename, None , 0, None)

if success:
    text = tesseract.TessBaseAPIGetUTF8Text(api)
    print("="*78)
    print(text.decode("utf-8").strip())
    print("="*78)

The output looks like this:

==============================================================================
This is a lot of 12 point text to test the
ocr code and see if it works on all types
of file format.

The quick brown dog jumped over the
lazy fox. The quick brown dog jumped
over the lazy fox. The quick brown dog
jumped over the lazy fox. The quick
brown dog jumped over the lazy fox.
==============================================================================

Edit: Replaced use of c_void_p with opaque types as suggested by eryksun. Thanks!

Sign up to request clarification or add additional context in comments.

5 Comments

c_void_p works, but it's not type safe. You should take advantage of all the tools to get clean Python exceptions for programming errors, rather than crashing the process with a segfault. Can you integrate my suggestions to define opaque types? It will just be a few lines of code to define PTessBaseAPI and PTessResultRenderer to use in place of c_void_p.
@eryksun I hadn't come across opaque types until reading your comments. Thanks for the enlightenment!
@Snorfalorpagus Thanks! that worked for me. Also, thanks for commenting on the related issue in tesseract repo. I opened another issue where I am getting different results from tesseract command line vs. API: github.com/tesseract-ocr/tesseract/issues/312 Do you know what might be causing the difference?
@Snorfalorpagus I'm noticing that using TessBaseAPIProcessPages returns text from only the LAST page of the multipage tiff rather than returning text from ALL pages. Have you come across this? I've filed an issue here as well github.com/tesseract-ocr/tesseract/issues/1138
Your usage of b"string" instead of just "string" helped me out. I don't see that in the documentation, but the b" is definitely required.
0

Segmentation faults occur when you run off of an array, or if you de-reference a null pointer. If you use a debugger, it will step you through all your code and show you exactly what is going on.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.