2011-12-15 10 views
12

Questo è qualcosa su cui sto lavorando e mi piacerebbe ricevere input dalle persone intelligenti qui su StackOverflow.PHP Riparare il testo errato

Quello che sto tentando è una funzione per riparare il testo basato sulla combinazione di varie versioni errate della stessa pagina di testo. Fondamentalmente questo può essere usato per combinare diversi risultati OCR in uno con maggiore accuratezza rispetto a ciascuno di essi individualmente.

Inizio con un dizionario di 600.000 parole inglesi, che è praticamente tutto compreso termini legali e medici e nomi comuni. Ho già questo.

Quindi ho 4 versioni del campione di testo.

Qualcosa di simile a questo:

$text[0] = 'Fir5t text sample is thisline'; 
$text[1] = 'Fir5t text Smplee is this line.'; 
$text[2] = 'First te*t sample i this l1ne.'; 
$text[3] = 'F i r st text s ample is this line.'; 

ho tentativo di combinare il sopra per ottenere un output che assomiglia a:

$text = 'First text sample is this line.'; 

Non mi dica che è impossibile, perché non è certo, solo molto difficile.

Apprezzerei molto ogni idea che qualcuno ha nei confronti di questo.

Grazie!

I miei pensieri attuali:

solo controllando le parole contro il dizionario non funziona, dal momento che alcuni degli spazi sono nel posto sbagliato e, occasionalmente, la parola non sarà presente nel dizionario.

Il problema principale è la riparazione delle spaziature interrotte, una volta che questo è stato risolto, allora è possibile scegliere la parola del dizionario più comune se esiste, oppure la parola non dizionario più comune.

+2

vuoi veramente unire le 4 versioni a una, o il tuo obiettivo è prendere una riga e risolverla con l'aiuto del tuo dizionario? – Flo

+0

Posso facilmente prendere una riga e "spellcheck" con il dizionario. Ma questo non aiuterà perché molte delle parole sono rotte, gli spazi sono nei posti sbagliati. Questo è il motivo per cui ho bisogno di confrontare le diverse linee, sì combinarle in una sola. – Alasdair

+0

Quello di cui parli qui sembra molto simile a un problema di Intelligenza Artificiale. Potrebbe essere possibile in PHP, ma non sarebbe certamente molto efficiente. Consiglierei di cercare uno strumento a riga di comando che faccia questo sia uno esistente ed exec() da PHP. Se un tale strumento non esiste, allora elaborare l'algoritmo sarebbe un diavolo di lavoro. Potresti iniziare con il controllo ortografico di tutte le varianti e assumendo che tutte le parole uguali in tutte le versioni siano corrette. Quindi per le linee in cui sono diversi, scegli la parola che appare più spesso. Dopo, chi lo sa? – GordonM

risposta

1

Affrontare algoritmi complessi come questo richiederà probabilmente più tempo ed è più incline all'errore rispetto all'utilizzo di uno strumento di terze parti - a meno che non sia davvero necessario programmarlo da soli, è possibile controllare lo Yahoo Spelling Suggestion API. Consentono 5.000 richieste per IP al giorno, credo.

Altri possono offrire qualcosa di simile (penso che ci sia anche un'API di bing).

UPDATE: Mi spiace, ho appena letto che hanno interrotto questo servizio nell'aprile 2011. Sostengono di offrire un servizio simile chiamato "Tabella YQL di Spelling Suggest" ora.

1

Questo è davvero un problema piuttosto complicato.

Quando mi chiedo come si scrive una parola, il modo diretto è aprire un dizionario. Ma cosa succede se si tratta di una piccola frase complessa che sto cercando di pronunciare correttamente? Uno dei miei trucchi personali, che funziona la maggior parte del tempo, è chiamare Google. Metto la mia frase tra virgolette su Google e conto i risultati. Ecco un esempio: inserendo "your very smart" su Google dà 13'600k pagina. Inserire "sei molto intelligente" dà 20.000 pagine. Quindi, probabilmente, l'ortografia corretta è "sei molto intelligente". E ... infatti lo è;)

Sulla base di questo concetto, immagino che tu abbia esempi che, per la maggior parte, sono errati correttamente (beh, forse non se lo sviluppo per un sito di gioco per ragazzi ...) . Puoi provare a dividere i campioni in sotto-pezzi, non andando alle parole, e abbinandoli per frequenza?Il pezzo più frequente è il più probabilmente scritto correttamente. Prima di questo, puoi già creare un controllo ortografico del dizionario con i tuoi 600'000 termini per aumentare la possibilità che i piccoli errori di ortografia vengano corretti. Questo dovrebbe aumentare la frequenza dei sotto pezzi corretti.

Dividere le frasi in pezzi e trovare la giusta "dimensione del pezzo" è anche complicato.

Ciò che mi preoccupa un po 'anche: come estrai i campioni e li abbini per sapere che la frase corretta è la stessa (o molto vicina?). La tua domanda sembra presupporre che tu abbia questo, che sembra anche qualcosa di molto complesso per me.

Bene, ciò che precede è solo un consiglio generale basato sulla mia esperienza personale e umana. Donno se questo può aiutare. Ovviamente questa non è una risposta reale e non è pensata per esserlo.

1

Si può provare a utilizzare google n-gram per ottenere ciò.

+1

Sembra molto bello, ma non vedo come sarebbe di aiuto? – Alasdair

1

Se è necessario ottenere la stringa corretta solo confrontando gli altri. Allora qualcosa del genere potrebbe essere d'aiuto.

Non ancora finito, ma offre già alcuni risultati.

$text[0] = 'Fir5t text sample is thisline'; 
$text[1] = 'Fir5t text Smplee is this line.'; 
$text[2] = 'First te*t sample i this l1ne.'; 
$text[3] = 'F i r st text s ample is this line.'; 

function getRight($arr){ 
    $_final=''; 
    $count=count($arr); 

    // Remove multi spaces AND get string lengths 
    for($i=0;$i<$count;$i++){ 
     $arr[$i]=preg_replace('/\s\s+/', ' ',$arr[$i]); 
     $len[$i]=strlen($arr[$i]); 
    } 

    // Max length 
    $_max=max($len); 

    for($i=0;$i<$_max;$i++){ 
     $_el=array(); 
     for($j=0;$j<$count;$j++){ 
      // Cheking letter counts 
      $_letter=$arr[$j][$i]; 
      if(isset($_el[$_letter]))$_el[$_letter]++; 
      else$_el[$_letter]=1; 
     } 
     //Most probably count 
     list($mostProbably) = array_keys($_el, max($_el)); 

     $_final.=$mostProbably; 

     // If probbaly example is not space 
     if($_el!=' '){ 
      // THERE NEED TO BE CODE FOR REMOVING SPACE FROM LINES WHERE $text[$i] is space 
     } 
    } 

    return $_final; 
} 


echo getRight($text); 
+1

Userei una distanza Levenshtein ('levenshtein()' in PHP) nel tuo caso :) – Minras

+0

Non ho mai sentito parlare di questa funzione, thaks! Ma non sappiamo quale parola sia "buona" da confrontare. O ho capito qualcosa di sbagliato? – Narek

+0

Sì, hai ragione. Per il compito di @ Alasdair sarebbe troppo costoso confrontare ogni parola con l'intero dizionario. Ma nel tuo caso la distanza di Levenshtein è una buona soluzione. Per quanto riguarda l'autore dell'argomento, suppongo che dovrebbe attenersi alle librerie di spelling esistenti. – Minras

8

Hai provato a utilizzare un algoritmo di sottosequenza comune più lungo? Questi sono comunemente visti negli strumenti di confronto del testo "diff" usati nelle app di controllo del codice sorgente e in alcuni editor di testo. Un algoritmo diff aiuta a identificare i caratteri cambiati e invariati in due campioni di testo. http://en.wikipedia.org/wiki/Diff

Alcuni anni fa ho lavorato a un'app OCR simile alla tua. Piuttosto che applicare più motori OCR a un'immagine, ho utilizzato un motore OCR per analizzare più versioni della stessa immagine. Ciascuna delle immagini elaborate era il risultato dell'applicazione di una tecnica di denoising diversa all'immagine originale: una tecnica funzionava meglio per il contrasto basso, un'altra tecnica funzionava meglio quando i personaggi erano formati male. Uno schema di "voto" che confrontava i risultati OCR su ciascuna immagine migliorava la velocità di lettura per stringhe arbitrarie di testo come "BQCM10032". Altri schemi di voto sono descritti nella letteratura accademica per l'OCR.

A volte potrebbe essere necessario abbinare una parola per la quale nessuna combinazione di risultati OCR produrrà tutte le lettere. Ad esempio, potrebbe mancare una lettera centrale, come in "w rd" o "c tch" (probabilmente "word" e "catch"). In questo caso può aiutare ad accedere al tuo dizionario con uno qualsiasi dei tre tasti: lettere iniziali, lettere centrali e lettere finali (o combinazioni di lettere). Ogni chiave è associata a un elenco di parole ordinato per frequenza di occorrenza nella lingua. (Ho usato questo tipo di ricerca multi-chiave per migliorare la velocità di un'applicazione di generazione di cruciverba, potrebbero esserci metodi migliori là fuori, ma questo è facile da implementare.)

Per risparmiare in memoria, è possibile applicare il metodo multi-tasto solo alle prime migliaia di parole comuni nella lingua, e quindi hanno solo una tecnica di ricerca per parole meno comuni.

Esistono diversi elenchi online di frequenza di parola. http://en.wiktionary.org/wiki/Wiktionary:Frequency_lists

Se si vuole essere fantasiosi, è anche possibile fare affidamento sulla frequenza precedente di occorrenza nel testo. Ad esempio, se "Byrd" appare più volte, allora potrebbe essere la scelta migliore se il/i motore/i OCR riporta "uccello" o "bardo" con un basso punteggio di confidenza. È possibile caricare un dizionario medico nella memoria solo se si verifica un'occorrenza statistica improbabile di termini medici nella stessa pagina, altrimenti lasciare i termini medici fuori dal dizionario di lavoro o almeno assegnare loro ragionevoli probabilità. "Protesi" è una parola comune; "prostatite" meno così.

Se si hanno esperienza con tecniche di elaborazione delle immagini come operazioni di denoising e morfologia, è anche possibile provare a sottoporre a pre-elaborazione l'immagine prima di passarla ai motori OCR. L'elaborazione delle immagini potrebbe anche essere applicata per selezionare le aree dopo che il software ha identificato le parole o le regioni in cui i motori OCR sono andati male.

Alcune lettere/lettere e lettere/numeri sono comuni. Il numero 0 (zero) può essere confuso con la lettera O, C per O, 8 per B, E per F, P per R, e così via. Se una parola viene trovata con un livello di confidenza basso o se ci sono due parole comuni che potrebbero corrispondere a una parola in lettura incompleta, allora potrebbero essere utili regole di corrispondenza di forma ad hoc. Ad esempio, "bcth" potrebbe corrispondere a "both" o "bath", ma per molti font (e contesti) "both" è la corrispondenza più probabile poiché "o" è più simile a "c" in forma. In una lunga serie di parole come un paragrafo tratto da un articolo di un romanzo o di una rivista, "il bagno" è una corrispondenza migliore di "b8th".

Infine, si potrebbe probabilmente scrivere un plug-in o uno script per passare i risultati in un motore di controllo ortografico che controlli l'accordo di verbo-nome e altri controlli grammaticali. Questo potrebbe rilevare alcuni errori aggiuntivi. Forse potresti provare VBA per Word o qualsiasi altro combo di script/app è popolare in questi giorni.

+1

Vorrei che tutti i nuovi utenti fossero come te. +1 –

+0

Grazie! Lo apprezzo. – Rethunk