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

Самые продвинутые планы развития науки о данных, которые вы когда-либо видели! Поставляется с тысячами бесплатных учебных ресурсов и интеграцией ChatGPT! https://aigents.co/learn/roadmaps/intro

Если вы пришли к этой статье, то должны знать, что извлечение текста из изображений — сложная задача. Извлечение текста разных размеров, форм и ориентаций из изображений является фундаментальной проблемой во многих контекстах, особенно в системах поддержки дополненной реальности, электронной коммерции и модерации контента на платформах социальных сетей. Чтобы решить эту проблему, нам нужно точно извлечь текст из изображений.

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

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

В этом уроке я сосредоточусь только на части извлечения слов из всего конвейера OCR:

Но полезно знать о конвейере самых популярных OCR, доступных сегодня. Как я уже сказал, большинство пайплайнов содержат этап обнаружения текста и этапы распознавания текста:

  • Распознавание текста помогает определить местоположение изображения, содержащего текст. Он принимает изображение в качестве входных данных и выдает поля с координатами в качестве выходных данных;
  • Распознавание текста извлекает текст из входного изображения с помощью ограничивающих рамок, полученных на основе модели обнаружения текста. Он вводит изображение с обрезанными частями изображения, используя ограничивающие рамки из детектора, и выводит необработанный текст.

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

Но было доказано, что мы можем добиться еще лучших результатов, используя различные методы сегментации вместо детекторов. Изучение каждого символа и интервалов между символами помогает обнаруживать тексты различной формы.[1]

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

Я заметил, что при разработке различных вещей мне приходится заново реализовывать то, что я уже использовал снова и снова. Так почему бы не упростить это, создав библиотеку для хранения всего этого? С помощью этого руководства я запускаю новую библиотеку MLTU (Machine Learning Training Utilities), исходный код которой я открою на GitHub, где я сохраню весь код руководства.

Конвейер распознавания текста:

После этапа локализации текста области, содержащие текст, обрезаются и отправляются через слои CNN для извлечения признаков изображения. Эти функции позже передаются в архитектуру LSTM «многие ко многим», которая выводит вероятности softmax через словарь. Эти выходные данные на разных временных шагах передаются декодеру CTC для получения необработанного текста из изображений. Я подробно расскажу о каждом шаге в следующих разделах руководства.

Во-первых, давайте посмотрим на мою модель TensorFlow, чтобы понять, как мы связываем слои CNN со слоями LSTM. Это руководство не предназначено для начинающих, поэтому я рассмотрю только некоторые части шаг за шагом, и я опубликую здесь только часть кода, более глубокие части кода, вы можете посмотреть на моем GitHub репозиторий.

Файлы для этого урока вы можете найти по ссылке https://github.com/pythonlessons/mltu/tree/main/Tutorials/01_image_to_word. Чтобы запустить это руководство, вы должны установить мой пакет версии 0.1.3 mltu с помощью pip:

pip install mltu==0.1.3

Вот код для построения нашей модели в TensorFlow:

Я использовал принцип из моделей ResNet для создания остаточных блоков, которые помогают нашей модели лучше изучать детали. Я изменю размер всех входных изображений до 32 на 128 пикселей. С этим размером сводка нашей модели будет выглядеть следующим образом:

Это может дать вам ограниченную информацию, если вы не знакомы с TensorFlow, но идея здесь состоит в том, чтобы создать модель с правильным выводом для нашей функции потерь CTC. Для этого мы должны перейти от слоев CNN к слоям LSTM. Для этого я использовал измененный последний слой CNN, чтобы удалить одно измерение, что было бы здорово для ввода LSTM.

Чтобы сделать все правильно, мы должны убедиться, что последний слой соответствует требованиям функции потерь CTC. Здесь у меня 63; в моем наборе данных слов я знаю, что у меня есть 62 разных символа, но нам нужно увеличить его на 1 (маркер разделения). у меня тоже 256; как вы можете видеть здесь, мы должны убедиться, что это значение больше, чем максимальная длина слова в нашем наборе данных, которая в моем наборе данных равна 23. Это будет рассматриваться как интервал в нашем прогнозе; подробнее об этом позже.

