Могу ли я сделать "string содержит X" с процентной точностью в python?

Мне нужно сделать OCR на большом фрагменте текста и проверить, содержит ли он определенную строку, но из-за неточности OCR мне нужно это, чтобы проверить, содержит ли оно что-то вроде соответствия 85% для строки.

Например, я могу распознать фрагмент текста, чтобы убедиться, что он не содержит no information available, но OCR может видеть n0 inf0rmation available или неправильно интерпретировать количество символов.

Есть ли простой способ сделать это в Python?

Ответы

Ответ 1

Как указано gauden, SequenceMatcher в difflib - это простой способ. Используя ratio(), возвращает значение между 0 и 1, соответствующее сходству между двумя строками, из документов:

Где T - общее количество элементов в обеих последовательностях, а M - количество совпадений, это 2.0 * M/T. Обратите внимание, что это 1.0, если последовательности идентичны и 0.0, если они не имеют ничего общего.

Пример:

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

Существует также get_close_matches, который может быть вам полезен, вы можете указать ограничение расстояния, и оно вернет все соответствия на этом расстоянии от списка:

>>> 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']

Обновление: для поиска частичного соответствия подпоследовательности

Чтобы найти близкие совпадения к последовательности из трех слов, я бы разделил текст на слова, затем сгруппировал их в три последовательности слов, затем применил difflib.get_close_matches, например:

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']

Ответ 2

Объект SequenceMatcher в стандартном библиотечном модуле difflib даст вам соотношение напрямую:

Ответ 4

Я не знаю ни одной доступной библиотеки python, которая бы делала это из коробки, но вы можете найти ее (или найти C или С++ lib и написать для нее оболочку Python).

Вы также можете попытаться свернуть свое собственное решение, основанное либо на сравнении "грубой силы" char на char, так и на правилах, определяющих "близость" между двумя заданными символами и вычисляя "точность" на основе этих правил (т.е. "o" = > "0": точность 90%, "o" = > "w": 1% точности и т.д.), или игра с более активными материалами IA (если вы не знакомы с ИА, Программирование коллективного интеллекта "может помочь вам начать работу, несмотря на несколько плохие примеры реализации).

Ответ 5

Просто для расширения на fraxel answer это позволяет найти любую произвольную длину. Извините за плохое форматирование, это сложно. Точность - это значение отсечки в 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)