webentwicklung-frage-antwort-db.com.de

Wie kann ich das Keras OCR-Beispiel verwenden?

Ich habe examples/image_ocr.py gefunden, was für OCR scheint. Daher sollte es möglich sein, dem Modell ein Bild zu geben und Text zu empfangen. Ich habe jedoch keine Ahnung, wie ich das machen soll. Wie füttere ich das Modell mit einem neuen Bild? Welche Art der Vorverarbeitung ist notwendig? 

Was ich getan habe

Installation der Depencencies:

  • Installiere cairocffi : Sudo apt-get install python-cairocffi
  • editdistance installieren: Sudo -H pip install editdistance
  • Ändern Sie train, um das Modell zurückzugeben und das trainierte Modell zu speichern.
  • Führen Sie das Skript aus, um das Modell zu trainieren.

Jetzt habe ich einen model.h5. Was kommt als nächstes?

Siehe https://github.com/MartinThoma/algorithms/tree/master/ML/ocr/keras für meinen aktuellen Code. Ich weiß, wie man das Modell lädt (siehe unten) und das scheint zu funktionieren. Das Problem ist, dass ich nicht weiß, wie ich neue Scans von Bildern mit Text dem Modell zuführen soll.

Verwandte Nebenfragen

  • Was ist CTC? Connectionist Temporale Klassifizierung ?
  • Gibt es Algorithmen, die die Rotation eines Dokuments zuverlässig erkennen?
  • Gibt es Algorithmen, die Linien/Textblöcke/Tabellen/Bilder zuverlässig erkennen (daher eine sinnvolle Segmentierung ermöglichen)? Ich denke, die Kantenerkennung mit Glättung und zeilenweisen Histogrammen funktioniert dafür schon einigermaßen?

Was ich versucht habe

#!/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))

das gibt

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)
18
Martin Thoma

Hier haben Sie ein Modell erstellt, das 4 Eingaben benötigt:

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

Ihr vorhergesagter Versuch dagegen lädt nur ein Bild.
Daher die Nachricht: Das Modell erwartet 4 Arrays, aber nur ein Array erhalten.

Die erforderlichen Eingaben lauten aus Ihrem Code: 

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')

Der ursprüngliche Code und Ihr Training funktionieren, weil sie die Variable TextImageGenerator verwenden. Dieser Generator gibt Ihnen die vier notwendigen Eingaben für das Modell. 

Was Sie also tun müssen, ist die Verwendung des Generators vorherzusagen. Da Sie die fit_generator()-Methode für das Training mit dem Generator haben, haben Sie auch die predict_generator () - Methode für die Vorhersage mit dem Generator. 


Um eine vollständige Antwort und Lösung zu erhalten, muss ich Ihren Generator studieren und sehen, wie er funktioniert (was einige Zeit in Anspruch nehmen würde). Aber jetzt wissen Sie, was zu tun ist, Sie können es wahrscheinlich herausfinden. 

Sie können den Generator entweder so verwenden, wie er ist, und wahrscheinlich eine große Menge an Daten vorhersagen, oder Sie können versuchen, einen Generator zu replizieren, der nur ein oder wenige Bilder mit den erforderlichen Beschriftungen, der Länge und der Beschriftungslänge ergibt. 

Oder erstellen Sie, falls möglich, nur die 3 verbleibenden Arrays manuell, stellen Sie dabei jedoch sicher, dass sie die gleiche Form (außer der ersten, dh der Batchgröße) wie die Generatorausgänge haben. 

Die einzige Sache, die Sie jedoch behaupten müssen, ist: Sie haben 4 Arrays mit den gleichen Formen wie die Generatorausgänge, mit Ausnahme der ersten Dimension. 

4
Daniel Möller

Nun, ich werde versuchen, alles zu beantworten, was Sie hier gefragt haben:

Wie im OCR-Code erläutert, unterstützt Keras keine Verluste mit mehreren Parametern. Daher wurde der NN-Verlust in einer Lambda-Schicht berechnet. Was bedeutet das in diesem Fall?

Das neuronale Netzwerk kann verwirrend aussehen, da es 4 Eingänge ([input_data, labels, input_length, label_length]) und loss_out als Ausgabe verwendet. Alle anderen Informationen sind neben input_data nur Informationen, die zur Berechnung des Verlusts verwendet werden. Dies bedeutet, dass sie nur für das Training verwendet werden. Wir wünschen etwas in Zeile 468 des ursprünglichen Codes:

Model(inputs=input_data, outputs=y_pred).summary()

was bedeutet "Ich habe ein Bild als Eingabe, bitte sagen Sie mir, was hier geschrieben wird". Wie kann ich das erreichen?

1) Behalten Sie den ursprünglichen Trainingscode wie er ist, machen Sie das Training normal;

