whales-identification

EcoMarineAI — Идентификация морских млекопитающих

License Python CI/CD Metrics Docs

Библиотека машинного обучения для автоматического детектирования и идентификации морских млекопитающих (китов и дельфинов) по снимкам аэрофотосъёмки. Система применяет метрическое обучение на основе ArcFace для идентификации 13 837 особей 30 видов и включает CLIP zero-shot антифрод-фильтр, отклоняющий изображения, не содержащие морских млекопитающих (целевая специфичность ≥ 90%).

Сайт проекта: https://whales.userstoday.net/ · Production-сервис: https://72.56.238.38.nip.io/ · Swagger REST API: https://ecomarineai-backend.fly.dev/docs


Метрики качества

Измерено на 202 изображениях: 100 снимков китов (Happy Whale) + 102 сцены без морских млекопитающих (Intel Image Dataset). Метрики вычисляются скриптом scripts/compute_metrics.py.

Метрика Значение Целевое значение по ТЗ
TPR / Чувствительность 0.950 > 0.85
TNR / Специфичность 0.902 > 0.90
Precision 0.905 ≥ 0.80
F1 0.927 > 0.60
ROC-AUC 0.984
Задержка p95 519 мс ≤ 8000 мс
Линейная масштабируемость R² = 1.000 линейная
Снижение точности при зашумлении 0.0% ≤ 20%
Доступность сервиса (7 дней) 99.40% ≥ 95%
make compute-metrics   # пересчитать метрики
cat reports/METRICS.md # читаемый отчёт

7-дневное непрерывное тестирование доступности задокументировано в reports/uptime_7day_summary.md: 2 016 проверок раз в 5 минут с 23.03.2026 по 29.03.2026 UTC, средняя доступность 99.40 % (значительно выше целевых 95 %).


Архитектура системы

Inference Pipeline

Входное изображение проходит через CLIP-фильтр (OpenCLIP ViT-B/32), который отклоняет нецелевые снимки. Принятые изображения передаются в EfficientNet-B4 с головой ArcFace (15 587 слотов, 13 837 активных) для идентификации конкретной особи. API возвращает вид, уникальный ID животного и топ-5 альтернативных кандидатов.


Веб-интерфейс

Веб-приложение доступно на http://localhost:8080 после запуска стека или по публичному адресу https://72.56.238.38.nip.io/.

Одиночный анализ

Загрузите снимок морского млекопитающего — система определит вид, идентификатор особи, уверенность модели и альтернативные варианты.

Главный экран — форма загрузки одиночного снимка

Результат идентификации горбатого кита

Отклонение антифродом

Если снимок недостаточно чёткий или особь отсутствует в базе, система возвращает объяснение причины и рекомендации по дальнейшим действиям.

Карточка отклонения с объяснением и рекомендациями

Пакетная обработка

Загрузите ZIP-архив с несколькими снимками. Результат включает сводную статистику, гистограмму распределения по видам и детальную таблицу с ID особей и уверенностью модели.

Пакетная обработка — статистика, гистограмма и таблица результатов


Быстрый запуск

Вариант 1: Docker Compose (рекомендуется)

Требуется Docker Desktop.

git clone https://github.com/0x0000dead/whales-identification
cd whales-identification
docker compose up --build

Модели запечены в образ; при первом старте недостающие веса докачиваются автоматически — предварительно скачивать ничего не нужно.

После запуска:

Доступ из другого устройства в сети:

Дополнительная настройка не требуется. По умолчанию переменная VITE_BACKEND пуста — фронтенд обращается к бэкенду по адресу http://<хост, на котором открыт UI>:8000, а dev-конфигурация Docker Compose задаёт ALLOWED_ORIGINS=*. Достаточно выполнить docker compose up --build и открыть http://<IP-адрес машины>:8080 с любого устройства в сети.

Переменная VITE_BACKEND нужна только для нестандартных схем — reverse-proxy или бэкенда на другом порту:

VITE_BACKEND=https://api.example.com docker compose up --build

Вариант 2: Локальная разработка (без Docker)

Prerequisites: Python 3.11+, Poetry ≥ 1.5, Node.js ≥ 20.19 (для Vite).

