web-dev-qa-db-ja.com

Python + OpenCV:OCR画像セグメンテーション

私は領収書のこのおもちゃの例からOCRをやろうとしています。 Python 2.7およびOpenCV 3.1を使用します。

enter image description here

グレースケール+ぼかし+外部エッジ検出+領収書の各エリアのセグメンテーション(たとえば、「カテゴリ」で、どちらがマークされているか(この場合は現金)を確認します)。

領収書の各セグメントを適切に変換して「自動的に」セグメント化できるように、画像が「歪んでいる」場合、私は複雑に感じます。

例:

enter image description here

なにか提案を?

以下のコードは、エッジ検出まで取得する例ですが、領収書は最初の画像のようなものです。私の問題は、テキストから画像への変換ではありません。画像の前処理です。

どんな助けでも感謝します! :)

import os;
os.chdir() # Put your own directory

import cv2 
import numpy as np

image = cv2.imread("Rent-Receipt.jpg", cv2.IMREAD_GRAYSCALE)

blurred = cv2.GaussianBlur(image, (5, 5), 0)

#blurred  = cv2.bilateralFilter(gray,9,75,75)

# apply Canny Edge Detection
edged = cv2.Canny(blurred, 0, 20)

#Find external contour

(_,contours, _) = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
14
donpresente

あなたが説明した最初のステップに関する素晴らしいチュートリアルは pyimagesearch で利用できます(そして彼らは一般に素晴らしいチュートリアルを持っています)

要するに、Ellaが説明したように、cv2.CHAIN_APPROX_SIMPLEを使用する必要があります。少し堅牢な方法は、cv2.RETR_LISTの代わりにcv2.RETR_EXTERNALを使用してから領域をソートすることです。白い背景でも、ページが背景に大きな形状を刻む場合でもうまく機能するはずです。

あなたの質問の2番目の部分に来て、文字をセグメント化する良い方法は、OpenCVで利用可能な最大限に安定した極値領域抽出器を使用することです。 CPPの完全な実装が利用可能です こちら 私が最近手伝っていたプロジェクトで。 Python実装は以下のコードに沿って進みます(OpenCV 3.0+で以下のコードが機能します。OpenCV2.x構文については、オンラインで確認してください)

import cv2

img = cv2.imread('test.jpg')
mser = cv2.MSER_create()

#Resize the image so that MSER can work better
img = cv2.resize(img, (img.shape[1]*2, img.shape[0]*2))

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
vis = img.copy()

regions = mser.detectRegions(gray)
hulls = [cv2.convexHull(p.reshape(-1, 1, 2)) for p in regions[0]]
cv2.polylines(vis, hulls, 1, (0,255,0)) 

cv2.namedWindow('img', 0)
cv2.imshow('img', vis)
while(cv2.waitKey()!=ord('q')):
    continue
cv2.destroyAllWindows()

これにより、出力が次のようになります。

enter image description here

ここで、誤検知を排除するために、単純にハル内のポイントを循環させ、周囲長を計算できます(ハル[i]内のすべての隣接ポイント間の距離の合計、ハル[i]は1つの凸型ハル内のすべてのポイントのリスト) )。境界が大きすぎる場合は、キャラクターとして分類しないでください。

画像の境界線が黒のため、画像を横切る診断線が来ています。画像が読み取られるとすぐに次の行を追加することで簡単に削除できます(7行目以下)

img = img[5:-5,5:-5,:]

出力を与える

enter image description here

15

私の頭の上のオプションでは、歪んだ画像の4つの角を抽出する必要があります。これは、輪郭を見つけるときにcv2.CHAIN_APPROX_SIMPLEの代わりにcv2.CHAIN_APPROX_NONEを使用して行われます。その後、cv2.approxPolyDPを使用して、領収書の4つの隅にとどまることができます(すべての画像がこのようなものである場合、動作しない理由はありません)。

次に、cv2.findHomographycv2.wardPerspectiveを使用して、歪んだ画像から抽出された4つのポイントであるソースポイントと、長方形を形成するデスティネーションポイント(たとえば、画像の全サイズ)に従って画像を修正します。

ここで、コードサンプルと詳細情報を見つけることができます。 画像のOpenCV-Geometric Transformations

また、この答えは役に立つかもしれません- SO-テキストのスキューを検出して修正する

編集:2番目のチェーンをおよそcv2.CHAIN_APPROX_NONEに修正しました。

5
Elia