Search
Write a publication
Pull to refresh

Распознавание текста на изображении и общение с распознанным текстом. Paddle OCR + LLM

Level of difficultyEasy
Reading time8 min
Views936
Кадр из фильма двухсотлетний человек
Кадр из фильма двухсотлетний человек

Данная статья описывает процесс создания проложения для распознавания текста на изображении и общения с распознанным текстом. 

Системные требования

  • Язык: Python

  • Оптическое Распознавание Символов(OCR): Paddle OCR

  • Площадка для языковой модели: Ollama

  • Большая языковая модель(LLM): qwen2:7b

  • Сетевой фреймворк для API: FastAPI

Архитектура

компоненты приложения
компоненты приложения

Этапы разработки приложения

  1. API для распознавания изображения

  2. API для общения с распознанным текстом

Этап 1. API для распознавания изображения

Процес: 1. Создаём код -> 2. Устанавливаем зависимости -> 3. Стартуем сервер -> 4. Делаем обращение к методу сервера -> 5. Проверяем результат

1. Создаём код

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

import numpy as np
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import JSONResponse
from paddleocr import PaddleOCR
from PIL import Image
import io

app = FastAPI(
    title="PaddleOCR API",
    description="A simple API for OCR using PaddleOCR",
    version="1.0.0"
)

ocr = PaddleOCR(
    use_doc_orientation_classify=False,
    use_doc_unwarping=False,
    use_textline_orientation=False
)

def ocr_pdf_paddle(image):
    print("START COMPRESSING...")
    COMPRESS_SCALE = 0.5
    width, height = image.size
    new_size = (int(width * COMPRESS_SCALE), int(height * COMPRESS_SCALE))
    img_resized = image.resize(new_size, Image.LANCZOS)
    image_array = np.array(img_resized)

    print("START PREDICTION...")
    page_text = ocr.predict(image_array)

    return page_text

@app.post("/ocr")
async def perform_ocr(file: UploadFile = File(...)):
    print("IMAGE READING...")

    contents = await file.read()
    image = Image.open(io.BytesIO(contents)).convert("RGB")  # Ensure RGB

    # Perform OCR
    result = ocr_pdf_paddle(image)
    print("FILE PREDICTION ENDED")

    if isinstance(result, list) and len(result) > 0:
        rec_texts = result[0].get("rec_texts", [])
    elif isinstance(result, dict):
        rec_texts = result.get("rec_texts", [])
    else:
        rec_texts = []

    print("SENDING RESPONSE...")
    return JSONResponse(content=rec_texts)

2. Устанавливаем зависимости

а) Установка Paddlepaddle: 

Лучше всего воспользоваться официальной инструкцией на официальном сайте

Установка paddlepaddle может быть самым утомительным этапом в процессе разработки этого приложения, т.к. требуется сопоставить твое железо, с драйверами процессора и версией paddlepaddle. То-есть потребуется настроить совместимость версий программного обеспечения. 

Обнаружь следующие свойства своей машины:

  • Операционная система

  • Железо: Тип видеокарты или процессор

  • Для графического процессора(GPU): версию драйвера

  • Для графического процессора(GPU): Версию программы для работы железом (СUDA, ArmV8 и тд ) 

Дополнительно: убедись, что версия драйвера для железа(процессора) и версия программы для работы железом совместимы. 

В зависимости от свойств твоей машины, подбери команду для установки paddlepaddle на официальном сайте paddlepaddle.

б) Установка Paddle OCR:

# Команда для установки
pip install paddleocr

Официальный источник Paddle OCR: https://github.com/PaddlePaddle/PaddleOCR

в) Установка FastAPI: 

# Команда для установки
pip install fastapi

3. Стартуем сервер:

# Команда для запуска приложения
# ocr_api_test - название файла с приложением
uvicorn ocr_api_test:app --reload --host 0.0.0.0 --port 8000

4. Делаем обращение к методу сервера

# Команда для обращения к методу серверу
curl -X POST "http://localhost:8000/ocr" \
     -F "file=@\"/yourTestPathDir/yourTestImageName.png\"" \
     | python -m json.tool

Дополнительная настройка с Paddle OCR:

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

5. Проверяем результат

а) Добавим код для отображения результатов распознавания текста на картинке

# ... ТУТ КОД ИЗ API МЕТОДА
result = ocr_pdf_paddle(image)

# Этот код нужен для тестирования отображения 
# результатов распознования текста на картинке
outputDirPath = "/yourRootPath/yourOutputDirPath"
for res in result:
  result_base = os.path.join(outputDirPath)
  res.save_to_img(result_base)  # e.g., page_1_result.jpg
  res.save_to_json(result_base)  # e.g., page_1_result.json

б) Проверим результат

Картинка для распознавания
Картинка для распознавания
Результат распознавания картинки
Результат распознавания картинки

Дополнительно:

Можно заметить, что PaddleOCR распознал не только английские, но и китайские буквы. Для настройки на конкретный язык потребуется указать настройку lang. Со списком языков, которые поддерживает paddleOCR можете ознакомиться на официальном сайте или в исходном коде.

