Привет, Хабр! Сегодня специально к старту нового потока курса по Maсhine Learning делимся с вами постом, автор которого создаёт устройство преобразования текста в речь. Такой механизм преобразования текста в речь (TTS) — ключевой элемент систем, которые стремятся сформировать естественное взаимодействие между людьми и машинами на основе встроенных устройств. Встроенные устройства могут, например, помочь людям с нарушениями зрения читать знаки, буквы и документы. В частности, устройство может, используя оптическое распознавание символов, дать понять пользователю, что видно на изображении. Впрочем, приступим к крафту…
Приложения TTS уже много лет доступны на настольных компьютерах и широко используются на большинстве современных смартфонов и мобильных устройств. Такие приложения можно найти среди средств специальных возможностей в операционной системе, кроме того, широко применяются для чтения с экрана, пользовательских оповещений и многого другого.
Обычно такие системы начинаются с некоторого машиночитаемого текста. Что делать, если у вас нет готового источника текста для документа, браузера или приложения? Программное обеспечение для оптического распознавания символов (OCR) может преобразовывать отсканированные изображения в текст. В контексте приложения TTS это глифы — отдельные символы. Программное обеспечение OCR само по себе занимается только точным извлечением цифр и букв.
Для точного обнаружения текста в реальном времени — распознавания наборов глифов как произносимых слов — можно обратиться к методам глубокого обучения ИИ. В этом случае для распознавания слов в тексте, захваченном при оптическом распознавании символов, можно было бы использовать рекуррентную нейронную сеть (РНС). А что, если бы это можно было сделать на встроенном устройстве, более лёгком и компактном, чем даже смартфон?
Такое лёгкое, мощное TTS-устройство может помочь людям с нарушениями зрения. Его можно встроить в защищённые от неумелого обращения устройства для повышения грамотности или обработки рассказов и найти ему многие другие применения.
В этой статье я покажу, как это сделать с помощью TensorFlow, OpenCV, Festival и Raspberry Pi. Для оптического распознавания текста я буду использовать платформу машинного обучения TensorFlow вместе с предварительно обученной моделью Keras-OCR. Библиотека OpenCV будет использоваться для захвата изображений с веб-камеры. Наконец, в качестве TTS-модуля будет выступать система синтеза речи Festival. Затем всё соединим, чтобы создать приложение на Python для Raspberry Pi.
Попутно я расскажу, как работают типичные OCR-модели и как дополнительно оптимизировать решение с помощью TensorFlow Lite, набора инструментов для запуска оптимизированных моделей TensorFlow в ограниченных средах, таких как встраиваемые устройства и устройства Интернета вещей. Полный исходный код, представленный здесь, доступен на моей странице GitHub.
Начало работы
Во-первых, чтобы создать устройство и приложение для этого туториала, понадобится Raspberry Pi. Для этого примера подойдут версии 2, 3 или 4. Вы также можете использовать собственный компьютер для разработки (мы тестировали код для Python 3.7).
Необходимо установить два пакета: tensorflow (2.1.0) и keras_ocr (0.7.1). Вот несколько полезных ссылок:
- keras-ocr
- Building TensorFlow OCR Systems: Key Approaches and Tutorials
- Преобразование TensorFlow RNN в TensorFlow Lite
OCR с помощью рекуррентных нейронных сетей
Здесь для распознавания текста на изображениях я использую пакет keras_ocr. Этот пакет основан на платформе TensorFlow и свёрточной нейронной сети, которая первоначально была опубликована в качестве примера OCR на веб-сайте Keras.
Архитектуру сети можно разделить на три важных этапа. На первом берут входное изображение, а затем извлекают элементы, используя несколько свёрточных слоёв. Эти слои разделяют входное изображение по горизонтали. Для каждой части эти слои определяют набор элементов столбцов изображения. Данная последовательность элементов столбцов используется на втором этапе рекуррентными слоями.
Рекуррентные нейронные сети (РНС) обычно состоят из слоёв долгой краткосрочной памяти (LTSM). Долгая краткосрочная память произвела революцию во многих применениях ИИ, включая распознавание речи, создание субтитров к изображениям и анализ временных рядов. OCR-модели используют РНС для создания так называемой матрицы вероятностей символов. Эта матрица определяет степень уверенности в том, что заданный символ находится в конкретной части входного изображения.
Таким образом, на последнем этапе эта матрица используется для декодирования текста на изображении. Обычно люди используют алгоритм классификации по рейтингу (Connectionist Temporal Classification, CTC). CTC стремится преобразовать матрицу в осмысленное слово или последовательность таких слов. Такое преобразование – не тривиальная задача, так как в соседних частях изображения могут быть найдены одинаковые символы. Кроме того, некоторые входные части могут не содержать символов.
Хотя OCR-системы на основе РНС эффективны, пытаясь внедрить их в свои проекты, можно столкнуться с множеством проблем. В идеале необходимо выполнить обучение преобразованию, чтобы настроить модель в соответствие со своими данными. Затем модель преобразуется в формат TensorFlow Lite, чтобы оптимизировать для вывода на оконечное устройство. Такой подход оказался успешным в мобильных приложениях компьютерного зрения. Например, многие предварительно обученные сети MobileNet эффективно классифицируют изображения на мобильных устройствах и устройствах Интернета вещей.
Однако TensorFlow Lite представляет собой подмножество TensorFlow, и поэтому в настоящее время поддерживается не каждая операция. Эта несовместимость становится проблемой, когда необходимо выполнить оптическое распознавание символов, подобное тому, что включено в пакет keras-ocr на устройстве Интернета вещей. Список возможных решений предоставлен на официальном сайте TensorFlow.
В этой статье я покажу, как использовать модель TensorFlow, поскольку двунаправленные слои LSTM (используемые в keras-ocr) еще не поддерживаются в TensorFlow Lite.
Предварительно обученная OCR-модель
Для начала я написал тестовый скрипт (ocr.py), который показывает, как использовать модель нейронной сети из keras-ocr:
# Imports
import keras_ocr
import helpers
# Prepare OCR recognizer
recognizer = keras_ocr.recognition.Recognizer()
# Load images and their labels
dataset_folder = 'Dataset'
image_file_filter = '*.jpg'
images_with_labels = helpers.load_images_from_folder(
dataset_folder, image_file_filter)
# Perform OCR recognition on the input images
predicted_labels = []
for image_with_label in images_with_labels:
predicted_labels.append(recognizer.recognize(image_with_label[0]))
# Display results
rows = 4
cols = 2
font_size = 14
helpers.plot_results(images_with_labels, predicted_labels, rows, cols, font_size)
Этот скрипт создаёт экземпляр объекта Recognizer на основе модуля keras_ocr.recognition. Затем скрипт загружает изображения и их метки из прикреплённого набора тестовых данных (папка Dataset). Этот набор данных содержит восемь случайно выбранных изображений из набора синтетических слов (Synth90k). Затем скрипт запускает оптическое распознавание символов на каждом изображении этого набора данных, а затем отображает результаты прогнозирования.
Для загрузки изображений и их меток я использую функцию load_images_from_folder, которую я реализовал в модуле helpers. Этот метод предполагает два параметра: путь к папке с изображениями и фильтр. Здесь я предполагаю, что изображения находятся в подпапке Dataset, и я читаю все изображения в формате JPEG (с расширением имени файла .jpg).
В наборе данных Synth90k каждое имя файла изображения содержит метку изображения между символами подчёркивания. Например: 199_pulpiest_61190.jpg. Таким образом, чтобы получить метку изображения, функция load_images_from_folder разделяет имя файла по символу подчёркивания, а затем берёт первый элемент полученной коллекции строк. Также обратите внимание, что функция load_images_from_folder возвращает массив кортежей. Каждый элемент такого массива содержит изображение и соответствующую метку. По этой причине я передаю обработчику OCR только первый элемент этого кортежа.
Для распознавания я использую метод распознавания объекта Recognizer. Этот метод возвращает прогнозируемую метку, которую я сохраняю в коллекции predicted_labels.
Наконец, я передаю коллекцию прогнозируемых меток, изображений и исходных меток другой вспомогательной функции, plot_results, которая отображает изображения в прямоугольной сетке размера «строки x столбцы». Внешний вид сетки можно изменить, изменив соответствующие переменные.
Камера
После тестирования OCR-модели я реализовал класс camera. В этом классе используется библиотека OpenCV, которая была установлена вместе с модулем keras-ocr. OpenCV предоставляет собой удобный программный интерфейс для доступа к камере. В явном виде вы сначала инициализируете объект VideoCapture, а затем вызываете его метод чтения (read), чтобы получить изображение с камеры.
import cv2 as opencv
class camera(object):
def __init__(self):
# Initialize the camera capture
self.camera_capture = opencv.VideoCapture(0)
def capture_frame(self, ignore_first_frame):
# Get frame, ignore the first one if needed
if(ignore_first_frame):
self.camera_capture.read()
(capture_status, current_camera_frame) = self.camera_capture.read()
# Verify capture status
if(capture_status):
return current_camera_frame
else:
# Print error to the console
print('Capture error')
В этом коде я создал объект VideoCapture в инициализаторе класса camera. Я передаю объекту VideoCapture значение 0, чтобы указать на камеру системы по умолчанию. Затем я сохраняю полученный объект в поле camera_capture класса camera.
Чтобы получать изображения с камеры, я реализовал метод capture_frame. У него есть дополнительный параметр, ignore_first_frame. Когда значение этого параметра равно True, я дважды вызываю метод caper_capture.read, но игнорирую результат первого вызова. Смысл этой операции заключается в том, что первый кадр, возвращаемый моей камерой, обычно пуст.
Второй вызов метода read дает статус захвата и кадр. Если сбор данных был успешным (capture_status = True), я возвращаю кадр камеры. В противном случае я печатаю строку «Ошибка захвата».
Преобразование текста в речь
Последний элемент данного приложения – TTS-модуль. Было решено использовать здесь систему Festival, потому что она может работать в автономном режиме. Другие возможные подходы к TTS хорошо описаны в статье Adafruit Speech Synthesis on the Raspberry Pi (Синтез речи на Raspberry Pi).
Чтобы установить Festival на Raspberry Pi, выполните следующую команду:
sudo apt-get install festival -y
Убедиться в том, что всё работает правильно, можно, введя следующую команду:
echo "Hello, Arm" | Festival –tts
Ваш Raspberry Pi должен произнести: «Hello, Arm».
Festival предоставляет API-интерфейс. Однако для простоты было решено взаимодействовать с Festival посредством командной строки. С этой целью модуль helpers был дополнен ещё одним методом:
def say_text(text):
os.system('echo ' + text + ' | festival --tts')
Собираем всё вместе
Наконец, мы можем собрать всё вместе. Я сделал это в скрипте main.py:
import keras_ocr
import camera as cam
import helpers
if __name__ == "__main__":
# Prepare recognizer
recognizer = keras_ocr.recognition.Recognizer()
# Get image from the camera
camera = cam.camera()
# Ignore the first frame, which is typically blank on my machine
image = camera.capture_frame(True)
# Perform recognition
label = recognizer.recognize(image)
# Perform TTS (speak label)
helpers.say_text('The recognition result is: ' + label)
Сначала я создаю OCR-распознаватель. Затем я создаю объект Camera и считываю кадр с веб-камеры по умолчанию. Изображение передаётся распознавателю, а полученная в результате метка произносится вспомогательным TTS-модулем.
Заключение
Итак, мы создали надёжную систему, которая способна оптически распознавать символы с использованием глубокого обучения, а затем передавать результаты пользователям посредством механизма преобразования текста в речь. Мы использовали пакет keras-OCR с предварительным обучением.
В более сложном сценарии распознаванию текста может предшествовать обнаружение текста. Сначала на изображении обнаруживаются строки текста, а затем распознаётся каждая из них. Для этого потребуются только возможности пакета keras-ocr по обнаружению текста. Это было показано в данной версии реализации Keras CRNN и опубликованной модели обнаружения текста CRAFT Фаусто Моралесом.
Расширяя указанное выше приложение функцией обнаружения текста, можно создать систему Интернета вещей, которая поддерживает РНС и выполняет OCR, чтобы помочь людям с нарушениями зрения читать меню в ресторанах или документы в государственных учреждениях. Более того, такое приложение с поддержкой службы переводов могло бы служить автоматическим переводчиком.
Хочется завершить этот материал цитатой третьего закона Артура Кларка:
Любая достаточно развитая технология неотличима от магии.
Если следовать ему — то можно спокойно сказать, что у нас в SkillFactory мы обучаем людей настоящей магии, просто она называется data science и machine learning.
Другие профессии и курсы
ПРОФЕССИИ
КУРСЫ
- Профессия Java-разработчик
- Профессия QA-инженер на JAVA
- Профессия Frontend-разработчик
- Профессия Этичный хакер
- Профессия C++ разработчик
- Профессия Разработчик игр на Unity
- Профессия Веб-разработчик
- Профессия iOS-разработчик с нуля
- Профессия Android-разработчик с нуля
КУРСЫ
- Курс по Machine Learning
- Курс «Математика и Machine Learning для Data Science»
- Курс «Machine Learning и Deep Learning»
- Курс по Data Engineering
- Курс «Python для веб-разработки»
- Курс «Алгоритмы и структуры данных»
- Курс по аналитике данных
- Курс по DevOps