Во-первых, давайте разберемся с концепцией рецептивных полей, чтобы было легче понять, как функции модели CNN переносятся в сеть LSTM.

Функции CNN для слоя LSTM:

На изображении выше показано, что изображение (размер 32x128) отправляется через сверточные слои. Слои спроектированы так, что в результате мы получаем карты признаков формы (None, 8, 32, 64). «Нет» — это размер пакета, который может принимать любое значение.

(Нет, 8, 32, 64) можно легко преобразовать в (Нет, 256, 64), а 256 соответствует количеству временных шагов, а 64 — не что иное, как количество признаков на каждом временном шаге. Это можно связать с обучением любой модели LSTM с встраиванием слов, и форма ввода обычно (batch_size, no_time_steps, word_embedding_dimension).

Позже эти карты функций передаются в модель LSTM, как показано выше. Возможно, сейчас вы думаете, что модели LSTM, как известно, работают с последовательными данными и с последовательностью карт объектов. Но идея здесь в том, что слои CNN изменяют последовательности, изменяя представление своими слоями.

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

Что такое потеря CTC и почему мы ее используем:

Это обширная тема, для которой я мог бы создать еще один учебник с объяснением. Но поскольку статей о потере СТС уже достаточно, я упомяну только всю идею.

Конечно, мы могли бы создать набор данных с изображениями текстовых строк, а затем указать соответствующий символ для каждой горизонтальной позиции изображения. Мы могли бы научить NN выводить оценку символа для каждой горизонтальной позиции, используя категориальную кросс-энтропию в качестве потерь. Однако есть несколько проблем с этим решением:

  • Аннотирование набора данных на уровне символов занимает очень много времени (и утомительно);
  • Мы получаем только оценки персонажей и нуждаемся в дальнейшей обработке, чтобы получить окончательный текст. Нам нужно удалить все повторяющиеся символы. Один символ может охватывать несколько позиций по горизонтали; Например, мы можем получить «Heeloo», потому что «е» или «е» широкие. Но что, если бы распознанный текст был «Хорошим»? Тогда удаление всех повторяющихся «о» даст нам неверный результат. Как с этим справиться?
  • Упомянутая потеря CTC также подходит для приложений преобразования речи в текст. Звуковой сигнал и соответствующий текст доступны в качестве обучающих данных, и нет отображения, например, первый символ произносится в течение «x» миллисекунд или от «x1» до «x2» миллисекунд произносится символ «z». Было бы невозможно аннотировать звуковые слова каждого персонажа во временном ряду.

CTC решает для нас все эти проблемы:

  1. При обучении модели с помощью функции потерь CTC нам нужно знать только точное слово на изображении. Поэтому мы игнорируем как положение, так и ширину символов в спектрограмме изображения или звука;
  2. Распознанный текст не требует дальнейшей обработки.

Чтобы различать два последовательных токена и повторяющиеся токены, используется токен «разделения», как я уже упоминал ранее. Лучший способ понять, как это работает, — представить, что мы работаем со звуковыми данными, которые произносят слово «Дом»:

Мы используем умную схему кодирования, чтобы решить проблему повторяющихся символов. При кодировании текста мы можем в любом месте вставить произвольное количество пробелов, которые будут удалены при его декодировании. Кроме того, мы можем повторять каждый символ столько раз, сколько захотим. Однако нам нужно вставить пробел между повторяющимися символами, например «Привет».

Мы можем создать несколько примеров:

  • От слова Home → «Х-о-м-е», «Х-ооо-м-е-е», «-ХХХХХХо-м-е» и т. д.;
  • от слова Good → «Б-о-о-д», «ГГГо-од», «Г-оооо-оооо-дддд» и т. д.;

