python - recognition - supervisely dataset
¿Cómo puedo usar el ejemplo de Keras OCR? (3)
Encontré examples/image_ocr.py
que parece ser para OCR. Por lo tanto, debería ser posible dar una imagen al modelo y recibir texto. Sin embargo, no tengo idea de cómo hacerlo. ¿Cómo alimentar el modelo con una nueva imagen? ¿Qué tipo de preprocesamiento es necesario?
Lo que hice
Instalando las dependencias:
- Instale
cairocffi
:sudo apt-get install python-cairocffi
- Instala
editdistance
:sudo -H pip install editdistance
- Cambie el
train
para devolver el modelo y guardar el modelo entrenado. - Ejecuta el script para entrenar al modelo.
Ahora tengo un model.h5
. ¿Que sigue?
Consulte https://github.com/MartinThoma/algorithms/tree/master/ML/ocr/keras para ver mi código actual. Sé cómo cargar el modelo (ver más abajo) y esto parece funcionar. El problema es que no sé cómo alimentar nuevos escaneos de imágenes con texto al modelo.
Preguntas secundarias relacionadas
- ¿Qué es CTC? ¿ Clasificación temporal conexista ?
- ¿Existen algoritmos que detecten de forma fiable la rotación de un documento?
- ¿Hay algoritmos que detecten de forma confiable líneas / bloques de texto / tablas / imágenes (por lo tanto, hacen una segmentación razonable)? ¿Supongo que la detección de bordes con histogramas de suavizado y de línea ya funciona razonablemente bien para eso?
Lo que intenté
#!/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))
esto da
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)
Ahora tengo un modelo.h5. ¿Que sigue?
Primero debo comentar que el model.h5
contiene los pesos de su red, si desea guardar la arquitectura de su red también debe guardarla como un json
como este ejemplo:
model_json = model_json = model.to_json()
with open("model_arch.json", "w") as json_file:
json_file.write(model_json)
Ahora, una vez que tenga su modelo y sus pesos, puede cargarlos a pedido haciendo lo siguiente:
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"])
Luego, con ese loaded_module
puede proceder a predecir la clasificación de ciertas entradas como esta:
prediction = loaded_model.predict(some_input, batch_size=20, verbose=0)
Lo que devolverá la clasificación de esa entrada.
Sobre las preguntas secundarias:
- CTC parece ser un término que están definiendo en el documento al que hace referencia, que extrae de él dice:
En lo que sigue, nos referimos a la tarea de etiquetar secuencias de datos no segmentadas como clasificación temporal (Kadous, 2002), y a nuestro uso de RNN para este propósito como clasificación temporal conexionista ( CTC ).
- Para compensar la rotación de un documento, imágenes o similar, puede generar más datos de su actual mediante la aplicación de dichas transformaciones (consulte this publicación de blog que explica una forma de hacerlo), o puede usar un neuronal convolucional. Enfoque de red , que también es en realidad lo que hace el ejemplo de
Keras
que está utilizando, como podemos ver en ese examples/image_ocr.py :
Este ejemplo utiliza una pila convolucional seguida de una pila recurrente y una función de pérdida de registros CTC para realizar el reconocimiento óptico de caracteres de las imágenes de texto generadas.
Puede consultar this tutorial relacionado con lo que está haciendo y dónde también explican más sobre las redes neuronales convolucionales.
- Bueno, esta es una pregunta amplia, pero para detectar líneas puede usar la Transformada de línea de Hough , o la Detección de borde de Canny puede ser una buena opción.
Edit: El error que está recibiendo es porque se espera que haya más parámetros en lugar de 1, de los docs Keras que podemos ver:
predict(self, x, batch_size=32, verbose=0)
Aumenta ValueError: en caso de discrepancia entre los datos de entrada proporcionados y las expectativas del modelo, o en caso de que un modelo con estado reciba una cantidad de muestras que no sea un múltiplo del tamaño del lote.
Aquí, creaste un modelo que necesita 4 entradas:
model = Model(inputs=[input_data, labels, input_length, label_length], outputs=loss_out)
Tu intento predecible, por otro lado, es cargar solo una imagen.
De ahí el mensaje: el modelo espera 4 matrices, pero solo recibió una matriz
Desde su código, las entradas necesarias son:
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'')
El código original y tu trabajo de entrenamiento porque están usando TextImageGenerator
. Este generador se preocupa por darle las cuatro entradas necesarias para el modelo.
Entonces, lo que tienes que hacer es predecir usando el generador. Como tiene el método fit_generator()
para entrenar con el generador, también tiene el método predict_generator() para predecir con el generador.
Ahora, para una respuesta completa y una solución, tendría que estudiar su generador y ver cómo funciona (lo que me llevaría algo de tiempo). Pero ahora que sabes lo que se debe hacer, probablemente puedas resolverlo.
Puede usar el generador tal como está y predecir una gran cantidad de datos, o puede intentar replicar un generador que produzca solo una o unas pocas imágenes con las etiquetas, la longitud y la longitud de etiqueta necesarias.
O tal vez, si es posible, simplemente cree las 3 matrices restantes manualmente, pero asegurándose de que tengan las mismas formas (excepto la primera, que es el tamaño del lote) que el generador genera.
Sin embargo, lo único que debe hacer valer es: tener 4 arreglos con las mismas formas que las salidas del generador, excepto la primera dimensión.
Bueno, intentaré contestar todo lo que pediste aquí:
Como se comentó en el código OCR, Keras no admite pérdidas con múltiples parámetros, por lo que calculó la pérdida NN en una capa lambda. ¿Qué significa esto en este caso?
La red neuronal puede parecer confusa porque utiliza 4 entradas ( [input_data, labels, input_length, label_length]
) y loss_out
como salida. Además de input_data, todo lo demás es información que se usa solo para calcular la pérdida, lo que significa que solo se usa para entrenamiento. Deseamos algo como en la línea 468 del código original:
Model(inputs=input_data, outputs=y_pred).summary()
que significa "Tengo una imagen como entrada, por favor dígame lo que está escrito aquí". Entonces, ¿cómo lograrlo?
1) Mantenga el código de entrenamiento original tal como está, realice el entrenamiento normalmente;
2) Después del entrenamiento, guarde este modelo de Model(inputs=input_data, outputs=y_pred)
en un archivo .h5 para cargarlo donde quiera;
3) Haz la predicción: si miras el código, la imagen de entrada se invierte y se traduce, de modo que puedes usar este código para facilitarlo:
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
Con la imagen cargada, vamos a hacer la predicción:
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
Esto debería ser suficiente. Desde mi experiencia, las imágenes utilizadas en el entrenamiento no son lo suficientemente buenas para hacer buenas predicciones, lanzaré un código con otros conjuntos de datos que mejoraron mis resultados más tarde si fuera necesario.
Respondiendo preguntas relacionadas:
- ¿Qué es CTC? ¿ Clasificación temporal conexista ?
Es una técnica utilizada para mejorar la clasificación de secuencias. El artículo original prueba que mejora los resultados al descubrir lo que se dice en audio. En este caso es una secuencia de caracteres. La explicación es un pequeño truco pero puedes encontrar una buena here.
- ¿Existen algoritmos que detecten de forma fiable la rotación de un documento?
No estoy seguro, pero podrías echar un vistazo al mecanismo de atención en redes neuronales. No tengo ningún buen enlace ahora, pero sé que podría ser el caso.
- ¿Hay algoritmos que detecten de forma confiable líneas / bloques de texto / tablas / imágenes (por lo tanto, hacen una segmentación razonable)? ¿Supongo que la detección de bordes con histogramas de suavizado y de línea ya funciona razonablemente bien para eso?
OpenCV implementa regiones extremas de máxima estabilidad (conocidas como MSER). Realmente me gustan los resultados de este algoritmo, es rápido y fue lo suficientemente bueno para mí cuando lo necesitaba.
Como dije antes, lanzaré un código pronto. Editaré la pregunta con el repositorio cuando lo haga, pero creo que la información aquí es suficiente para que el ejemplo se ejecute.