web-dev-qa-db-ja.com

画像から数字を認識する

画像内の数値を検索して加算するアプリケーションを作成しようとしています。

画像に書かれた番号をどのように識別できますか?

enter image description here

画像には多くのボックスがあり、左側の数字を取得して合計すると合計になります。どうすればこれを達成できますか?

編集:画像にJava tesseract ocrを実行しましたが、正しい結果が得られませんでした。どのようにトレーニングできますか?

また

私はこれを手に入れたエッジ検出を行いました:

enter image description here

35
Hash

ほとんどの場合、次のことを行う必要があります。

  1. Hough Transform アルゴリズムをページ全体に適用すると、一連のページセクションが生成されます。

  2. 取得したセクションごとに、再度適用します。現在のセクションで2つの要素が生成された場合、上記と同様の長方形を扱う必要があります。

  3. 完了したら、OCRを使用して数値を抽出できます。

この場合は、ハフ変換部分に取り組むことができる JavaCV (OpenCV Java Wrapper)を参照することをお勧めします。次に、 Tess4j (Tesseract Java Wrapper)これにより、後の数値を抽出できます。

補足として、誤検知の量を減らすために、次のことを実行することをお勧めします。

  1. 特定の座標に後のデータが含まれないことが確実な場合は、画像をトリミングします。これにより、操作する画像が小さくなります。

  2. 画像をグレースケールに変更するのが賢明な場合があります(カラー画像で作業している場合)。色は、画像を解決するOCRの機能に悪影響を与える可能性があります。

編集:あなたのコメントに従って、次のようなものが与えられます:

+------------------------------+
|                   +---+---+  |
|                   |   |   |  |
|                   +---+---+  |
|                   +---+---+  |
|                   |   |   |  |
|                   +---+---+  |
|                   +---+---+  |
|                   |   |   |  |
|                   +---+---+  |
|                   +---+---+  |
|                   |   |   |  |
|                   +---+---+  |
+------------------------------+

画像をトリミングして、関連データのない領域(左側の部分)を削除するように画像をトリミングすると、次のようになります。

+-------------+
|+---+---+    |
||   |   |    | 
|+---+---+    |
|+---+---+    |
||   |   |    |
|+---+---+    |
|+---+---+    |
||   |   |    |
|+---+---+    |
|+---+---+    |
||   |   |    |
|+---+---+    |
+-------------+

アイデアは、次のように長方形を含むページのセグメントを取得できるように、ハフ変換を実行することです。

+---+---+    
|   |   |     
+---+---+ 

次に、ハフ変換を再度適用し、最終的に2つのセグメントを作成し、左側のセグメントを選択します。

左のセグメントを作成したら、OCRを適用します。

あなたは事前にOCRを適用することができますが、せいぜい、OCRは両方の数値を認識します。得る、あなたが求めているものではありません。

また、四角形を描く余分な線がOCRをトラックから外し、悪い結果をもたらす可能性があります。

20
npinti

2つの基本的なニューラルネットワークコンポーネントを組み合わせることをお勧めします。

  • パーセプトロン
  • 自己組織化マップ(SOM)

A perceptronは非常にシンプルなニューラルネットワークコンポーネントです。複数の入力を取り、1つの出力を生成します。 train入力と出力の両方に入力する必要があります。これは自己学習コンポーネントです。

内部的には、出力の計算に使用される重み係数のコレクションがあります。これらの重み係数は、トレーニング中に完成されます。パーセプトロンの美しいところは、(適切なトレーニングを行うことで)これまでに見たことのないデータを処理できることです。

in a multi-layer networkを配置することで、パーセプトロンをより強力にすることができます。つまり、あるパーセプトロンの出力が別のパーセプトロンの入力として機能します。

あなたの場合、各数値(0-9)に1つずつ、10個のパーセプトロンネットワークを使用する必要があります。

ただし、パーセプトロンを使用するには、数値入力の配列が必要です。したがって、最初に視覚的なイメージを数値に変換するための何かが必要です。 A 自己組織化マップ (SOM)相互接続されたポイントのグリッドを使用します。ポイントは画像のピクセルに引き付けられる必要があります(以下を参照)

Self Organized Map

2つのコンポーネントはうまく連携します。 SOMには固定数のグリッドノードがあり、パーセプトロンには固定数の入力が必要です。

