# ============================================================
# HOMOGRAPHY_INTEGRATION.py
# Как подключить homography-enabled motion saliency в main.py
# ============================================================

# ─────────────────────────────────────────────────────────────
# ИМПОРТЫ
# ─────────────────────────────────────────────────────────────
"""
from camera_motion import (
    estimate_ego_motion_adaptive,
    estimate_global_homography_ex,
    estimate_global_affine_ex,
    homography_is_plausible,
    affine_is_plausible,
    warp_is_plausible,
)
from motion_saliency import MotionSaliency
"""

# ─────────────────────────────────────────────────────────────
# ВАРИАНТ A (простой, рекомендуется начать с него):
# adaptive — homography с автоматическим fallback на affine
# ─────────────────────────────────────────────────────────────
"""
    motion_sal = MotionSaliency()
    prev_gray_for_ms = None
    ms_kind_stats = {"homography": 0, "affine": 0, "none": 0}

    # В главном цикле:
    gray_eff = cv2.cvtColor(frame_eff_bgr, cv2.COLOR_BGR2GRAY)

    M, kind, ego_inliers, ego_outliers = estimate_ego_motion_adaptive(
        prev_gray_for_ms, gray_eff
    )
    ms_kind_stats[kind] = ms_kind_stats.get(kind, 0) + 1

    if not warp_is_plausible(M, kind):
        M = None
        kind = "none"
        ego_outliers = np.zeros((0, 2), dtype=np.float32)

    # В терминальной фазе отключаем — слишком большой parallax
    ms_active = True
    if intercept_params is not None:
        phase = intercept_params.get("phase", "")
        if phase in ("terminal", "critical"):
            ms_active = False

    if ms_active:
        motion_sal.update(gray_eff, prev_gray_for_ms, M, kind=kind,
                          outlier_pts=ego_outliers)
    else:
        motion_sal.reset()

    prev_gray_for_ms = gray_eff
"""

# ─────────────────────────────────────────────────────────────
# ВАРИАНТ B (dual residual, максимально устойчивый):
# считаем обе модели, берём min residual. Дороже по CPU но
# устойчивее на сценах с несколькими плоскостями (горизонт+земля).
# ─────────────────────────────────────────────────────────────
"""
    # Считаем обе модели
    H, h_in, h_out, h_meta = estimate_global_homography_ex(
        prev_gray_for_ms, gray_eff
    )
    A, a_in, a_out = estimate_global_affine_ex(
        prev_gray_for_ms, gray_eff
    )

    # Фильтруем по качеству
    H_use = H if homography_is_plausible(H, h_meta) else None
    A_use = A if affine_is_plausible(A) else None

    # Объединяем outliers обеих моделей (точки, не объяснённые НИ одной)
    # — пересечение дает самый чистый сигнал, но можно и объединение
    if len(h_out) > 0 and len(a_out) > 0:
        # Простое объединение обычно достаточно
        ego_outliers = np.concatenate([h_out, a_out], axis=0)
    elif len(h_out) > 0:
        ego_outliers = h_out
    elif len(a_out) > 0:
        ego_outliers = a_out
    else:
        ego_outliers = np.zeros((0, 2), dtype=np.float32)

    motion_sal.update_dual(
        gray_eff, prev_gray_for_ms,
        H=H_use, A=A_use,
        outlier_pts=ego_outliers,
    )

    prev_gray_for_ms = gray_eff
"""

# ─────────────────────────────────────────────────────────────
# ТЮНИНГ ПО СЦЕНАМ
# ─────────────────────────────────────────────────────────────
#
# 1) Если в логах ms_kind_stats почти всегда "affine" — значит
#    homography не проходит пороги качества. Варианты:
#    - понизить HOMO_MIN_INLIERS до 35
#    - понизить HOMO_MIN_FILLED_CELLS до 3
#    - увеличить CAM_MOTION_MAX_CORNERS чтобы было больше точек
#
# 2) Если homography выбирается часто но daёт странные residual
#    (вся земля горит) — это признак того, что она фитится в
#    одну плоскость (небо), а земля как вторая плоскость даёт
#    fake residual. Решение — переключиться на Variant B (dual),
#    min-из-двух карт это исправляет.
#
# 3) Для сложных сцен с ЛЭП и лесом рекомендую сразу Variant B.
#    Overhead ~2x по CPU для ego-motion, но motion_saliency
#    всё равно дешёвый относительно YOLO, общий FPS просядет
#    минимально.
#
# 4) Если летите очень низко над лесом (parallax огромный, никакая
#    модель не помогает) — тогда motion saliency просто отключайте
#    на такие периоды по высоте/скорости носителя, а полагайтесь
#    на KLT+IMM которые у вас уже есть.
#
# 5) Если homography выдаёт вырожденные матрицы часто — уменьшите
#    HOMO_MAX_CORNER_SHIFT до 80, это агрессивнее отсеивает плохие
#    фиты (ценой иногда пропустить валидный резкий манёвр камеры).

# ─────────────────────────────────────────────────────────────
# ДИАГНОСТИКА
# ─────────────────────────────────────────────────────────────
# В конце сессии напечатайте статистику:
"""
    total = sum(ms_kind_stats.values())
    if total > 0:
        print(f"Ego motion stats: "
              f"homography={ms_kind_stats['homography']/total*100:.1f}% "
              f"affine={ms_kind_stats['affine']/total*100:.1f}% "
              f"none={ms_kind_stats['none']/total*100:.1f}%")
"""
# Здоровая статистика на вашем типе данных:
#   homography: 50-80% (когда хватает текстуры)
#   affine:     15-40% (чистое небо, слабая текстура)
#   none:       < 5%   (если больше — проблема с LK/feature detection)
