Преобразуйте распознанный неструктурированный текст в правильный текст
-
21-12-2019 - |
Вопрос
Я использую Microsoft MODI
в VB6
для распознавания изображения.(Я знаю о других инструментах распознавания текста, таких как tesseract и т.д., но я нахожу MODI более точным, чем другие)
Изображение, подлежащее распознаванию, выглядит следующим образом
и текст, который я получаю после распознавания, выглядит следующим образом
Text1
Text2
Text3
Number1
Number2
Number3
Проблема здесь в том, что соответствующий текст из противоположного столбца не сохраняется.Как я могу сопоставить Number1 с Text1?
Я могу придумать только такое решение, как это.
MODI предоставляет координаты всех распознанных слов следующим образом
LeftPos = Img.Layout.Words(0).Rects(0).Left
TopPos = Img.Layout.Words(0).Rects(0).Top
Таким образом, чтобы выровнять слова в одной строке, мы можем сопоставить верхние позиции каждого слова, а затем отсортировать их по левым позициям.Мы получим полную строку.Итак, я перебрал все слова и сохранил их текст, а также слева и сверху в таблице mysql.затем запустил этот запрос
SELECT group_concat(word ORDER BY `left` SEPARATOR ' ')
FROM test_copy
GROUP BY `top`
Моя проблема в том, что верхние позиции не совсем одинаковы для каждого слова, очевидно, будет пара различий в пикселях.
Я попробовал добавить DIV 5
, для объединения слов, находящихся в диапазоне 5 пикселей, но в некоторых случаях это не работает.Я также пробовал делать это в node.js, вычисляя допуск для каждого слова, а затем сортируя по левым точкам, но я все еще чувствую, что это не лучший способ сделать это.
Обновление: js-код выполняет эту работу, но за исключением случая, когда Number1 имеет разницу в 5 пикселей, а Text2 не имеет соответствия в этой строке.
Есть ли какая-нибудь идея получше, как это сделать?
Решение
Я не уверен на 100%, как вы идентифицируете те слова, которые находятся в вашем "левом" столбце, но как только вы определите это слово, вы сможете найти другие слова в этой строке, спроецировав не только верхнюю координату, но и весь прямоугольник поперек (как сверху, так и снизу).Определите перекрытие (пересечение) с другими словами.Обратите внимание на область, отмеченную красным цветом ниже.
Это допуск, который вы можете использовать, чтобы определить, находится ли что-то в одной строке.Если что-то перекрывается всего на пиксель, то это, вероятно, из нижней или верхней строки.Но если он перекрывается, скажем, на 50% или более от высоты Text1, то, скорее всего, он находится в той же строке.
Пример SQL для поиска всех слов в "строке" на основе верхних и нижних координат
select
word.id, word.Top, word.Left, word.Right, word.Bottom
from
word
where
(word.Top >= @leftColWordTop and word.Top <= @leftColWordBottom)
or (word.Bottom >= @leftColWordTop and word.Bottom <= @leftColWordBottom)
Пример псевдокода VB6 для вычисления строк также.
'assume words is a collection of WordInfo objects with an Id, Top,
' Left, Bottom, Right properties filled in, and a LineAnchorWordId
' property that has not been set yet.
'get the words in left-to-right order
wordsLeftToRight = SortLeftToRight(words)
'also get the words in top-to-bottom order
wordsTopToBottom = SortTopToBottom(words)
'pass through identifying a line "anchor", that being the left-most
' word that starts (and defines) a line
for each anchorWord in wordsLeftToRight
'check if the word has been mapped to aline yet by checking if
' its anchor property has been set yet. This assumes 0 is not
' a valid id, use -1 instead if needed
if anchorWord.LineAnchorWordId = 0 then
'not locate every word on this line, as bounded by the
' anchorWord. every word determined to be on this line
' gets its LineAnchorWordId property set to the Id of the
' anchorWord
for each lineWord in wordsTopToBottom
if lineWord.Bottom < anchorWord.Top Then
'skip it,it is above the line (but keep searching down
' because we haven't reached the anchorWord location yet)
else if lineWord.Top > anchorWord.Bottom Then
'skip it,it is below the line, and exit the search
' early since all the rest will also be below the line
exit for
else if OverlapsWithinTolerance(anchorWord, lineWord) then
lineWord.LineAnchorWordId = anchorWord.Id
endif
next
end if
next anchorWord
'at this point, every word has been assigned a LineAnchorWordId,
' and every word on the same line will have a matching LineAnchorWordId
' value. If stored in a DB you can now group them by LineAnchorWordId
' and sort them by their Left coord to get your output.