Подтвердить что ты не робот

Как я могу использовать пример Keras OCR?

Я нашел examples/image_ocr.py, который, как представляется, для OCR. Следовательно, должно быть возможно предоставить модели изображение и получить текст. Однако я понятия не имею, как это сделать. Как мне подать модель с новым изображением? Какая предварительная обработка необходима?

Что я сделал

Установка зависимостей:

  • Установите cairocffi: sudo apt-get install python-cairocffi
  • Установить editdistance: sudo -H pip install editdistance
  • Измените train, чтобы вернуть модель и сохранить подготовленную модель.
  • Запустите script для обучения модели.

Теперь у меня есть 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)
4b9b3361

Ответ 1

Здесь вы создали модель, которая нуждается в 4 входах:

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

Ваша попытка прогноза, с другой стороны, загружает только изображение.
Отсюда сообщение: модель ожидает 4 массива, но получает только один массив

Из вашего кода необходимые входные данные:

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. Этот генератор должен предоставить вам четыре необходимых входа для модели.

Итак, вам нужно предсказать использование генератора. Поскольку у вас есть метод fit_generator() для обучения с генератором, у вас также есть метод predict_generator() для прогнозирования с помощью генератора.


Теперь, для полного ответа и решения, мне нужно будет изучить ваш генератор и посмотреть, как он работает (что займет у меня некоторое время). Но теперь вы знаете, что нужно сделать, вы, вероятно, можете это понять.

Вы можете использовать генератор так, как есть, и прогнозировать, вероятно, огромное количество данных, или вы можете попытаться воспроизвести генератор, который даст только одно или несколько изображений с необходимыми метками, длиной и длиной метки.

Или, если возможно, просто создайте 3 оставшихся массива вручную, но убедитесь, что они имеют одинаковые формы (за исключением первого, который является размером партии), когда выходы генератора.

Единственное, что вы должны утверждать, это: иметь 4 массива с теми же формами, что и выходы генератора, за исключением первого измерения.

Ответ 2

Теперь у меня есть model.h5. Что дальше?

Сначала я должен прокомментировать, что model.h5 содержит веса вашей сети, если вы хотите сохранить архитектуру своей сети, а также сохранить ее как 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)

который вернет классификацию этого ввода.

О боковых вопросах:

  • CTC, по-видимому, является термином, который они определяют в документе, который вы указали, извлечение из него говорит:

В дальнейшем мы ссылаемся на задачу маркировки un- сегментированные последовательности данных как временная классификация (Kadous, 2002), и к нашему использованию RNN для этого изображать из себя временная классификация подключения (СТС).

  1. Чтобы компенсировать вращение документа, изображений или аналогичных данных, вы можете либо генерировать больше данных с вашего текущего, применяя такие преобразования (посмотрите это сообщение в блоге, в котором объясняется, как это сделать), или вы можете использовать Сверторная нейронная сеть, который также является тем, что использует этот пример Keras, как мы можем видеть из этого git:

В этом примере используется сверточный стек, за которым следует повторяющийся стек и функцию CTC logloss для выполнения оптического распознавания символов генерируемых текстовых изображений.

Вы можете проверить этот учебник, связанный с тем, что вы делаете, и где они также объясняют больше о сверточных нейронных сетях.

  1. Ну, это широкий вопрос, но для обнаружения строк вы можете использовать Hough Line Transform, а также Canny Edge Detection может быть хорошим вариантом.

Изменить: Ошибка, которую вы получаете, потому что ожидается больше параметров вместо 1, от keras docs мы можем видеть:

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

Повышает ValueError: в случае несоответствия между предоставленными входными данными и ожиданиями модели или в случае, если модель с состоянием принимает несколько выборок, которые не кратно размеру партии.

Ответ 3

Хорошо, я постараюсь ответить на все, что вы здесь задали:

Как указано в коде 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

Этого должно быть достаточно. По моему опыту, изображения, используемые в тренинге, недостаточно хороши для хороших прогнозов, я выпущу код, используя другие наборы данных, которые при необходимости улучшали мои результаты.

Отвечая на следующие вопросы:

Это метод, используемый для улучшения классификации последовательностей. Оригинальная статья доказывает, что она улучшает результаты при обнаружении того, что сказано в аудио. В этом случае это последовательность символов. Объяснение - это трюк, но вы можете найти здесь хорошего .

  • Существуют ли алгоритмы, которые надежно обнаруживают вращение документа?

Я не уверен, но вы можете взглянуть на механизм Attention в нейронных сетях. У меня сейчас нет хорошей ссылки, но я знаю, что это может быть так.

  • Существуют ли алгоритмы, которые надежно обнаруживают строки/текстовые блоки/таблицы/изображения (следовательно, делают разумную сегментацию)? Я думаю, что обнаружение края с помощью сглаживания и линейных гистограмм уже хорошо работает для этого?

OpenCV реализует максимально стабильные экстремальные регионы (известные как MSER). Мне очень нравятся результаты этого алгоритма, это быстро и было достаточно для меня, когда мне было нужно.

Как я уже говорил, скоро вышлю код. Когда я это сделаю, я отредактирую вопрос с репозиторием, но я верю, что информации здесь достаточно, чтобы запустить этот пример.