Привет, Хабр! На просторах интернета, да и на самом Хабре есть огромное количество статей про OCR. Сегодня я бы хотел рассказать не про процесс распознавания текста а про методику развертывания решения в закрытом контуре (проще говоря - без интернета)
Дисклеймер
В статье рассматривается простейший метод сборки готового решения, работающего offline в закрытом контуре предприятия
Update 1
В комментариях ниже писали
Не специалист, но вероятнее всего проблема вашей статьи в том, что вместо нее достаточно двух строк:
...
Причем эти две строчки берутся и первого же ответа, первой же ссылки "pip offline install".
Эта статья появилась как раз потому, что pip download проблему с easyocr в закрытом контуре не решает (точнее решает но не до конца - подробное описание проблемы есть ниже в статье на этапе описания скрипта init.py)
Что будет в статье
Напишем простенький код для распознавания текста с картинок (Python + easyocr)
Соберем Docker образ, позволяющий запускать наш код offline
Выгрузим образ в архив, для того чтобы его можно было развернуть offline
Развернем образ в закрытом контуре из архива
1. Код для распознавания текста с картинок
Предположим, что перед нами стоит задача парсить изображение, содержащее таблицу из четырех колонок (например скриншот со списком американских президентов)
![Изображение 1 - тестовая таблица для проверки модуля OCR Изображение 1 - тестовая таблица для проверки модуля OCR](https://habrastorage.org/getpro/habr/upload_files/99f/b4c/b0a/99fb4cb0a201d7fb09002f7010537cd2.png)
Для того, чтобы решить эту задачу воспользуемся библиотекой easyocr
import easyocr
qty = 4
reader = easyocr.Reader(['en'])
result = reader.readtext('test.png', detail=0)
rows = [result[start:start+qty] for start in range(0, len(result), qty)]
print(rows)
Данный код выведет в консоль двумерный список, с результатами парсинга изображения
![Изображение 2 - результат парсинга изображения Изображение 2 - результат парсинга изображения](https://habrastorage.org/getpro/habr/upload_files/adc/0a1/5ff/adc0a15ff8d88e9e9698dde7837dcbeb.png)
Разумеется, для того, чтобы этот код работал потребуется установить библиотеку easyocr
pip3 install easyocr
2. Сборка Docker образа для работы offline
Так как одно из требований для модуля OCR - автономная работа после разветрывания, необходимо не только подготовить окружение, но и подгрузить все необходимые компоненты для работы easyocr в offline режиме, для этого напишем Dockerfile следующего содержания
FROM python:3.11.4
WORKDIR /usr/src/ocr
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY init.py ./
RUN python ./init.py
CMD [ "tail", "-f", "/dev/null" ]
В Dockerfile используется файл requirements.txt в котором описываются все необходимые Python библиотеки
easyocr == 1.7.0
Pillow == 9.5.0
Обратите внимание на downgrade библиотеки Pillow, это поможет избавиться от проблем совместимости с deprecated функциями. Спасибо добрым людям на stackoverflow
![Изображение 3 - совет из stackoverflow Изображение 3 - совет из stackoverflow](https://habrastorage.org/getpro/habr/upload_files/a69/e94/830/a69e94830824d4a5b693451abe6b0102.png)
Еще один необходимый файл для сборки образа - скрипт init.py
import easyocr
reader = easyocr.Reader(['en'])
Обратите внимание, что скрипт не только добавляется к образу, но и запускается в процессе сборки, тем самым выкачивая и сохраняя в образе все необходимое для работы модуля OCR при обработке изображений (в данном примере выкачивается набор данных для обработки и парсинга текста на английском языке)
Компоненты для сборки образа у нас есть, осталось только собрать все воедино
docker build -t easyocr .
3. Выгрузка образа в tar архив
На самом деле этот пункт достаточно короткий, наверное, зря я выделил для него отдельный раздел в статье, но тем не менее он тоже важен, поэтому оставлю структуру статьи без изменений.
Для того чтобы запаковать подготовленный образ в tar архив воспользуемся следующей командой
docker save easyocr | gzip > easyocr.tar.gz
Процесс может занять некоторое время, так как архив получится довольно увесистый, но в итоге вы получите готовый к транспортировке в закрытый контур архив easyocr.tar.gz
4. Развертывание образа в закрытом контуре
Все что осталось сделать на данном этапе - поместить архив на носитель информации, пронести в заерытый контур и загрузить архив на подопытную машину. С первыми двумя пунктами нашего плана вы и сами прекрасно справитесь, а для реализации третьего пункта нужно воспользоваться следующей командой (выполняется из каталога с архивом)
docker load -i ./easyocr.tar.gz
Разумеется для того, чтобы все это работало на испытуемой машине должен стоять Docker (сейчас это совсем не проблема для закрытого контура, даже для отечественных ОС можно использовать локальные репозитории, в которых Docker есть - в эксперименте использовалась РЕД ОС).
Для того, чтобы запустить модуль нужно выполнить следующую команду
docker run -d -v ./shared:/shared --name easyocr --restart always easyocr
Обратите внимание, что мы расшариваем директорию на хосте для контейнера (shared) в эту директорию мы положим наш скрипт, который писали в первом разделе этой статьи и тестовое изображение, которое нужно распарсить
Таким образом нам не потребуется пересобирать образ каждый раз - когда мы меняем логику работы скрипта или хотим распарсить другое изображение
Другими словами - контекйнер который мы запустили просто является подготовленным окружением для выполнения скрипта
Для того, чтобы использовать OCR в закрытом контуре на хосте нужно выполнить следующую команду
docker exec easyocr bash -c "python /shared/parser.py"
Заключение
Спасибо, что дочитали статью до конца, надеюсь эта информация поможет вам сэкономить время, опытные читатели Хабра в курсе, что easyocr может использовать CUDA ядра для распознавания текста из картинок, если вам интересна тема контейнеризации easyocr с использованием GPU - я могу написать отдельную статью про то как все это подружить и запаковать в образ, желаю вам хорошего дня, карьерных и творческих успехов, до встречи!
ivankudryavtsev
Возможно, автор не понимает почему статья в минусах. Вот как я это вижу:
легенда, простите, но это не легенда, это ‘pip install’;
закрытый контур, вообще ни о каком закрытом контуре речи нет;
сама проблема - не проблема.
Итог: ценности нет, пафоса много
andrewfromtver Автор
Добрый день Иван, спасибо за пояснения, я так понимаю тригером для хейта стало слово "Легенда" в описании? Я на этой платформе новичек, честно признаться даже не слышал о ней до этого года (я без сарказма), поэтому не знаю какие здесь правила и обычаи, помимо тех, что расписаны в официальных гайдах. Буду рад любым вашим предложениям по смене заголовка этой статьи.
Что касается вашего комментария относительно pip install, закрытого контура и пафоса
на самом деле шаг не один, как вы изложили, помимо pip install еще есть как минимум docker build, docker save а уже в закрытом контуре docker load а если прочитать статью повнимательнее то встретится еще одно нужное действие на этапе сборки, которое некоторые могут упустить по невнимательности (я про init.py)
еще немного про закрытый контур - основная идея сводится к тому, что вы берете архив, загружаете образ на машину без выхода в интернет, запускаете контейнер и все работает
по поводу пафоса - хочу обратить ваше внимание на тот факт, что у статьи выставлен уровень сложности - простой
xi-tauw
Не специалист, но вероятнее всего проблема вашей статьи в том, что вместо нее достаточно двух строк:
Там где есть интернет:
pip download -r requirements.txt
Там где нет интернета:
pip install --no-index --find-links /path/to/download/dir/ -r requirements.txt
Причем эти две строчки берутся и первого же ответа, первой же ссылки "pip offline install".
В итоге:
Легенды нет. Проблемы нет. Зачем докер не написано. Почему решали именно так, а не иначе не написано. Почему не стали брать более легкое решение (выше) или более сложное (просто притащить виртуалку) тоже нет.
andrewfromtver Автор
Добрый вечер, по началу было как раз ваше решение с pip download, но библиотеке easyocr помимо зависимых библиотек так же для работы нужны дополнительные данные выгружаемые при первой инициализации, к сожалению pip download не решал эту проблему, поэтому пришлось использовать Docker образ (в статье про это написано там где указан скрипт init.py), так же реализация ocr в контейнере позволяет повысить отказоустойчивость и доступность методом репликации контейнера еще один немаловажный пункт что контейнеру можно задать лимит по используемым на хосте ресурсам (об этом в статье не писал)
andrewfromtver Автор
Добавил дополнительное описание в дисклеймер, спасибо за пояснения
ivankudryavtsev
Да нет тут никакого хейта. Просто нет четкой идеи и если уж пишете про деплой без интернета, это и должно быть во главе угла, а никак не EasyOCR.
Люди же не дураки, все, кто Docker знают, знают про загрузку через tar. Если бы вы назвали статью условно «Развертывание контейнеров Docker в средах без интернета», Вы бы попали на правильный сегмент аудитории, а дальше хоть через tar в локальный реестр, хоть через частный реестр.
Но это не легенда, не Python, не EasyOCR.
andrewfromtver Автор
Изменил заголовок статьи, спасибо за рекомендации
andrewfromtver Автор
Пока писал ответ вам, в голову пришла мысль - возможно стоит более подробно писать о содержании статьи в описании? Просто у меня сложилось мнение, что люди просто не дочитывают статью до конца.