Как вы видите, этот метод также позволяет нам легко создавать различные выравнивания точного текста, например, «H-o-m-e», «H-ooo-m-ee», «-HHHHHHo-m-e» представляют фактический текст (Home), но с разными выравниваниями к изображению. Нейронная сеть обучена выводить зашифрованный текст (закодированный в выводе NN softmax).

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

  1. Он вычисляет лучший путь на основе наиболее вероятного символа за временной шаг;
  2. Он отменяет кодировку, удаляя повторяющиеся символы и все пробелы из пути. То, что осталось, представляет собой распознанный текст!

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

Код потери CTC:

Вернемся к части кодирования. Я буду кодировать только некоторые математические вычисления, рассмотренные ранее. Мы можем использовать функцию «keras.backend.ctc_batch_cost» для расчета потери CTC, и ниже приведен код для того же, где определен пользовательский слой CTC, который используется как в части обучения, так и в части оценки. Чтобы использовать его в качестве функции потерь, нам нужно построить объект наследования для этого:

Теперь, когда мы строим и компилируем нашу модель, мы используем ее как обычную функцию потерь:

Вот и все; наша модель готова для загрузки изображений и аннотаций и для обучения. Но вы можете заметить, что я использую некоторые показатели CWER. Это верно! При обучении моделей распознавания слов, речи и предложений не рекомендуется полагаться только на потерю проверки. Лучше знать, сколько ошибок делает наша модель в наборе данных проверки. Таким образом, мы сможем улучшить архитектуру нашей модели для достижения лучших результатов.

Чтобы не тратить наши ресурсы впустую, я реализовал его как метрику TensorFlow, чтобы запускать ее по мере обучения.

Частота ошибок символов (CER) измеряет точность транскрипции или перевода, обычно используемого при распознавании речи или обработке естественного языка. Он сравнивает наземную транскрипцию или перевод (правильную версию) с фактической транскрипцией или переводом, произведенным системой, и вычисляет процент ошибок в выводе.

Чтобы рассчитать CER, мы сначала подсчитываем общее количество символов в исходной транскрипции или переводе, включая пробелы. Затем мы подсчитываем количество вставок, замен и удалений символов, которые необходимы для преобразования выходной транскрипции или перевода в истину. Затем CER рассчитывается как сумма этих ошибок, деленная на общее количество символов, выраженное в процентах.

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

Например, предположим, что у нас есть следующая транскрипция истинной истины: «Это тестовое предложение».

И предположим, что у нас есть следующая выходная транскрипция, созданная системой распознавания речи: «Это тестовое предложение».

В этом случае выходная транскрипция совпадает с исходной, поэтому ошибок нет. CER будет 0%.

С другой стороны, если бы у нас была следующая выходная транскрипция: «Это тестовое предложение».

Ошибка в одном символе (дополнительная буква «e» в конце предложения), поэтому CER составит 1/23 = 4,3%.

Обратные вызовы для обучения:

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

Я склонен использовать обратные вызовы почти во всех моих обучаемых моделях».

Мы можем насчитать шесть различных обратных вызовов, которые говорят сами за себя, и, как вы можете видеть, вместо отслеживания потери проверки я следую проверке CER («val_CER»)!

Большинство из нас обучают эти модели развертыванию там, где мы не хотим использовать установленный TensorFlow. Итак, я создал обратный вызов «Model2onxx», который в конце обучения конвертирует модель в формат .onnx, который можно использовать без этой огромной библиотеки TensorFlow, и обычно он работает в два раза быстрее!

Подготовка набора данных:

Это еще одна обширная тема, которую я постараюсь быстро осветить, упомянув только самые важные аспекты. Итак, для этого урока мы создаем модель для распознавания текста из простых текстовых изображений. Я нашел обширную базу данных Данные распознавания текста, которая позволяет нам это сделать.

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

Если вы следуете моему руководству, загрузите этот набор данных размером 10 ГБ и распакуйте его в папку «Datasets/90kDICT32px».

С помощью следующего кода мы прочитаем все пути для нашего набора данных для обучения и проверки:

Это простой цикл for, который в каждом цикле считывает путь к файлу и извлекает фактическую метку слова. Также мы собираем словарный запас и максимально возможную длину слова. Эти два параметра позже используются для построения подходящей модели для нашей задачи.

