SchoolOCR - API для автоматического распознавания данных с титульных листов Всероссийских Проверочных Работ (ВПР) с использованием нейросетевых технологий. Решение позволяет:
- Автоматизировать обработку бланков
- Снизить нагрузку на преподавателей
- Минимизировать ошибки ручного ввода
- Распознавание структурированных данных:
- Предмет, класс, вариант
- Код участника
- Баллы по заданиям
- Поддержка форматов:
- Изображения (JPG/PNG)
- PDF-документы
- Технологический стек:
- YOLOv11 для детекции ячеек
- Кастомная CNN для распознавания цифр
- Tesseract OCR для распознавания печатного текста
- API:
- RESTful интерфейс
- Поддержка base64-кодирования
- Авторизация по API-ключу
- Экспериментальное LLM-распознавание:
- Отдельная ручка
/llm/recognize - Использование мультимодальной модели через Ollama Cloud
- Полноценный альтернативный контур распознавания документа
- Предназначено для замены классического пайплайна в отдельных сценариях
- Имеет экспериментальный статус, так как находится на этапе активной настройки и проверки
- Отдельная ручка
Сервис доступен по публичному IP-адресу:
http://89.169.138.153/recognize
Помимо основного пайплайна распознавания в сервисе доступна экспериментальная ручка:
POST /llm/recognizeДанная функция представляет собой полноценный альтернативный способ распознавания документа с использованием мультимодальной языковой модели.
Ручка предназначена для:
- распознавания титульного листа целиком одним запросом;
- замены классического пайплайна в отдельных сценариях использования;
- обработки документов со сложными, нестандартными или плохо читаемыми фрагментами;
- апробации нового подхода к извлечению структурированных данных.
Ручка /llm/recognize имеет экспериментальный статус.
Это означает, что:
- функция рассматривается как новый полноценный контур распознавания, а не только вспомогательный инструмент;
- логика промпта, состав ответа и параметры обработки могут дорабатываться;
- качество распознавания и время ответа зависят от выбранной облачной модели;
- перед использованием в массовой эксплуатации рекомендуется отдельно проверить качество на своем наборе документов.
Для работы экспериментальной ручки /llm/recognize требуется отдельный API-ключ для доступа к облачной модели Ollama.
- Зарегистрируйтесь или войдите в аккаунт Ollama.
- Перейдите в настройки или раздел управления API-ключами в личном кабинете.
- Создайте новый API key.
- Сохраните его в безопасном месте, так как после создания он может больше не отображаться полностью.
В текущей реализации ключ Ollama Cloud передается в теле запроса в поле api_key при вызове ручки /llm/recognize.
Пример:
curl -X POST http://localhost:8000/llm/recognize \
-F "file=@doc.pdf" \
-F "api_key=YOUR_OLLAMA_API_KEY" \
-F "model=qwen3-vl:235b-cloud"API-ключ Ollama Cloud и API-ключ самого SchoolOCR — это разные ключи:
- API-ключ SchoolOCR используется для авторизации в самом сервисе;
- API-ключ Ollama Cloud используется только для доступа к облачной LLM-модели.
- Запуск для разработки производится с помощью команды:
docker-compose --profile dev up -d --build
Фронтенд приложения запускается на порту 5173, поддерживает HMR.
- Продовый запуск производится с помощью команды:
docker-compose --profile prod up -d --build
Разница с версией для разработки в том, что статика фронтенда продовой версии раздается с помощью nginx.
- Клонируйте репозиторий:
git clone https://github.com/LISA-ITMO/SchoolOCR
cd SchoolOCR- Создайте и активируйте виртуальное окружение:
# Для Windows
python -m venv venv
venv\Scripts\activate
# Для Linux/macOS
python3 -m venv venv
source venv/bin/activate- Установите зависимости:
pip install -r requirements.txt- Запустите API
python ./app.py- Можете сделать тестовый запрос
python ./scripts/app_interaction/sender.py- Клонируйте репозиторий:
git clone https://github.com/LISA-ITMO/SchoolOCR
cd SchoolOCR- Поднимите контейнер
docker-compose up --build- Можете сделать тестовый запрос
python ./scripts/app_interaction/sender.pyВсе эндпоинты защищены API-ключом. Ключ передаётся в заголовке X-API-Key.
При отсутствии или неверном ключе сервер возвращает 401 Unauthorized.
Ключи хранятся в файле app/api_keys.json:
{
"keys": ["ваш_уникальный_ключ_1", "ваш_уникальный_ключ_2"]
}Файл читается при старте приложения. После изменения необходима перезагрузка сервиса.
curl:
curl -X POST "http://localhost:8000/recognize" \
-H "X-API-Key: ваш_ключ" \
-F "file=@image.jpg"Python:
import requests
response = requests.post(
"http://localhost:8000/recognize",
headers={"X-API-Key": "ваш_ключ"},
files={"file": open("image.jpg", "rb")},
)
print(response.json())-
app.py
Точка входа FastAPI с эндпоинтами:/recognize- Основной обработчик изображений
/llm/recognize- Экспериментальная LLM-ручка для полного распознавания документа через мультимодальную модель
/healthcheck- Проверка состояния сервиса -
utils/code_rec.py
def recognize_code(image: np.ndarray, model) -> str:
"""Извлекает код участника из изображения"""utils/table_rec.py
def recognize_table(image: np.ndarray, model) -> dict:
"""Обрабатывает таблицу с ответами и возвращает баллы"""utils/preprocess_general.py
def preprocess_general(img):
"""Предобработка изображения перед распознаванием"""| Модель | Назначение | Путь |
|---|---|---|
| YOLOv11 | Детекция ячеек | models/cell_detect.pt |
| CNN | Распознавание цифр | models/digit_model.h5 |
| Библиотека | Версия | Назначение |
|---|---|---|
fastapi |
0.115.12 | Веб-фреймворк для API |
uvicorn |
0.34.0 | ASGI-сервер |
tensorflow |
2.19.0 | Нейросетевой фреймворк |
ultralytics |
8.3.105 | YOLO модели |
| Библиотека | Версия |
|---|---|
opencv-python |
4.11.0 |
pillow |
11.1.0 |
pytesseract |
0.3.13 |
scikit-image |
0.25.2 |
| Библиотека | Назначение |
|---|---|
PyMuPDF |
Работа с PDF |
pydantic |
Валидация данных |
numpy |
Матричные операции |
В настоящий момент решение крайне чувствительно к исходному качеству, поэтому для наиболее корректной обработки важно соблюдать требования:
- Скан, насколько это возможно, сделать ровным и четким;
- Цифры пишутся раздельно, черной (лучше гелиевой) ручкой, без разъединений - в идеале, как печатные. Для таблиц - ровно в клетке, не выходя за рамки;
- Для каждой цифры в таблице - отдельная клетка, границы должны быть как можно четче.
- Передавать API файл в jpg или pdf формате через base64, разрешение исходное
