OCRED非構造化テキストを適切なテキストに変換します
-
21-12-2019 - |
質問
MODI
でMicrosoft VB6
を使用して画像をOCRにしています。 (私はTesseractなどのような他のOCRツールについて知っていますが、私は他のよりも正確な修正を見つけました)
オスコルド画像はこの
のようなものです。
、OCRの後に取得したテキスト
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
.
だから言葉を同じ行に整列させるために、私たちは各単語のTOPPOを一致させてから左の順に並べ替えることができます。私たちは完全な行を手に入れます。だから私はすべての単語をループして、彼らのテキストと左と上をMySQLテーブルに保存しました。その後、このクエリ
を実行しましたSELECT group_concat(word ORDER BY `left` SEPARATOR ' ')
FROM test_copy
GROUP BY `top`
.
私の問題は、各単語について上位位置がまったく同じではないことです。
私は5ピクセルの範囲内の単語をマージするために、DIV 5
を追加しましたが、それがいくつかの場合には機能しません。また、各単語の許容誤差を計算してから、左の順に並べ替えることで、まだやるべきことではないと感じています。
アップデート: JSコードはジョブを行いますが、Number1が5つのピクセル差があり、TEXT2にはその行に対応していない場合を除きます。
これをやるべきより良い考えはありますか?
解決
私はあなたの「左」の列にある単語を識別する方法100%ではありませんが、あなたがその単語を識別したらあなたがその単語の中の他の単語を見つけることができます。横方向の長方形(上下両方)。他の単語と重複(交差点)を決定します。下の赤でマークされた領域に注意してください。
これは、何かが同じ行にあるかどうかを検出するために使用できる許容範囲です。何かがピクセルだけで重なっている場合は、おそらくより低いまたは上位のラインからのものです。しかし、それが重なっている場合は、高さの50%以上の高さ `text1であれば、それは同じ行にある可能性があります。
ATOPと下のcoordに基づいて「行」のすべての単語を見つけるための例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.
.