Tesseract Gambas (antes Python)


Ir a la página 1, 2  Siguiente

Objetivo: Tesseract Gambas (antes Python)
Hola a todos, encontré este código python que según dice en la web de donde lo saque, pasa de imagen de tabla a tabla.

Me gustaría poder pasarlo a gambas pero, por decirlo de alguna manera, python no es mi fuerte

Saludos.

import Image, ImageOps
import subprocess, sys, os, glob

# minimum run of adjacent pixels to call something a line
H_THRESH = 300
V_THRESH = 300

def get_hlines(pix, w, h):
"""Get start/end pixels of lines containing horizontal runs of at least THRESH black pix"""
hlines = []
for y in range(h):
x1, x2 = (None, None)
black = 0
run = 0
for x in range(w):
if pix[x,y] == (0,0,0):
black = black + 1
if not x1: x1 = x
x2 = x
else:
if black > run:
run = black
black = 0
if run > H_THRESH:
hlines.append((x1,y,x2,y))
return hlines

def get_vlines(pix, w, h):
"""Get start/end pixels of lines containing vertical runs of at least THRESH black pix"""
vlines = []
for x in range(w):
y1, y2 = (None,None)
black = 0
run = 0
for y in range(h):
if pix[x,y] == (0,0,0):
black = black + 1
if not y1: y1 = y
y2 = y
else:
if black > run:
run = black
black = 0
if run > V_THRESH:
vlines.append((x,y1,x,y2))
return vlines

def get_cols(vlines):
"""Get top-left and bottom-right coordinates for each column from a list of vertical lines"""
cols = []
for i in range(1, len(vlines)):
if vlines[i][0] - vlines[i-1][0] > 1:
cols.append((vlines[i-1][0],vlines[i-1][1],vlines[i][2],vlines[i][3]))
return cols

def get_rows(hlines):
"""Get top-left and bottom-right coordinates for each row from a list of vertical lines"""
rows = []
for i in range(1, len(hlines)):
if hlines[i][1] - hlines[i-1][3] > 1:
rows.append((hlines[i-1][0],hlines[i-1][1],hlines[i][2],hlines[i][3]))
return rows

def get_cells(rows, cols):
"""Get top-left and bottom-right coordinates for each cell usings row and column coordinates"""
cells = {}
for i, row in enumerate(rows):
cells.setdefault(i, {})
for j, col in enumerate(cols):
x1 = col[0]
y1 = row[1]
x2 = col[2]
y2 = row[3]
cells[i][j] = (x1,y1,x2,y2)
return cells

def ocr_cell(im, cells, x, y):
"""Return OCRed text from this cell"""
fbase = "working/%d-%d" % (x, y)
ftif = "%s.tif" % fbase
ftxt = "%s.txt" % fbase
cmd = "tesseract %s %s" % (ftif, fbase)
# extract cell from whole image, grayscale (1-color channel), monochrome
region = im.crop(cells[x][y])
region = ImageOps.grayscale(region)
region = region.point(lambda p: p > 200 and 255)
# determine background color (most used color)
histo = region.histogram()
if histo[0] > histo[255]: bgcolor = 0
else: bgcolor = 255
# trim borders by finding top-left and bottom-right bg pixels
pix = region.load()
x1,y1 = 0,0
x2,y2 = region.size
x2,y2 = x2-1,y2-1
while pix[x1,y1] != bgcolor:
x1 += 1
y1 += 1
while pix[x2,y2] != bgcolor:
x2 -= 1
y2 -= 1
# save as TIFF and extract text with Tesseract OCR
trimmed = region.crop((x1,y1,x2,y2))
trimmed.save(ftif, "TIFF")
subprocess.call([cmd], shell=True, stderr=subprocess.PIPE)
lines = [l.strip() for l in open(ftxt).readlines()]
return lines[0]

def get_image_data(filename):
"""Extract textual data[rows][cols] from spreadsheet-like image file"""
im = Image.open(filename)
pix = im.load()
width, height = im.size
hlines = get_hlines(pix, width, height)
sys.stderr.write("%s: hlines: %d\n" % (filename, len(hlines)))
vlines = get_vlines(pix, width, height)
sys.stderr.write("%s: vlines: %d\n" % (filename, len(vlines)))
rows = get_rows(hlines)
sys.stderr.write("%s: rows: %d\n" % (filename, len(rows)))
cols = get_cols(vlines)
sys.stderr.write("%s: cols: %d\n" % (filename, len(cols)))
cells = get_cells(rows, cols)

data = []
for row in range(len(rows)):
data.append([ocr_cell(im,cells, row, col) for col in range(len(cols))])
return data

