OCRのクリーニング画像


9

OCRの画像をクリアしようとしています:(行)

ここに画像の説明を入力してください

時々画像をさらに処理するためにこれらの行を削除する必要があり、かなり近づきつつありますが、多くの場合、しきい値がテキストから取りすぎています。

    copy = img.copy()
    blur = cv2.GaussianBlur(copy, (9,9), 0)
    thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,30)

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
    dilate = cv2.dilate(thresh, kernel, iterations=2)

    cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]

    for c in cnts:
        area = cv2.contourArea(c)
        if area > 300:
            x,y,w,h = cv2.boundingRect(c)
            cv2.rectangle(copy, (x, y), (x + w, y + h), (36,255,12), 3)

編集:さらに、フォントが変更された場合、定数を使用しても機能しません。これを行う一般的な方法はありますか?


2
これらの行の一部、またはそれらの断片は、正当なテキストと同じ特性を持っているため、有効なテキストを損なうことなくそれらを取り除くことは困難です。これが当てはまる場合は、それらが文字よりも長く、やや孤立しているという事実に焦点を当てることがあります。したがって、最初のステップは、文字のサイズと近さを推定することです。
Yves Daoust、

@YvesDaoustキャラクターの近さを見つけるにはどうしたらいいですか?(純粋にサイズでのフィルタリングは、文字と混同されることが多いため)
K41F4r

1
すべてのブロブについて、最も近い隣接物までの距離を見つけることができます。次に、距離のヒストグラム分析により、「近い」と「離れた」(分布のモードのようなもの)の間、または「囲まれた」と「分離された」の間のしきい値を見つけます。
Yves Daoust

互いに近い複数の小さな線の場合、それらの最も近い隣は他の小さな線ではないでしょうか?他のすべてのblobまでの平均距離を計算するにはコストがかかりすぎますか?
K41F4r

「彼らの最も近い隣人は他の小さな線ではないでしょうか?」:あなたの名誉、良い反対 実際、非常に短い配列の集まりは、完全にありそうもない配置ではありますが、正当なテキストと違いはありません。破線のフラグメントを再グループ化する必要がある場合があります。すべての人との平均距離があなたを救うかどうかはわかりません。
Yves Daoust

回答:


14

ここにアイデアがあります。この問題をいくつかのステップに分けます。

  1. 平均的な長方形の輪郭領域を決定します。次に、等高線を検出し、等高線の外接する四角形領域を使用してフィルター処理します。これを行う理由は、典型的な特性は非常に大きくなるだけで、大きなノイズはより大きな長方形の領域に広がるという観察のためです。次に、平均面積を決定します。

  2. 大きな外れ値の輪郭を削除します。等高線を繰り返し処理5xし、等高線を塗りつぶして平均等高線領域よりも大きい場合は、大きい等高線を削除します。固定されたしきい値領域を使用する代わりに、この動的しきい値を使用してロバスト性を高めています。

  3. 垂直カーネルで拡張して文字を接続します。このアイデアは、文字が列に配置されているという観察を利用しています。垂直カーネルで拡張することにより、テキストを結合して、ノイズがこの結合された輪郭に含まれないようにします。

  4. 小さなノイズを取り除きます。保持するテキストが接続されたので、輪郭を見つけ4x、平均輪郭領域よりも小さい輪郭を削除します。

  5. ビット単位-および画像を再構成します。マスクを維持するために必要な輪郭のみがあるため、ビット単位でテキストを保持し、結果を取得します。


これはプロセスの視覚化です:

我々大津の閾値バイナリ画像を得るための輪郭を見つける平均矩形の輪郭領域を決定するために。ここから、輪郭を塗りつぶして、緑色で強調表示された大きな外れ値の輪郭を削除します

ここに画像の説明を入力してください ここに画像の説明を入力してください

我々が構築次の垂直カーネルをして拡張文字を接続します。この手順では、保持する必要なすべてのテキストを接続し、ノイズを個々のブロブに分離します。

ここに画像の説明を入力してください

次に、輪郭を見つけ、輪郭領域を使用してフィルタリングして、小さなノイズを除去します

ここに画像の説明を入力してください

削除されたすべてのノイズ粒子が緑色で強調表示されています

ここに画像の説明を入力してください

結果

ここに画像の説明を入力してください

コード

import cv2

# Load image, grayscale, and Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Determine average contour area
average_area = [] 
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = w * h
    average_area.append(area)

average = sum(average_area) / len(average_area)

# Remove large lines if contour area is 5x bigger then average contour area
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = w * h
    if area > average * 5:  
        cv2.drawContours(thresh, [c], -1, (0,0,0), -1)

# Dilate with vertical kernel to connect characters
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,5))
dilate = cv2.dilate(thresh, kernel, iterations=3)

# Remove small noise if contour area is smaller than 4x average
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < average * 4:
        cv2.drawContours(dilate, [c], -1, (0,0,0), -1)

# Bitwise mask with input image
result = cv2.bitwise_and(image, image, mask=dilate)
result[dilate==0] = (255,255,255)

cv2.imshow('result', result)
cv2.imshow('dilate', dilate)
cv2.imshow('thresh', thresh)
cv2.waitKey()

注:従来の画像処理は、しきい値処理、モルフォロジー演算、および輪郭フィルタリング(輪郭近似、面積、アスペクト比、またはブロブ検出)に限定されています。入力画像は文字テキストのサイズに基づいて変化する可能性があるため、特異解を見つけることは非常に困難です。動的ソリューションの機械/ディープラーニングを使用して独自の分類子をトレーニングすることを検討したい場合があります。


1
大きなフォントの場合、これもテキストを削除しませんか?
K41F4r

はい、そうかもしれません、それであなたは閾値面積値を調整しなければならないでしょう。より動的なアプローチのアイデアは、その後、使用する平均的な文字領域を決定することで、その閾値として
nathancy

この例では具体的すぎるようです。平均面積を使用すると、テキストが
頻繁に削除さ

投稿に追加できる別の入力画像の例はありますか?
ナンシー

1
従来の画像処理技術を使用してすべての状況で機能するソリューションを見つけることは非常に困難です。ディープラーニングを使用して独自の分類器をトレーニングすることを検討することもできます。幸運を!
ナンシー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.