tutorial recognition pytesseract opencv image-processing ocr tesseract

recognition - Imagen de preprocesamiento para Tesseract OCR con OpenCV



tesseract ocr python opencv (3)

Estoy tratando de desarrollar una aplicación que use Tesseract para reconocer texto de documentos tomados por la cámara de un teléfono. Estoy usando OpenCV para preprocesar la imagen para un mejor reconocimiento, aplicando un desenfoque gaussiano y un método de umbral para binarización, pero el resultado es bastante malo.

Here está la imagen que estoy usando para las pruebas:

Y here la imagen preprocesada:

¿Qué otros filtros puedo usar para hacer que la imagen sea más legible para Tesseract?


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

  2. Convertir la imagen a escala de grises mejora la precisión en la lectura de texto en general.

He escrito un módulo que lee el texto en la imagen que a su vez procesa la imagen para obtener 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


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

En tu ejemplo, hay varias cosas sucediendo ...

Necesita que el texto sea negro y el resto de la imagen en blanco ( no al revés). Eso es lo que sintoniza el reconocimiento de caracteres. La escala de grises está bien, siempre y cuando el fondo sea en su mayoría blanco y el texto en su mayoría negro; los bordes del texto pueden ser grises (suavizados) y eso puede ayudar al reconocimiento (pero no necesariamente, tendrá 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 blanco aparecen después del umbral), mientras que en otras partes es realmente "grueso" (y las letras comienzan fusión). A Tesseract no le va a gustar eso: 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 "umbrales de adaptación local" donde se calcula un umbral diferente para cada vecindario de la imagen. Hay muchas formas de hacerlo, pero echa un vistazo, por ejemplo:

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

Por último: creo que harías mucho mejor trabajando con el ecosistema de Python (ndimage, skimage) que con OpenCV en C ++. Las envolturas de Python de OpenCV están bien para cosas simples, pero para lo que estás tratando de hacer no funcionarán, tendrás que agarrar muchas piezas que no están en OpenCV (por supuesto, puedes mezclar y combinar). Implementar algo como la detección de líneas curvas en C ++ llevará un orden de magnitud más largo que en python (* esto es cierto incluso si no sabes python).

¡Buena suerte!


Nota: este debe ser un comentario para Alex, respondo, pero es demasiado largo, así que lo puse como respuesta.

de "Una descripción general del motor OCR de Tesseract, por 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 fueron inusuales en su día, y posiblemente permanezcan así 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 La decisión de diseño era computacionalmente costosa en ese momento, pero tenía una ventaja significativa: al inspeccionar el anidado de los esquemas y la cantidad de contornos de niños y nietos, es sencillo detectar el texto inverso y reconocerlo tan fácilmente como el texto en blanco y negro . Tesseract fue probablemente el primer motor de OCR capaz de manejar texto blanco sobre negro de manera trivial ".

Así que parece que no es necesario tener un texto negro sobre fondo blanco, y debería funcionar lo contrario también.