Recensione di EasyOCR: ottimi risultati sul testo pulito, un crollo con le dimensioni e un processo CPU da 1 GB

Ultimo aggiornamento il August 17, 2026
Recensione di EasyOCR: ottimi risultati sul testo pulito, un crollo con le dimensioni e un processo CPU da 1 GB
Riepilogo AI
EasyOCR è la libreria OCR pronta all’uso di JaidedAI per Python: pip install easyocr, due righe di codice e il testo contenuto in un’immagine torna sotto forma di stringhe. È distribuita con licenza Apache-2.0, dichiara il supporto per oltre 80 lingue e funziona come una pipeline composta da due modelli PyTorch: un rilevatore CRAFT che disegna riquadri attorno a ciò che ritiene testo, e poi un riconoscitore che legge i caratteri dentro ogni riquadro. I pesi preaddestrati si scaricano automaticamente al primo utilizzo. Per struttura è un’alternativa self-hosted a Tesseract e PaddleOCR, non una API OCR cloud a consumo per singola pagina.

EasyOCR è la libreria OCR pronta all’uso di JaidedAI per Python: pip install easyocr, due righe di codice e il testo dentro un’immagine torna fuori come stringhe. È rilasciata con licenza Apache-2.0, dichiara il supporto per oltre 80 lingue e funziona come una pipeline composta da due modelli PyTorch: un rilevatore CRAFT che traccia riquadri attorno a ciò che ritiene testo, e poi un riconoscitore che legge i caratteri dentro ogni riquadro. I pesi preaddestrati si scaricano in automatico al primo utilizzo. Come struttura è un’alternativa self-hosted a Tesseract e PaddleOCR, non una API OCR cloud a consumo per singola pagina.

L’API base è essenziale: Reader(['en']), poi readtext(). Ma il deployment è tutta un’altra storia: in questo ambiente ci sono circa 2 GB di PyTorch, e nel processo CPU a freddo misurato si arriva quasi a un gigabyte di memoria residente al picco. Ho renderizzato 36 fixture PNG in inglese, eseguito easyocr 1.7.2 su CPU e confrontato i risultati carattere per carattere con il ground truth generato. Dimensioni e orientamento hanno causato i cali più marcati del CER; il pannello ha anche messo in evidenza errori sui token brevi e sul riconoscimento del simbolo del dollaro.

Il fallimento più evidente riguarda proprio il parametro che tutti consigliano. rotation_info ha fama, nelle issue, di essere la soluzione per le immagini ruotate, così l’ho provato su tre copie della stessa frase ruotate di 90 gradi. A 270° ha fatto esattamente ciò che promette, portando il character error rate da 0,83 a 0,10. A 180° ha funzionato solo a metà: da 0,85 a 0,67, con una frase eliminata. A 90° è andato al contrario, da 0,81 a 0,92, e il recognizer ha iniziato a restituire testo specchiato. Stesso parametro, stessa lista di angoli, tre risultati diversi: quindi attivarlo non vuol dire automaticamente “la rotazione è gestita”. Le stesse 36 fixture hanno anche mostrato un crollo netto sulla dimensione del font, un errore sistematico sul simbolo $ e una mia previsione che si è rivelata completamente sbagliata.

Due modelli in un impermeabile

EasyOCR non è un solo modello. È una pipeline di due modelli, e capire quale fase ha fallito cambia del tutto il debug.

La prima fase è CRAFT, il detector. Il suo unico compito è localizzare: stabilire dove nell’immagine c’è del testo e restituire i box. Non legge mai un singolo carattere. La seconda fase è un CRNN recognizer — estrazione delle feature con ResNet, poi BiLSTM, poi decodifica greedy CTC — che legge i caratteri dentro ogni box. Entrambi girano su PyTorch. Su CPU, il recognizer viene eseguito con quantizzazione dinamica int8 di default, ed è per questo che risulta più veloce e leggero di quanto faccia pensare il numero grezzo di parametri.

System diagram: Detection Before Recognition

La conseguenza pratica: EasyOCR ha due modalità di errore completamente diverse, e richiedono rimedi diversi. Se il detector non disegna nessun box, non serve a nulla tarare il recognizer — i caratteri non sono mai entrati nella pipeline. Se il box c’è ma la stringa è sbagliata, allora è un problema di recognition e il preprocessing può aiutare. Quasi tutti i thread del tipo “EasyOCR si è perso il mio testo” che ho letto confondono questi due casi.

Stato attuale del progetto, verificato il 27 luglio 2026: 29.825 stelle, 528 issue aperte, licenza Apache-2.0 e v1.7.2 di settembre 2024, con l’ultimo push su master risalente a dicembre 2025. Queste date non dimostrano né stabilità architetturale né salute della manutenzione. Prima di adottarlo, verifica la compatibilità con il tuo stack Python/PyTorch, la reattività recente dei manutentori e le issue rilevanti per i tuoi input.

L’OCR viene spesso associato alla risoluzione dei CAPTCHA, ma non è questo il caso d’uso qui. Non è stato testato nulla contro sistemi anti-bot, e nulla in questo articolo approva il superamento di challenge anti-detection. L’ambito è la lettura del testo da immagini e screenshot che hai il diritto di consultare.

Cosa ho misurato, e cosa queste cifre non coprono

Il set di test è composto da 36 PNG renderizzati da me: 35 immagini a una sola riga che coprono sette font, otto dimensioni, sette livelli di contrasto, sette angoli di inclinazione, tre rotazioni ortogonali e tre sfondi — più uno screenshot sintetico di una dashboard con 19 elementi etichettati singolarmente. Ogni immagine è stata generata da una stringa fissa (Sphinx of black quartz, judge my vow. 1234567890 — 48 caratteri, maiuscole/minuscole, cifre e punteggiatura) nello stesso passaggio che scriveva l’etichetta ground truth, quindi immagine ed etichetta non possono essersi allontanate l’una dall’altra.

L’accuratezza è il character error rate (CER): distanza di Levenshtein in caratteri divisa per la lunghezza del ground truth. CER 0 significa lettura perfetta. CER 0,10 significa che circa un carattere su dieci è sbagliato. Riporto il CER sensibile alle maiuscole come metrica principale e quello insensibile accanto, perché in pratica è soprattutto il maiuscolo/minuscolo a generare la maggior parte dell’“errore”.

I limiti contano più dei numeri:

  • Solo inglese. Il recognizer english_g2. EasyOCR dichiara oltre 80 lingue; io ne ho testata una sola. Questo non dice nulla sugli script non latini, che sono proprio il terreno delle comparazioni accademiche pubblicate sull’OCR.
  • Solo sintetico. Testo renderizzato, non fotografie. Nessun rumore della fotocamera, nessun artefatto JPEG, nessuna illuminazione, nessuna prospettiva.
  • Niente handwriting. Il progetto stesso indica il riconoscimento della scrittura a mano come non ancora supportato.
  • Solo CPU. macOS arm64, gpu=False. La macchina aveva MPS disponibile, ma EasyOCR usa la CPU su tutto ciò che non è CUDA. Le prestazioni GPU non sono state misurate, quindi qui non compare nessun numero GPU.
  • Una macchina, una versione. easyocr 1.7.2, torch 2.13.0, Python 3.12.

Quindi: sono curve controllate a singola variabile che mostrano esattamente dove si rompe la fedeltà, su testo latino pulito renderizzato. Non sono un punteggio su un corpus reale, e non lo sostituiscono.

La prova è consultabile, non chiusa in un notebook. Il generatore delle fixture e le stringhe esatte sono in tests/build_fixtures.py e tests/fixtures/ground_truth.json; il riconoscimento, i tempi e la raccolta delle risorse sono in tests/run_easyocr.py; e tests/metrics.py calcola i tassi di errore riportati a partire dall’output grezzo. I record di riconoscimento risultanti e le metriche aggregate sono conservati in artifacts/raw/. Rieseguire quella catena è utile per controllare questa macchina e questa versione. Ma non risponde ancora a come EasyOCR si comporterà con le foto del tuo telefono, le tue lingue, i tuoi layout o la tua pipeline di preprocessing, quindi per l’adozione in produzione servono input rappresentativi e non queste sole fixture come certificazione.

Vale la pena segnalare un trabocchetto del harness, perché per poco non mi dava un headline number sbagliato. Il primo passaggio di metriche riportava CER 0,375 su Arial nero pulito, un valore pessimo per l’input più semplice possibile. Il problema non era EasyOCR. Il detector aveva diviso una singola riga visiva in un box per le parole e un box per le cifre, e la mia unione ingenua ordinata per y poi x metteva le cifre prima. Risolto con un raggruppamento consapevole delle righe (raggruppa i box per sovrapposizione verticale, poi leggi da sinistra a destra), i font puliti sono scesi intorno a 0,04–0,10. Se stai costruendo anche tu una valutazione OCR, quel tranello ti aspetta.

Setup: l’installazione è leggera, la dipendenza no

System diagram: Setup: the install is small, the dependency is not

pip install easyocr

Tutto qui, e dice con sincerità molto poco. Il pacchetto in sé è minuscolo; quello che si porta dietro è PyTorch, circa 2 GB. Poi, la prima volta che chiami readtext(), EasyOCR scarica in silenzio i pesi in ~/.EasyOCR/model/93,7 MiB totali, divisi in 79,30 MiB per il detector CRAFT (craft_mlt_25k.pth) e 14,44 MiB per il recognizer inglese (english_g2.pth).

Nessuno lo segnala nei tutorial, quindi: la prima esecuzione richiede accesso alla rete e si fermerà per il download, e ogni deployment containerizzato dovrà o incorporare quei pesi nell’immagine oppure assorbire il download all’avvio a freddo. Una volta in cache, tutto funziona offline.

L’inizializzazione a freddo di Reader() — modelli caricati da disco in RAM, più il passaggio di quantizzazione int8 — ha richiesto 1,3–1,7 secondi tra le varie esecuzioni. Dopo di che:

import easyocr
reader = easyocr.Reader(['en'], gpu=False)
result = reader.readtext('screenshot.png')

E funziona. Due righe, nessuna configurazione, nessun checkpoint da cercare. L’aggettivo “easy” nel nome è davvero meritato in questa fase — l’attrito sta tutto nel peso della dipendenza, non nell’API.

Il pavimento del testo pulito: caratteri quasi perfetti, maiuscole imperfette

Sette font di sistema, nero su bianco, 32 px, stessa stringa ogni volta:

FontCER (sensibile alle maiuscole)CER (insensibile alle maiuscole)
Georgia0.06250.0000
Times0.04170.0417
Comic Sans0.04170.0208
Arial0.08330.0208
Verdana0.08330.0208
Impact0.08330.0208
Courier0.10420.0417
Media0.07140.0238

CER medio 0,071, che scende a 0,024 una volta normalizzato il case. Questo è il dato chiave. EasyOCR non sta perdendo caratteri sul testo latino pulito — sta prendendo bene la forma ma sbagliando il case.

In concreto, la parola minuscola vow viene resa come VOW in sei font su sette (Comic Sans si accontenta di Vow). Impact aggiunge anche ofOf come bonus. L’altro errore ricorrente è la punteggiatura: il punto finale della frase ritorna come : o _ in diversi font. Georgia è una lettura perfetta se smetti di preoccuparti delle maiuscole.

È un’informazione davvero utile. Se il passaggio successivo è fuzzy matching, ricerca per parole chiave o input per un modello linguistico, un cambio di maiuscole costa quasi nulla. Se invece il passaggio a valle è un confronto esatto con una chiave di database, allora costa tutto. Normalizza il case prima del confronto e metà del tasso di errore apparente di EasyOCR sparisce.

Il fatto che Courier sia il peggiore (0,1042) è coerente: i font monospazio allargano in modo innaturale lo spazio tra i caratteri, cosa più difficile per un decoder CTC che ha imparato spaziature più tipiche.

Il crollo di dimensione è esattamente dove la documentazione dice che sia

Measured results chart: Character error rate by glyph height

readtext() ha un parametro documentato, min_size=10, che scarta i box rilevati più bassi di 10 pixel. Molti lo ignorano. È il numero più importante nell’API per chi estrae dati da screenshot o PDF, e questo è l’effetto quando si varia l’altezza dei glifi renderizzati:

px renderizzatiCERCosa è successo
80.7708Crollo — i box scendono sotto il filtro min_size e vengono scartati; sopravvivono solo frammenti
100.1458Degradato — proprio sul limite, il detector frammenta la riga in 3 box
120.0417Recuperato
160.0000Lettura perfetta
200.0208Pulito
280.0208Pulito
400.0625Pulito (riappare il cambio di case)
640.0625Pulito (cambio di case)

Il salto da 0,04 a 0,77 tra 12 px e 8 px non è un degrado graduale. È un filtro che fa esattamente ciò che promette di fare, e il risultato è che il testo sotto circa 10 px diventa di fatto invisibile per EasyOCR predefinito.

Il punto dolce è 12–28 px, con CER pari a 0 a 16 px. Sopra i 40 px, il CER risale leggermente — non perché i caratteri si perdano, ma perché ritorna il flip vowVOW. Il testo grande non è più difficile da leggere; semplicemente non beneficia più di quella spaziatura che faceva funzionare in modo perfetto i 16 px.

Per chi estrae testo da screenshot: controlla l’altezza dei glifi renderizzati prima di dare la colpa al modello. Una dashboard catturata a 1× su un display HiDPI, o una pagina PDF rasterizzata a 72 DPI, mette regolarmente il testo principale sotto i 10 px. Cattura a 2× o fai upscale prima dell’OCR, e ti risparmierai tutta la classe di bug report del tipo “EasyOCR mi ha ignorato metà pagina”. Se non puoi farlo, abbassa min_size — ma aspettati rumore, perché quel filtro serve proprio a sopprimere le rilevazioni spazzatura.

Rotazione: 10° di tolleranza, e una correzione non simmetrica

Prima lo skew. Angoli piccoli, Arial 32 px, impostazioni predefinite contro rotation_info=[90,180,270]:

Angolo di skewCER (default)CER (con rotation_info)
0.08330.0833
0.04170.0417
10°0.02080.0833
15°0.29170.3750
20°0.75000.7708
30°0.89580.8750
45°0.89580.8750

EasyOCR di default gestisce lo skew fino a circa 10° senza problemi (CER ≤ 0,083), vacilla a 15° e crolla a 20°. rotation_info non fa nulla per lo skew, il che ha senso una volta capito cosa fa: ritenta solo agli angoli che gli indichi, e uno skew di 15° non è 90, 180 o 270. A 10° in realtà peggiora leggermente le cose (0,021 → 0,083), perché un retry con l’angolo sbagliato può vincere il voto di confidenza.

Le rotazioni ortogonali sono il punto strano:

RotazioneCER (default)CER (con rotation_info)Recuperato?
90°0.81250.9167No — peggio
180°0.85420.6667Parzialmente
270°0.83330.1042

Stesso parametro. Stessa lista di angoli. Tre risultati diversi.

A 270°, rotation_info fa esattamente quello che promette la issue: il CER scende da 0,83 a 0,10, una lettura davvero utilizzabile. A 180°, funziona solo in parte: il CER migliora a 0,67, ma la frase my vow. sparisce del tutto. A 90°, peggiora, da 0,81 a 0,92, e l’output grezzo spiega il perché: il recognizer restituisce stringhe specchiate. VOW ritorna come MOA. quartz ritorna come zuuenb. Le leggi in uno specchio e sono corrette, che è un gran bel trucco da festa e una pipeline dati inutile.

Ho verificato questo sui prediction grezzi e non sulle metriche aggregate, perché la mia prima ipotesi era che l’ordine di unione avesse mescolato tutto. Non è un artefatto di join — è ciò che EasyOCR ha davvero restituito.

Il meccanismo è un’ipotesi, non una misura; non è stato eseguito alcun esperimento sulla convenzione di rotazione. Pillow renderizza gli angoli positivi in senso antiorario, quindi solo l’immagine renderizzata a 270° finisce per allinearsi con un’orientazione di retry che il recognizer gestisce bene, mentre il caso a 90° ha il miglior retry che cade su un orientamento ribaltato. Qualunque sia il meccanismo, la lezione operativa non dipende da questo:

Questa fixture mostra che rotation_info non può essere considerato simmetrico tra orientamenti. Verifica le rotazioni che ti aspetti nei tuoi input; la normalizzazione dell’orientamento a monte è un possibile rimedio, non un requisito dimostrato da tre esempi renderizzati.

La previsione che ho sbagliato

Partivo pensando che il basso contrasto fosse il punto debole di EasyOCR. Testo grigio tenue su bianco: il classico fallimento OCR, e c’è anche una strada documentata per recuperarlo: contrast_ths=0.1 con adjust_contrast=0.5, che riesegue i box a basso contrasto con una copia più contrastata e mantiene il risultato più sicuro.

Non è mai entrato in funzione, perché non ce n’era bisogno.

Grigio del testoContrasto di WeberCER (default)CER (adjust_contrast=1.0)
0 (nero)1.0000.08330.0833
640.7490.08330.0833
1100.5690.08330.0833
1500.4120.10420.1042
1800.2940.06250.0625
2000.2160.04170.0417
2200.1370.04170.0417

Il CER non esce mai dalla fascia del testo pulito, fino a Weber 0,14 — grigio 220 su bianco, talmente tenue che ho dovuto strizzare gli occhi sulla fixture per confermare che il testo ci fosse davvero. E la colonna del contrasto aumentato è identica alla colonna default a ogni passaggio, perché il default aveva già successo.

Gli sfondi raccontavano la stessa storia. Testo nero in tutti i casi:

SfondoCER
Pannello blu chiaro uniforme0.083
Gradiente verticale0.021
Rumore gaussiano (μ200, σ22)0.000

Una lettura perfetta sulla fixture più rumorosa dell’intero set.

L’ambito è ristretto: si tratta di basso contrasto a colore uniforme e senza rumore, non di uno scontrino fotografato con rumore del sensore e compressione JPEG. In questo set di fixture, i problemi maggiori sono stati la geometria e i token brevi; le varianti di colore e rumore sintetico testate non lo sono state.

Uno scenario reale: estrarre numeri da uno screenshot di dashboard

Questo è il caso che, in pratica, la maggior parte del lavoro OCR in Python finisce per essere. Qualcuno ti manda lo screenshot di una dashboard interna, oppure stai eseguendo una pipeline di scraping in Python su una pagina analytics piena di grafici in cui i numeri esistono solo come pixel renderizzati, e vuoi i valori come dati.

Ho renderizzato una finestra “Sales Dashboard” — header scuro con titolo e badge avatar circolare, tre pannelli KPI, tre pulsanti, una tabella 2×3 — e ho etichettato tutti i 19 elementi di testo con le rispettive stringhe esatte e i box pixel, poi ho confrontato l’output di EasyOCR con questi tramite sovrapposizione dei box.

Recall del detection: 16 su 19. I tre mancati:

  • il badge a una lettera, "A"
  • la cella della tabella "Q1"
  • la cella della tabella "Q2"

Invece "Q3" è stato rilevato. Stesso font, stessa dimensione, stessa colonna: il detector ha mantenuto un token da due caratteri e ne ha scartati due altri. La rilevazione è stata incoerente tra celle visivamente simili. Poiché in queste esecuzioni l’output era deterministico, questo non è un indizio di comportamento casuale tipo “moneta lanciata”. Un problema simile sulla qualità degli screenshot è tracciato in #460.

Sui 16 elementi trovati, il testo era quasi perfetto: CER medio 0,027, con 13 su 16 esatti. Titoli, etichette, pulsanti (“Save”, “Cancel”, “Export CSV”), intestazioni di colonna e numeri con separatore delle migliaia tornavano con CER 0. 1,284 è stato letto correttamente, virgola inclusa.

Le tre letture imperfette sono tutte lo stesso errore. Importi in dollari:

Ground truthLettura EasyOCR
$57,912S57,912
$18,330S18,330
$25,178S25,178
$12,004$12,004 (corretto)

Tre dollari su quattro sono diventati una S maiuscola. Visivamente non è assurdo — ma significa che ogni campo di valuta nell’estrazione è a un carattere dal diventare spazzatura, e un banale float() andrà in errore su tutti.

Se la tua pipeline per screenshot contiene etichette brevi o valori monetari, valuta mitigazioni candidate come upscale, crop con padding, vincoli sui campi attesi o post-processing consapevole dei simboli. Nulla di tutto questo è stato benchmarkato qui, e una regex che riscrive la S iniziale può corrompere valori legittimi. Applica correzioni solo dove schema e regole di validazione le rendono sicure.

Quanto costa eseguirlo

Numeri sulla stessa macchina (macOS arm64, CPU, un solo host, misurati sotto possibile carico concorrente — da trattare come forma, non come benchmark universale):

MetricaValore
Pesi del modello su disco93,7 MiB (79,30 detector + 14,44 recognizer)
Memoria residente di picco, processo CPU a freddo984,5 MiB
Inizializzazione a freddo di Reader()1,3–1,7 s
Latenza a caldo, una riga pulita di 48 caratteri (p50)~0,062 s (p25–p75: 0,059–0,067 s, n=20)
detail=0 vs detail=1~uguale (mediana 0,062 vs 0,063 s)

Il costo principale non sono i 94 MB di pesi — è circa un gigabyte di memoria residente per processo worker, in aggiunta a ~2 GB di installazione torch. È questo il numero che decide se entra o meno nel tuo container, ed è il numero che quasi nessuno cita.

La velocità è buona nel caso facile. Meno di 0,1 s a caldo per una singola riga pulita su CPU è perfettamente utilizzabile. Ma questo è il caso facile: una sola riga breve e ad alto contrasto. Le ricorrenti lamentele “EasyOCR takes tens of seconds on CPU” riguardano documenti grandi con più regioni e dimensione del canvas completa, e io non le ho riprodotte — workload diverso, che segnalo senza attribuirmelo.

Un piccolo mito da sfatare: detail=0 non rende EasyOCR più veloce. Rimuove box di delimitazione e punteggi di confidenza dal valore di ritorno. Il calcolo è già stato fatto. Le mediane differiscono di un millisecondo, cioè rumore.

Pro e contro

Pro

  • Recupero dei caratteri su testo latino renderizzato pulito praticamente perfetto — CER medio 0,071 sensibile alle maiuscole, 0,024 insensibile, con CER pieno pari a 0 ottenibile a 16 px.
  • API davvero in due righe. Reader(['en']) poi readtext(), senza configurazioni né selezione manuale del modello.
  • Molto più robusto al contrasto di quanto dica il passaparola: nessun crollo fino a Weber 0,14 su testo pulito, e sfondi rumorosi/gradienti/colorati non hanno degradato il risultato (la fixture con rumore gaussiano è stata letta perfettamente).
  • Quasi perfetto sugli elementi di screenshot che riesce a rilevare: CER medio 0,027, 13 su 16 esatti, numeri con separatore delle migliaia inclusi.
  • Deterministico. Ogni valore di accuratezza qui è stato identico al byte in due esecuzioni di processo completamente indipendenti; si è mosso solo il timing.
  • Apache-2.0 e self-hosted, senza fee d’uso del vendor; i costi ricadono su compute, memoria, storage e coda.

Contro

  • Crollo netto sotto la soglia documentata min_size=10 — CER 0,77 a 8 px. Il testo UI piccolo è invisibile di default.
  • La tolleranza allo skew si ferma intorno a 10° e crolla entro 20°.
  • rotation_info non è una correzione simmetrica: 270° recupera, 180° recupera solo in parte, 90° peggiora e restituisce testo specchiato.
  • Il detector scarta token brevi isolati — un badge a una lettera e due celle da 2 caratteri, pur mantenendo una terza cella identica per formato.
  • Lettura sistematica di $ come S sui valori monetari (3 su 4).
  • Circa 1 GB di memoria residente per processo, più una dipendenza torch da ~2 GB.
  • L’ultima release è di settembre 2024; il progetto è stabile più che in forte evoluzione.

Chi dovrebbe usarlo e chi dovrebbe lasciar perdere

Valuta EasyOCR quando i tuoi input sono testo pulito, diritto e renderizzato a dimensione ragionevole — screenshot, catture UI, PDF rasterizzati o report generati — e vuoi una pipeline Python self-hosted senza fee di utilizzo del vendor. I risultati sintetici in inglese su CPU valgono per questo scenario; fotografie, handwriting e altri script richiedono test separati.

Lascia perdere se i tuoi input assomigliano a uno di questi casi. Fotografie — i miei numeri sono su testo sintetico renderizzato e non dicono nulla su rumore della fotocamera, prospettiva o illuminazione. Scrittura a mano — il progetto stesso non la dichiara supportata. Script non latini — EasyOCR supporta oltre 80 lingue, ma io ne ho testata una sola, e per questi casi il riferimento sono le comparazioni accademiche pubblicate, non una scansione sintetica dell’inglese. Input ruotati in modo arbitrario — a meno che tu non faccia prima una correzione dell’orientamento. Deployment con memoria limitata — un gigabyte per worker si somma in fretta.

Prima di scegliere l’OCR, ispeziona DOM e risposte di rete. Se i valori desiderati esistono già come testo strutturato, estrarre da quella fonte evita gli errori di detection e recognition dell’OCR. L’OCR ha senso dove i pixel sono l’unica rappresentazione disponibile.

Alternative, e dove si colloca il nostro stack

EasyOCR è Apache-2.0 e self-hosted, senza fee di utilizzo del vendor ma con costi reali di compute e operativi. PaddleOCR, Tesseract e i modelli vision-language non sono stati eseguiti in questo benchmark, quindi non viene fatta alcuna conclusione diretta uno contro uno.

Il confronto più interessante non è OCR contro OCR. È capire se l’OCR serva davvero.

Gran parte del lavoro di estrazione da screenshot che vedo è un workaround per una pagina web difficile da fare scraping: una tabella renderizzata via JavaScript, una dashboard dietro login, un sito che oppone resistenza. Fare screenshot e poi OCR sembra la strada più semplice, ma stai buttando via testo strutturato perfettamente buono e poi pagando una tassa sul simbolo del dollaro per riaverne una versione peggiore.

Nota dell’autore: Thunderbit è la nostra opzione gestita per estrarre dati dalle pagine web. Non è stata eseguita su queste fixture immagine. Il confine rilevante è la rappresentazione della sorgente: usa l’estrazione da DOM/network quando esistono dati web strutturati, e valuta l’OCR quando i pixel sono l’unica fonte.

Letture correlate dallo stesso banco di test: la confronto completo degli scraper open source, la recensione di Crawl4AI e uno sguardo più ampio su estrazione guidata dall’AI per le pagine che resistono ai selettori.

Prova Thunderbit per l’estrazione di dati dal web

Verdetto

Vale la pena usare EasyOCR? Sì, se le tue immagini sono dritte, i glifi sono alti almeno 12 pixel e stai leggendo script latini. In questi casi è molto buono — CER medio 0,071 sul testo pulito, 0,024 una volta normalizzato il case, lettura perfetta a 16 px e una robustezza al contrasto migliore della sua reputazione. L’API è davvero di due righe e l’output è deterministico, cosa che conta più di quanto si ammetta quando si sta debuggando una pipeline.

Fuori da questi confini, fallisce in modi specifici e prevedibili. Il testo sotto i 10 px sparisce nel filtro min_size. Lo skew oltre i 20° rovina la lettura. rotation_info corregge un orientamento ortogonale, ne corregge solo a metà un altro e peggiora il terzo con testo specchiato. Lettere singole e token da due caratteri cadono fuori dal detector mentre i vicini sopravvivono. I simboli $ diventano la lettera S.

I fallimenti sulle fixture sono arrivati da entrambe le fasi: box mancati o orientati male sul lato geometrico, e confusione sul simbolo del dollaro sul lato recognition. Considera upscale, normalizzazione dell’orientamento, crop con padding e correzione dei simboli consapevole dello schema come candidati da validare, non come fix universalmente sicuri.

Soprattutto, non testarlo nel modo in cui ho quasi fatto io, con un harness di valutazione rotto e un numero che non capisci. Genera le tue fixture, conosci esattamente il tuo ground truth e trova il tuo crollo personale.

Prova Thunderbit per l’estrazione di dati dal web Get Started Free

FAQ

EasyOCR è abbastanza accurato per l’estrazione di testo da screenshot in produzione? Sulla dashboard sintetica, gli elementi allineati hanno mostrato CER medio 0,027 con 13 su 16 esatti. Tre dei 19 elementi non sono stati rilevati e tre dollari su quattro sono diventati S. Se questo sia accettabile — e se upscale o correzioni consapevoli dello schema aiutino — va verificato sui layout di destinazione.

Qual è la dimensione minima del font che EasyOCR riesce a leggere? In pratica, circa 12 pixel di altezza dei glifi renderizzati. Il parametro readtext() min_size=10 scarta i box rilevati più bassi di 10 px, e l’effetto è un crollo netto più che una pendenza: CER 0,77 a 8 px, 0,15 a 10 px, 0,04 a 12 px e 0 a 16 px. La fascia pulita nel mio sweep era 12–28 px. Se la tua sorgente è uno screenshot HiDPI catturato a 1× o un PDF rasterizzato a 72 DPI, fai upscale prima dell’OCR invece di abbassare min_size, perché quel filtro serve a sopprimere le rilevazioni spazzatura.

rotation_info risolve le immagini ruotate in EasyOCR? Non in modo affidabile, e non in modo simmetrico. Con rotation_info=[90,180,270] su tre copie ruotate ortogonalmente della stessa frase, l’immagine a 270° è stata recuperata bene (CER 0,83 → 0,10), quella a 180° solo in parte (0,85 → 0,67, con una frase eliminata), e quella a 90° è peggiorata (0,81 → 0,92) restituendo testo specchiato come VOWMOA. Inoltre non fa nulla per piccoli angoli di skew, perché ritenta solo agli angoli specificati. Correggi l’orientamento prima di chiamare EasyOCR invece di affidarti a questo parametro.

Quanta memoria e spazio su disco richiede EasyOCR? I pesi occupano 93,7 MiB, scaricati in ~/.EasyOCR/model/ al primo uso — 79,30 MiB per il detector più 14,44 MiB per il recognizer inglese. La memoria residente di picco nel processo CPU a freddo misurato era 984,5 MiB, in aggiunta a un’installazione torch di circa 2 GB. L’inizializzazione a freddo di Reader ha richiesto 1,3–1,7 secondi; una singola riga pulita ha poi girato con p50 vicino a 0,062 secondi su questa macchina. detail=0 ha cambiato la forma del ritorno, non il runtime misurato.

EasyOCR è gratuito per uso commerciale ed è ancora mantenuto? È sotto licenza Apache-2.0, quindi permissiva e adatta anche all’uso commerciale. Al 27 luglio 2026 il repository conta 29.825 stelle con 528 issue aperte, l’ultima release è v1.7.2 di settembre 2024 e l’ultimo push su master è stato a dicembre 2025. Leggilo come stabile più che abbandonato — l’architettura non cambia da un po’ e l’attività si è spostata sulle issue. Verifica da solo la licenza e lo stato delle release prima di costruirci sopra.

Ke
Ke
CTO di Thunderbit | Senior Data Scientist ed esperto di ML Con quasi un decennio di esperienza nel machine learning e nella data science, Ke Shen è un ex studente della Columbia University ed ex Senior Data Scientist presso Walmart Labs. Grazie a una profonda competenza, riconosciuta dai suoi pari, in Python, R, Java e statistica, condivide insight collaudati sul passaggio di algoritmi AI complessi dalla teoria a un'architettura pronta per la produzione.
Indice
Thunderbit · Agente AI per dati web

Estrai dati da qualsiasi pagina in 1 clic

Scelto da oltre 250.000 utenti
piano gratuito disponibile
Dalla pagina web al foglio di calcolo
Descrivi ciò che ti serve — l'agente AI di Thunderbit lo estrae ed esporta in Excel, Google Sheets, Airtable o Notion. Puoi iniziare gratis.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week