Question

J'utilise Microsoft MODI dans VB6 pour OCR une image.(Je connais d'autres outils OCR comme tesseract, etc. mais je trouve MODI plus précis que les autres)

L'image à OCRed est comme ça

enter image description here

et le texte que je reçois après l'OCR est comme ci-dessous

Text1
Text2
Text3
Number1
Number2
Number3

Le problème ici est que le texte correspondant de la colonne opposée n'est pas conservé.Comment puis-je mapper Number1 avec Text1 ?

Je ne peux que penser à une solution comme celle-ci.

MODI fournit les coordonnées de tous les mots OCRed comme celui-ci

LeftPos = Img.Layout.Words(0).Rects(0).Left
TopPos = Img.Layout.Words(0).Rects(0).Top

Ainsi, pour aligner les mots sur la même ligne, nous pouvons faire correspondre les TopPos de chaque mot, puis les trier par LeftPos.Nous aurons la ligne complète.J'ai donc parcouru tous les mots et stocké leur texte ainsi que ceux de gauche et de haut dans une table MySQL.puis j'ai exécuté cette requête

SELECT group_concat(word ORDER BY `left` SEPARATOR ' ')
FROM test_copy
GROUP BY `top`

Mon problème est que les premières positions ne sont pas exactement les mêmes pour chaque mot. Il y aura évidemment quelques différences de pixels.

J'ai essayé d'ajouter DIV 5, pour fusionner des mots compris dans une plage de 5 pixels, mais cela ne fonctionne pas dans certains cas.J'ai également essayé de le faire dans node.js en calculant la tolérance pour chaque mot, puis en triant par LeftPos, mais je pense toujours que ce n'est pas la meilleure façon de le faire.

Mise à jour: Le code js fait le travail, mais sauf dans le cas où Number1 a une différence de 5 pixels et Text2 n'a pas de correspondance dans cette ligne.

Y a-t-il une meilleure idée pour faire ça ?

Était-ce utile?

La solution

Je ne suis pas sûr à 100% de la façon dont vous identifiez les mots qui se trouvent dans votre colonne "gauche", mais une fois que vous avez identifié ce mot, vous pouvez trouver d'autres mots dans la ligne en projetant non seulement la coordonnée supérieure mais tout le rectangle ( en haut et en bas).Déterminez le chevauchement (intersection) avec les autres mots.Notez la zone marquée en rouge ci-dessous.

Horizontal projection

Il s'agit de la tolérance que vous pouvez utiliser pour détecter si quelque chose se trouve sur la même ligne.Si quelque chose ne chevauche que d'un pixel, il s'agit probablement d'une ligne inférieure ou supérieure.Mais s'il chevauche, disons, 50 % ou plus de la hauteur de « Texte1 », alors il est probablement sur la même ligne.


Exemple SQL pour trouver tous les mots de la "ligne" en fonction des coordonnées supérieure et inférieure

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)

Exemple de code pseudo VB6 pour calculer également les lignes.

'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.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top