Tesseract OCR può riconoscere pedici e apici?

Aug 24 2020

Ho problemi con il riconoscimento generale di pedice e apice nei frammenti di testo.

Immagine di esempio:

Ho usato Tesseract 4.1.1 con i dati di allenamento disponibili sotto https://github.com/tesseract-ocr/tessdata_best. Le numerose opzioni avevano valori predefiniti tranne:

  • tessedit_create_hocr = 1 (per ottenere il risultato come HOCR)
  • hocr_font_info = 1 (per ottenere ulteriori informazioni sui caratteri come la dimensione del carattere)
  • hocr_char_boxes = 1 (per ottenere risultati basati sui caratteri)

La lingua è stata impostata su ing. Né con la modalità di segmentazione della pagina 3 (PSM_AUTO_OSD) né 11 (PSM_SPARSE_TEXT) né 12 (PSM_SPARSE_TEXT_OSD) il pedice / apice è stato riconosciuto correttamente.

Nell'output i sub / sup-frammenti erano tutti più o meno sbagliati:

  • "Subtext Sub " è riconosciuto come "Subtextsu",
  • "Suptext Sub " è riconosciuto come "Suptexts?"
  • "P 0 " è riconosciuto come "Po"
  • "P 100 " è riconosciuto come "P1go"
  • "a 2 + b 2 " è riconosciuto come "a + b?"

Utilizzando Tesseract per OCR c'è un modo per ...?

  1. ottimizzare la gestione di pedici / apici
  2. ottenere informazioni su pedice / apice riconosciuto (nell'output hocr - idealmente per ogni carattere)

Risposte

1 MaS Sep 22 2020 at 06:52

Lavorare sulla qualità dell'immagine come suggerito in altre domande / risposte a questo argomento non ha davvero cambiato nulla.

Seguendo questi 2 link dal tesseract-google-newsgroup all'inizio sembrava davvero una questione di formazione: link1 e link2 .

Ma dopo aver fatto alcuni esperimenti ho scoperto che la modalità del motore OEM_DEFAULT-OCR utilizzata non riporta le informazioni necessarie. Ho trovato una soluzione parziale al problema. Parziale, perché ora ricevo la maggior parte delle informazioni su sub / sup e anche i caratteri riconosciuti sono corretti nella maggior parte dei casi, ma non per tutti i personaggi.

Utilizzando la modalità motore OEM_TESSERACT_ONLY-OCR (= la modalità legacy) e alcuni metodi API forniti da Tess4J, ho creato la seguente classe di test java:

public class SubSupEvaluator {
    public void determineSubSupCharacters(BufferedImage image) {
        //1. initialize Tesseract and set image infos
        TessBaseAPI handle = TessAPI1.TessBaseAPICreate();
        try {
            int bpp = image.getColorModel().getPixelSize();
            int bytespp = bpp / 8;
            int bytespl = (int) Math.ceil(image.getWidth() * bpp / 8.0);
            TessBaseAPIInit2(handle, new File("./tessdata/").getAbsolutePath(), "eng", TessOcrEngineMode.OEM_TESSERACT_ONLY);
            TessBaseAPISetPageSegMode(handle, TessPageSegMode.PSM_AUTO_OSD);
            TessBaseAPISetImage(handle, ImageIOHelper.convertImageData(image), image.getWidth(), image.getHeight(), bytespp, bytespl);

            //2. start actual OCR run
            TessBaseAPIRecognize(handle, null);

            //3. iterate over the result character-wise
            TessResultIterator ri = TessBaseAPIGetIterator(handle);
            TessPageIterator pi = TessResultIteratorGetPageIterator(ri);
            TessPageIteratorBegin(pi);
            do {
                //determine character
                Pointer ptr = TessResultIteratorGetUTF8Text(ri, TessPageIteratorLevel.RIL_SYMBOL);
                String character = ptr.getString(0);
                TessDeleteText(ptr); //release memory

                //determine position information
                IntBuffer leftB = IntBuffer.allocate(1);
                IntBuffer topB = IntBuffer.allocate(1);
                IntBuffer rightB = IntBuffer.allocate(1);
                IntBuffer bottomB = IntBuffer.allocate(1);
                TessPageIteratorBoundingBox(pi, TessPageIteratorLevel.RIL_SYMBOL, leftB, topB, rightB, bottomB);

                //write info to console
                System.out.println(String.format("%s - position [%d %d %d %d], subscript: %b, superscript: %b", character, leftB.get(), topB.get(),
                    rightB.get(), bottomB.get(), TessAPI1.TessResultIteratorSymbolIsSubscript(ri) == TessAPI1.TRUE,
                    TessAPI1.TessResultIteratorSymbolIsSuperscript(ri) == TessAPI1.TRUE));
            } while (TessPageIteratorNext(pi, TessPageIteratorLevel.RIL_SYMBOL) == TessAPI1.TRUE);
        } finally {
            TessBaseAPIDelete(handle); //release memory
        }
    }
}

La modalità legacy funziona solo con i dati di addestramento "normali". L'utilizzo dei dati di addestramento "migliori" genera un errore.

sancho.sReinstateMonicaCellio Sep 10 2020 at 07:50

Ci sono pochissime informazioni su questo argomento. Un'opzione per migliorare il riconoscimento dei caratteri sub / apici (anche se non la posizione stessa) è preelaborare l'immagine, con cv2/ pil(anche cuscino ) ad es., E poi tesserarla.

Vedi Come rilevare i numeri in pedice in un'immagine utilizzando OCR?

Correlati (ma altrimenti non rispondendo alla domanda):

https://www.mail-archive.com/[email protected]/msg19434.html

https://github.com/tesseract-ocr/tesseract/blob/master/src/ccmain/superscript.cpp

mjpablo23 Nov 07 2020 at 02:43

cosa ne pensate di far riconoscere a tesseract le singole lettere?

Tesseract non riconosce i singoli caratteri

L'ho provato con l'opzione --psm 10

tesseract imTstg.png out5 --psm 10

ma non sembrava funzionare. Sto pensando di eseguire yolo solo per rilevare le singole lettere.