Хорошо, далее мы создадим наших поставщиков данных для обучения и проверки, используя базовую модель DataProvider из моего пакета «mltu»:

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

Специально для задачи преобразования изображения в текст я использую простой препроцессор OpenCV «ImageReader». Затем я использую преобразователи для стандартизации наших изображений и меток; во-первых, мы изменяем размеры всех изображений до одинакового размера. Затем мы преобразуем строковые метки в индексы, поскольку наша модель не понимает строк; это должны быть числовые значения. И на последнем шаге мы дополняем наши слова неизвестными значениями, чтобы наш ввод соответствовал точным требованиям к форме.

Обучение модели:

Мы подошли к моменту, когда наконец обучили нашу модель. Поскольку для завершения даже одной эпохи на моем графическом процессоре 1080TI требуется больше часа, я не показываю весь процесс обучения. Но из-за наших отличных обратных вызовов мы можем проверить наши журналы обучения и журналы Tensorboard.

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

Теперь я могу открыть панель инструментов Tensorboard с путем к журналам моей обученной модели, выполнив следующую команду в терминале:

tensorboard --logdir Models/1_image_to_word/202211270035/logs

Поскольку наш набор данных огромен, большинство вещей, которые он изучает в своей первой эпохе, поэтому, когда он закончит первую эпоху обучения, наш CER даст нам довольно хорошие результаты:

Как мы видим, в каждую эпоху скорость нашего CER уменьшается. Это то, что мы ожидаем!

Когда наш процесс обучения был завершен, были сохранены две модели: модель Keras по умолчанию .h5 и модель формата .onnx. Итак, давайте проведем вывод по нашей сохраненной модели.

Тестирование модели:

В настоящее время все знают, как выполнять вывод по модели Keras «.h5» по умолчанию, но обычно это не лучший выбор, когда мы хотим где-то развернуть наши решения. Именно по этой причине я конвертирую модель в формат .onnx. Это облегченный формат модели, который обычно работает быстрее и не требует установки огромных библиотек.

Во-первых, я создаю объект, который будет загружать модель «.onnx» и выполнять всю предварительную и постобработку данных. Для этого мой объект наследуется от объекта OnnxInferenceModel:

Единственное, что нам нужно будет передать в ImageToWordModel при создании объекта, — это словарь. Вот почему важно сериализовать и сохранять конфигурации при обучении модели.

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

Я могу выполнить это для 1000 примеров и получу следующие результаты:

Average CER: 0.07760155677655678

Это означает, что в пределах 1000 примеров моя модель имеет 7% CER; это очень хорошо, зная, что наш набор данных для обучения и проверки может быть лучше!

Вот несколько примеров:

Я показал здесь только несколько примеров. Вы можете проверить это на гораздо большем количестве примеров.

Заключение:

В заключение, извлечение текста из изображений — сложная задача, важная в различных контекстах, включая дополненную реальность, электронную коммерцию и модерацию контента. Существует два основных подхода к извлечению текста из изображений: использование детекторов текста или методов сегментации для локализации текста и обучение одной модели, которая выполняет обнаружение и распознавание текста. В этом руководстве основное внимание уделяется последнему подходу, сочетающему слои CNN и LSTM с функцией потери CTC для извлечения текста из изображений. В учебнике также представлена ​​новая библиотека с открытым исходным кодом под названием MLTU (Machine Learning Training Utilities), которая будет использоваться для хранения кода из будущих руководств.

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

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

Я надеюсь, что это руководство было полезным для вас, и вы можете использовать мой код или даже мою новую библиотеку «mltu» для своего проекта. Увидимся в следующем уроке!

Модель, которую я тренировал, можно скачать по этой ссылке (поместить в папку Модели). Веселиться!

Ссылка:

[1] Пэк, Ёнмин и др. «Распознавание области символов для обнаружения текста. Материалы конференции IEEE/CVF по компьютерному зрению и распознаванию образов. 2019.»

Первоначально опубликовано на https://pylessons.com/ctc-text-recognition