¿Cómo determinar la similitud de caracteres?

Estoy usando la distancia de Levenshtein para encontrar cadenas similares después de OCR. Sin embargo, para algunas cadenas la distancia de edición es la misma, aunque la apariencia visual obviamente es diferente.

Por ejemplo, la cadena Co devolverá estos partidos:

CY (1)
CZ (1)
Ca (1)

Teniendo en cuenta que Co es el resultado de un motor OCR, Ca sería la coincidencia más probable que los unos. Por lo tanto, después de calcular la distancia de Levenshtein, me gustaría refinar el resultado de la consulta ordenándolo por similitud visual. Para calcular esta similitud, me gustaría usar una fuente sans-serif estándar, como Arial.

¿Hay una biblioteca que pueda usar para este propósito, o cómo podría implementar esto yo mismo? Alternativamente, ¿hay algoritmos de similitud de cadenas que sean más precisos que la distancia de Levenshtein, que podría usar además?

preguntado el 03 de mayo de 12 a las 15:05

Puede ser muy específico para la máquina de imágenes que está utilizando y el propio programa OCR. La mejor estrategia, en mi humilde opinión, es crear un conjunto de datos de entrenamiento y calcular estas probabilidades empíricamente. -

3 Respuestas

Si está buscando una tabla que le permita calcular una especie de 'costo de reemplazo' en función de la similitud visual, he estado buscando algo así durante un tiempo con poco éxito, así que comencé a verlo como un nuevo problema. No estoy trabajando con OCR, pero estoy buscando una forma de limitar los parámetros de búsqueda en una búsqueda probabilística de escrito mal caracteres. Dado que están mal escritos porque un humano confundió los caracteres visualmente, el mismo principio debería aplicarse a usted.

Mi enfoque fue clasificar las letras en función de sus componentes de trazo en un campo de 8 bits. los bits son, de izquierda a derecha:

7: Left Vertical
6: Center Vertical
5: Right Vertical
4: Top Horizontal
3: Middle Horizontal
2: Bottom Horizontal
1: Top-left to bottom-right stroke
0: Bottom-left to top-right stroke

Para los caracteres en minúsculas, los descendientes de la izquierda se registran en el bit 1 y los descendientes de la derecha en el bit 0, como diagonales.

Con ese esquema, se me ocurrieron los siguientes valores que intentan clasificar a los personajes según la similitud visual.

m:               11110000: F0
g:               10111101: BD
S,B,G,a,e,s:     10111100: BC
R,p:             10111010: BA
q:               10111001: B9
P:               10111000: B8
Q:               10110110: B6
D,O,o:           10110100: B4
n:               10110000: B0
b,h,d:           10101100: AC
H:               10101000: A8
U,u:             10100100: A4
M,W,w:           10100011: A3
N:               10100010: A2
E:               10011100: 9C
F,f:             10011000: 98
C,c:             10010100: 94
r:               10010000: 90
L:               10000100: 84
K,k:             10000011: 83
T:               01010000: 50
t:               01001000: 48
J,j:             01000100: 44
Y:               01000011: 43
I,l,i:           01000000: 40
Z,z:             00010101: 15
A:               00001011: 0B
y:               00000101: 05
V,v,X,x:         00000011: 03

Esto, tal como está, es demasiado primitivo para mis propósitos y requiere más trabajo. Sin embargo, es posible que pueda utilizarlo o tal vez adaptarlo para que se adapte a sus propósitos. El esquema es bastante simple. Esta clasificación es para una fuente monoespaciada. Si está utilizando una fuente sans-serif, es probable que tenga que volver a trabajar los valores.

Esta tabla es una tabla híbrida que incluye todos los caracteres, minúsculas y mayúsculas, pero si la divide en mayúsculas y minúsculas solamente, podría resultar más eficaz, y eso también permitiría aplicar penalizaciones de mayúsculas y minúsculas específicas.

Tenga en cuenta que se trata de una experimentación temprana. Si ve una forma de mejorarlo (por ejemplo, cambiando la secuencia de bits), no dude en hacerlo.

contestado el 17 de mayo de 12 a las 19:05

En general he visto Damerau-Levenshtein se usa mucho más a menudo que solo Levenshtein , y básicamente agrega la operación de transposición. Se supone que representa más del 80 % de los errores ortográficos humanos, por lo que deberías tenerlo en cuenta.

En cuanto a su problema específico, podría modificar fácilmente el algoritmo para aumentar el costo al sustituir una letra mayúscula con una letra no mayúscula, y lo contrario para obtener algo así:

dist(Co, CY) = 2
dist(Co, CZ) = 2
dist(Co, Ca) = 1

contestado el 03 de mayo de 12 a las 15:05

Entonces, en su función de distancia, solo tenga un costo diferente para reemplazar diferentes pares de caracteres.

Es decir, en lugar de un reemplazo que agregue un costo fijo de uno o dos, independientemente de los personajes involucrados, en su lugar, tenga un reemplazar la función de costo que devuelve algo entre 0.0 y 2.0 por el costo de reemplazar ciertos caracteres en ciertos contextos.

En cada paso de la memorización, simplemente llame a esta función de costo:

cost[x][y] = min(
    cost[x-1][y] + 1, // insert
    cost[x][y-1] + 1, // delete,
    cost[x-1][y-1] + cost_to_replace(a[x],b[y]) // replace
);

Aquí está mi implementación completa de Editar distancia, simplemente cambie la constante replace_cost por una función replace_cost como se muestra:

https://codereview.stackexchange.com/questions/10130/edit-distance-between-two-strings

En términos de implementar la función cost_to_replace, necesita una matriz de caracteres con costos basados ​​en cuán similares son los caracteres. Puede haber una tabla de este tipo flotando, o puede implementarla usted mismo escribiendo cada par de caracteres en un par de imágenes y luego comparando las imágenes en busca de similitudes utilizando técnicas de visión estándar.

Alternativamente, puede usar un método supervisado mediante el cual corrige varios errores de lectura de OCR y anota las ocurrencias en una tabla que luego se convertirá en la tabla de costos anterior. (es decir, si el OCR se equivoca, entonces los caracteres deben ser similares).

Respondido 13 Abr '17, 13:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.