J'ai trouvé examples/image_ocr.py
qui semble pour OCR. Il devrait donc être possible de donner une image au modèle et de recevoir du texte. Cependant, je ne sais pas comment faire. Comment nourrir le modèle avec une nouvelle image? Quel type de prétraitement est nécessaire?
Installer les dépendances:
cairocffi
: Sudo apt-get install python-cairocffi
editdistance
: Sudo -H pip install editdistance
train
pour renvoyer le modèle et enregistrez le modèle formé.Maintenant, j'ai un model.h5
. Et après?
Voir https://github.com/MartinThoma/algorithms/tree/master/ML/ocr/keras pour le code actuel. Je sais comment charger le modèle (voir ci-dessous) et cela semble fonctionner. Le problème est que je ne sais pas comment alimenter de nouvelles numérisations d'images avec du texte dans le modèle.
#!/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))
cela donne
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)
Ici, vous avez créé un modèle qui nécessite 4 entrées:
model = Model(inputs=[input_data, labels, input_length, label_length], outputs=loss_out)
En revanche, votre tentative de prédiction consiste à ne charger qu'une image.
D'où le message: Le modèle attend 4 tableaux, mais n'a reçu qu'un tableau
À partir de votre code, les entrées nécessaires sont les suivantes:
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')
Le code d'origine et votre formation fonctionnent car ils utilisent la variable TextImageGenerator
. Ce générateur se charge de vous fournir les quatre entrées nécessaires pour le modèle.
Donc, ce que vous devez faire est de prédire en utilisant le générateur. Comme vous disposez de la méthode fit_generator()
pour vous entraîner au générateur, vous disposez également de la méthode predict_generator () pour la prédiction avec le générateur.
Maintenant, pour une réponse complète et une solution, je devrais étudier votre générateur et voir comment il fonctionne (ce qui me prendrait un peu de temps). Mais maintenant que vous savez ce qu'il faut faire, vous pouvez probablement le comprendre.
Vous pouvez utiliser le générateur tel quel et prévoir probablement beaucoup de données, ou vous pouvez essayer de répliquer un générateur qui ne produira qu'une ou plusieurs images avec les étiquettes, la longueur et la longueur d'étiquette nécessaires.
Ou peut-être, si possible, créez simplement les 3 tableaux restants manuellement, mais en vous assurant qu'ils ont les mêmes formes (à l'exception du premier, qui est la taille du lot) que les sorties du générateur.
La seule chose que vous devez affirmer, cependant, est la suivante: disposez de 4 tableaux ayant les mêmes formes que les sorties du générateur, à l’exception de la première dimension.
Eh bien, je vais essayer de répondre à tout ce que vous avez demandé ici:
Comme indiqué dans le code OCR, Keras ne prend pas en charge les pertes avec plusieurs paramètres. Il a donc calculé la perte NN dans une couche lambda. Qu'est-ce que cela signifie dans ce cas?
Le réseau de neurones peut sembler déroutant car il utilise 4 entrées ([input_data, labels, input_length, label_length]
) et loss_out
en sortie. Outre input_data, tout le reste est une information utilisée uniquement pour calculer la perte, cela signifie qu'elle n'est utilisée que pour la formation. Nous désirons quelque chose comme à la ligne 468 du code original:
Model(inputs=input_data, outputs=y_pred).summary()
ce qui signifie "j'ai une image en entrée, dites-moi s'il vous plaît ce qui est écrit ici". Alors, comment y arriver?
1) Conservez le code de formation original tel quel, faites la formation normalement;
2) Après l’entraînement, enregistrez ce modèle Model(inputs=input_data, outputs=y_pred)
dans un fichier .h5 qui sera chargé où vous voulez;
3) Faites la prédiction: si vous regardez le code, l’image d’entrée est inversée et traduite, vous pouvez donc utiliser ce code pour simplifier:
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
Avec l'image chargée, faisons la prédiction:
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
Cela devrait suffire. D'après mon expérience, les images utilisées lors de la formation ne sont pas suffisantes pour faire de bonnes prédictions. Je publierai un code à l'aide d'autres jeux de données qui amélioreront mes résultats ultérieurement si nécessaire.
Répondre aux questions liées:
C'est une technique utilisée pour améliorer la classification des séquences. Le document original prouve qu'il améliore les résultats de la découverte de ce qui est dit en audio. Dans ce cas, c'est une séquence de caractères. L'explication est un peu compliquée mais vous pouvez en trouver un bon ici.
Je ne suis pas sûr, mais vous pouvez jeter un coup d'œil au mécanisme d'attention dans les réseaux de neurones. Je n'ai plus aucun lien, mais je sais que cela pourrait être le cas.
OpenCV implémente les régions extrêmes à stabilité maximale (connues sous le nom de MSER). J'aime beaucoup les résultats de cet algorithme, il est rapide et était assez bon pour moi quand j'en avais besoin.
Comme je l'ai déjà dit, je publierai bientôt un code. Lorsque je le ferai, je modifierai la question avec le référentiel, mais j'estime que les informations fournies sont suffisantes pour que l'exemple soit exécuté.
Maintenant, j'ai un model.h5. Et après?
Tout d'abord, je dois dire que le model.h5
contient les poids de votre réseau. Si vous souhaitez enregistrer le architecture de votre réseau, vous devez également l'enregistrer sous la forme d'une json
comme dans l'exemple suivant:
model_json = model_json = model.to_json()
with open("model_Arch.json", "w") as json_file:
json_file.write(model_json)
Maintenant, une fois que vous avez votre modèle et ses poids, vous pouvez les charger à la demande en procédant comme suit:
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"])
Ensuite, avec ce loaded_module
, vous pouvez continuer à prédire la classification de certaines entrées comme ceci:
prediction = loaded_model.predict(some_input, batch_size=20, verbose=0)
Ce qui retournera le classement de cette entrée.
À propos des questions secondaires:
Dans ce qui suit, nous nous référons à la tâche d'étiquetage un - séquences de données segmentées en tant que classification temporelle (Kadous, 2002), et à notre utilisation des RNN à cette fin. poser comme classification temporelle connexionniste (CTC).
Keras
que vous utilisez, comme nous pouvons le constater à partir de cela git :Cet exemple utilise une pile convolutional suivie d'une pile récurrente et une fonction logloss CTC pour effectuer la reconnaissance optique de caractères d'images de texte générées.
Vous pouvez vérifier this tutoriel qui est lié à ce que vous faites et où ils expliquent également davantage les réseaux de neurones convolutionnels.
Edit: L'erreur que vous obtenez est due au fait qu'il est attendu plus de paramètres au lieu de 1, à partir des keras docs nous pouvons voir:
predict(self, x, batch_size=32, verbose=0)
Lève ValueError: en cas de discordance entre les données d'entrée fournies et les attentes du modèle, ou si un modèle avec état reçoit un nombre d'échantillons différent de la taille du lot.