# Загрузка весов модели (~400 МБ с Hugging Face)
pip install huggingface_hub==0.20.3
./scripts/download_models.sh

# Бэкенд
cd whales_be_service
poetry install
poetry run python -m uvicorn whales_be_service.main:app \
  --host 0.0.0.0 --port 8000 --reload

# Фронтенд (в отдельном терминале)
cd frontend
npm install
VITE_BACKEND=http://localhost:8000 npm run dev   # http://localhost:5173

Вариант 3: Streamlit-демо

cd research/demo-ui
poetry install
poetry run streamlit run streamlit_app.py --server.port=8501

Приложение доступно на http://localhost:8501.

Запуск с GPU

Требуется установленный NVIDIA Container Toolkit.

docker compose -f docker-compose.yml -f docker-compose.gpu.yml up --build

Проверка: поле "device": "cuda:0" в ответе GET /health. Подробности — в docs/DEPLOYMENT.md.


API

Одиночная идентификация

curl -X POST http://localhost:8000/v1/predict-single \
  -F "file=@/path/to/whale.jpg"

Пример ответа:

{
  "image_ind": "whale.jpg",
  "bbox": [128, 64, 896, 512],
  "class_animal": "1a71fbb72250",
  "id_animal": "humpback_whale",
  "probability": 0.847,
  "mask": "iVBORw0KGgoAAAANS...",
  "is_cetacean": true,
  "cetacean_score": 0.993,
  "rejected": false,
  "rejection_reason": null,
  "model_version": "effb4-arcface-v1",
  "candidates": [
    {"class_animal": "abc456def789", "id_animal": "humpback_whale", "probability": 0.543},
    {"class_animal": "cafe0987ba54", "id_animal": "fin_whale", "probability": 0.271}
  ]
}

Поле mask — base64-кодированный PNG с удалённым фоном (в примере значение сокращено). Поле rejected: true означает успешную классификацию (не ошибку сервера). rejection_reason принимает значения not_a_marine_mammal, low_confidence или corrupted_image.

Пакетная обработка

zip archive.zip image_001.jpg image_002.jpg image_003.jpg
curl -X POST http://localhost:8000/v1/predict-batch \
  -F "archive=@archive.zip"

Ответ: массив объектов Detection, по одному на каждое изображение в архиве.

Полная документация: http://localhost:8000/docs

Примеры реальных ответов API

Real API responses


CLI-утилита

Интерфейс командной строки для работы без веб-браузера.

# Установка
cd whales_be_service && poetry install

# Идентифицировать один снимок
python -m whales_identify predict /path/to/whale.jpg

# Обработать каталог и сохранить результаты в CSV
python -m whales_identify batch /path/to/dir/ --csv report.csv

# Проверить только антифрод-фильтр (да/нет)
python -m whales_identify verify /path/to/image.png

# Вывод в JSON
python -m whales_identify predict /path/to/whale.jpg --json

Антифрод-фильтр

Каждое изображение проходит через CLIP zero-shot фильтр перед идентификационной моделью.

Входное изображение
       ↓
  CLIP-фильтр (OpenCLIP ViT-B/32 LAION-2B)
       ├── gate passed → EfficientNet-B4 ArcFace → результат идентификации
       └── gate failed → rejected: true, reason: "not_a_marine_mammal"

Пороговое значение CLIP калибруется командой make calibrate-clip на тестовой выборке (data/test_split/), добиваясь TNR ≥ 90% при TPR ≥ 85%. Результат хранится в whales_be_service/src/whales_be_service/configs/anti_fraud_threshold.yaml.

ROC-кривая антифрод-фильтра


Структура репозитория

whales_identify/          # Основная библиотека ML (обучение, модели, датасет)
whales_be_service/        # FastAPI REST API бэкенд
  └── src/whales_be_service/
      ├── main.py             # Приложение FastAPI, CORS
      ├── routers.py          # Маршруты API
      ├── response_models.py  # Pydantic-схемы и логика вывода
      └── inference/          # Pipeline, антифрод, идентификатор
frontend/                 # React 18 + TypeScript веб-приложение
research/
  ├── notebooks/          # Jupyter-ноутбуки: эксперименты и сравнение архитектур
  ├── demo-ui/            # Streamlit-демо (лучшая модель — ViT)
  └── demo-ui-mask/       # Альтернативное демо с бинарной маской
