AI-система для мониторинга биоразнообразия под ключ
Мы разрабатываем AI-системы для автоматизированного мониторинга биоразнообразия. Наша команда реализовала проекты для заповедников, природоохранных организаций и экологических исследователей. Фотоловушки, дроны с мультиспектральными камерами, гидрофоны и акустические датчики генерируют терабайты данных в сутки. Без AI обработать их невозможно. Ручные полевые наблюдения охватывают ограниченные территории: 2–3 специалиста за сезон обходят несколько квадратных километров. AI-система покрывает тысячи гектаров в реальном времени.
Мы решаем четыре ключевые задачи: определение видов по фото и звуку, подсчёт особей на аэрофотоснимках, re-ID конкретных животных для долгосрочного мониторинга, обнаружение изменений ареалов обитания. Обратитесь к нам за консультацией — оценим ваш проект за 2 рабочих дня.
AI мониторинг биоразнообразия: архитектура системы
Система строится на двухступенчатом пайплайне: YOLO-детектор выделяет животных на снимке, EfficientNet-классификатор определяет вид. Для re-ID особей используется ArcFace-эмбеддинг, сравниваемый с галереей. Акустические данные анализирует BirdNET или PANN для классификации птиц и других животных по звуку.
Все компоненты разворачиваются в Docker-контейнерах. Результаты сохраняются в PostGIS для геопространственного анализа. Дашборд на Grafana отображает карту активности и динамику популяций.
AI-детектор видов для мониторинга биоразнообразия
import numpy as np
import cv2
import torch
from ultralytics import YOLO
from torchvision import models, transforms
from PIL import Image
from dataclasses import dataclass
from typing import Optional
import json
@dataclass
class WildlifeDetection:
track_id: int
species: str
common_name_ru: str
confidence: float
bbox: list
individual_id: Optional[str] # re-ID если обучена модель
behavior: Optional[str] # resting / moving / feeding
camera_id: str
timestamp: float
class WildlifeMonitor:
"""
Детекция и классификация диких животных по снимкам с фотоловушек.
Датасеты:
- iNaturalist (1.4M изображений, 5000+ видов) — для предобучения
- LILA BC (camera trap images) — leopard, snow leopard, пр.
- Snapshot Serengeti (22M изображений, 48 видов)
- CaltechCameraTraps (20 видов, Северная Америка)
Двухступенчатый пайплайн: YOLO detection → EfficientNet species classification.
"""
def __init__(self, detector_path: str,
classifier_path: str,
species_vocab_path: str,
reid_model_path: Optional[str] = None,
device: str = 'cuda'):
self.detector = YOLO(detector_path)
self.device = device
# Classifier: EfficientNet-B3 fine-tuned on iNaturalist
with open(species_vocab_path) as f:
vocab_data = json.load(f)
self.species_list = vocab_data['species']
self.species_ru = vocab_data.get('species_ru', {})
self.classifier = models.efficientnet_b3(pretrained=False)
n_classes = len(self.species_list)
self.classifier.classifier[-1] = torch.nn.Linear(
self.classifier.classifier[-1].in_features, n_classes
)
state = torch.load(classifier_path, map_location=device)
self.classifier.load_state_dict(state)
self.classifier = self.classifier.to(device).eval()
self.classify_transform = transforms.Compose([
transforms.Resize((300, 300)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
# Re-ID (опционально): мегапиксельная модель для паттернов меха
self.reid_model = None
if reid_model_path:
self.reid_model = torch.load(reid_model_path,
map_location=device).eval()
self._individual_gallery: dict[str, np.ndarray] = {}
def process_camera_trap_image(self, image: np.ndarray,
camera_id: str,
timestamp: float) -> list[WildlifeDetection]:
"""
Обработка снимка с фотоловушки.
Фотоловушки: ночные (ИК) + дневные, разное разрешение.
"""
# Улучшение ночного снимка
enhanced = self._enhance_camera_trap(image)
detections_raw = self.detector(
enhanced, conf=0.25, verbose=False
)
results = []
for box in detections_raw[0].boxes:
x1, y1, x2, y2 = map(int, box.xyxy[0])
track_id = int(box.id.item()) if box.id is not None else -1
# Вырезать crop для классификации
crop = enhanced[max(0,y1):y2, max(0,x1):x2]
if crop.size == 0:
continue
species, conf = self._classify_species(crop)
species_ru = self.species_ru.get(species, species)
behavior = self._estimate_behavior(crop, box)
# Re-ID
individual_id = None
if self.reid_model:
individual_id = self._get_individual_id(crop, species)
results.append(WildlifeDetection(
track_id=track_id,
species=species,
common_name_ru=species_ru,
confidence=round(conf, 3),
bbox=[x1, y1, x2, y2],
individual_id=individual_id,
behavior=behavior,
camera_id=camera_id,
timestamp=timestamp
))
return results
@torch.no_grad()
def _classify_species(self, crop: np.ndarray) -> tuple[str, float]:
pil = Image.fromarray(cv2.cvtColor(crop, cv2.COLOR_BGR2RGB))
tensor = self.classify_transform(pil).unsqueeze(0).to(self.device)
logits = self.classifier(tensor)
probs = torch.softmax(logits, dim=-1).squeeze()
conf, idx = probs.max(dim=0)
species = self.species_list[int(idx.item())]
return species, float(conf.item())
def _enhance_camera_trap(self, image: np.ndarray) -> np.ndarray:
"""Улучшение ИК-снимков фотоловушек"""
# Проверка на ИК (низкая цветность)
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
saturation = float(np.mean(hsv[:, :, 1]))
if saturation < 20: # ИК снимок
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
enhanced_gray = clahe.apply(gray)
return cv2.cvtColor(enhanced_gray, cv2.COLOR_GRAY2BGR)
# Дневной снимок с избыточной тенью
lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
lab[:, :, 0] = clahe.apply(lab[:, :, 0])
return cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
def _estimate_behavior(self, crop: np.ndarray,
box) -> str:
"""Простая классификация поведения по bbox aspect ratio"""
x1, y1, x2, y2 = map(int, box.xyxy[0])
w, h = x2 - x1, y2 - y1
aspect = w / max(h, 1)
if aspect > 2.0:
return 'resting' # лежит горизонтально
elif aspect < 0.6:
return 'alert' # стоит вертикально, голова поднята
return 'moving'
@torch.no_grad()
def _get_individual_id(self, crop: np.ndarray,
species: str) -> Optional[str]:
"""Re-ID через embedding similarity (для леопардов, тигров)"""
pil = Image.fromarray(cv2.cvtColor(crop, cv2.COLOR_BGR2RGB))
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
])
tensor = transform(pil).unsqueeze(0).to(self.device)
embedding = self.reid_model(tensor).squeeze().cpu().numpy()
embedding /= np.linalg.norm(embedding) + 1e-8
# Поиск в галерее
best_match = None
best_sim = 0.75 # порог
gallery_key = f'{species}_'
for ind_id, gallery_emb in self._individual_gallery.items():
if not ind_id.startswith(gallery_key):
continue
sim = float(np.dot(embedding, gallery_emb))
if sim > best_sim:
best_sim = sim
best_match = ind_id
if best_match is None:
# Новая особь
new_id = f'{species}_{len(self._individual_gallery)+1:04d}'
self._individual_gallery[new_id] = embedding
return new_id
return best_match
class AerialAnimalCounter:
"""
Подсчёт животных на аэрофотоснимках (дрон/самолёт).
Применение: мониторинг стад копытных, подсчёт пингвинов,
инвентаризация морских котиков на лежбищах.
SAHI обязателен для ортофото 50+ МПикс.
"""
from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction
def __init__(self, model_path: str, device: str = 'cuda'):
from sahi import AutoDetectionModel
self.sahi_model = AutoDetectionModel.from_pretrained(
model_type='ultralytics',
model_path=model_path,
confidence_threshold=0.35,
device=device
)
def count_herd(self, aerial_image: np.ndarray,
species_hint: str = 'ungulate') -> dict:
from sahi.predict import get_sliced_prediction
result = get_sliced_prediction(
aerial_image, self.sahi_model,
slice_height=640, slice_width=640,
overlap_height_ratio=0.2, overlap_width_ratio=0.2
)
count = len(result.object_prediction_list)
density = count / (aerial_image.shape[0] * aerial_image.shape[1] / 1e6)
return {
'species_hint': species_hint,
'count': count,
'density_per_km2': round(density * 1e6, 1), # пикс² → км²
'detections': [
{'bbox': [p.bbox.minx, p.bbox.miny, p.bbox.maxx, p.bbox.maxy],
'conf': p.score.value}
for p in result.object_prediction_list
]
}
Метрики точности и сроки реализации
Ниже — ориентировочные показатели качества для типичных задач мониторинга биоразнообразия. Метрики зависят от качества датасета и условий съёмки.
| Датасет / Задача | Метод | Метрика |
|---|---|---|
| iNaturalist (10k видов) | EfficientNet-B5 fine-tune | Top-1 85–91% |
| Snapshot Serengeti (48 видов) | YOLOv8 + classifier | mAP 73–79% |
| Aerial penguin count | SAHI + YOLOv8 | MAE < 3% |
| Re-ID (леопарды, AmurTiger) | ResNet50 + ArcFace | Rank-1 82–89% |
| Bioacoustics (BirdCLEF 2024) | BirdNET / PANN | cmAP 72–78% |
Акустический мониторинг биоразнообразия
Звуковые данные открывают доступ к видам, которые сложно обнаружить визуально. Ночные птицы, летучие мыши, водные млекопитающие — все они оставляют акустический след. Мы разворачиваем гидрофоны и акустические рекордеры (AudioMoth, SongMeter) и обрабатываем записи с помощью BirdNET и PANN.
Процесс акустического анализа включает три этапа. Сначала аудиофайл нарезается на сегменты по 3–5 секунд. Затем каждый сегмент преобразуется в мел-спектрограмму и передаётся в классификатор. Финальный шаг — post-processing: объединение смежных детекций одного вида в событие, фильтрация по минимальному порогу уверенности 0.5.
Точность BirdNET на птицах Европы и Северной Америки достигает cmAP 72–78% на соревновании BirdCLEF. Для экзотических или тропических видов требуется дообучение на региональных данных. Мы помогаем собрать и разметить обучающий корпус.
Интеграция с геоинформационными системами
Данные мониторинга хранятся в PostGIS. Каждое наблюдение имеет координаты, временную метку и идентификатор источника. QGIS и ArcGIS подключаются напрямую через PostGIS-коннектор. Для дашборда используем Grafana с плагином Geomap — сетка наблюдений обновляется каждый час.
Популяционные тренды рассчитываются через скользящее окно 30 дней. Аномальное снижение активности вида более чем на 30% от среднего базиса автоматически генерирует алерт. Это позволяет экологам оперативно реагировать на изменения до составления квартального отчёта.
Что входит в работу
- Аудит данных: инвентаризация датчиков, форматов и объёмов материала.
- Разметка и обучение: создание датасета, fine-tuning детектора и классификатора.
- Пайплайн обработки: автоматическая обработка снимков фотоловушек, ортофото или аудиозаписей.
- Картографический дашборд: визуализация активности видов на карте с фильтрами.
- Документация и обучение команды: инструкции по эксплуатации и API-спецификация.
- Техническая поддержка: 3 месяца сопровождения после запуска.
Ориентировочные сроки
| Задача | Срок |
|---|---|
| Camera trap classifier (один биом, 20–50 видов) | 5–8 недель |
| Полный pipeline: detection + classification + re-ID | 12–18 недель |
| Мониторинговая платформа с картой и отчётами | 18–28 недель |
Закажите консультацию — оценим ваши данные и предложим оптимальную архитектуру. Свяжитесь с нами для предварительного аудита материала. Мы помогли 15+ организациям автоматизировать мониторинг биоразнообразия: заповедники, экологические НКО, промышленные предприятия, проводящие оценку воздействия на окружающую среду. Гарантируем передачу исходного кода и документации после завершения проекта. Нашим клиентам важно, что система работает офлайн: все модели разворачиваются на собственной инфраструктуре, данные не покидают периметр.







