Tesseract OCR può riconoscere pedici e apici?
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 ...?
- ottimizzare la gestione di pedici / apici
- ottenere informazioni su pedice / apice riconosciuto (nell'output hocr - idealmente per ogni carattere)
Risposte
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.
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
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.