В качестве дополнительного файла ты получишь JSON, c распознанным текстом, координатами расположения этого текста на изображении и т.д.

# Пример текста в JSON:
"rec_texts": [
        "WOOD",
        "JOINING",
        "AND CHISELING TOOLS",
        "CUTTING",
        "ng projeet you",
        "take on",
        "W",
        "hatever",
...
],

Этап 2. API для общения с распознанным текстом

Процес: 1. Создаём код -> 2. Устанавливаем зависимости -> 3. Стартуем сервер с LLM -> 4. Стартуем сервер с приложением -> 5. Делаем обращение к методу сервера -> 6.Проверяем результат

1. Создаём код

# ... ТУТ ДОЛЖЕН БЫТЬ КОД ИЗ ПЕРВОГО ПРИМЕРА

@app.post("/ocrWithLlm")
async def perform_ocr(file: UploadFile = File(...)):
    print("IMAGE READING...")

    contents = await file.read()
    image = Image.open(io.BytesIO(contents)).convert("RGB")  # Ensure RGB

    result = ocr_pdf_paddle(image)
    print("FILE PREDICTION ENDED")

    if isinstance(result, list) and len(result) > 0:
        rec_texts = result[0].get("rec_texts", [])
    elif isinstance(result, dict):
        rec_texts = result.get("rec_texts", [])
    else:
        rec_texts = []

    print("SENDING REQUEST TO OLLAMA...")
    resFromOllama = analyze_ocr_text(rec_texts)
    print("RESPONSE FROM OLLAMA FETCHED SUCCESSFULLY")

    print("SENDING RESPONSE...")
    return JSONResponse(content={'ocrText': rec_texts, 'llmResult': resFromOllama})


def analyze_ocr_text(text: str, model: str = "ollama/qwen2:7b"):
    print("LLM MODEL IS: ", model)
    try:
        response = completion(
            model=model,
            api_base="http://localhost:11434",  # Ollama address
            messages=[
                {"role": "system", "content": "You are an OCR analyzer. Extract key facts, summarize, and detect language."},
                {"role": "system",
                 "content": "Given a text, carefully analyze the text and categorize document into JSON format."},
                {"role": "user", "content": f"Analyze this OCR text:\n\n{text}"}
            ],
            timeout=60
        )
        return response.choices[0].message.content
    except Exception as e:
        return f"Error: {str(e)}"

2.Устанавливаем зависимости

  • Площадка для запуска LLM: Ollama или LM Studio

  • Клиент для общения с LLM: litellm или OpenAI

В данном примере используется Ollama и litellm. Ollama не содержит в себе графический интерфейс, т.к. подразумевается, что мы используем только терминал. Если тебе необходимо иметь готовый графический интерфейс, попробуй LM Studio, это приложение очень просто в установке и настройке.

а) установка Ollama:

Тут 2 вариант: 1 через официальный сайт либо 2 через терминал.

# Команда для установки ollama через терминал
curl -fsSL https://ollama.com/install.sh | sh

б) установка клиента для LLM litelm:

# Команда для установки litellm через терминал
pip install litellm  

3. Стартуем сервер с LLM через ollama

а) выбрать LLM:

На официальном сайте ollama сайте выбери LLM модель для своей машины. В качестве теста можно выбрать qwen:7b, или qwen2:7b они достаточно легкие.

б) запустить ollama:

Выполни в отдельном терминале команду 

# Команда для запуска ollama
ollama serve

Пункты В и Г должны выполняться в новом терминальном окне.

в) скачать LLM с помощью ollama:

Открой новое терминальное окно и для скачивания LLM выполни следующую команду:

# Команда для скачивания LLM qwen2:7b
ollama pull qwen2:7b

г) запустить LLM с помощью ollama:

Выполни следующую команду для запуска модели на твоем локальном сервере ollama:

# Команда для запуска LLM qwen2:7b
ollama run qwen2:7b

д) проверь работу LLM:

В итоге у тебя будет два терминальных окна. Одно показывает состояние сервера ollama, второй позволяет общаться с LLM. Напиши что нибудь в терминальное окно для проверки работоспособности языковой модели.

4. Стартуем сервер с приложением

# Команда для запуска приложения
# ocr_api_test - название файла с приложением
uvicorn ocr_api_test:app --reload --host 0.0.0.0 --port 8000

5. Делаем обращение к методу сервера

# Команда для обращения к методу серверу
curl -X POST "http://localhost:8000/ocrWithLlm" \
     -F "file=@\"/yourTestPathDir/yourTestImageName.png\"" \
     | python -m json.tool

6. Проверяем результат

Ответ от метода /ocrWithLlm:

{
  "categories": [
    "Wood Joining",
    "Cutting Tools",
    "Project Guidance",
    "Quality of Cuts",
    "Joint Selection",
    "Layout and Marking",
    "Power Tools",
    "Measuring Tools"
  ],
  "text_content": {
    "title": "WOOD JOINING AND CHISELING TOOLS",
    "paragraphs": [
      "Cutting ng project you take on whatever woodwork box ora tne EZE le you'l isa umg The quality of the loints, cutters whether joinifs.",
      "FE Doveralsaw\u8679LEXO., N Themou com wihadoren or so. lap.",
      "gone in this chapter the right joint questions for choosing layout and marking.and results mo.",
      "You joint tip on for the Miter saw for achieving and power tools. procedures try to be withaw varietyof",
      "to make Ifyou're new at the yet meets your require and appearance. For Cranked-neck paring chisel selecting joints for spe.",
      "dific applications, tum to pages 95 to 114; the chapter beginning on page 4I contains infomation on how to use",
      "the various tools.Keep Comer chisel Skew chesel the basic measuring and marking tools on your workbench you'll he using them often",
      "For a properly fitted joint, the dimensions must have an accura cy greater than the Morise chitel Bure chisel Thee Netr jnn ig",
      "graduations on your wth ther soreron cove the masuring tools.Achiey pd ing this precislon may seem impossible but Firmer chisel drg pin fid ad",
      "mor co Bhin chapr the relative tit of the two in practice its actually the actual stock."
    ]
  },
  "language": "English"
}

Так же можно добавить перевод на русский язык:

# Добавь просьбу о переводе ответа на русский язык
{"role": "user", "content": f" Translate your answer into Russian language. Analyze this OCR text:\n\n{text}"}

Ответ:

{
  "category": "Сервисы соединения и резки древесины",
  "text_segments": [
    {
      "header": "СЕРВИСЫ СОЕДИНЕНИЯ И РЕЗКИ ДРЕВЕСИНЫ"
    },
    {
      "sub_header": "Строительство проектов, которые вы берете на себя, всё, что удобно для деревообработки — проекты, коробки или задачи, которые вы выполняете."
    },
    {
      "details": [
        "Качество соединений",
        "Будь то сопряжения."
      ]
    },
    {
      "brands_and_products": [
        {
          "brand": "Сверление Saw",
          "model": "Lexo."
        },
        {
          "note": "Для мастеров дерева, с советами или предложениями. Лап."
        }
      ]
    },
    {
      "info_chapter": [
        "Информация о правильном соединении для разметки и маркировки.",
        "Результаты разметки и процедур."
      ]
    },
    {
      "layout_and_tools": [
        {
          "note": "Вы должны выбирать умно",
          "tools_information": "Схема и меточные инструменты."
        }
      ]
    },
    {
      "power_tools_section": [
        {
          "tool_type": "Митер saw"
        },
        {
          "note": "Достижение с помощью мощных инструментов."
        }
      ]
    },
    {
      "tutorials_chapter": [
        {
          "page_numbers": ["95 to 114"],
          "content": "Следующие страницы содержат информацию о том, как использовать различные инструменты."
        },
        {
          "note": "Страница 4I содержит информацию о том, как использовать различные инструменты."
        }
      ]
    },
    {
      "measuring_tools_notes": [
        {
          "note": "Храните измерительные и меточные инструменты на своём рабочем столе: вы часто будете их использовать."
        },
        {
          "tip_for_joints": "Для правильно подогнанного соединения размеры должны иметь точность большую, чем древесина."
        }
      ]
    }
  ]
}

Проверка понимания русского языка

1. Добавим изображение с картинками и текстами

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

2. Добавим изображение с картинками и текстами

Результат распознавания картинки
Результат распознавания картинки

3. Проверяем текст полученный от Paddle OCR

...
"rec_texts": [
        "ЇМиХЯиЙ Тии9ФЕЕБИЧ",
        "Загородный дом",
        "преоБрЯжеНсКИй",
        "н детали к нему",
        "Арх. М. Преображенскии",
        "1860 70R",
        "Праздничный русский стиль притягивал к себе архитекто-",
        "ров разных возрастов и устремлений. Таких, например, как",
        "молодой М.Т. Преображенский (1854—1930). тогда еще",
        "студент Московского училиша живописи. ваяния и зодче-",
        "ства и Петербургской академии художеств. А в будущем —",
        "маститый архитектор. профессор Академии, крупнейший",
        "специалист по реставрашии. Любовь к истории, объединяв-",
        "шая последователей русского стиля, привела его в импера-",
        "торскую Археологическую комиссию, членом которой он",
        "был долгое время. Его работа во многом способствовала со-",
        "хранности бесценных памятников архитектуры: Генуэзской",
        "стены в Феодосии, псковских Поганкиных палат. Смолен-",
        "ской крепостной стены. Исаакиевского собора в Петербур-",
        "ге. Софийского собора в Новгороде."
    ],
...

Дополнительные материалы

О Paddle OCR: https://habr.com/ru/companies/jetinfosystems/articles/660405/

О настройке ollama черерз UI: https://habr.com/ru/articles/879076/

Tags:
Hubs:
+2
Comments0

Articles