data/                     # Тестовая выборка, аннотации, образцы
scripts/                  # Загрузка моделей, вычисление метрик, калибровка
docs/                     # Техническая документация и скриншоты
models/                   # Веса моделей (не хранятся в git)
reports/                  # Отчёты о метриках (METRICS.md, metrics_latest.json)

Исследовательские ноутбуки

Ноутбук Описание
02_ViT_train_efficientnet.ipynb Обучение метрической модели (ViT/EfficientNet, ArcFace)
03_efficientnet_experiments.ipynb Сравнение EfficientNet-B0, B3, B5
04_resnet_classification_experiments.ipynb Классификация ResNet-54, ResNet-101
05_swinT_experiments.ipynb Эксперименты со Swin Transformer
06_benchmark_binary.ipynb Бинарная классификация всех архитектур
06_benchmark_multiclass.ipynb Мультиклассовая классификация всех архитектур
07_onnx_inference_compare.ipynb Ускорение через ONNX
08_benchmark_all_compare.ipynb Сводное сравнение архитектур

Полный индекс с описанием и ссылками: docs/NOTEBOOKS_INDEX.md.


Разработка

Установка зависимостей

make install              # Python + npm зависимости
make pre-commit-install   # хуки pre-commit (ruff, mypy, bandit)
make download-models      # веса моделей с Hugging Face

Команды

make test           # pytest (без медленных и интеграционных тестов)
make test-cov       # тесты с отчётом о покрытии
make lint           # ruff lint + format check
make format         # авто-форматирование ruff
make up             # запустить полный стек в Docker
make smoke          # сквозной smoke-тест

Ветвление и код-ревью

  1. Создайте ветку от main: git checkout -b feature/<описание>
  2. Сделайте коммиты с описательными сообщениями
  3. Откройте Pull Request в main
  4. Дождитесь прохождения CI (lint, test, security, docker)
  5. Получите одобрение от минимум одного участника команды
  6. Слейте PR и удалите ветку

Устранение типичных проблем

Проблема Решение
docker: command not found Установите Docker Desktop и перезапустите терминал
Порты 8000 или 8080 заняты docker compose down, затем измените порты в docker-compose.yml
Frontend: «Failed to fetch» Укажите адрес сервера: VITE_BACKEND=http://<ip>:8000 docker compose up --build
No such file or directory: models/ Выполните ./scripts/download_models.sh
ImportError: libGL.so.1 Ubuntu/Debian: sudo apt-get install -y libgl1-mesa-glx libglib2.0-0
huggingface-cli: command not found pip install huggingface_hub==0.20.3
Poetry could not find a pyproject.toml Перейдите в whales_be_service/ перед запуском poetry install

Дополнительные решения: GitHub Wiki — FAQ.


Документация

Ресурс Описание
GitHub Wiki Установка, API Reference, Architecture, Model Cards, Testing
MODEL_CARD.md Метрики, ограничения, характеристики модели
API_CHANGELOG.md История изменений REST API
docs/ML_ARCHITECTURE.md Сравнение архитектур: ResNet → ViT
docs/NOTEBOOKS_INDEX.md Индекс исследовательских ноутбуков
docs/ROADMAP.md Дорожная карта: работы этапов, мобильная версия UI, планы развития
docs/DATASET_CONTRIBUTION.md Состав и лицензирование датасетов

Модели и артефакты


Лицензирование

Артефакт Лицензия Файл
Исходный код MIT LICENSE
Обученные модели CC-BY-NC-4.0 (некоммерческое использование) LICENSE_MODELS.md
Датасеты CC-BY-NC-4.0 (наследуется от Happy Whale) LICENSE_DATA.md

Ограничение на коммерческое использование моделей обусловлено лицензией upstream-датасета Happy Whale и условиями предобученных ImageNet-весов. Использование разрешено в академических исследованиях, образовательных целях и некоммерческих природоохранных проектах.

Полный анализ совместимости 159 зависимостей: LICENSES_ANALYSIS.md.

Авторы: Baltsat Konstantin, Tarasov Artem, Vandanov Sergey, Serov Alexandr (2024–2026)