Converter Ocr de texto não estruturados para bom texto
-
21-12-2019 - |
Pergunta
Eu estou usando Microsoft MODI
no VB6
para OCR em uma imagem.(Eu sei sobre outras ferramentas de OCR tesseract como etc, mas eu acho MODI mais precisos do que outros)
A imagem a ser Ocr é assim
e, o texto o eu chegar depois do OCR é como abaixo
Text1
Text2
Text3
Number1
Number2
Number3
O problema aqui é que o texto correspondente em frente coluna não é mantida.Como posso mapa Número1 com Texto1?
Eu só posso pensar em uma solução como essa.
MODI fornece as coordenadas de todos os Ocr palavras como essa
LeftPos = Img.Layout.Words(0).Rects(0).Left
TopPos = Img.Layout.Words(0).Rects(0).Top
Então, para alinhar palavras na mesma linha, podemos combinar a TopPos de cada palavra e, em seguida, classificá-los por LeftPos.Teremos a linha completa.Então eu loop através de todas as palavras e armazenado em seu texto, bem como de esquerda e superior em uma tabela mysql.em seguida, correu esta consulta
SELECT group_concat(word ORDER BY `left` SEPARATOR ' ')
FROM test_copy
GROUP BY `top`
O meu problema é Que posições de Topo não são exatamente iguais para cada palavra, Obviamente, haverá casal de pixel diferenças.
Eu tentei adicionar DIV 5
, para a fusão de palavras que estão em 5 pixels, mas que não funciona para alguns casos.Eu também tentei fazê-lo em node.js através do cálculo de tolerância para cada palavra e, em seguida, a classificação por LeftPos, mas ainda sinto esta não é a melhor maneira de o fazer.
Atualização: O código js faz o trabalho, mas, exceto para o caso onde Número1 tem 5 pixel de diferença e Texto2 não tem correspondente na linha.
Existe alguma ideia melhor para fazer isso?
Solução
Eu não tenho 100% de certeza de como você a identificar essas palavras que estão no seu "esquerda" coluna, mas uma vez que o word identificado, você pode encontrar outras palavras na mesma linha projetando-se não apenas o Topo de coordenadas, mas a todo o retângulo em (superior e inferior).Determinar a sobreposição (interseção) com o outras palavras.Observe a área marcada em vermelho abaixo.
Esta é a tolerância que você pode usar para detectar se algo está na mesma linha.Se algo se sobrepõe por apenas um pixel, em seguida, é, provavelmente, do maior ou menor linha.Mas se ele se sobrepõe a, digamos, 50% ou mais de altura `Texto1, então é provável que na mesma linha.
Exemplo de SQL para encontrar todas as palavras na "linha", baseado no topo e no fundo coord
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)
Exemplo psuedo código do VB6 para calcular as linhas bem.
'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.