PyTesseract: Reconocimiento óptico de caracteres en Python

    Introducción

    Los humanos pueden comprender el contenido de una imagen simplemente mirando. Percibimos el texto de la imagen como texto y podemos leerlo.

    Las computadoras no funcionan de la misma manera. Necesitan algo más concreto, organizado de una manera que puedan entender.

    Aquí es donde entra en juego el reconocimiento óptico de caracteres (OCR). Ya sea que se trate del reconocimiento de placas de automóviles desde una cámara o de documentos escritos a mano que deben convertirse en una copia digital, esta técnica es muy útil. Si bien no siempre es perfecto, es muy conveniente y hace que sea mucho más fácil y rápido para algunas personas hacer su trabajo.

    En este artículo, profundizaremos en la profundidad del reconocimiento óptico de caracteres y sus áreas de aplicación. También crearemos un script simple en Python que nos ayudará a detectar personajes a partir de imágenes y exponerlos a través de una aplicación Flask para un medio de interacción más conveniente.

    ¿Qué es el reconocimiento óptico de caracteres?

    El reconocimiento óptico de caracteres implica la detección de contenido de texto en imágenes y la traducción de las imágenes a texto codificado que la computadora puede comprender fácilmente. Una imagen que contiene texto se escanea y analiza para identificar los caracteres en ella. Tras la identificación, el carácter se convierte en texto codificado por máquina.

    ¿Cómo se logra realmente? Para nosotros, el texto de una imagen es fácilmente discernible y podemos detectar caracteres y leer el texto, pero para una computadora, todo es una serie de puntos.

    Primero se escanea la imagen y los elementos de texto y gráficos se convierten en un mapa de bits, que es esencialmente una matriz de puntos blancos y negros. Luego, la imagen se procesa previamente donde se ajustan el brillo y el contraste para mejorar la precisión del proceso.

    La imagen ahora se divide en zonas que identifican las áreas de interés, como dónde están las imágenes o el texto, y esto ayuda a iniciar el proceso de extracción. Las áreas que contienen texto ahora se pueden dividir aún más en líneas, palabras y caracteres, y ahora el software puede hacer coincidir los caracteres mediante la comparación y varios algoritmos de detección. El resultado final es el texto de la imagen que se nos da.

    Es posible que el proceso no sea 100% preciso y que necesite la intervención humana para corregir algunos elementos que no se escanearon correctamente. La corrección de errores también se puede lograr utilizando un diccionario o incluso el procesamiento del lenguaje natural (NLP).

    La salida ahora se puede convertir a otros medios, como documentos de Word, PDF o incluso contenido de audio a través de tecnologías de conversión de texto a voz.

    Usos de OCR

    Anteriormente, la digitalización de documentos se lograba escribiendo manualmente el texto en la computadora. A través de OCR, este proceso se hace más fácil ya que el documento se puede escanear, procesar y el texto se puede extraer y almacenar en una forma editable, como un documento de Word.

    Si tiene un escáner de documentos en su teléfono, como Adobe Scan, probablemente haya encontrado tecnología OCR en uso.

    Los aeropuertos también pueden utilizar OCR para automatizar el proceso de reconocimiento de pasaportes y extracción de información de ellos.

    Otros usos de OCR incluyen la automatización de los procesos de entrada de datos, la detección y el reconocimiento de matrículas de automóviles.

    Que usaremos

    Para este proyecto de OCR, usaremos la biblioteca Python-Tesseract , o simplemente PyTesseract, que es un contenedor para el motor Tesseract-OCR de Google .

    Elegí esto porque es completamente de código abierto y está siendo desarrollado y mantenido por el gigante que es Google. Siga estas instrucciones para instalar Tesseract en su máquina, ya que PyTesseract depende de ello.

    También usaremos el marco web Flask para crear nuestro servidor OCR simple donde podemos tomar fotos a través de la cámara web o cargar fotos con fines de reconocimiento de personajes.

    También usaremos Pipenv, ya que también maneja la configuración del entorno virtual y la gestión de requisitos.

    Además de eso, también usaremos la biblioteca Pillow , que es una bifurcación de la Biblioteca de imágenes de Python (PIL) para manejar la apertura y manipulación de imágenes en muchos formatos en Python.

    En esta publicación, nos concentraremos en PyTesseract, aunque hay otras bibliotecas de Python que pueden ayudarlo a extraer texto de imágenes como:

    • Textract : que puede extraer datos de archivos PDF pero es un paquete pesado.
    • Pyocr : ofrece más opciones de detección como frases, dígitos o palabras.

    Preparar

    Comience instalando Pipenv usando el siguiente comando a través de Pip (en caso de que necesite configurarlo, consulte esto ).

    $ pip install pipenv
    

    Cree el directorio del proyecto e inicie el proyecto ejecutando el siguiente comando:

    $ mkdir ocr_server && cd ocr_server && pipenv install --three
    

    Ahora podemos activar nuestro entorno virtual y empezar a instalar nuestras dependencias:

    $ pipenv shell
    $ pipenv install pytesseract Pillow 
    

    En caso de que no vaya a utilizar Pipenv, siempre puede utilizar el enfoque de Pip y entorno virtual. Siga la documentación oficial que lo ayudará a comenzar con Pip y Virtual Environment :

    Nota : En ese caso, en lugar de pipenv install Pillow, el comando será pip install Pillow.

    Implementación

    Vamos a implementar este proyecto en 2 fases. En el primero, crearemos el script y en el siguiente crearemos una aplicación Flask para que actúe como interfaz.

    Script de OCR

    Con la configuración completa, ahora podemos crear una función simple que toma una imagen y devuelve el texto detectado en la imagen; este será el núcleo de nuestro proyecto:

    try:
        from PIL import Image
    except ImportError:
        import Image
    import pytesseract
    
    def ocr_core(filename):
        """
        This function will handle the core OCR processing of images.
        """
        text = pytesseract.image_to_string(Image.open(filename))  # We'll use Pillow's Image class to open the image and pytesseract to detect the string in the image
        return text
    
    print(ocr_core('images/ocr_example_1.png'))
    

    La función es bastante sencilla, en las primeras 5 líneas importamos Imagede la Pillowbiblioteca y nuestra PyTesseractbiblioteca.

    Luego creamos una ocr_corefunción que toma un nombre de archivo y devuelve el texto contenido en la imagen.

    Veamos cómo le va al script con una imagen simple que contiene algo de texto:

    Y al ejecutar el fragmento de código, somos recibidos con esto:

    ¡Nuestro sencillo script OCR funciona! Obviamente, esto fue algo fácil ya que se trata de texto digital, perfecto y preciso, a diferencia de la escritura a mano. Hay mucho más que podemos hacer con la biblioteca PyTesseract, pero más sobre esto más adelante en la publicación.

    Primero integremos este script en una aplicación Flask, para facilitar la carga de imágenes y realizar operaciones de reconocimiento de caracteres.

    Interfaz web del matraz

    Nuestro script se puede utilizar a través de la línea de comandos, pero una aplicación Flask lo haría más fácil de usar y versátil. Por ejemplo, podemos cargar fotos a través del sitio web y hacer que el texto extraído se muestre en el sitio web o podemos capturar fotos a través de la cámara web y realizar el reconocimiento de caracteres en ellas.

    Si no está familiarizado con el marco de Flask, este es un buen tutorial para ponerse al día y ponerse en marcha.

    Comencemos instalando el paquete Flask:

    $ pipenv install Flask
    

    Ahora, definamos una ruta básica:

    from flask import Flask
    app = Flask(__name__)
    
    @app.route("https://Pharos.sh.com/")
    def home_page():
        return "Hello World!"
    
    if __name__ == '__main__':
        app.run()
    

    Guarde el archivo y ejecute:

    $ python3 app.py
    

    Si abre su navegador y se dirige a 127.0.0.1:5000o localhost:5000debería ver «¡Hola mundo!» en la pagina. Esto significa que nuestra aplicación Flask está lista para los siguientes pasos.

    Ahora crearemos una templatescarpeta para alojar nuestros archivos HTML. Sigamos adelante y creemos un simple index.html:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Index</title>
      </head>
      <body>
        Hello World.
      </body>
    </html>
    

    También modifiquemos nuestro app.pypara renderizar nuestra nueva plantilla:

    from flask import Flask, render_template
    app = Flask(__name__)
    
    @app.route("https://Pharos.sh.com/")
    def home_page():
        return render_template('index.html')
    
    if __name__ == '__main__':
        app.run()
    

    Observe que ahora lo hemos importado render_templatey usado para renderizar el archivo HTML. Si reinicia su aplicación Flask, aún debería ver «¡Hola mundo!» en la página de inicio.

    Eso es suficiente en el curso intensivo de Flask, integremos ahora nuestro script OCR en la aplicación web.

    Primero, agregaremos funcionalidad para cargar imágenes a nuestra aplicación Flask y las pasaremos a la ocr_corefunción que escribimos anteriormente. Luego, renderizaremos la imagen junto al texto extraído en nuestra aplicación web como resultado:

    import os
    from flask import Flask, render_template, request
    
    # import our OCR function
    from ocr_core import ocr_core
    
    # define a folder to store and later serve the images
    UPLOAD_FOLDER = '/static/uploads/'
    
    # allow files of a specific type
    ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg'])
    
    app = Flask(__name__)
    
    # function to check the file extension
    def allowed_file(filename):
        return '.' in filename and 
               filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
    
    # route and function to handle the home page
    @app.route("https://Pharos.sh.com/")
    def home_page():
        return render_template('index.html')
    
    # route and function to handle the upload page
    @app.route('/upload', methods=['GET', 'POST'])
    def upload_page():
        if request.method == 'POST':
            # check if there is a file in the request
            if 'file' not in request.files:
                return render_template('upload.html', msg='No file selected')
            file = request.files['file']
            # if no file is selected
            if file.filename == '':
                return render_template('upload.html', msg='No file selected')
    
            if file and allowed_file(file.filename):
    
                # call the OCR function on it
                extracted_text = ocr_core(file)
    
                # extract the text and display it
                return render_template('upload.html',
                                       msg='Successfully processed',
                                       extracted_text=extracted_text,
                                       img_src=UPLOAD_FOLDER + file.filename)
        elif request.method == 'GET':
            return render_template('upload.html')
    
    if __name__ == '__main__':
        app.run()
    

    Como podemos ver en nuestra upload_page()función, recibiremos la imagen a través de POST y renderizaremos el HTML de carga si la solicitud es GET.

    Verificamos si el usuario realmente ha subido un archivo y usamos la función allowed_file()para verificar si el archivo es de un tipo aceptable.

    Tras verificar que la imagen es del tipo requerido, la pasamos al script de reconocimiento de caracteres que creamos anteriormente.

    La función detecta el texto en la imagen y lo devuelve. Finalmente, como respuesta a la carga de la imagen, renderizamos el texto detectado junto a la imagen para que el usuario vea los resultados.

    El upload.htmlarchivo manejará la publicación de la imagen y la representación del resultado con la ayuda del motor de plantillas Jinja , que se envía con Flask por defecto:

    <!DOCTYPE html>
    <html>
     <head>
       <title>Upload Image</title>
     </head>
     <body>
    
       {% if msg %}
       <h1>{{ msg }}</h1>
       {% endif %}
      
       <h1>Upload new File</h1>
      
       <form method=post enctype=multipart/form-data>
         <p><input type=file name=file>
            <input type=submit value=Upload>
       </form>
    
       <h1>Result:</h1>
       {% if img_src %}
         <img src="{{ img_src }}">
       {% endif %}
      
       {% if extracted_text %}
         <p> The extracted text from the image above is: <b> {{ extracted_text }} </b></p>
      
       {% else %}
         The extracted text will be displayed here
       {% endif %}
     </body>
    </html>
    

    Las plantillas de Jinja nos permiten mostrar texto en escenarios específicos a través de las {% if %} {% endif %}etiquetas. También podemos pasar mensajes desde nuestra aplicación Flask para que se muestren en la página web dentro de las {{ }}etiquetas. Usamos un formulario para cargar la imagen en nuestra aplicación Flask.

    El resultado es:

    Ahora, si seguimos adelante y cargamos nuestra imagen de antes:

    ¡Si! Nuestra aplicación Flask ha podido integrar la funcionalidad OCR y mostrar el texto en el navegador. Esto facilita el proceso de imágenes en lugar de ejecutar comandos en la CLI cada vez que tenemos una nueva imagen para procesar.

    Adjuntemos algunas imágenes más para explorar más a fondo los límites de nuestro sencillo script OCR, ya que no funcionará en todas las situaciones.

    Por ejemplo, intentemos extraer texto de la siguiente imagen y el resultado se ha resaltado en la imagen:

    Esta es una evidencia de que el OCR no siempre es 100% exacto y puede necesitar la intervención humana de vez en cuando.

    También probé el script OCR con mi escritura a mano para ver cómo funcionaría, y este es el resultado:

    Como puede ver, no puede extraer texto de mi letra como lo hizo con otras imágenes que hemos visto antes. Decidí darle otra oportunidad, esta vez con una imagen de esta fuente , y estos fueron los resultados:

    El reconocimiento de caracteres en esta imagen es mucho mejor que en el que usé mi propia letra. Como puede ver, las líneas en la imagen descargada son más gruesas y hay un mejor contraste entre el texto y el fondo y esta podría ser la razón de la mala detección en mi letra.

    Esta es un área para explorar más, puede obtener notas escritas a mano de amigos o colegas y ver qué tan bien el guión será capaz de detectar personajes. Incluso puede enviar carteles a eventos e intentar escanearlos en busca de texto, las posibilidades son muchas.

    Otras opciones de PyTesseract

    Python-Tesseract tiene más opciones que puede explorar. Por ejemplo, puede especificar el idioma usando una langbandera:

    pytesseract.image_to_string(Image.open(filename), lang='fra')
    

    Este es el resultado de escanear una imagen sin la langbandera:

    Y ahora con la langbandera:

    El marco también está optimizado para detectar mejor los idiomas, como se ve en las capturas de pantalla. ( Fuente de la imagen ).

    Sin la langbandera, el guión omitió algunas palabras en francés, pero después de introducir la bandera pudo detectar todo el contenido en francés. La traducción no es posible, pero sigue siendo impresionante. La documentación oficial de Tesseract incluye los idiomas admitidos en esta sección.

    La orientación y la detección de secuencias de comandos también se encuentran entre las capacidades de PyTesseract y esto ayuda a detectar las fuentes utilizadas y la orientación del texto en la imagen dada. Si podemos hacer referencia a la imagen manuscrita que descargamos anteriormente:

    print(pytesseract.image_to_osd(Image.open('downloaded_handwritten.png')))
    

    No había información sobre el número de página en la imagen, por lo que no se detectó. El motor Tesseract es capaz de extraer información sobre la orientación del texto en la imagen y la rotación. La confianza de orientación es una cifra de la seguridad del motor sobre la orientación detectada para actuar como guía y también para mostrar que no siempre es 100% precisa. La sección del guión denota el sistema de escritura utilizado en el texto y también va seguida del marcador de confianza.

    Si buscáramos los personajes reconocidos y sus límites de caja, PyTesseract logra esto a través de pytesseract.image_to_boxes(Image.open('downloaded_handwritten.png')).

    Estas son algunas de las capacidades de PyTesseract, entre otras, como la conversión del texto extraído en un PDF con capacidad de búsqueda o una salida HOCR.

    Lo que no hemos hecho

    Hemos logrado mucho en esta publicación, pero aún queda mucho por hacer para refinar nuestro proyecto y prepararlo para el mundo real. Primero, podemos agregar estilo a nuestro sitio web y hacerlo más atractivo para el usuario final usando CSS. También podemos agregar la opción de cargar y escanear varias imágenes a la vez y mostrar toda su salida a la vez. ¿No haría esto más conveniente escanear varios documentos?

    El navegador nos permite acceder a la cámara de una máquina y capturar imágenes, con el permiso del usuario, por supuesto. Esto puede ser de gran ayuda, especialmente en dispositivos móviles. En lugar de que el usuario tenga que capturar y guardar la imagen y luego cargarla en el sitio web, si agregamos la funcionalidad de la cámara, podemos permitir que el usuario realice las operaciones directamente desde la aplicación web Flask. Esto hará que el proceso de escaneo sea más rápido.

    Suponga que una aplicación Flask no es lo que pretendía exponer su escáner OCR, también puede crear una herramienta CLI. La herramienta le permitiría ejecutar un comando que incluye la ubicación de la imagen y luego imprimir la salida del escáner a su terminal o enviarla a una base de datos o API. Si elige esta ruta, Docopt es una herramienta fantástica para crear herramientas de línea de comandos usando Python.

    Conclusión

    A través de Tesseract y la biblioteca Python-Tesseract, hemos podido escanear imágenes y extraer texto de ellas. Este es el reconocimiento óptico de caracteres y puede ser de gran utilidad en muchas situaciones.

    Hemos construido un escáner que toma una imagen y devuelve el texto contenido en la imagen y lo integramos en una aplicación Flask como interfaz. Esto nos permite exponer la funcionalidad en un medio más familiar y de una manera que puede servir a varias personas simultáneamente.

    El código fuente de este proyecto está disponible aquí en Github .

    .

    Etiquetas:

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *