Как стать автором
Обновить

Программа для распознавания текста и перевода AssistAnt

Время на прочтение5 мин
Количество просмотров5.9K

Хорош ли ваш английский? Мой – нет. По крайней мере точно недостаточно, чтобы обходиться без переводчика в играх.
Недолгий поиск бесплатных программ в интернете мне не помог. Возможно, я просто плохо искал :) Но когда я поймал себя на мысли, что сейчас возьму в руки сотовый и буду переводить экран с помощью камеры, я понял, что пора спасаться. И путь к спасению - сделать переводчик самому.
Я нашел широко известную в узких кругах программу распознавания текста Tesseract OCR и свободное API для Google Translate. В результате получилась программа, которая может на лету переводить выделенную надпись на экране. Выглядит это примерно так: вы зажимаете горячую клавишу Win+Alt и прямоугольной областью выделяете часть изображения, где находится непонятный текст. Область выделяется, только пока зажата горячая клавиша. Вуаля – перед вами перевод во всплывающей подсказке! Выглядит это примерно вот так:

Можно распознать и с картинки в буфере обмена через меню иконки в трее:

Ссылки:
Собственно проект AssistAnt https://github.com/AantCoder/AssistAnt/releases/latest
Компонент распознавания текста Tesseract OCR https://github.com/tesseract-ocr
Переводчик Google Translate Rest API (Free) с помощью GTranslatorAPI https://github.com/franck-gaspoz/GTranslatorAPI
Если совсем коротко, то это всё :) Некоторые нюансы и альтернативные способы использования есть в пункте приложения «О программе». Дальше опишу технические сложности, с которыми столкнулся в процессе разработки для заинтересовавшихся.

Горячие клавиши всё портят

Какую клавишу на клавиатуре ни возьми: или занята, или неудобна. Если кажется, что обнаружил свободную и удобную, то значит просто не нашел программу, которая уже её использует. Поэтому я не стал биндить горячую клавишу, а решил лишь отлавливать нажатие на Win+Alt. По моему разумению, ни одна программа не использует две эти клавиши отдельно от остальных. Разумеется, если вместе с Win+Alt нажать ещё что-то третье, то мой переводчик не отреагирует.
Такая комбинация хорошо выполняет свою цель: позволяет выделить область на экране, минимально влияя на активную программу. Правда, есть один минус, опишу его в следующем пункте.

Перевод из всплывающих подсказок

В попытке выделить текст двигаем мышкой – она покидает элемент интерфейса – всплывающая подсказка исчезает. Это заставило меня сделать стандартную систему, как при вырезании скриншотов. Если нажать Win+Alt и отпустить, не двигая мышкой, то создается скрин всего экрана, который открывается поверх всех окон. И уже в нем предлагается выделить область для перевода, как при стандартной комбинации Win+Shift+S (правда, реализовано это не столь красиво). Дальше всё как в первом способе: выдается всплывающая подсказка с переводом, за исключением того, что выделенное изображение помещается в буфер обмена (зачем? просто могу).

Плохой разбор мелкого текста

Оказалось, что Tesseract (может быть и все подобные?) плохо распознает текст с высотой строки меньше 20 пикселей. Особенно, когда он с тенью или размытием. Эффекты безусловно очень помогают прочесть надпись человеку, но нейронке не нравятся.
Помучавшись несколько вечеров, накидал сложную комбинацию простых фильтров изображений. После этого мелкий текст иногда стал читаться даже лучше, чем текст среднего размера. Из-за этого решил добавить повторное распознавание без фильтров, если качество распознания было меньше 90%. В конечном итоге вышло вот так:
Первый прогон (хорош для самого мелкого текста):

  • Увеличиваем картинку в 2 раза (красиво, с «высококачественной бикубической интерполяцией»),

  • Переводим в градации серого,

  • Увеличиваем изображение, добавляя пустую рамку в 7 пикселей и пустое пространство справа на 200 (так лучше распознаются короткие слова. Видимо, в вытянутом изображении ожидается меньшее количество строк),

  • Увеличиваем резкость,

  • Увеличиваем картинку ещё в 2 раза,

  • Ещё раз увеличиваем резкость (двойной подход немного уменьшает артефакты).

Второй прогон (обработка попроще, если качество распознания с первого прогона меньше 90%):

  • Увеличиваем картинку в 3 раза,

  • Переводим в градации серого,

  • Увеличиваем резкость

Третий прогон (вдруг при обесцвечивании текст стало не видно, или резкость ухудшает распознаваемость текста):

  • Увеличиваем картинку в 3 раза.

Медленно работает

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

  • Если размер изображения больше миллиона пикселей (ширина*высота), то не обрабатываем его, а отправляем на распознавание как есть.

  • Если изображение больше 20000 пикселей, то увеличиваем только в 3 раза. В этом случае во всплывающей подсказке после % появляется *.

  • Если размер изображения меньше указанного в предыдущем пункте, то применяем все описанные выше фильтры. В этом случае во всплывающей подсказке после % появляется * с числом прогонов, которые понадобились, чтобы добиться качества распознавания выше 90%.

Утечка памяти

Иногда проще убить, чем прокормить. Так я и поступил, не желая возиться с утечкой памяти в чужих библиотеках (правда же в чужих?..) Теперь, спустя пять минут с момента последнего обращения к переводчику, программа автоматически перезапустится, и уж точно освободит всю память. Если же её будут интенсивно использовать на слабых компьютерах, то должен помочь перезапуск после 20 переводов: программа ждет 30 секунд после последней активации (чтобы дать прочитать текст) и перезапускается. Надеюсь, это будет достаточно незаметно для пользователя.

Переносы строк

Спасибо комментаторам @aborouhin, @danilasar и другим – открыли мне глаза на ухудшение качества перевода из-за переноса строк. Google Translate видя текст на разных строках воспринимает его как отдельные предложения. Первая мысль: отказаться от Google Translate удалить переносы строк. Но тогда переводчик может начать воспринимать, например, списки как единое предложение. А даже если и нет, то мы теряем форматирование текста.
Вдоволь помучив переводчик появилось такое решение: на место переноса вставить спец. разделитель, который переводчик не может игнорировать, но и предложение не разрывает.
Это решение дало хороший результат, но оно не идеальное, так как переводчик не может свободно менять слова в предложении.

Вот пример старого варианта с двумя строками:
Okay—now we're going
to check your reflexes.
Хорошо, теперь мы собираемся
чтобы проверить свои рефлексы.

Пример хорошего перевода:
Okay—now we're going to check your reflexes.
Ладно, сейчас мы проверим твои рефлексы.

Пример с подстановкой (в переводе ## заменяется на перенос строки):
Okay—now we're going ## to check your reflexes.
Ладно, теперь мы собираемся ## проверить твои рефлексы.

Вроде бы самое интересное описал. Сам проект можно посмотреть на гитхабе: https://github.com/AantCoder/AssistAnt
Скажу с лишним хвастовством – программа классная. Мне с моим ужасным знанием английского очень помогает.


P.S. Если есть какие-то комментарии, идеи, что можно улучшить или предложения по поводу производительности, то напишите мне здесь или в Issues на гитхаб.

UPD 27.11.2022: Добавил раздел Переносы строк, обновил картинку

Теги:
Хабы:
+10
Комментарии33

Публикации

Истории

Работа

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн