2009-08-18 15 views
11

Tengo que limpiar algunas entradas de OCR que reconoce la escritura manuscrita como un galimatías. ¿Alguna sugerencia para una expresión regular para eliminar los caracteres aleatorios? Ejemplo:Regex para reemplazar galimatías


 
Federal prosecutors on Monday charged a Miami man with the largest 
case of credit and debit card data theft ever in the United States, 
accusing the one-time government informant of swiping 130 million 
accounts on top of 40 million he stole previously. 

, ':, Ie 
':... 11'1 
. '(.. ~!' ': f I I 
. " .' I ~ 
I' ,11 l 
I I I ~ \ :' ,! .~ , .. r, 1 , ~ I . I' , .' I ,. 
, i 
I ; J . I.' ,.\) .. 
. : I 
'I', I 
.' ' 
r," 

Gonzalez is a former informant for the U.S. Secret Service who helped 
the agency hunt hackers, authorities say. The agency later found out that 
he had also been working with criminals and feeding them information 
on ongoing investigations, even warning off at least one individual, 
according to authorities. 

eh....l 
~.\O ::t 
e;~~~ 
s: ~ ~. 0 
qs c::; ~ g 
o t/J (Ii ., 
::3 (1l Il:l 
~ cil~ 0 2: 
t:lHj~(1l 
. ~ ~a 
0~ ~ S' 
N ("b t/J :s 
Ot/JIl:l"-<:! 
v'g::!t:O 
-....c...... 
VI (:ll <' 0 
:= - ~ 
< (1l ::3 
(1l ~ ' 
t/J VJ ~ 
Pl 
..... 
.... 
(II 
+3

+1 porque es una pregunta interesante, a pesar de que sospecho no obtendrá una respuesta que funciona. –

+0

Es una buena pregunta, y el reconocimiento de palabras/frases (o al revés) es un tema candente como parte de la IA. – Russell

+1

Creo firmemente que un REGEX es la herramienta incorrecta para este trabajo. – Breton

Respuesta

0

bien un grupo de símbolos podría coincidir con un poco de galimatías. Tal vez consultar con un diccionario las palabras?

Parece que hay muchos saltos de línea donde hay galimatías, por lo que también puede ser un indicador.

+0

Investigué hace unos años en Uni sobre la extracción de frases (estás haciendo lo contrario). Hay muchos documentos (p. Ej., Http://portal.acm.org/citation.cfm?id=1097059), pero desafortunadamente no existe una única solución "para todos". – Russell

0

Problema interesante.

Si esto es representativo, supongo que podría compilar una biblioteca de palabras comunes y eliminar cualquier línea que no coincida con ninguna de ellas.

O tal vez podría hacer coincidir caracteres y caracteres de puntuación y ver si hay un límite de razón confiable, o simplemente una frecuencia de aparición de algunos caracteres que lo señala como un galimatías.

Independientemente, creo que tendrá que haber alguna lógica de programación, no simplemente una expresión regular única.

0

Supongo que una expresión regular no ayudaría aquí. Regex básicamente coincidiría con una entrada determinista, es decir, una expresión regular tendrá un conjunto predefinido de patrones que coincidirá. Y el galimatías en la mayoría de los casos sería aleatorio. Una forma sería invertir el problema, es decir, hacer coincidir el texto relevante en lugar de coincidir con el galimatías.

1

Una de las soluciones SimpleSet (no regexpes que implican):

#pseudopython

number_of_punct = sum ([1 si c.ispunct() else 0 para c en línea])

if number_of_punct> len (línea)/2: line_is_garbage()

bien. O rude regexpish s/[! '"@ # ~ $%^&] {5,} // g

+0

qué pasa con esta línea:, i – Breton

+0

Nada. Quítalo a mano más tarde. No espere que la heurística elimine toda la basura. Proverbio del día: "No tires al bebé con el agua del baño". – maykeye

1

Regex no ayuda aquí. Yo diría que si usted tiene control sobre la parte de reconocimiento, entonces enfoque de mejor calidad que hay: http://www.neurogy.com/ocrpreproc.html

también puede pedir usuario para ayudarle y especificar el tipo de texto que trabaja con, por ejemplo si se trata de una página de un libro, entonces se puede esperar que la mayoría de las líneas a ser el mismo. longitud y consiste principalmente en letras, espacios y signos de puntuación

0

Me gustaría reclamar una expresión regular como "cualquier signo seguido de cualquier cosa, excepto un espacio es correo no deseado".

Así que en .NET que es, posiblemente, algo así como

.Replace("\\p{1,}[a-zA-Z0-9]{1,}", ""); 

Entonces consideraría "palabra con dos o más signos de puntuación consecutivos:

.Replace(" \\p{2,} ", ""); 

parece un buen comienzo de todos modos.

+0

> Me gustaría decir que una expresión regular como "cualquier signo seguido de cualquier cosa, excepto un espacio es correo no deseado" No siempre, sin embargo. Algunos apellidos tienen guiones. No solo los apellidos (considere nomeolvides). También " comillas "comienzan con signos de puntuación. – maykeye

+0

Cierto, entonces no incluya la comilla doble en esa parte de la expresión regular. No creo que esté buscando un sistema infalible, solo algo para hacer un 'primer corte'. –

+0

No estoy de acuerdo. ... :-) –

2

Una heurística simple, similar a anonymous respuesta:

listA = [0,1,2..9, a,b,c..z, A,B,C,..Z , ...] // alphanumerical symbols 
listB = [[email protected]$%^&...] // other symbols 

Na = number_of_alphanumeric_symbols(line) 
Nb = number_of_other_symbols(line) 

if Na/Nb <= garbage_ratio then 
    // garbage 
+0

Esto supone que toda la línea es basura o no, pero en base a la muestra, es razonable suponer. –

+0

sí, es para filtrar líneas enteras. con el texto * normal * no será tan simple :-) –

2

Ni idea de lo bien que funcionaría, pero he considerado este problema en el pasado, sin hacer nada. En ocasiones he jugado con un pequeño dispositivo programático llamado markov chain

Ahora el artículo de la wikipedia probablemente no tendrá mucho sentido hasta que vea algunas de las otras cosas que una cadena de markov es buena. Un ejemplo de una cadena de markov en acción es este Greeking generator. Otro ejemplo es el MegaHAL chatbot.

Greeking es un galimatías que se parece a las palabras. Las cadenas de Markov proporcionan una forma de generar aleatoriamente una secuencia de letras, pero ponderan las elecciones aleatorias para emular los patrones de frecuencia de un corpus examinado. Entonces, por ejemplo, dada la letra "T", es más probable que aparezca la letra h que cualquier otra letra. Entonces, examina un corpus (digamos algunos periódicos o publicaciones en el blog) para producir una especie de huella digital del idioma al que apunta.

Ahora que tiene esa tabla de frecuencia/huella digital, puede examinar el texto de muestra y calificar cada letra de acuerdo con la probabilidad de que aparezca. Luego, puede marcar las letras bajo un umbral particular para eliminarlas. En otras palabras, un filtro sorpresa. Filtra las sorpresas.

Hay un margen de maniobra para la generación de tablas de frecuencia. No está limitado a una letra después de otra. Puede construir una tabla de frecuencias que predice qué letra seguirá probablemente a cada dígrafo (grupo de dos letras), o a cada trigraph, o quadgraph. Puede trabajar al otro lado, prediciendo los trigrafos probables e improbables para aparecer en ciertas posiciones, dado algún texto anterior.

Es como una expresión regular difusa. En lugar de MATCH o NO MATCH, el texto completo se puntúa en una escala variable de acuerdo con la similitud del texto de referencia.

1

Hice un combo de eliminación de líneas que no contengan al menos dos palabras de 3 letras o una palabra de 6 letras.

([az | AZ] {3} \ s) {2} | ([az | AZ] {6})

http://www.regexpal.com/

+0

Agregaría una comparación de diccionario para asegurarme de que las palabras que encuentra sean reales y no solo letras aleatorias. –

0

me gusta @ respuesta de Breton - I' Sugiero usar su enfoque de Corpus también con una biblioteca de 'escaneos defectuosos' conocidos, que podrían ser más fáciles de identificar porque 'basura' tiene más consistencia interna que 'texto bueno' si proviene de escaneos de OCR incorrectos (el número de glifos distintos es más bajo, por ejemplo).

0

Otra buena técnica es utilizar un corrector ortográfico/diccionario y buscar las 'palabras' después de haber eliminado las cosas no legibles con regex.

1

Aquí es una aplicación Perl del garbage_ratio heurística:

#!/usr/bin/perl 

use strict; 
use warnings; 

while (defined(my $chunk = read_chunk(\*DATA))) { 
    next unless length $chunk; 

    my @tokens = split ' ', $chunk; 
    # what is a word? 
    my @words = grep { 
     /^[A-Za-z]{2,}[.,]?$/ 
      or /^[0-9]+$/ 
      or /^a|I$/ 
      or /^(?:[A-Z][.])+$/ 
    } @tokens; 

    # completely arbitrary threshold 
    my $score = @words/@tokens; 
    print $chunk, "\n" if $score > 0.5; 
} 

sub read_chunk { 
    my ($fh) = @_; 
    my ($chunk, $line); 

    while (my $line = <$fh>) { 
     if($line =~ /\S/) { 
      $chunk .= $line; 
      last; 
     } 
    } 

    while (1) { 
     $line = <$fh>; 
     last unless (defined $line) and ($line =~ /\S/); 
     $chunk .= $line; 
    } 

    return $chunk; 
} 


__DATA__ 

pega el siguiente texto anterior después de __DATA__ anterior (no repetir el texto aquí para ahorrar espacio). Por supuesto, el uso de la sección __DATA__ tiene el propósito de publicar una secuencia de comandos independiente. En la vida real, tendrías código para abrir el archivo, etc.

Salida:

 
Federal prosecutors on Monday charged a Miami man with the largest 
case of credit and debit card data theft ever in the United States, 
accusing the one-time government informant of swiping 130 million 
accounts on top of 40 million he stole previously. 

Gonzalez is a former informant for the U.S. Secret Service who helped 
the agency hunt hackers, authorities say. The agency later found out that 
he had also been working with criminals and feeding them information 
on ongoing investigations, even warning off at least one individual, 
according to authorities.
Cuestiones relacionadas