web-dev-qa-db-ja.com

Keras OCRの例を使用するにはどうすればよいですか?

見つけました examples/image_ocr.py これはOCRのようです。したがって、モデルに画像を与え、テキストを受け取ることができるはずです。ただし、その方法はわかりません。モデルに新しい画像をフィードするにはどうすればよいですか?どのような前処理が必要ですか?

私がしたこと

依存関係のインストール:

  • インストール cairocffiSudo apt-get install python-cairocffi
  • インストールeditdistanceSudo -H pip install editdistance
  • trainを変更してモデルを返し、トレーニング済みのモデルを保存します。
  • スクリプトを実行してモデルをトレーニングします。

今、私はmodel.h5。次は何ですか?

現在のコードについては、 https://github.com/MartinThoma/algorithms/tree/master/ML/ocr/keras をご覧ください。私はモデルをロードする方法を知っていて(以下を参照)、これはうまくいくようです。問題は、テキストを含む画像の新しいスキャンをモデルにフィードする方法がわからないことです。

関連するサイドの質問

  • CTCとは何ですか? コネクショニストの時間的分類
  • 文書の回転を確実に検出するアルゴリズムはありますか?
  • 行/テキストブロック/テーブル/画像を確実に検出するアルゴリズムがあります(したがって、合理的なセグメンテーションを行います)。平滑化と行単位のヒストグラムを使用したエッジ検出は、すでにかなりうまく機能していると思いますか?

私が試したもの

#!/usr/bin/env python

from keras import backend as K
import keras
from keras.models import load_model
import os

from image_ocr import ctc_lambda_func, create_model, TextImageGenerator
from keras.layers import Lambda
from keras.utils.data_utils import get_file
import scipy.ndimage
import numpy

img_h = 64
img_w = 512
pool_size = 2
words_per_Epoch = 16000
val_split = 0.2
val_words = int(words_per_Epoch * (val_split))
if K.image_data_format() == 'channels_first':
    input_shape = (1, img_w, img_h)
else:
    input_shape = (img_w, img_h, 1)

fdir = os.path.dirname(get_file('wordlists.tgz',
                                Origin='http://www.mythic-ai.com/datasets/wordlists.tgz', untar=True))

img_gen = TextImageGenerator(monogram_file=os.path.join(fdir, 'wordlist_mono_clean.txt'),
                             bigram_file=os.path.join(fdir, 'wordlist_bi_clean.txt'),
                             minibatch_size=32,
                             img_w=img_w,
                             img_h=img_h,
                             downsample_factor=(pool_size ** 2),
                             val_split=words_per_Epoch - val_words
                             )
print("Input shape: {}".format(input_shape))
model, _, _ = create_model(input_shape, img_gen, pool_size, img_w, img_h)

model.load_weights("my_model.h5")

x = scipy.ndimage.imread('example.png', mode='L').transpose()
x = x.reshape(x.shape + (1,))

# Does not work
print(model.predict(x))

これは与える

2017-07-05 22:07:58.695665: I tensorflow/core/common_runtime/gpu/gpu_device.cc:996] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX TITAN Black, pci bus id: 0000:01:00.0)
Traceback (most recent call last):
  File "eval_example.py", line 45, in <module>
    print(model.predict(x))
  File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 1567, in predict
    check_batch_axis=False)
  File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 106, in _standardize_input_data
    'Found: array with shape ' + str(data.shape))
ValueError: The model expects 4 arrays, but only received one array. Found: array with shape (512, 64, 1)
20
Martin Thoma

さて、私はあなたがここで尋ねたすべてに答えようとします:

OCRコードでコメントされているように、Kerasは複数のパラメーターでの損失をサポートしていないため、ラムダレイヤーのNN損失を計算しました。この場合、これはどういう意味ですか?

ニューラルネットワークは4つの入力(_[input_data, labels, input_length, label_length]_)と_loss_out_を出力として使用しているため、混乱を招く場合があります。 input_dataに加えて、他のすべては損失の計算にのみ使用される情報であり、トレーニングにのみ使用されることを意味します。元のコードの468行目のようなものが必要です。

_Model(inputs=input_data, outputs=y_pred).summary()
_

これは、「入力として画像があります。ここに何が書かれているか教えてください」という意味です。それでそれを達成する方法は?

1)元のトレーニングコードをそのまま保持し、通常どおりトレーニングを行います。

2)トレーニング後、このモデルModel(inputs=input_data, outputs=y_pred)を.h5ファイルに保存して、必要な場所にロードします。

3)予測を行います。コードを見ると、入力画像が反転されて変換されるため、このコードを使用して簡単に実行できます。

_from scipy.misc import imread, imresize
#use width and height from your neural network here.

def load_for_nn(img_file):
    image = imread(img_file, flatten=True)
    image = imresize(image,(height, width))
    image = image.T

    images = np.ones((1,width,height)) #change 1 to any number of images you want to predict, here I just want to predict one
    images[0] = image
    images = images[:,:,:,np.newaxis]
    images /= 255

    return images
_

画像を読み込んで、予測を行いましょう。

_def predict_image(image_path): #insert the path of your image 
    image = load_for_nn(image_path) #load from the snippet code
    raw_Word = model.predict(image) #do the prediction with the neural network
    final_Word = decode_output(raw_Word)[0] #the output of our neural network is only numbers. Use decode_output from image_ocr.py to get the desirable string.
    return final_Word
_

