Saltar al contenido

Tesseract siempre falta una línea de texto en la imagen

Posterior a de una extensa recopilación de información resolvimos esta inconveniente que tienen muchos de nuestros lectores. Te regalamos la solución y deseamos serte de mucha ayuda.

Solución:

Mi referencia está aquí.

Nota: No es necesario que se ocupe de los pasos previos al proceso porque parece que ya tiene una imagen pura. No hace mucho ruido.

Mi información de entorno:

Operating system: Ubuntu 16.04

Versión Tesseract por el comando de tesseract --version:

tesseract 4.1.1-rc2-21-gf4ef
 leptonica-1.78.0
  libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 1.4.2) : libpng 1.2.54 : libtiff 4.0.6 : zlib 1.2.8 : libwebp 0.4.4 : libopenjp2 2.1.2
 Found AVX
 Found SSE
 Found libarchive 3.1.2

Versión OpenCV por el comando de pkg-config --modversion opencv:

3.4.3

Diferencia: Cuando verifiqué su código, solo vi la clara diferencia con este. Estás abriendo la imagen con la biblioteca leptonica una vez más en lugar de opencv.

Aquí está el código y la salida resultante:

Aporte:

ingrese la descripción de la imagen aquí

Textos de salida:

Al AQ A3 Ad AS A6 Al A8

| 2 3 4 5 6 7 8

WH GN YE GY PK Bu RD VT
K101 K102 K103 K104 K105 K107 K109 K110
Q30,0 Q30.1 Q30.2 Q30.3 Q30.4 Q30.5 Q30.6 Q30.7
=13/L.2 =13/2.2 =13/4.2 =13/6.2 =13/7.2 =13/10.2 FIBL.2 = 1312.2

AS AlO All Al2 AL3 Al4 ALS AL6

9 10 ll 12 13 14 15 16
GY /PK RD/BU WH/GN BN/GN WH/YE YE/BN WH/GY GY/BN
Kl1l K112 y114 K115 K117 K118 K124
Q31,0 Q31.1 Q31.2 Q31.3 Q31.4 Q31.5 Q31.6 Q31.7
=13/13.2 =13/14.2 =13/15.2 =13/16.2 =1B7.2 PIB. =13/21.2

Beckhoff KL 2809

Código:

#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;

int main(int argc, char* argv[])

    string outText;


    // Create Tesseract object
    tesseract::TessBaseAPI *ocr = new tesseract::TessBaseAPI();

    ocr->Init(NULL, "eng", tesseract::OEM_LSTM_ONLY);


    // Set Page segmentation mode to PSM_AUTO (3)
    ocr->SetPageSegMode(tesseract::PSM_AUTO);


    // Open input image using OpenCV
    Mat im = cv::imread("/ur/image/directory/tessatest.png", IMREAD_COLOR);


    // Set image data
    ocr->SetImage(im.data, im.cols, im.rows, 3, im.step);

    // Run Tesseract OCR on image
    outText = string(ocr->GetUTF8Text());

    // print recognized text
    cout << outText << endl;

    // Destroy used object and release memory
    ocr->End();

    return EXIT_SUCCESS;

La compilación del código:

g++ -O3 -std=c++11 test.cpp -o output `pkg-config --cflags --libs tesseract opencv`

Tesseract tiene tendencia a dejar caer líneas o fragmentos de texto en varias circunstancias:

  • Hay algunas cosas que no son de texto que interfieren (líneas, artefactos, gradientes de iluminación)
  • Hay demasiadas cosas que no se reconocen como personaje con suficiente certeza.
  • La línea es irregular (protuberancias) / mal alineada, también distorsiones como la perspectiva
  • Hay espacios demasiado grandes dentro de la línea.
  • El texto está demasiado cerca de otro texto, especialmente si el tamaño de fuente también es desigual

No publicaré una solución o código listos, pero puedo escribir lo que probaría basándome en mi experiencia con Tesseract:

  1. No limite las imágenes escaneadas, a menudo empeora el efecto a medida que se pierde la información, tiene más sentido cuando no se escanea el texto sino una foto con gradientes de luz / sombra, etc. (en tales escenas, el umbral adaptativo u otros filtros + umbral funcionan relativamente bien) . De lo contrario, no hay razón para hacer eso, Tesseract realiza algunas binarizaciones internamente (lo que funciona bastante mal para los gradientes de rayos / sombras, ya que no es adaptativo, sino bastante bueno para las imágenes escaneadas).

  2. Intente comprobar cómo va con diferentes tamaños de imagen / ppp. Puede funcionar mejor si lo encuentra óptimo (se trata más de una versión anterior de Tesseract, en la actualidad importa menos).

EDITAR: Para cambiar el tamaño en opencv puede usar:

cv::resize(inImg, outImg, cv::Size(), 0.7, 0.7);
  1. Eliminar esos rectángulos alrededor del texto puede ayudar.

    • Se puede hacer mediante detección de líneas o detección de rectángulos o detección de contornos, filtrando por longitud / tamaño en relación con el ancho de la imagen (o absoluto si siempre es el mismo) y dibujando en blanco para eliminarlo.

    EDITAR: Hay varios tutoriales de detección de rectángulos en Internet. La mayoría de ellos detectan y dibujan. Por ejemplo, alyssaq / opencv / squares.cpp en Github. Puede detectar cuadrados, luego filtrarlos por tamaño en c ++ y luego dibujarlos en blanco para que dibuje el blanco sobre el negro y los elimine de manera efectiva.

    • Alternativamente, se puede hacer mediante copia con enmascaramiento, pero puede ser más difícil de escribir y peor en rendimiento.
  2. Puede resultar útil procesar línea por línea. Si el escaneo siempre está bien alineado o puede alinearlo (por ejemplo, midiendo los ángulos de las cajas), entonces puede hacer un histograma de números de píxeles oscuros por Y (vertical) y encontrar espacios entre líneas, cortar esas líneas, agregar algo de relleno blanco. a cada uno de ellos y procesar cada uno de ellos uno por uno. Por supuesto, todo eso después de la eliminación de las líneas de cajas. Es peor cuando se trata de rendimiento, pero raramente pierde líneas.

EDITAR: para histograma sobre Y y encontrar espacios entre líneas, consulte esta pregunta Encuentre todos los picos para Mat () en OpenCV C ++; debería hacerse de manera similar pero en otro eje.

para recortar, consulte esta pregunta y respuestas ¿Cómo recortar un CvMat en OpenCV?

para agregar relleno hay un método copyMakeBorder (), consulte Agregar bordes a sus imágenes en la documentación.

  1. También puede intentar encontrar dónde está el texto mediante otros métodos y procesar cada campo / palabra individualmente (lo que es incluso menos eficiente pero menos probable que suelte texto). Luego, puede volver a conectarse en líneas (haciendo coincidir Y en líneas y clasificando en línea por X).

    • puede erosionar la imagen del umbral para agrupar las letras, encontrar contornos, filtrarlos, tomar unos de tamaños específicos para procesarlos, recortarlos con máscara, rellenarlos con blanco, procesar cada uno

    EDITAR: para esto, puede encontrar preguntas y respuestas útiles en este enlace: Extracción de texto OpenCV

    • puede usar los rectángulos que tiene visibles: encuentre sus posiciones con detección de forma, recorte el contenido, procese individualmente
  2. También puede intentar usar Tesseract para obtener palabras o símbolos que delimiten cuadros + certezas en lugar de texto, que es menos probable que suelte algunas partes del texto (pero aún así puede hacerlo). Luego puede conectar cuadros en líneas por su cuenta (lo cual es un problema bastante difícil si tiene una foto con una hoja de papel desigual + diferentes tamaños de fuente + perspectiva, pero bastante fácil si tiene un escaneo bien alineado de un documento normal). Probablemente también necesite establecer un umbral para filtrar los artefactos que puedan aparecer.

EDITAR: Para averiguar palabras o símbolos puede usar este código:

tesseract::ResultIterator *iter = tess.GetIterator();
tesseract::PageIteratorLevel level = tesseract::RIL_WORD; // may use RIL_SYMBOL

if (iter != 0) 
  do 
    const char *word = iter->GetUTF8Text(level);
    float conf = iter->Confidence(level);
    int x1, y1, x2, y2;
    iter->BoundingBox(level, &x1, &y1, &x2, &y2);

    if (word) 
      printf("word: '%s';  tconfidence: %.2ft bounding box: [%d,%d,%d,%d]n", word, conf, x1, y1, x2, y2);

      // ... use that info

      delete[] word;
    
   while (iter->Next(level));

Código no probado, el código adecuado puede diferir para diferentes versiones de Tesseract, esto es para 3.0.

  1. Por último, pero no menos importante, si no todas las imágenes son escaneos bien alineados, entonces, por supuesto, debe realizar un procesamiento para que estén bien alineados y enderezados, también deberá eliminar los degradados / sombras si las imágenes se realizan con una foto en lugar de un escáner. Sin embargo, por ejemplo, veo que esos son escaneos relativamente buenos, por lo que no es necesario aquí (veo un problema con algunos caracteres que no están bien impresos / fotocopiados, será difícil hacer algo al respecto).

EDITAR: no pondré ejemplos o enlaces para este punto, ya que es un tema muy amplio y depende de la calidad de las imágenes, cómo se hacen, cómo se ve el texto, cuál es el fondo, etc.

Aquí tienes las comentarios y puntuaciones

Al final de todo puedes encontrar las interpretaciones de otros sys admins, tú igualmente tienes la opción de dejar el tuyo si te gusta.

¡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 *