Saltar al contenido

Imagen de preprocesamiento para Tesseract OCR con OpenCV

Traemos la mejor respuesta que descubrimos en todo internet. Nosotros queremos que te sea útil y si quieres aportar alguna mejora puedes hacerlo..

Solución:

Describí algunos consejos para preparar imágenes para Tesseract aquí: Uso de tesseract para reconocer matrículas

En su ejemplo, están sucediendo varias cosas …

Necesitas que el texto sea negro y el resto de la imagen blanco (no el revés). Eso es en lo que está sintonizado el reconocimiento de personajes. Escala de grises es ok, siempre que el fondo sea mayormente blanco y el texto mayormente negro; los bordes del texto pueden ser grises (suavizados) y que mayo ayuda al reconocimiento (pero no necesariamente, tendrás que experimentar)

Uno de los problemas que está viendo es que en algunas partes de la imagen, el texto es realmente “delgado” (y los espacios en las letras aparecen después del umbral), mientras que en otras partes es realmente “grueso” (y las letras comienzan fusión). A Tesseract no le gustará 🙂 Sucede porque la imagen de entrada no está iluminada de manera uniforme, por lo que un solo umbral no funciona en todas partes. La solución es hacer un “umbral adaptativo localmente” donde se calcula un umbral diferente para cada vecindario de la imagen. Hay muchas formas de hacerlo, pero echa un vistazo, por ejemplo:

  • Umbral adaptativo gaussiano en OpenCV con cv2.adaptiveThreshold(...,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,...)
  • Método local de Otsu
  • Ecualización de histograma adaptativo local

Otro problema que tienes es que las líneas no son rectas. En mi experiencia, Tesseract puede manejar una muy limitado grado de líneas no rectas (un pequeño porcentaje de distorsión de perspectiva, inclinación o sesgo), pero realmente no funciona con ondulado líneas. Si puede, asegúrese de que las imágenes de origen tengan líneas rectas 🙂 Desafortunadamente, no existe una respuesta simple para esto; tendría que buscar en la literatura de investigación e implementar uno de los algoritmos de última generación usted mismo (y abrirlo si es posible; existe una necesidad real de una solución de código abierto para esto). Una búsqueda en Google Académico de “extracción de OCR de línea curva” lo ayudará a comenzar, por ejemplo:

  • Segmentación de líneas de texto de imágenes de documentos curvas

Por último: creo que sería mucho mejor trabajar con el ecosistema de Python (ndimage, skimage) que con OpenCV en C ++. Los envoltorios de Python de OpenCV están bien para cosas simples, pero para lo que está tratando de hacer no harán el trabajo, necesitará tomar muchas piezas que no están en OpenCV (por supuesto, puede mezclar y combinar). Implementar algo como la detección de líneas curvas en C ++ tomará un orden de magnitud más que en Python (* esto es true incluso si no conoces Python).

¡Buena suerte!

  1. El escaneo a 300 ppp (puntos por pulgada) no es oficialmente un estándar para OCR (reconocimiento óptico de caracteres), pero se considera el estándar de oro.

  2. La conversión de imágenes a escala de grises mejora la precisión en la lectura de texto en general.

He escrito un módulo que lee texto en Image que a su vez procesa la imagen para un resultado óptimo de OCR, Image Text Reader.

import tempfile

import cv2
import numpy as np
from PIL import Image

IMAGE_SIZE = 1800
BINARY_THREHOLD = 180

def process_image_for_ocr(file_path):
    # TODO : Implement using opencv
    temp_filename = set_image_dpi(file_path)
    im_new = remove_noise_and_smooth(temp_filename)
    return im_new

def set_image_dpi(file_path):
    im = Image.open(file_path)
    length_x, width_y = im.size
    factor = max(1, int(IMAGE_SIZE / length_x))
    size = factor * length_x, factor * width_y
    # size = (1800, 1800)
    im_resized = im.resize(size, Image.ANTIALIAS)
    temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
    temp_filename = temp_file.name
    im_resized.save(temp_filename, dpi=(300, 300))
    return temp_filename

def image_smoothening(img):
    ret1, th1 = cv2.threshold(img, BINARY_THREHOLD, 255, cv2.THRESH_BINARY)
    ret2, th2 = cv2.threshold(th1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    blur = cv2.GaussianBlur(th2, (1, 1), 0)
    ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    return th3

def remove_noise_and_smooth(file_name):
    img = cv2.imread(file_name, 0)
    filtered = cv2.adaptiveThreshold(img.astype(np.uint8), 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 41,
                                     3)
    kernel = np.ones((1, 1), np.uint8)
    opening = cv2.morphologyEx(filtered, cv2.MORPH_OPEN, kernel)
    closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel)
    img = image_smoothening(img)
    or_image = cv2.bitwise_or(img, closing)
    return or_image

Nota: esto debería ser un comentario para Alex, respondo, pero es demasiado largo, así que lo pongo como respuesta.

de “Una descripción general del motor Tesseract OCR, de Ray Smith, Google Inc.” en https://github.com/tesseract-ocr/docs/blob/master/tesseracticdar2007.pdf

“El procesamiento sigue un proceso tradicional paso a paso, pero algunas de las etapas eran inusuales en su día y posiblemente lo sigan siendo incluso ahora. El primer paso es un análisis de componentes conectados en el que se almacenan los esquemas de los componentes. Este fue un decisión de diseño computacionalmente costosa en ese momento, pero tenía una ventaja significativa: mediante la inspección del anidamiento de contornos y la cantidad de contornos de hijos y nietos, es simple detectar texto inverso y reconocerlo tan fácilmente como texto en blanco y negro . Tesseract fue probablemente el primer motor de OCR capaz de manejar texto en blanco sobre negro de manera tan trivial “.

Entonces, parece que no es necesario tener texto negro sobre fondo blanco, y también debería funcionar al revés.

valoraciones y reseñas

Ten en cuenta comunicar este escrito si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

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