Puis-je faire un "string contains X" avec un pourcentage de précision en python?

j'ai besoin de faire un peu de OCR sur un gros morceau de texte et de vérifier s'il contient une certaine chaîne mais en raison de l'inexactitude de L'OCR j'en ai besoin pour vérifier si elle contient quelque chose comme une correspondance ~85% pour la chaîne.

par exemple je peux OCR un morceau de texte pour s'assurer qu'il ne contient pas no information available mais L'OCR pourrait voir n0 inf0rmation available ou mal interpréter un certain nombre de caractères.

y a-t-il un moyen facile de faire cela en Python?

14
demandé sur Jacxel 2012-06-01 15:09:33

5 réponses

publié par gauden,SequenceMatcherdifflib est une voie facile à suivre. En utilisant ratio(), renvoie une valeur entre 0 et 1 correspondant à la similitude entre les deux chaînes, de la docs:

Où T est le nombre total d'éléments dans les deux séquences, et M est le nombre de correspondances, c'est 2.0*M / T. notez que c'est 1.0 si le les séquences sont identiques, et 0,0 s'ils n'ont rien en commun.

exemple:

>>> import difflib
>>> difflib.SequenceMatcher(None,'no information available','n0 inf0rmation available').ratio()
0.91666666666666663

Il y a aussi get_close_matches, ce qui pourrait vous être utile, vous pouvez spécifier une coupure de distance et il retournera toutes les correspondances à l'intérieur de cette distance à partir d'une liste:

>>> difflib.get_close_matches('unicorn', ['unicycle', 'uncorn', 'corny', 
                              'house'], cutoff=0.8)
['uncorn']
>>> difflib.get_close_matches('unicorn', ['unicycle'  'uncorn', 'corny',
                              'house'], cutoff=0.5)
['uncorn', 'corny', 'unicycle']

mise à Jour: trouver une partielle de la sous-séquence match

pour trouver des correspondances à une séquence de trois mots, je diviserais le texte en mots, puis je les regrouperais en trois séquences de mots, puis j'appliquerais difflib.get_close_matches, comme ceci:

import difflib
text = "Here is the text we are trying to match across to find the three word
        sequence n0 inf0rmation available I wonder if we will find it?"    
words = text.split()
three = [' '.join([i,j,k]) for i,j,k in zip(words, words[1:], words[2:])]
print difflib.get_close_matches('no information available', three, cutoff=0.9)
#Oyutput:
['n0 inf0rmation available']
26
répondu fraxel 2012-06-01 11:56:21

SequenceMatcher objet dans le difflib le module de bibliothèque standard vous donnera directement un rapport:

6
répondu gauden 2012-06-01 12:22:40

vous pouvez calculer le Levenshtein. Voici une implémentation Python: http://pypi.python.org/pypi/python-Levenshtein/

4
répondu NPE 2012-06-01 11:16:21

Je ne connais pas de lib python disponible qui ferait cela hors de la boîte, mais vous pourriez en trouver une (ou trouver une lib C ou C++ et écrire un wrapper Python pour elle).

vous pouvez également essayer de lancer votre propre solution, basée soit sur un char "force brute" par comparaison char, avec des règles définissant la "proximité" entre deux chars donnés et calculant la "précision" basée sur ces règles (i.e. "o" = > "0": Précision de 90%, "o" = > "w": précision de 1%, etc), ou jouer avec des trucs plus impliqués IA (si vous n'êtes pas familiarisé avec L'intelligence D'affaires, le livre "Programmer L'Intelligence Collective" pourrait vous aider à démarrer, malgré les quelques exemples de mise en œuvre plutôt médiocre).

0
répondu bruno desthuilliers 2012-06-01 11:28:58

juste pour développer la réponse de fraxel, cela permet de trouver n'importe quelle chaîne de longueur arbitraire. Désolé pour le mauvais formatage, donc est difficile. La précision est la valeur de coupure dans findWords

def joinAllInTupleList(toupe):
#joinAllInTuple( [("hello", "world"),("face","book")]) = ['hello world', 'face book']
result=[]
for i in toupe:
    #i is the tuple itself
    carry = " "
    for z in i:
        #z is an element of i
        carry+=" "+z

    result.append(carry.strip())
return result

def findWords(text,wordSequence):

#setup
words = text.split(" ")

#get a list of subLists based on the length of wordSequence
#i.e. get all wordSequence length sub-sequences in text!

result=[]
numberOfWordsInSequence = len(wordSequence.strip().split(" ")) 
for i in range(numberOfWordsInSequence):
    result.append(words[i:])

# print 'result',result
c=zip(*result)

# print 'c',c
#join each tuple to a string
joined = joinAllInTupleList(c)

return difflib.get_close_matches(wordSequence, joined, cutoff=0.72389)
0
répondu Julian 2014-01-09 06:29:33