2016-04-26 4 views
3

Ich versuche this cpp function von Python zu nennen:Segmentation fault während CPP Funktion von Python Aufruf

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; 
} 

Der letzte Parameter dieser Funktion TessResultRenderer ist. Es another cpp function ist TessResultRenderer zum Erstellen Jetzt

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

beim Aufruf aus meiner Python, ich habe folgende:

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 

aber ich erhalte immer Segmentation fault Fehler.

Meine Frage ist, wie kann ich TessBaseAPIProcessPages von Python?

Einige weitere Referenz-Links in die Code-Basis:

referer api

Implementation of processPages(...)

bearbeiten

Nachdem die kommentierten Vorschläge versuchen, habe ich die folgenden, aber ich erhalte eine Fehlermeldung: 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 
+1

Der Standard-Ergebnistyp ist 'c_int'. Es ist auch der Standardkonvertierungstyp für Integer-Argumente. Lerne, wie man 'artype' und 'artypes' setzt. – eryksun

+0

@eryksun Der Ergebnistyp von 'TessTextRendererCreate' ist' neuer TessTextRenderer'. Ich bin mir der Argentypen bewusst, bin mir aber nicht sicher, wie ich sie hier anwenden soll. – Anthony

+1

Verwenden Sie einen undurchsichtigen Typ: 'class TessResultRenderer (ctypes.Structure): pass '. Erstellen Sie dafür einen Zeigertyp: 'PTessResultRenderer = ctypes.POINTER (TessResultRenderer)'. Setzen Sie dann 'tesseract.TessTextRendererCreate.rrestype = PTessResultRenderer'. – eryksun

Antwort

3

Es gibt ein Beispiel für die Verwendung der Tesseract C-API aus Ctypes im Contrib-Ordner. Es scheint jedoch etwas veraltet zu sein. contrib/tesseract-c_api-demo.py

Sie müssen die restype und argtypes für ein paar Methoden einstellen. Vergessen Sie auch nicht, die Init-Funktion für den Handler aufzurufen. Das folgende Beispiel funktioniert für mich. Es liest den Text aus einer Datei namens "test.bmp" in Englisch in die Variable text.

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) 

Die Ausgabe sieht wie folgt aus:

============================================================================== 
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: Ersetzt Verwendung von c_void_p mit undurchsichtigen Typen wie eryksun vorgeschlagen. Vielen Dank!

+1

'c_void_p' funktioniert, aber es ist nicht typsicher. Sie sollten alle Tools nutzen, um saubere Python-Ausnahmen für Programmierfehler zu erhalten, anstatt den Prozess mit einem segfault abzustürzen. Können Sie meine Vorschläge integrieren, um undurchsichtige Typen zu definieren? Es sind nur ein paar Zeilen Code, um 'PTessBaseAPI' und' PTessResultRenderer' zu definieren, die anstelle von 'c_void_p' verwendet werden. – eryksun

+0

@eryksun Ich habe keine undurchsichtigen Typen gefunden, bis ich deine Kommentare gelesen habe. Danke für die Aufklärung! – Snorfalorpagus

+0

@Snorfalorpagus Danke! das hat für mich funktioniert. Danke, dass Sie sich zu dem Thema in tesseract repo geäußert haben. Ich öffnete ein anderes Problem, wo ich verschiedene Ergebnisse von tesseract Befehlszeile vs. API erhalte: https://github.com/tesseract-ocr/tesseract/issues/312 Weißt du, was den Unterschied verursachen könnte? – Anthony

0

Segmentierungsfehler treten auf, wenn Sie von einem Array ablaufen oder wenn Sie einen Nullzeiger de-referenzieren. Wenn Sie einen Debugger verwenden, wird er Sie durch Ihren gesamten Code führen und Ihnen genau zeigen, was vor sich geht.