Hace un par de semanas, Cesar Capillas y yo intercambiamos unos correos, ente los temas que tratamos hablamos sobre qué estábamos pensando escribir en los blogs respectivos y ambos coincidíamos con algo relacionado con Alfresco y OCR, algo sencillo pero que ofreciera una nueva funcionalidad al usuario final, así que quedamos unos días más tarde para profundizar en el tema y ponernos manos a la obra. Aquí está el resultado.
En el siguiente artículo vamos a ver cómo configurar Alfresco para poder indexar automáticamente el contenido de un fichero TIF escaneado, subirlo al repositorio y poder localizarlo posteriormente buscando por el contenido del mismo. Todo ello pasándole a cada fichero TIF un OCR de forma transparente para el usuario.
En materia de escaneo y almacenamiento de información en Alfresco se ha escrito mucho y hay muchas soluciones disponibles de diferente índole que ya vimos aquí hace tiempo.
Cuando se va ha digitalizar una gran cantidad de contenidos en papel y se quiere extraer su contenido vía OCR para poderlo indexar con Alfresco, disponemos de varias herramientas empresariales que permiten revisión, OCR zonal, mayor escalabilidad, mapeo de metadatos, capacidades de integración, inyección masiva y otras funcionalidades propias de entornos donde se va a hacer un uso intensivo de estas características. Para eso se encuentra aplicaciones como las siguientes:
–Kofax Ascent Capture: conector soportado con Alfresco Enterprise.
–Introspeqt InstaCapture: guía.
–Ephesoft: CMIS
–Cobra Technologies: CMIS
–Sira Systems.
Como hemos comentado anteriormente, con las indicaciones que se explican a continuación conseguimos extraer la información OCR de un fichero TIF de forma transparente, el texto extraído del documento escaneado es indexado automáticamente.
En principio las pruebas las hemos hecho en Linux (Ubuntu y CentOS) usando Tesseract versión 2.04 y Alfresco 3.3/3.4 (tanto Community como Enterprise)
Hemos elegido Tesseract por ser uno de los más comunes OCR en el mundo Open Source, pero se puede usar cualquier otro, e incluso añadiendo más características. Usando Tesseract 2.X hay que tener en cuenta que los TIF que se suben deben estar sin comprimir ya que es el único formato que soporta esta versión. Para soportar TIF comprimido hay que usar la versión 3 de Tesseract.
Hay otros OCR tanto libres como privativos, cada uno soporta unos ficheros de entrada u otros aunque en casi todos los casos el común denominador es el formato TIF. Algunos ejemplos de software alternativo a Tesseract son gocr, ocrad, ocropus o cuneiform. Para Windows hay otros como TigerOCR o incluso los mismos Tesseract y cuneiform tienen versiones para Windows.
Una vez instalado Tesseract bien sea compilando o mediante apt/yum. Podemos probar su correcto funcionamiento con el siguiente comando (especificamos el idioma aunque por defecto está en inglés, así que debes instalar el idioma correspondiente que viene con el paquete):
[php]# tesseract documento.tif documento -l spa[/php]
Recuerda que el documento.tif debería ser un fichero de un documento escaneado en español y con formato TIF sin comprimir, documento es la salida del comando, es decir, un fichero txt con el contenido detectado mediante el ocr. La opción –l permite especificar el idioma del documento escaneado para afinar el reconocimiento.
Si el comando anterior ha funcionado correctamente podemos seguir.
Ejecutando el comando anterior obtendremos en un archivo de texto el conjunto de palabras extraídas de la imagen en cuestión. Esto en principio no es una tarea sencilla para el motor de OCR y no siempre extraerá con éxito las palabras, a no ser que este bien entrenado.
Desde el punto de vista de Alfresco prepararemos un transformador, que invoca un script de shell que transforma un archivo tif a texto plano (extrae el texto identificado). Automaticamente el texto obtenido se indexará en el motor de Lucene de Alfresco. Esta misma idea se ha utilizado en otros transformadores como la siguiente, donde extraiamos el texto de un texto XML via xmlstarlet:
El script va hacer algunas cosas más y está hecho en python (ocr-simple.py) y para su ejecución se necesita un interprete de python. El script hace algunas cosillas más que la ejecución del comando en cuestión. Por ejemplo, utiliza un diccionario de palabras donde cotejar las coincidencias. Por defecto utiliza una ruta que apunta al diccionario de palabras de ispell en Linux (paquete ispell o aspell dependiendo de la distribución), pero se puede utilizar otro archivo. Por otro lado, el script limpia y normaliza las palabras obtenidas por el ocr y recoge aquellas que tienen más de tres caracteres. Buena parte de estas acciones de limpieza y normalización seguro que las hace internamente Lucene pero nunca están de más. Aquí podemos ver el contenido del fichero ocr-simple.py (modifica las rutas según tu sistema y hazlo ejecutable):
[bash]
#!/usr/bin/python
from os import popen
from string import split,join
from pprint import *
import re
import sys
def uniq(seq):
# Not order preserving
keys = {}
for e in seq:
keys[e] = 1
return keys.keys()
# Tamano maximo
maxstr = 3
# Comando ocr en la salida estandar
#command = popen(‘/usr/bin/pngtopnm ‘+sys.argv[1]+’ | /usr/bin/ocrad’)
#command = popen(‘/usr/bin/pngtopnm ‘+sys.argv[1]+’ | /usr/bin/gocr -‘)
command = popen(‘/usr/bin/tesseract ‘+sys.argv[1]+’ /tmp/tesser-$$ 2> /dev/null; cat /tmp/tesser-$$.txt’)
# Diccionario
dictwrd = open("/usr/share/dict/words","r")
s = dictwrd.read()
# Lineas ocr
lines = command.readlines()
#pprint(lines)
text = []
for i in lines:
# Quitar los saltos de linea
i = i.strip("\n")
# En minusculas
i = i.lower()
for j in i.split(" "):
# Quitar los puntos y comas….
myregex = re.compile(r"[^\w\s]")
j = myregex.sub(”, j)
# Tamano maximo de palabra
if len(j) >= maxstr:
if re.search(j, s):
text.append(j)
# print j, "Match!" # char literal
#else:
# print j, "upppss!"
zz = open("/tmp/ocr.log","w")
zz.write(sys.argv[1]+"\n")
zz.write(join(uniq(text), " "))
# Palabras unicas
outputf = open(sys.argv[2],"w")
outputf.write(join(uniq(text), " "))
[/bash]
Un sitio para alojarlo puede ser: $ALF_HOME/bin
HINT: Se pueden usar otros OCR, por ejemplo, sustituyendo el comando de tesseract e instalando el OCR correspondiente (ocrad, gocr)
[bash]
#command = popen(‘/usr/bin/pngtopnm ‘+sys.argv[1]+’ | /usr/bin/ocrad’)
[/bash]
o
[bash]
#command = popen(‘/usr/bin/pngtopnm ‘+sys.argv[1]+’ | /usr/bin/gocr -‘)
[/bash]
- Creación del transformador
El transformador se configura en el directorio de extensiones de Alfresco es decir:
$ALF_HOME/tomcat/shared/classes/alfresco/extension
Se define el worker, la invocación al script ocr-simple.py (que tiene que tener permisos de ejecución) y el mimetype de los archivos sobre los que se aplica la transformación, en este caso, de tif a texto plano (revisa las rutas de este xml para que estén acorde a tu instalación):
[xml]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="transformer.OCRToText" class="org.alfresco.repo.content.transform.ProxyContentTransformer" parent="baseContentTransformer">
<property name="worker">
<ref bean="transformer.worker.OCRToText" />
</property>
</bean>
<bean id="transformer.worker.OCRToText" class="org.alfresco.repo.content.transform.RuntimeExecutableContentTransformerWorker">
<property name="mimetypeService">
<ref bean="MimetypeService"/>
</property>
<property name="transformCommand">
<bean class="org.alfresco.util.exec.RuntimeExec">
<property name="commandsAndArguments">
<map>
<entry key="Linux">
<list>
<value>/usr/bin/python</value>
<value>/opt/alfresco33/bin/ocr-simple.py</value>
<value>${source}</value>
<value>${target}</value>
</list>
</entry>
</map>
</property>
</bean>
</property>
<property name="explicitTransformations">
<list>
<bean class="org.alfresco.repo.content.transform.ExplictTransformationDetails">
<property name="sourceMimetype"><value>image/tiff</value></property>
<property name="targetMimetype"><value>text/plain</value></property>
</bean>
</list>
</property>
</bean>
</beans>
[/xml]
Por descontado el transformador se puede extender a otros mimetypes de tipo imagen aunque esto no lo detallaremos aquí. También se podría implementar fácilmente en Windows.
Una vez dispuesto el fichero ocr-context.xml en el directorio de extensiones y el script de python ocr-simple.py en el directorio bin y reiniciado el servidor, tan sólo tenemos que subir una imagen en formato tif (con extension .tif). Una vez subida podemos buscar alguno de los términos en el buscador de la parte superior derecha de Alfresco Explorer o Share, por ejemplo, las palabras lazy o fox. De este modo subimos el archivo simple.tif a Alfresco:
Y buscamos la palabra fox de la imagen:
El resultado es el siguiente, aparecen un conjunto de archivos indexados que contienen la palabra fox, entre ellos la imagen que acabamos de subir.
Para trazar lo que esta haciendo el transformador se puede activar el log4j ($ALF_HOME/tomcat/webapps/alfresco/WEB-INF/classes/log4j.properties)
[bash]
log4j.logger.org.alfresco.util.exec.RuntimeExec=DEBUG
log4j.logger.org.alfresco.repo.content.transform.ContentTransformerRegistry=DEBUG
[/bash]
Entrada en el foro de Alfresco en Español:
http://forums.alfresco.com/es/viewtopic.php?f=11&t=2979&start=0&hilit=tesseract
Tesseract OCR:
http://code.google.com/p/tesseract-ocr/wiki/ReadMe
Ficheros usados en el artículo: ocr-files-web.
Nota: En Alfresco Share el comportamiento es el mismo, esta integración es independiente del cliente web.