これで十分でしょう。私の経験から、トレーニングで使用される画像は良い予測をするのに十分ではありません。必要に応じて後で結果を改善する他のデータセットを使用してコードをリリースします。

関連する質問への回答:

これは、シーケンス分類を改善するために使用される手法です。オリジナルの論文は、音声で言われていることを発見することで結果を改善することを証明しています。この場合、文字のシーケンスです。説明はちょっとしたトリックですが、良いものを見つけることができます こちら

  • 文書の回転を確実に検出するアルゴリズムはありますか?

よくわかりませんが、ニューラルネットワークのアテンションメカニズムをご覧ください。現在、良いリンクはありませんが、そうなる可能性があります。

  • 行/テキストブロック/テーブル/画像を確実に検出するアルゴリズムがあります(したがって、合理的なセグメンテーションを行います)。平滑化と行単位のヒストグラムを使用したエッジ検出は、すでにかなりうまく機能していると思いますか?

OpenCVは、Maximally Stable Extremal Regions(MSER)を実装しています。私はこのアルゴリズムの結果が本当に好きです。それは高速で、必要なときに十分でした。

前にも言ったように、すぐにコードをリリースします。リポジトリを使用して質問を編集しますが、ここでの情報でサンプルを実行することができます。

6
Claudio

ここでは、4つの入力が必要なモデルを作成しました。

_model = Model(inputs=[input_data, labels, input_length, label_length], outputs=loss_out)
_

一方、予測の試みは、画像だけをロードすることです。
したがって、メッセージ:モデルは4つのアレイを想定していますが、1つのアレイのみを受け取りました

コードから、必要な入力は次のとおりです。

_input_data = Input(name='the_input', shape=input_shape, dtype='float32')
labels = Input(name='the_labels', shape=[img_gen.absolute_max_string_len],dtype='float32')
input_length = Input(name='input_length', shape=[1], dtype='int64')
label_length = Input(name='label_length', shape=[1], dtype='int64')
_

元のコードとトレーニングは、TextImageGeneratorを使用しているため機能します。このジェネレーターは、モデルに必要な4つの入力を提供します。

したがって、ジェネレーターを使用して予測する必要があります。ジェネレーターでトレーニングするfit_generator()メソッドがあるので、ジェネレーターで予測する predict_generator() メソッドもあります。


さて、完全な答えと解決策のために、私はあなたの発電機を研究し、それがどのように機能するかを見る必要があります(これには時間がかかります)。しかし、今、あなたは何をすべきかを知っています、あなたはおそらくそれを理解することができます。

ジェネレータをそのまま使用して、おそらく膨大な量のデータを予測するか、必要なラベル、長さ、ラベルの長さを備えた1つまたはいくつかの画像を生成するジェネレータを複製することができます。

または、可能であれば、残りの3つの配列を手動で作成しますが、ジェネレーターの出力と同じ形状(バッチサイズである最初のものを除く)であることを確認します。

ただし、アサートする必要がある1つのことは、最初の次元を除き、ジェネレーター出力と同じ形状の4つの配列があることです。

4
Daniel Möller

これでmodel.h5ができました。次は何ですか?

最初に、model.h5にネットワークのweightsが含まれていることをコメントする必要があります。ネットワークのarchitectureも保存する場合は、 jsonこの例のように:

model_json = model_json = model.to_json()
with open("model_Arch.json", "w") as json_file:
    json_file.write(model_json)

これで、モデルとその重みを取得したら、次の手順を実行してオンデマンドでロードできます。

json_file = open('model_Arch.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
# load weights into new model
# if you already have a loaded model and dont need to save start from here
loaded_model.load_weights("model.h5")    
# compile loaded model with certain specifications
sgd = SGD(lr=0.01)
loaded_model.compile(loss="binary_crossentropy", optimizer=sgd, metrics=["accuracy"])

次に、そのloaded_moduleを使用して、次のように特定の入力の分類を予測することができます。

prediction = loaded_model.predict(some_input, batch_size=20, verbose=0)

その入力の分類を返します。

サイド質問について:

  1. CTCは、あなたが参照した論文で定義している用語のようです。

以下では、非セグメント化データシーケンスを一時的な分類としてラベル付けするタスク(Kadous、2002)、およびRNNの使用を参照しますこれは、コネクショニストの一時的分類としての目的です([〜#〜] ctc [〜#〜])。

  1. ドキュメント、画像などの回転を補正するには、そのような変換を適用することで現在のデータからより多くのデータを生成できます(その方法を説明する this ブログ投稿をご覧ください)、 または畳み込みニューラルネットワーク アプローチを使用できますが、これは実際に使用しているKerasの例でもありますそのことからわかるように、 git

この例では、convolutionalスタックに続いて再帰スタックとCTCログロス関数を使用して、生成されたテキスト画像の光学文字認識を実行します。

this あなたがやっていることに関連するチュートリアルと、畳み込みニューラルネットワークについてさらに説明している場所を確認できます。

  1. まあ、これは幅広い質問ですが、ラインを検出するには Hough Line Transform を使用するか、または Canny Edge Detection を使用することをお勧めします。

編集:取得しているエラーは、kerasから1ではなく、より多くのパラメータが予想されるためです docs

predict(self, x, batch_size=32, verbose=0)

ValueErrorを発生させます:提供された入力データとモデルの期待値が一致しない場合、またはステートフルモデルがバッチサイズの倍数ではないサンプルの数を受け取る場合。

2
DarkCygnus