Привет, Хабр! На просторах интернета, да и на самом Хабре есть огромное количество статей про OCR. Сегодня я бы хотел рассказать не про процесс распознавания текста а про методику развертывания решения в закрытом контуре (проще говоря - без интернета)

Дисклеймер

В статье рассматривается простейший метод сборки готового решения, работающего offline в закрытом контуре предприятия

Update 1

В комментариях ниже писали

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

...

Причем эти две строчки берутся и первого же ответа, первой же ссылки "pip offline install".

Эта статья появилась как раз потому, что pip download проблему с easyocr в закрытом контуре не решает (точнее решает но не до конца - подробное описание проблемы есть ниже в статье на этапе описания скрипта init.py)

Что будет в статье

  • Напишем простенький код для распознавания текста с картинок (Python + easyocr)

  • Соберем Docker образ, позволяющий запускать наш код offline

  • Выгрузим образ в архив, для того чтобы его можно было развернуть offline

  • Развернем образ в закрытом контуре из архива

1. Код для распознавания текста с картинок

Предположим, что перед нами стоит задача парсить изображение, содержащее таблицу из четырех колонок (например скриншот со списком американских президентов)

Изображение 1 - тестовая таблица для проверки модуля OCR
Изображение 1 - тестовая таблица для проверки модуля OCR

Для того, чтобы решить эту задачу воспользуемся библиотекой 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 - результат парсинга изображения

Разумеется, для того, чтобы этот код работал потребуется установить библиотеку 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

Еще один необходимый файл для сборки образа - скрипт 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 - я могу написать отдельную статью про то как все это подружить и запаковать в образ, желаю вам хорошего дня, карьерных и творческих успехов, до встречи!

Комментарии (8)


  1. ivankudryavtsev
    26.08.2023 13:50
    +7

    Возможно, автор не понимает почему статья в минусах. Вот как я это вижу:

    • легенда, простите, но это не легенда, это ‘pip install’;

    • закрытый контур, вообще ни о каком закрытом контуре речи нет;

    • сама проблема - не проблема.

    Итог: ценности нет, пафоса много


    1. andrewfromtver Автор
      26.08.2023 13:50

      Добрый день Иван, спасибо за пояснения, я так понимаю тригером для хейта стало слово "Легенда" в описании? Я на этой платформе новичек, честно признаться даже не слышал о ней до этого года (я без сарказма), поэтому не знаю какие здесь правила и обычаи, помимо тех, что расписаны в официальных гайдах. Буду рад любым вашим предложениям по смене заголовка этой статьи.

      Что касается вашего комментария относительно pip install, закрытого контура и пафоса

      1. на самом деле шаг не один, как вы изложили, помимо pip install еще есть как минимум docker build, docker save а уже в закрытом контуре docker load а если прочитать статью повнимательнее то встретится еще одно нужное действие на этапе сборки, которое некоторые могут упустить по невнимательности (я про init.py)

      2. еще немного про закрытый контур - основная идея сводится к тому, что вы берете архив, загружаете образ на машину без выхода в интернет, запускаете контейнер и все работает

      3. по поводу пафоса - хочу обратить ваше внимание на тот факт, что у статьи выставлен уровень сложности - простой


      1. xi-tauw
        26.08.2023 13:50
        +2

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

        Там где есть интернет:

        pip download -r requirements.txt

        Там где нет интернета:

        pip install --no-index --find-links /path/to/download/dir/ -r requirements.txt

        Причем эти две строчки берутся и первого же ответа, первой же ссылки "pip offline install".

        В итоге:

        Легенды нет. Проблемы нет. Зачем докер не написано. Почему решали именно так, а не иначе не написано. Почему не стали брать более легкое решение (выше) или более сложное (просто притащить виртуалку) тоже нет.


        1. andrewfromtver Автор
          26.08.2023 13:50

          Добрый вечер, по началу было как раз ваше решение с pip download, но библиотеке easyocr помимо зависимых библиотек так же для работы нужны дополнительные данные выгружаемые при первой инициализации, к сожалению pip download не решал эту проблему, поэтому пришлось использовать Docker образ (в статье про это написано там где указан скрипт init.py), так же реализация ocr в контейнере позволяет повысить отказоустойчивость и доступность методом репликации контейнера еще один немаловажный пункт что контейнеру можно задать лимит по используемым на хосте ресурсам (об этом в статье не писал)


        1. andrewfromtver Автор
          26.08.2023 13:50

          Добавил дополнительное описание в дисклеймер, спасибо за пояснения


      1. ivankudryavtsev
        26.08.2023 13:50

        Да нет тут никакого хейта. Просто нет четкой идеи и если уж пишете про деплой без интернета, это и должно быть во главе угла, а никак не EasyOCR.

        Люди же не дураки, все, кто Docker знают, знают про загрузку через tar. Если бы вы назвали статью условно «Развертывание контейнеров Docker в средах без интернета», Вы бы попали на правильный сегмент аудитории, а дальше хоть через tar в локальный реестр, хоть через частный реестр.

        Но это не легенда, не Python, не EasyOCR.


        1. andrewfromtver Автор
          26.08.2023 13:50
          +1

          Изменил заголовок статьи, спасибо за рекомендации


    1. andrewfromtver Автор
      26.08.2023 13:50

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