def split_pdf(filename):
"""Split PDF into PNG pages, return filenames"""
prefix = filename[:-4]
cmd = "convert -density 600 %s working/%s-%%d.png" % (filename, prefix)
subprocess.call([cmd], shell=True)
return [f for f in glob.glob(os.path.join('working', '%s*' % prefix))]

def extract_pdf(filename):
"""Extract table data from pdf"""
pngfiles = split_pdf(filename)
sys.stderr.write("Pages: %d\n" % len(pngfiles))
# extract table data from each page
data = []
for pngfile in pngfiles:
pngdata = get_image_data(pngfile)
for d in pngdata:
data.append(d)
# remove temp files for this page
os.system("rm working/*.tif")
os.system("rm working/*.txt")
# remove split pages
os.system("rm working/*")
return data

if __name__ == '__main__':
if len(sys.argv) != 2:
print "Usage: ctocr.py FILENAME"
exit()
# split target pdf into pages
filename = sys.argv[1]
data = extract_pdf(filename)
for row in data:
print "\t".join(row)

última edición por tincho el Lunes, 04 Abril 2016, 17:56; editado 1 vez
Perfil MP  
Objetivo: Re: Tesseract Python
Hola Tincho.

Es solo por hablar y por preguntar. Tengo conocimientos de Python, pero no tantos como quisiera.
Algún que otro compañero más de la comunidad de gambas, han hecho los mismos cursos de Python
y pueden opinar muy parecido a lo que te puedo decir.

Uno de los problemas que me encuentro cuando veo el código, ademas de que es un poco largo. ( Suele pasar ).

No conozco los módulos que usa o importa al código. Image, ImageOps, subprocess, glob.
A saber lo que hay detrás.

De los otros conozco algunas cosas.

Parece para Python 2. Python 3 tiene cosas que no son iguales, incluso instrucciones distintas.
Me he encontrado alguna que otra vez este problema. Siempre se debe buscar para comprobar las similitudes.

No creas que es tan difícil de entender el código. Hay cosas que hay cambiar, pero tampoco es algo extremo.
El problema en partes es que no conocemos las funciones que está importando.

¿ Qué problema te has encontrado para no poder hacerlo en gambas ?.

Por otra parte, no me extrañaría que se pudiera llamar externamente a este código desde Gambas.
Si se hace con C. A menos que se requiera algo que pida gambas en concreto.

No recuerdo si nuestro compañero Julio hizo algo de esto. Que se pudiese llamar a un código de Python
desde gambas.

Nunca lo he intentado.

¿ Lo ejecutaste con Python 2 y es lo que quieres ?.

¿ Probaste alguna herramienta o aplicación para hacer lo que quieres ?.

5 herramientas digitales para extraer datos de archivos pdf protegidos

Saludos

Objetivo: Re: Tesseract Python
Así, a bote pronto, lo que hace el código es invocar a un proceso externo que es el ejecutable "tesseract", que es una utilidad OCR (reconocimiento de caracteres a partir de imágenes). Primero se extrae la imagen en formato tiff o desde un pdf, luego se escanea con el OCR y finalmente las rutinas interpretan su posición en la tabla, creando filas y columnas para componer el gridview o tabla.

Nada que no se pueda hacer en gambas directamente, eso sí, usando el binario tesseract como un proceso externo.

Saludos

Perfil MP  
Objetivo: Re: Tesseract Python
Shell:
Bueno me interesa traducir este código a gambas, para poder importar escaneados de planillas de datos, pero no es mi objetivo meterme a programar (todavía) en python y respecto a las herramientas externas que propones no es posible adaptarlas al scripting con tesseract ya que hay que para usar estra herramientas hay que trabajar de forma mas o menos manual.

Jguardon:
Lo que describes es lo que hace el código, salvo que las paginas, en vez de .tif, las extrae en .png y luego las convierte en .tif.
Efectivamente creo que se puede hacer con gambas sin inconvenientes. Pero estoy estudiando el código este en python y no logro entender como hace para determinar las tablas, las filas y las columnas.
La parte de la extracción ya la tengo lista en destornillador la parte del ocr también.
El inconveniente es determinar y fraccionar las celdas de las tablas.

Saludos.

Perfil MP  
Objetivo: Re: Tesseract Python
Tincho:

¿ Tienes problemas con alguna función en concreto ?.

Saludos

Objetivo: Re: Tesseract Python
Shell escribió:  
¿ Tienes problemas con alguna función en concreto ?.


Pendiente:
def get_hlines(pix, w, h):
def get_vlines(pix, w, h):
def get_cols(vlines):
def get_rows(hlines):
def get_cells(rows, cols):
if __name__ == '__main__':

Solucionado:
os.system("rm working/*.tif") supongo que se puede reemplazar por shell "rm working/*.tif"
Extraer las imágenes desde el pdf

Información:
Post desde donde descargue el código en python: http://craiget.com/blog/extracting-...-pdfs-with-ocr/

Teoria sobre el tema:
http://users.iit.demokritos.gr/~bgat/ICAPR2005.pdf
http://clement.chatelain.free.fr/pu...r_icdar2013.pdf

Pero el mayor problema que tengo a la hora de traducir el código desde python a gambas es que las variables no están definidas claramente como en gambas y eso me dificulta la "decodificación" del código python

Saludos.

Perfil MP  
Objetivo: Re: Tesseract Python
Bueno, como es verdad que el código es extenso, voy a ir por partes.
¿Que esto en python?

sys.stderr.write("%s: hlines: %d\n" % (filename, Len(hlines)))


Saludos.

Perfil MP  
Objetivo: Re: Tesseract Python
Hola Tincho.

Citar:

if __name__ == '__main__':


Eso en Python es para averiguar si el modulo actual se está ejecutando o lo están importando.
Así que si lo ejecutas directamente, __name__ es igual a '__main__'.

Ejemplo:

if __name__ == "__main__":
print ("Soy el programa principal.")
else:
print("Otro modulo me esta importando.")


Si lo ejecutas tal como está, te mostraría "Soy el programa principal".
Ahora imagina que ese programa se llama, prueba.

Si lo importases en otro modulo, de esta forma, escribiendo esto en las primeras lineas del modulo actual.

import prueba

Se ejecutaría "Otro modulo me está importando"

Otro ejemplo:

#!/usr/bin/python3

# Creando un Script principal
# Sintaxis

def main():
print('Este es el fichero sintasis.py')
huevo()

def huevo():
print ('huevo')

# Esta linea que veremos en muchos scripts de python nos permite
# llamar a funciones que son escritas o definidas despues de la llamada

if __name__=="__main__": main()


Es lo primero que quieres que se ejecute al iniciar la aplicación.

Citar:

def get_hlines(pix, w, h):


Hay algo que se repite mucho en la mayoría de estas funciones.

...
if pix[x,y] == (0,0,0)
...


Veo el bucle anidado, como va comparando si en cada coordenada el color es negro (R, G, B)
No entendí que tipo de datos es pix. Recuerda a un array de dos dimensiones.

Citar:

Pero el mayor problema que tengo a la hora de traducir el código desde python a gambas es que las variables no están definidas claramente como en gambas y eso me dificulta la "decodificación" del código python


Si, eso es un problema. Se le puede preguntar a Python por el tipo de datos.

type(variable)

Ejemplo:

Citar:

>>> num = 1
>>> type (num)
<type 'int'>
>>> num2 = 1.2
>>> type (num2)
<type 'float'>
>>>


Tu ve sobre la marcha, llega hasta donde no entiendas y preguntas.

Saludos

Objetivo: Re: Tesseract Python
tincho escribió:  

¿Que esto en python?

sys.stderr.write("%s: hlines: %d\n" % (filename, Len(hlines)))




No soy muy "informático que digamos", o programador. Pero parece que escribe en la salida de errores un mensaje.

Lo primero es el nombre del archivo y luego un valor que cuenta la longitud de hlines

"%s: hlines: %d\n" % (filename, Len(hlines))


El %s en este caso es una cadena, es algo como &1. Se parece en gambas a Subst.
Python usa Len tanto para contar caracteres como para contar elementos de un lista, tupla...(abreviando de un array).

Casi parece esto:

Print Subst$("&1: hlines: &2\n", "nombrearchivo", 12)


Pero, claro se imprime en la salida estándar de error.

Saludos

última edición por Shell el Lunes, 04 Abril 2016, 11:05; editado 3 veces
Objetivo: Re: Tesseract Python
Sí, stderr es una la vías de comunicación de un programa. En este caso de salida y en especial de errores.

mejor explicado acá redirigir stdin, stdout y stderr en Unix/Linux

Ahora no recuerdo cual programa (Creo que lo decía el libro de gambas) hay un programa cuya comunicación al exterior es sólo con stderr.

Perfil MP  
Ir a la página 1, 2  Siguiente

Página 1 de 2


  
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas
No puede adjuntar archivos
Puede descargar archivos
No puede publicar eventos en el calendario

   

Está utilizando la versión (Lo-Fi). Para ver la versión completa del foro, haga clic aquí.

Powered by Icy Phoenix based on phpBB
Design by DiDiDaDo

Página generada en:: 0.2454s (PHP: 44% SQL: 56%)
Consultas SQL: 26 - Debug off - GZIP Activado