2) Speichern Sie dieses Modell Model(inputs=input_data, outputs=y_pred) in einer .h5-Datei, um es dort zu laden, wo Sie möchten.

3) Machen Sie die Vorhersage: Wenn Sie sich den Code ansehen, wird das Eingabebild invertiert und übersetzt, sodass Sie diesen Code zur Vereinfachung verwenden können:

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

Wenn das Bild geladen ist, lassen Sie uns die Vorhersage treffen:

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

Das sollte reichen. Aus meiner Erfahrung sind die Bilder, die im Training verwendet werden, nicht gut genug, um gute Vorhersagen zu treffen. Ich werde einen Code mit anderen Datensätzen veröffentlichen, die meine Ergebnisse später ggf. verbessern.

Antworten auf verwandte Fragen:

Es ist eine Technik zur Verbesserung der Sequenzklassifizierung. Das Originalpapier beweist, dass es bessere Ergebnisse beim Erkennen von Audioinhalten erzielt. In diesem Fall handelt es sich um eine Folge von Zeichen. Die Erklärung ist ein bisschen Trick, aber Sie finden hier eine gute .

  • Gibt es Algorithmen, die die Rotation eines Dokuments zuverlässig erkennen?

Ich bin mir nicht sicher, aber Sie könnten sich den Aufmerksamkeitsmechanismus in neuronalen Netzwerken anschauen. Ich habe jetzt keine gute Verbindung, aber ich weiß, dass dies der Fall sein könnte.

  • Gibt es Algorithmen, die Linien/Textblöcke/Tabellen/Bilder zuverlässig erkennen (daher eine sinnvolle Segmentierung ermöglichen)? Ich denke, die Kantenerkennung mit Glättung und zeilenweisen Histogrammen funktioniert dafür schon einigermaßen?

OpenCV implementiert maximal stabile Extremalregionen (bekannt als MSER). Ich mag die Ergebnisse dieses Algorithmus sehr, er ist schnell und war gut genug für mich, wenn ich gebraucht hätte. 

Wie ich schon sagte, werde ich bald einen Code veröffentlichen. Ich werde die Frage dann mit dem Repository bearbeiten, aber ich glaube, die Informationen hier reichen aus, um das Beispiel zum Laufen zu bringen.

4
Claudio

Jetzt habe ich ein model.h5. Was kommt als nächstes?

Zuerst sollte ich sagen, dass der model.h5 die Gewichte Ihres Netzwerks enthält. Wenn Sie auch die Architektur Ihres Netzwerks speichern möchten, sollten Sie es als json wie im folgenden Beispiel speichern:

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

Sobald Sie Ihr Modell und seine Gewichte erworben haben, können Sie sie bei Bedarf laden, indem Sie folgende Schritte ausführen:

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"])

Dann können Sie mit diesem loaded_module die Klassifizierung bestimmter Eingaben wie folgt vorhersagen:

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

Dies gibt die Klassifizierung dieser Eingabe zurück.

Über die Nebenfragen:

  1. CTC scheint ein Begriff zu sein, den sie in dem von Ihnen referierten Papier definieren.

Wir verweisen auf die Aufgabe, un -.__ zu kennzeichnen. segmentierte Datensequenzen als zeitliche Klassifizierung (Kadous, 2002) und zu unserer Verwendung von RNNs für diesen Zweck. darstellen als Verbindungistische zeitliche Klassifizierung (CTC).

  1. Um die Rotation eines Dokuments, von Bildern oder Ähnlichem zu kompensieren, können Sie entweder mehr Daten aus Ihren aktuellen erzeugen, indem Sie solche Transformationen anwenden (siehe this blog - Beitrag, der eine Möglichkeit erläutert), oder Sie könnten einen Convolutional Neural Network -Ansatz verwenden, was eigentlich auch das ist, was das Keras-Beispiel, das Sie verwenden, macht, wie wir aus dem git sehen können:

In diesem Beispiel wird ein convolutional - Stapel gefolgt von einem wiederkehrenden Stapel verwendet und eine CTC-Logloss-Funktion zum Durchführen einer optischen Zeichenerkennung von generierten Textbildern. 

Sie können das dieses Tutorial überprüfen, das sich auf Ihre Aktivitäten bezieht und wo sie auch mehr über Convolutional Neural Networks erklären.

  1. Nun, dies ist eine weit gefasste Frage, aber um Linien zu erkennen, können Sie die Hough-Linienumwandlung oder auch Canny Edge Detection verwenden.

Edit: Der Fehler, den Sie erhalten, ist, weil von den Keras docs mehr Parameter als von 1 erwartet werden:

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

Löst ValueError aus: Falls die angegebenen Eingabedaten nicht mit den Erwartungen des Modells übereinstimmen oder ein Stateful-Modell eine Anzahl von Proben erhält, die kein Vielfaches der Stapelgröße ist.

2
DarkCygnus