どちらのコンポーネントも非常に人気があり、 [〜#〜] matlab [〜#〜] などの教育用ソフトウェアパッケージで利用できます。

更新:2018年6月1日-テンソルフロー

このビデオチュートリアル は、python GoogleのTensorFlowフレームワークを使用してどのように実行できるかを示しています。(チュートリアルについては こちら をクリックしてください)。

10
bvdb

ニューラルネットワークは、この種の問題に対する典型的なアプローチです。

このシナリオでは、手書きの各数字をピクセルのマトリックスと見なすことができます。認識したい画像と同じサイズの画像でニューラルネットワークをトレーニングすると、より良い結果が得られる場合があります。

手書きの数字のさまざまな画像を使用してニューラルネットワークをトレーニングできます。トレーニング後、手書きの数字の画像を渡して識別すると、最も類似した数字が返されます。

もちろん、トレーニング画像の品質は、良い結果を得るための重要な要素です。

8
xeeevi

ほとんどの画像処理の問題では、可能な限り多くの情報を活用したいと考えています。画像が与えられれば、私たちができる(そしておそらくそれ以上の)仮定が存在します:

  1. 数字の周りのボックスは一貫しています。
  2. 右側の数字は常に8(または事前にわかっている)です
  3. 左側の数字は常に数字です
  4. 左側の数字は常に手書きで、同じ人物が書いたものです

次に、これらの仮定を使用して問題を単純化できます。

  1. より単純な方法で数値を見つけることができます(テンプレートマッチング)。マッチの座標がわかったら、サブ画像を作成してテンプレートを差し引くと、OCRエンジンに与えたい数字だけを残すことができます。 http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html
  2. 予想される数値がわかっている場合は、別のソースから数値を取得でき、OCRエラーのリスクはありません。テンプレートの一部として8を含めることもできます。
  3. これに基づいて、語彙(可能なOCR結果)を大幅に削減し、OCRエンジンの精度を向上させることができます。 TesseractOCRがこれを行うためのホワイトリスト設定があります( https://code.google.com/p/tesseract-ocr/wiki/FAQ#How_do_I_recognize_only_digits ?を参照)。
  4. 手書きは、OCRエンジンが認識するのがはるかに困難です(印刷フォント用です)。ただし、作成者の「フォント」を認識するようにOCRエンジンをトレーニングできます。 ( http://michaeljaylissner.com/posts/2012/02/11/adding-new-fonts-to-tesseract-3-ocr-engine/ を参照)

ただし、要点は、問題を小さく、より単純なサブ問題に縮小するために想定できることを使用することです。次に、これらの各サブ問題を個別に解決するために使用できるツールを確認します。

これらがスキャンされる場合など、現実世界について心配し始める必要がある場合も、仮定を立てることは困難です。「テンプレート」または数値の傾斜または回転を考慮する必要があります。

5
Noremac

それを放棄。本当に。人間としての私は、3番目の文字が「1」であるか「7」であるかを確実に言うことはできません。人間は解読に優れているため、コンピュータはこれに失敗します。 「1」と「7」は問題のあるケースの1つにすぎず、「8」と「6」、「3」と「9」も解読/識別が困難です。エラー見積もりは> 10%になります。すべての手書きが同じ人からのものである場合は、そのためにOCRをトレーニングすることもできますが、この場合でも約3%のエラーが発生します。ユースケースが特別な場合もありますが、この数のエラーは通常、あらゆる種類の自動処理を禁止します。これを自動化する必要がある場合は、Mechanical Turkを調べます。

1
tobltobs

ここに簡単なアプローチがあります:

  1. バイナリイメージを取得します。イメージを読み込み、グレースケールに変換してから、大津のしきい値を使用して、[0...255]

  2. 水平線と垂直線を検出します。水平線と垂直線を作成します 構造化要素 次に、- morphologicalオペレーション

  3. 水平線と垂直線を削除します。bitwise_or 演算を使用して水平マスクと垂直マスクを結合し、次に bitwise_and 演算。

  4. OCRを実行します。ガウスぼかし を適用し、次に Pytesseract を使用してOCRを適用します。


各ステップの視覚化は次のとおりです。

入力画像->バイナリイメージ->水平マスク->垂直マスク

enter image description hereenter image description hereenter image description hereenter image description here

結合マスク->結果->わずかなぼかしを適用

enter image description hereenter image description hereenter image description here

OCRからの結果

38
18
78

Python=で実装しましたが、Javaを使用して同様のアプローチを適応させることができます

import cv2
import pytesseract

pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

# Load image, grayscale, 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]

# Detect horizontal lines
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,1))
horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=1)

# Detect vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,25))
vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=1)

# Remove horizontal and vertical lines
lines = cv2.bitwise_or(horizontal, vertical)
result = cv2.bitwise_not(image, image, mask=lines)

# Perform OCR with Pytesseract
result = cv2.GaussianBlur(result, (3,3), 0)
data = pytesseract.image_to_string(result, lang='eng', config='--psm 6')
print(data)

# Display
cv2.imshow('thresh', thresh)
cv2.imshow('horizontal', horizontal)
cv2.imshow('vertical', vertical)
cv2.imshow('lines', lines)
cv2.imshow('result', result)
cv2.waitKey()
1
nathancy