I tried running this code and it crashed my kernel (on Mac OSX 10.12.6). Do 
you know why this could be?

On Wednesday, April 3, 2019 at 1:05:16 AM UTC-4, Guru Govindan wrote:
>
> Thanks a lot for your response and example. I will try today. I dont have 
> much experience with cffi. So I decided to write my tesseract python 
> interface with just ctypes.
> The following is my code for the same. It seems to work. So for loading 
> the tesseract library it takes about 160ms and recognizing the text with 
> (psm 6) takes about 140ms. These are the results with tessdata_best.
> So in order to get better performance I decided to create 100 instances of 
> my class and rotate them in an array. That way my recognizing time is under 
> ~140ms.
> But I definetely want to try with cffi as it is a cleaner interface to 
> understand and somehow feel might be better in performance.
>
> import cv2
> import ctypes
> import ctypes.util
> from datetime import datetime
>
>
> class TesseractError(Exception):
>     pass
>
> class Tesseract(object):
>     _lib = None
>     _api = None
>
>     class TessBaseAPI(ctypes._Pointer):
>         _type_ = type('_TessBaseAPI', (ctypes.Structure,), {})
>
>     @classmethod
>     def setup_lib(cls, lib_path=None):
>         if cls._lib is not None:
>             return
>         if lib_path is None:
>             lib_path = "/usr/local/lib/libtesseract.so.4"
>         cls._lib = lib = ctypes.CDLL(lib_path)
>
>         # source:
>         # 
> https://github.com/tesseract-ocr/tesseract/blob/95ea778745edd1cdf6ee22f9fe653b9e061d5708/src/api/capi.h
>
>         lib.TessBaseAPICreate.restype = cls.TessBaseAPI
>
>         lib.TessBaseAPIDelete.restype = None # void
>         lib.TessBaseAPIDelete.argtypes = (
>             cls.TessBaseAPI,) # handle
>
>         lib.TessBaseAPIInit3.argtypes = (cls.TessBaseAPI, ctypes.c_char_p, 
> ctypes.c_char_p) 
>
>         lib.TessBaseAPISetImage.restype = None
>         lib.TessBaseAPISetImage.argtypes = (cls.TessBaseAPI, 
> ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int)    
>
>         lib.TessBaseAPISetVariable.argtypes = (cls.TessBaseAPI, 
> ctypes.c_char_p, ctypes.c_char_p)
>
>         lib.TessBaseAPIGetUTF8Text.restype = ctypes.c_char_p
>         lib.TessBaseAPIGetUTF8Text.argtypes = (
>             cls.TessBaseAPI,)
>
>     def __init__(self, language='eng_best', datapath=None, lib_path=None):
>         if self._lib is None:
>             self.setup_lib(lib_path)
>         self._api = self._lib.TessBaseAPICreate()
>         print "initializing tesseract!!!!"
>         if self._lib.TessBaseAPIInit3(self._api, datapath, language):
>             print "Tesseract initialization failed!!"
>             raise TesseractError('initialization failed')
>
>     def __del__(self):
>         if not self._lib or not self._api:
>             return
>         if not getattr(self, 'closed', False):
>             self._lib.TessBaseAPIDelete(self._api)
>             self.closed = True
>
>     def _check_setup(self):
>         if not self._lib:
>             raise TesseractError('lib not configured')
>         if not self._api:
>             raise TesseractError('api not created')
>
>     def set_image(self, imagedata, width, height,
>                   bytes_per_pixel, bytes_per_line=None):
>         self._check_setup()
>         if bytes_per_line is None:
>             bytes_per_line = width * bytes_per_pixel
>         print "bytes per line={}".format(bytes_per_line)
>         self._lib.TessBaseAPISetImage(self._api,
>                                       imagedata, width, height,
>                                       bytes_per_pixel, bytes_per_line)
>
>     def set_variable(self, key, val):
>         self._check_setup()
>         self._lib.TessBaseAPISetVariable(self._api, key, val)
>
>     def get_utf8_text(self):
>         self._check_setup()
>         return self._lib.TessBaseAPIGetUTF8Text(self._api)
>
>     def get_text(self):
>         self._check_setup()
>         result = self._lib.TessBaseAPIGetUTF8Text(self._api)
>         if result:
>             return result.decode('utf-8')
>
> def convert_to_grayscale(image_data):
>     return cv2.cvtColor(image_data, cv2.COLOR_BGR2GRAY)
>
> # a method to make it look similar to tesslib.py
> def tesseract_process_image2(tess, frame_piece):
>     grayscaled = len(frame_piece.frame.shape) == 2
>     if not grayscaled:
>         image_data = convert_to_grayscale(frame_piece.frame)
>
>     height, width = frame_piece.frame.shape
>     tess.set_variable("tesseract_char_whitelist", frame_piece.whitelist)
>     tess.set_variable("tessedit_pageseg_mode", str(frame_piece.psm))
>     # tess.set_variable("user_words_suffix", "user-data")
>     # tess.set_variable("user_pattern_suffix", "user-pattern")
>     tess.set_variable("image_default_resolution", "70")
>     tess.set_image(frame_piece.frame.ctypes, width, height, 1)
>     text = tess.get_utf8_text()
>     return text.strip()
>
> class FramePiece(object):
>   def __init__(self, img, whitelist):
>     self.frame = img
>     self.whitelist = whitelist if whitelist else 
> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"
>     self.psm = 6
>
> # overloaded method for view page
> def tesseract_process_image(tess, frame, whitelist=None):
>     frame_piece = FramePiece(frame, whitelist)
>     return tesseract_process_image2(tess, frame_piece)
>
> ############################### TESTING ######################
>
>
> if __name__ == '__main__':
>     img = cv2.imread('/data/framecache/testing.jpg')
>     height, width, depth = img.shape
>     print datetime.utcnow()
>     tess = Tesseract()
>     print "ocr image Start:{}".format(datetime.utcnow())
>     frame_piece = FramePiece(img)
>     res = tesseract_process_image2(tess, frame_piece)
>     print res
>
>
>
> On Tuesday, April 2, 2019 at 2:45:13 PM UTC-7, zdenop wrote:
>>
>> OK. I have more time to look at you code and I see there few problems:
>>
>>    - Whitelist does not work at tesseract 4.0 (search for more details 
>>    in forum/issue tracker)
>>    - Setting variable: there is no variable like "
>>    image_default_resolution" in tesseract 4.x - you need to check return 
>>    value of command. Try something like this:
>>
>> # Example to set variable
>> var = "user_defined_dpi"
>> value = "250"
>> ret_val = tesseract.TessBaseAPISetVariable(api, var.encode(), 
>> value.encode())
>> print(f"SetVariable for {var}={value} {'was sucessfull' if ret_val else 
>> 'failed'}.")
>> # Example to get int variable
>> dpi = ffi.new('int *')
>> ret_val = tesseract.TessBaseAPIGetIntVariable(api, var.encode(), dpi)
>> print((f"Can not get int value for '{var}'.", f"{var}: 
>> {dpi[0]}.")[ret_val])
>>
>>
>>    - Setting data to tesseract: did you check if there in no error? Try 
>>    to get thresholded (binarized) image from tesseract to check that:
>>
>> thresholded_pix = tesseract.TessBaseAPIGetThresholdedImage(api)
>> if thresholded_pix == ffi.NULL:
>>     print(thresholded_pix)
>>     print("There is no image in tesseract api. Did you use SetImage 
>> function?")
>> else:
>>     filename = "thresholded_pix.png"
>>     if leptonica.pixWrite(filename.encode(), thresholded_pix, 
>> leptonica.IFF_PNG):
>>         print("There was problem to save thresholded image to disk.")
>>     else:
>>         print(f"Thresholded image to disk as '{filename}'.")
>>
>>
>>    - and then you will see that your usage of  TessBaseAPISetImagedoes 
>>    not what you expect. Following code worked for my test images, but  I do 
>>    not guarantee it will for for all types of image (RGBA, grays scale, 
>>    binary):
>>
>> img = cv2.imread("test.jpg", flags=cv2.IMREAD_COLOR)
>> tesseract.TessBaseAPISetImage(api,
>>     ffi.cast("unsigned char*", img.ctypes.data),
>>     img.shape[1], img.shape[0], img.shape[2], int(img.size/img.shape[0]))
>>
>>
>> I hope this will help you. Please share you result, especially if you 
>> make this code more robust.
>>
>>
>> Zdenko
>>
>>
>> ut 2. 4. 2019 o 8:54 Zdenko Podobny <zde...@gmail.com> napísal(a):
>>
>>> My code use PIL to open image files.
>>>
>>> You need to convert cv image structure to pix or send the data to 
>>>  tesseract[1] with 
>>> void SetImage(const unsigned char* imagedata, int width, int height, int 
>>> bytes_per_pixel, int bytes_per_line)[2]
>>>
>>> [1] 
>>> https://stackoverflow.com/questions/8115368/converting-cvmat-for-tesseract
>>>   
>>> [2] https://github.com/tesseract-
>>>
>>> ocr/tesseract/blob/3e7144e79654d9da7a180a3c51e843afb4a77491/src/api/baseapi.h#L333
>>>
>>> If you have problem, post your code and image.
>>>
>>> Zdenko
>>>
>>>
>>> ut 2. 4. 2019 o 8:46 Guru Govindan <gurunatha...@gmail.com> napísal(a):
>>>
>>>> Hi Thanks a lot for the great post. I am trying to use cffi wrapper in 
>>>> my project as the pytesseract was really slow.
>>>> I use opencv to read my image and I am trying to use your cffi setup 
>>>> and initiate. But I the tesseract is not recognizing any text. 
>>>>
>>>> import ctypes
>>>> import os
>>>>
>>>> import cffi
>>>>
>>>> import cv2
>>>>
>>>> tessdata = "/home/vagrant/reelz_base/shared/tessdata/"
>>>>
>>>> ffi = cffi.FFI()
>>>>
>>>> ffi.cdef("""
>>>> typedef signed char             l_int8;
>>>> typedef unsigned char           l_uint8;
>>>> typedef short                   l_int16;
>>>> typedef unsigned short          l_uint16;
>>>> typedef int                     l_int32;
>>>> typedef unsigned int            l_uint32;
>>>> typedef float                   l_float32;
>>>> typedef double                  l_float64;
>>>> typedef long long               l_int64;
>>>> typedef unsigned long long      l_uint64;
>>>> typedef int l_ok; /*!< return type 0 if OK, 1 on error */
>>>>
>>>>
>>>>
>>>> typedef struct TessBaseAPI TessBaseAPI;
>>>> typedef struct ETEXT_DESC ETEXT_DESC;
>>>> typedef struct TessPageIterator TessPageIterator;
>>>> typedef struct TessResultIterator TessResultIterator;
>>>> typedef int BOOL;
>>>>
>>>> typedef enum TessOcrEngineMode  {
>>>>     OEM_TESSERACT_ONLY          = 0,
>>>>     OEM_LSTM_ONLY               = 1,
>>>>     OEM_TESSERACT_LSTM_COMBINED = 2,
>>>>     OEM_DEFAULT                 = 3} TessOcrEngineMode;
>>>>
>>>> typedef enum TessPageSegMode {
>>>>     PSM_OSD_ONLY               =  0,
>>>>     PSM_AUTO_OSD               =  1,
>>>>     PSM_AUTO_ONLY              =  2,
>>>>     PSM_AUTO                   =  3,
>>>>     PSM_SINGLE_COLUMN          =  4,
>>>>     PSM_SINGLE_BLOCK_VERT_TEXT =  5,
>>>>     PSM_SINGLE_BLOCK           =  6,
>>>>     PSM_SINGLE_LINE            =  7,
>>>>     PSM_SINGLE_WORD            =  8,
>>>>     PSM_CIRCLE_WORD            =  9,
>>>>     PSM_SINGLE_CHAR            = 10,
>>>>     PSM_SPARSE_TEXT            = 11,
>>>>     PSM_SPARSE_TEXT_OSD        = 12,
>>>>     PSM_COUNT                  = 13} TessPageSegMode;
>>>>
>>>> typedef enum TessPageIteratorLevel {
>>>>      RIL_BLOCK    = 0,
>>>>      RIL_PARA     = 1,
>>>>      RIL_TEXTLINE = 2,
>>>>      RIL_WORD     = 3,
>>>>      RIL_SYMBOL    = 4} TessPageIteratorLevel;    
>>>>
>>>> TessPageIterator* TessBaseAPIAnalyseLayout(TessBaseAPI* handle);
>>>> TessPageIterator* TessResultIteratorGetPageIterator(TessResultIterator* 
>>>> handle);
>>>>
>>>> BOOL TessPageIteratorNext(TessPageIterator* handle, 
>>>> TessPageIteratorLevel level);
>>>> BOOL TessPageIteratorBoundingBox(const TessPageIterator* handle, 
>>>> TessPageIteratorLevel level,
>>>>                                  int* left, int* top, int* right, int* 
>>>> bottom);
>>>>
>>>> const char* TessVersion();
>>>>
>>>> TessBaseAPI* TessBaseAPICreate();
>>>> void  TessBaseAPIDelete(TessBaseAPI* handle);
>>>>
>>>> size_t TessBaseAPIGetOpenCLDevice(TessBaseAPI* handle, void **device);
>>>>
>>>> void  TessBaseAPISetInputName( TessBaseAPI* handle, const char* name);
>>>>
>>>> const char* TessBaseAPIGetInputName(TessBaseAPI* handle);
>>>>
>>>> void  TessBaseAPISetInputImage(TessBaseAPI* handle, struct Pix* pix);
>>>>
>>>> int   TessBaseAPIGetSourceYResolution(TessBaseAPI* handle);
>>>>
>>>>
>>>> BOOL  TessBaseAPISetVariable(TessBaseAPI* handle, const char* name, 
>>>> const char* value);
>>>> BOOL  TessBaseAPISetDebugVariable(TessBaseAPI* handle, const char* 
>>>> name, const char* value);
>>>>
>>>> void  TessBaseAPIPrintVariables(      const TessBaseAPI* handle, FILE* 
>>>> fp);
>>>>
>>>> BOOL  TessBaseAPIPrintVariablesToFile(const TessBaseAPI* handle, const 
>>>> char* filename);
>>>>
>>>> int   TessBaseAPIInit1(TessBaseAPI* handle, const char* datapath, const 
>>>> char* language, TessOcrEngineMode oem,
>>>>                                          char** configs, int 
>>>> configs_size);
>>>> int   TessBaseAPIInit2(TessBaseAPI* handle, const char* datapath, const 
>>>> char* language, TessOcrEngineMode oem);
>>>>
>>>> int   TessBaseAPIInit3(TessBaseAPI* handle, const char* datapath, const 
>>>> char* language);
>>>>
>>>> int TessBaseAPIInit4(TessBaseAPI* handle, const char* datapath, const 
>>>> char* language, TessOcrEngineMode mode,
>>>>    char** configs, int configs_size,
>>>>    char** vars_vec, char** vars_values, size_t vars_vec_size,
>>>>    BOOL set_only_non_debug_params);
>>>>    
>>>> void TessBaseAPISetImage(TessBaseAPI* handle, const unsigned char* 
>>>> imagedata, int width, int height,
>>>>                                              int bytes_per_pixel, int 
>>>> bytes_per_line);
>>>>    
>>>> int TessBaseAPIRecognize(TessBaseAPI* handle, ETEXT_DESC* monitor);
>>>> TessResultIterator* TessBaseAPIGetIterator(TessBaseAPI* handle);
>>>> BOOL   TessResultIteratorNext(TessResultIterator* handle, 
>>>> TessPageIteratorLevel level);
>>>> char*  TessResultIteratorGetUTF8Text(const TessResultIterator* handle, 
>>>> TessPageIteratorLevel level);
>>>> float  TessResultIteratorConfidence(const TessResultIterator* handle, 
>>>> TessPageIteratorLevel level);
>>>> char*  TessBaseAPIGetUTF8Text(TessBaseAPI* handle);
>>>> const char*  TessResultIteratorWordFontAttributes(const 
>>>> TessResultIterator* handle, BOOL* is_bold, BOOL* is_italic,
>>>>                                                               BOOL* 
>>>> is_underlined, BOOL* is_monospace, BOOL* is_serif,
>>>>                                                               BOOL* 
>>>> is_smallcaps, int* pointsize, int* font_id);
>>>> BOOL TessResultIteratorWordIsFromDictionary(const TessResultIterator* 
>>>> handle);
>>>> BOOL TessResultIteratorWordIsNumeric(const TessResultIterator* handle);
>>>> BOOL TessResultIteratorSymbolIsSuperscript(const TessResultIterator* 
>>>> handle);
>>>> BOOL TessResultIteratorSymbolIsSubscript(const TessResultIterator* 
>>>> handle);
>>>> BOOL TessResultIteratorSymbolIsDropcap(const TessResultIterator* 
>>>> handle);
>>>>
>>>> void   TessBaseAPIEnd(TessBaseAPI* handle);
>>>> """)
>>>>
>>>> tess_libname = "/usr/local/lib/libtesseract.so.4"
>>>>
>>>> if os.path.exists(tess_libname):
>>>>     tesseract = ffi.dlopen(tess_libname)
>>>>
>>>> api = None
>>>> tesseract_version = ffi.string(tesseract.TessVersion())
>>>> print('Tesseract-ocr version', tesseract_version.decode('utf-8'))
>>>> api = tesseract.TessBaseAPICreate()
>>>>
>>>> c_ubyte_p = ctypes.POINTER(ctypes.c_ubyte)
>>>>
>>>> lang="eng"
>>>> oem = tesseract.OEM_DEFAULT
>>>> tesseract.TessBaseAPIInit3(api, tessdata.encode(), lang.encode())
>>>> img = cv2.imread("/data/framecache/testing.jpg")
>>>>
>>>> tesseract.TessBaseAPISetDebugVariable(api, "tesseract_char_whitelist", 
>>>> "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
>>>> tesseract.TessBaseAPISetDebugVariable(api, "tessedit_pageseg_mode", "8")
>>>> tesseract.TessBaseAPISetVariable(api, "image_default_resolution", "72")
>>>>
>>>> tesseract.TessBaseAPISetImage(api, ffi.cast("unsigned char*", 
>>>> img.ctypes.data), img.shape[0], img.shape[1], 1, img.shape[1])
>>>>
>>>> # tesseract.TessBaseAPIRecognize(api, ffi.NULL)
>>>>
>>>> utf8_text = 
>>>> ffi.string(tesseract.TessBaseAPIGetUTF8Text(api)).decode('utf-8')
>>>> print utf8_text
>>>>
>>>>
>>>>
>>>>
>>>> On Sunday, March 24, 2019 at 10:10:36 AM UTC-7, zdenop wrote:
>>>>>
>>>>> Hi all,
>>>>>
>>>>> I publish my test / example how to use tesseract C-API in python3 via 
>>>>> cffi[1]. 
>>>>>
>>>>> I am aware of pytesseract module, which seems to be widely used. It is 
>>>>> wrapping tesseract executable, so IMO it could have some limitation e.g. 
>>>>> from point of performance (it using disk operation for input and output).
>>>>>  
>>>>> It is in form of jupyter notebook[3] (github is able to show it, but 
>>>>> not run ;-)) so you can interactively view what is happening.
>>>>>
>>>>> My aim is not to create new tesseract python wrapper (I do not have a 
>>>>> time for it, and I am not able to create nice python code as pytesseract  
>>>>> has :-) ) so it is not robust: I just did it on windows 64 bit, but IMO 
>>>>> is 
>>>>> should be possible with small modification to use in Linux and Mac. If 
>>>>> needed I can add 32bit windows libs...
>>>>>
>>>>> Personally I would like have python tesseract and leptonica module 
>>>>> using directly its API... I know that James Barlow already started to 
>>>>> wrapping leptonica, but it is (not yet?) available as independent module 
>>>>> (it is part of OCRmyPDF). 
>>>>>
>>>>> Anyway I hope this will help somebody.
>>>>>
>>>>> [1] https://github.com/zdenop/SimpleTesseractPythonWrapper  
>>>>> [2] https://pypi.org/project/pytesseract/
>>>>> [3] 
>>>>> https://github.com/zdenop/SimpleTesseractPythonWrapper/blob/master/SimpleTesseractPythonWrapper.ipynb
>>>>>  
>>>>> [4] https://github.com/jbarlow83/OCRmyPDF/tree/master/src/ocrmypdf/lib
>>>>>   
>>>>>
>>>>> Zdenko
>>>>>
>>>> -- 
>>>> You received this message because you are subscribed to the Google 
>>>> Groups "tesseract-ocr" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to tesser...@googlegroups.com.
>>>> To post to this group, send email to tesser...@googlegroups.com.
>>>> Visit this group at https://groups.google.com/group/tesseract-ocr.
>>>> To view this discussion on the web visit 
>>>> https://groups.google.com/d/msgid/tesseract-ocr/d6253a61-d796-4cce-8412-f2cc61e83000%40googlegroups.com
>>>>  
>>>> <https://groups.google.com/d/msgid/tesseract-ocr/d6253a61-d796-4cce-8412-f2cc61e83000%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>

-- 
You received this message because you are subscribed to the Google Groups 
"tesseract-ocr" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to tesseract-ocr+unsubscr...@googlegroups.com.
To post to this group, send email to tesseract-ocr@googlegroups.com.
Visit this group at https://groups.google.com/group/tesseract-ocr.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/tesseract-ocr/aadcec62-c198-4b61-9318-17ff27e26876%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to