нечеткое соответствие слова на странице OCR

У меня есть статическая фраза, которую я ищу в OCR-изображении.

string KeywordToFind = "Account Number"

string OcrPageText = "
GEORGIA
POWER

A SOUTHERN COMPANY

AecountNumber

122- 493

Pagel of2

Please Pay By
Jan 29,2014

Total Due
39.11
"

Как мне найти слово "AecountNumber" по ключевому слову "Номер счета"?

Я пытался использовать варианты алгоритма расстояния Левенштейна ЗДЕСЬ с переменным успехом. Я также пробовал регулярные выражения, но OCR часто преобразует текст по-разному, что делает регулярное выражение бесполезным.

Предложения? Я могу предоставить больше кода, если ссылка не дает достаточно информации. Кроме того, спасибо!


person Milne    schedule 07.02.2014    source источник
comment
Перетекание из вашего другого вопроса; хорошо, теперь я понимаю, почему поиск «счета» и «номера» по отдельности не сработает для вас. Итак, вы можете опубликовать подробности об этом случае, т.е. какой у тебя лев. algo выдает ошибки в таком случае?   -  person Jim W says reinstate Monica    schedule 07.02.2014


Ответы (2)


Почему бы не попробовать что-то в основном произвольное, например это - хотя это, безусловно, будет соответствовать гораздо большему, чем просто номер счета, шансы на то, что начальный и конечный символы существуют где-либо еще в этом порядке, довольно малы.

A.?c.?.?nt ?N.?[mn]b.?r

http://regex101.com/r/zV1yM2

Это будет соответствовать таким вещам, как:

Account Number
AccntNumbr
Aecnt Nunber
person brandonscript    schedule 07.02.2014
comment
Что делать, если первый или последний символ — это тот, который OCR распознал неправильно? - person Milne; 07.02.2014
comment
Вот беда с OCR. Слишком много неизвестных. Вам нужно будет указать /какие-то/ ожидаемые критерии, если вы хотите, чтобы он работал с регулярным выражением. Лучше всего взять несколько образцов OCR и выяснить, какие буквы, скорее всего, будут правильно идентифицированы (я бы предположил, что заглавные A и N?), а затем наименее вероятным должно стать .?. - person brandonscript; 07.02.2014

Ответил на мой вопрос с использованием подстрок. Публикация на случай, если другие столкнутся с такой же проблемой. Немного неортодоксально, но на мне работает отлично.

int TextLengthBuffer = (int)StaticTextLength - 1; //start looking for correct result with one less character than it should have.
int LowestLevenshteinNumber = 999999; //initialize insanely high maximum
decimal PossibleStringLength = (PossibleString.Length); //Length of string to search
decimal StaticTextLength = (StaticText.Length); //Length of text to search for
decimal NumberOfErrorsAllowed = Math.Round((StaticTextLength * (ErrorAllowance / 100)), MidpointRounding.AwayFromZero); //Find number of errors allowed with given ErrorAllowance percentage

    //Look for best match with 1 less character than it should have, then the correct amount of characters.
    //And last, with 1 more character. (This is because one letter can be recognized as 
    //two (W -> VV) and visa versa) 

for (int i = 0; i < 3; i++) 
{
    for (int e = TextLengthBuffer; e <= (int)PossibleStringLength; e++)
    {
        string possibleResult = (PossibleString.Substring((e - TextLengthBuffer), TextLengthBuffer));
        int lAllowance = (int)(Math.Round((possibleResult.Length - StaticTextLength) + (NumberOfErrorsAllowed), MidpointRounding.AwayFromZero));
        int lNumber = LevenshteinAlgorithm(StaticText, possibleResult);

        if (lNumber <= lAllowance && ((lNumber < LowestLevenshteinNumber) || (TextLengthBuffer == StaticText.Length && lNumber <= LowestLevenshteinNumber)))
        {
            PossibleResult = (new StaticTextResult { text = possibleResult, errors = lNumber });
            LowestLevenshteinNumber = lNumber;
        }
    }
    TextLengthBuffer++;
}




public static int LevenshteinAlgorithm(string s, string t) // Levenshtein Algorithm
{
    int n = s.Length;
    int m = t.Length;
    int[,] d = new int[n + 1, m + 1];

    if (n == 0)
    {
        return m;
    }

    if (m == 0)
    {
        return n;
    }

    for (int i = 0; i <= n; d[i, 0] = i++)
    {
    }

    for (int j = 0; j <= m; d[0, j] = j++)
    {
    }

    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;

            d[i, j] = Math.Min(
                Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
                d[i - 1, j - 1] + cost);
        }
    }
    return d[n, m];
}
person Milne    schedule 11.02.2014