Commit cca1df11 authored by Jerome Flesch's avatar Jerome Flesch

Tesseract C-API: Begin implementing detect_orientation().

(For some reason, tesseract doesn't detect any script in the image ; SetImage() failed silently ?)
Signed-off-by: Jerome Flesch's avatarJerome Flesch <jflesch@gmail.com>
parent d18912d4
......@@ -51,8 +51,34 @@ def can_detect_orientation():
def detect_orientation(image, lang=None):
# TODO
pass
handle = tesseract_raw.init(lang=lang)
try:
tesseract_raw.set_page_seg_mode(
handle, tesseract_raw.PageSegMode.OSD_ONLY
)
tesseract_raw.set_image(handle, image)
tesseract_raw.recognize(handle)
page_iterator = tesseract_raw.analyse_layout(handle)
if page_iterator is None:
raise TesseractError(
"failed", "Orientation detection failed. No script ?"
)
try:
orientation = page_iterator_orientation(page_iterator)
angle = {
tesseract_raw.Orientation.PAGE_UP: 0,
tesseract_raw.Orientation.PAGE_RIGHT: 90,
tesseract_raw.Orientation.PAGE_DOWN: 180,
tesseract_raw.Orientation.PAGE_LEFT: 270
}[orientation['orientation']]
return {
"angle": angle,
# TODO: confidence
}
finally:
tesseract_raw.page_iterator_delete(page_iterator)
finally:
tesseract_raw.cleanup(handle)
def get_name():
......@@ -83,7 +109,11 @@ def is_available():
def get_available_languages():
return tesseract_raw.get_available_languages()
handle = tesseract_raw.init()
try:
return tesseract_raw.get_available_languages(handle)
finally:
tesseract_raw.cleanup(handle)
def get_version():
......
......@@ -32,7 +32,7 @@ if g_libtesseract:
g_libtesseract.TessBaseAPICreate.argtypes = []
g_libtesseract.TessBaseAPICreate.restype = ctypes.c_void_p # TessBaseAPI*
g_libtesseract.TessBaseAPIDelete.argtypes = [
ctypes.c_void_p # TessBaseAPI*
ctypes.c_void_p, # TessBaseAPI*
]
g_libtesseract.TessBaseAPIDelete.argtypes = None
......@@ -49,8 +49,84 @@ if g_libtesseract:
g_libtesseract.TessBaseAPIGetAvailableLanguagesAsVector.restype = \
ctypes.POINTER(ctypes.c_char_p)
g_libtesseract.TessBaseAPISetPageSegMode.argtypes = [
ctypes.c_void_p, # TessBaseAPI*
ctypes.c_int, # See PageSegMode
]
g_libtesseract.TessBaseAPISetPageSegMode.restype = None
g_libtesseract.TessBaseAPIInitForAnalysePage.argtypes = [
ctypes.c_void_p, # TessBaseAPI*
]
g_libtesseract.TessBaseAPIInitForAnalysePage.restype = None
g_libtesseract.TessBaseAPISetImage.argtypes = [
ctypes.c_void_p, # TessBaseAPI*
ctypes.POINTER(ctypes.c_char), # imagedata
ctypes.c_int, # width
ctypes.c_int, # height
ctypes.c_int, # bytes_per_pixel
ctypes.c_int, # bytes_per_line
]
g_libtesseract.TessBaseAPISetImage.restype = None
g_libtesseract.TessBaseAPIRecognize.argstypes = [
ctypes.c_void_p, # TessBaseAPI*
ctypes.c_void_p, # ETEXT_DESC*
]
g_libtesseract.TessBaseAPIRecognize.restype = ctypes.c_int
g_libtesseract.TessBaseAPIAnalyseLayout.argstypes = [
ctypes.c_void_p, # TessBaseAPI*
]
g_libtesseract.TessBaseAPIAnalyseLayout.restype = \
ctypes.c_void_p # TessPageIterator*
g_libtesseract.TessBaseAPIGetUTF8Text.argstype = [
ctypes.c_void_p, # TessBaseAPI*
]
g_libtesseract.TessBaseAPIGetUTF8Text.restype = ctypes.c_char_p
g_libtesseract.TessPageIteratorDelete.argstypes = [
ctypes.c_void_p, # TessPageIterator*
]
g_libtesseract.TessPageIteratorDelete.restype = None
g_libtesseract.TessPageIteratorOrientation.argstype = [
ctypes.c_void_p, # TessPageIterator*
ctypes.POINTER(ctypes.c_int), # TessOrientation*
ctypes.POINTER(ctypes.c_int), # TessWritingDirection*
ctypes.POINTER(ctypes.c_int), # TessTextlineOrder*
ctypes.POINTER(ctypes.c_float), # deskew_angle
]
g_libtesseract.TessPageIteratorOrientation.restype = None
def _init(lang=None):
class PageSegMode(object):
OSD_ONLY = 0
AUTO_OSD = 1
AUTO_ONLY = 2
AUTO = 3
SINGLE_COLUMN = 4
SINGLE_BLOCK_VERT_TEXT = 5
SINGLE_BLOCK = 6
SINGLE_LINE = 7
SINGLE_WORD = 8
CIRCLE_WORD = 9
SINGLE_CHAR = 10
SPARSE_TEXT = 11
SPARSE_TEXT_OSD = 12
COUNT = 13
class Orientation(object):
PAGE_UP = 0
PAGE_RIGHT = 1
PAGE_DOWN = 2
PAGE_LEFT = 3
def init(lang=None):
assert(g_libtesseract)
handle = g_libtesseract.TessBaseAPICreate()
try:
......@@ -70,7 +146,7 @@ def _init(lang=None):
return handle
def _cleanup(handle):
def cleanup(handle):
g_libtesseract.TessBaseAPIDelete(handle)
......@@ -81,21 +157,108 @@ def is_available():
def get_version():
global g_libtesseract
assert(g_libtesseract)
return g_libtesseract.TessVersion().decode("utf-8")
def get_available_languages():
def get_available_languages(handle):
global g_libtesseract
assert(g_libtesseract)
langs = []
handle = _init()
try:
c_langs = g_libtesseract.TessBaseAPIGetAvailableLanguagesAsVector(
handle
)
i = 0
while c_langs[i]:
langs.append(c_langs[i].decode("utf-8"))
i += 1
finally:
_cleanup(handle)
c_langs = g_libtesseract.TessBaseAPIGetAvailableLanguagesAsVector(
handle
)
i = 0
while c_langs[i]:
langs.append(c_langs[i].decode("utf-8"))
i += 1
return langs
def set_page_seg_mode(handle, mode):
global g_libtesseract
assert(g_libtesseract)
g_libtesseract.TessBaseAPISetPageSegMode(
handle, ctypes.c_int(mode)
)
def init_for_analyse_page(handle):
global g_libtesseract
assert(g_libtesseract)
g_libtesseract.TessBaseAPIInitForAnalysePage(handle)
def set_image(handle, image):
global g_libtesseract
assert(g_libtesseract)
image = image.convert("RGB")
image.load()
imgdata = image.tobytes()
imgsize = image.size
g_libtesseract.TessBaseAPISetImage(
handle,
imgdata,
ctypes.c_int(imgsize[0]),
ctypes.c_int(imgsize[1]),
ctypes.c_int(3), # RGB = 3 * 8
ctypes.c_int(imgsize[0] * 3)
)
def recognize(handle):
global g_libtesseract
assert(g_libtesseract)
return g_libtesseract.TessBaseAPIRecognize(handle, ctypes.c_void_p(None))
def analyse_layout(handle):
global g_libtesseract
assert(g_libtesseract)
return g_libtesseract.TessBaseAPIAnalyseLayout(handle)
def get_utf8_text(handle):
return g_libtesseract.TessBaseAPIGetUTF8Text(handle).decode("utf-8")
def page_iterator_delete(iterator):
global g_libtesseract
assert(g_libtesseract)
return g_libtesseract.TessPageIteratorDelete(iterator)
def page_iterator_orientation(iterator):
global g_libtesseract
assert(g_libtesseract)
orientation = ctypes.c_int(0)
writing_direction = ctypes.c_int(0)
textline_order = ctypes.c_int(0)
deskew_angle = ctypes.c_float(0.0)
g_libtesseract.TessPageIteratorOrientation(
iterator,
ctypes.POINTER(orientation),
ctypes.POINTER(writing_direction),
ctypes.POINTER(textline_order),
ctypes.POINTER(deskew_angle)
)
return {
"orientation": orientation.value,
"writing_direction": writing_direction.value,
"textline_order": textline_order.value,
"deskew_angle": deskew_angle.value,
}
......@@ -264,8 +264,8 @@ def get_all_tests():
'test_european',
'test_french',
]
tests = unittest.TestSuite(map(TestTxt, test_names))
all_tests.addTest(tests)
#tests = unittest.TestSuite(map(TestTxt, test_names))
#all_tests.addTest(tests)
test_names = [
'test_basic',
......@@ -274,10 +274,10 @@ def get_all_tests():
'test_japanese',
'test_write_read',
]
tests = unittest.TestSuite(map(TestWordBox, test_names))
all_tests.addTest(tests)
tests = unittest.TestSuite(map(TestLineBox, test_names))
all_tests.addTest(tests)
#tests = unittest.TestSuite(map(TestWordBox, test_names))
#all_tests.addTest(tests)
#tests = unittest.TestSuite(map(TestLineBox, test_names))
#all_tests.addTest(tests)
test_names = [
'test_can_detect_orientation',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment