Domanda

Sto usando Microsoft MODI In VB6 per eseguire l'OCR di un'immagine.(Conosco altri strumenti OCR come tesseract ecc. Ma trovo MODI più accurato di altri)

L'immagine da sottoporre a OCR è così

enter image description here

e il testo che ottengo dopo l'OCR è come sotto

Text1
Text2
Text3
Number1
Number2
Number3

Il problema qui è che il testo corrispondente della colonna opposta non viene mantenuto.Come posso mappare Number1 con Text1?

Posso solo pensare ad una soluzione come questa.

MODI fornisce le coordinate di tutte le parole OCR come questa

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

Quindi, per allineare le parole sulla stessa riga, possiamo abbinare la TopPos di ciascuna parola e quindi ordinarle in base alla LeftPos.Otterremo la linea completa.Quindi ho eseguito il loop di tutte le parole e ho memorizzato il loro testo, nonché sinistra e parte superiore in una tabella mysql.quindi ha eseguito questa query

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

Il mio problema è che le posizioni in alto non sono esattamente le stesse per ogni parola, ovviamente ci saranno un paio di differenze di pixel.

Ho provato ad aggiungere DIV 5, per unire parole che si trovano nell'intervallo di 5 pixel ma che in alcuni casi non funziona.Ho anche provato a farlo in node.js calcolando la tolleranza per ogni parola e quindi ordinando per LeftPos, ma sento ancora che questo non è il modo migliore per farlo.

Aggiornamento: Il codice js fa il lavoro, ma ad eccezione del caso in cui Number1 ha una differenza di 5 pixel e Text2 non ha corrispondenti in quella riga.

C'è qualche idea migliore per farlo?

È stato utile?

Soluzione

Non sono sicuro al 100% di come identifichi quelle parole che si trovano nella colonna "sinistra", ma una volta identificata quella parola puoi trovare altre parole nella riga proiettando non solo la coordinata Superiore ma l'intero rettangolo attraverso ( sia in alto che in basso).Determina la sovrapposizione (intersezione) con le altre parole.Notare l'area contrassegnata in rosso di seguito.

Horizontal projection

Questa è la tolleranza che puoi utilizzare per rilevare se qualcosa è nella stessa linea.Se qualcosa si sovrappone solo di un pixel, probabilmente proviene da una linea inferiore o superiore.Ma se si sovrappone, diciamo, del 50% o più dell'altezza "Testo1", è probabile che sia sulla stessa riga.


Esempio SQL per trovare tutte le parole nella "riga" in base alla coordinazione superiore e inferiore

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)

Esempio di pseudo codice VB6 per calcolare anche le linee.

'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.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top