You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

822 lines
25 KiB
Python

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import cv2
# Configuration and tunables (extracted from original script)
# =========================
# ВАЖНО: укажите путь к новой YOLO11s-P2-CBAM модели (best.pt, imgsz=1280)
MODEL_PATH = r"D:\PycharmProjects\YOLOTrain\BYTETRACK\TEST\fpv_tracker_optimized\best.pt"
DEVICE = 0
USE_HALF = True
# Универсальный источник:
# Видео:
# SOURCE = r"C:\Users\Legion\Desktop\dataset01.26\24-01_2.mp4"
# Камера / capture card:
#SOURCE = 0
# SOURCE = 1
# RTSP:
# SOURCE = "rtsp://192.168.1.10:8554/live"
# UDP:
# SOURCE = "udp://@0.0.0.0:5600"
SOURCE = r"C:\Users\Legion\Desktop\Видео для МАИ ФУЛЛ\Группа 1\23-01_10один.mp4"
VIDEO_REALTIME = True
# Windows:
CAP_BACKEND = cv2.CAP_DSHOW # или cv2.CAP_MSMF
# Linux обычно:
# CAP_BACKEND = cv2.CAP_V4L2
SHOW_OUTPUT = True
WINDOW_NAME = "FPV LOCK PAL + ByteTrack"
TARGET_OUT_FPS = 0 # <=0: file -> source fps, camera/stream -> no forced pacing
# Frame timebase / dt stabilization
TIMESTAMP_USE_SOURCE_CLOCK = True
INPUT_FPS_FALLBACK = 25.0
DT_MIN_SEC = 1.0 / 120.0
DT_MAX_SEC = 0.20
DT_RESET_GAP_SEC = 0.40
# Effective resolution policy (for analog PAL)
EFFECTIVE_W = 720
EFFECTIVE_H = 576
FORCE_EFFECTIVE_PAL = True
# YOLO inference settings
CONF = 0.25
IMG_SIZE_ROI = 640
IMG_SIZE_FULL = 1280
MAX_DET = 60
TARGET_CLASS_ID = 0
# Filters (small drones far away)
MIN_BOX_AREA = 8
MAX_BOX_AREA = 0
ASPECT_RANGE = (0.15, 6.0)
# FSM
CONFIRM_HITS = 2
MAX_MISSES = 20
RECOVER_FULLSCAN_EVERY = 30
RECOVER_FORCED_DET_EVERY = 2
# ROI sizing (in effective pixels)
BASE_RADIUS = 150
MAX_RADIUS = 520
SPEED_RADIUS_FACTOR = 18.0
FORWARD_BIAS = 1.8
SIDE_BIAS = 1.2
# KLT optical flow tracker (effective)
KLT_MAX_CORNERS = 140
KLT_QUALITY = 0.01
KLT_MIN_DIST = 6
KLT_WIN = (21, 21)
KLT_MAX_LEVEL = 3
KLT_OUTLIER_THRESH = 20.0
# KLT validity gates (anti-drift)
KLT_OK_Q = 0.22
KLT_OK_PTS = 14
KLT_REINIT_MIN_POINTS = 18
KLT_REFRESH_WITH_YOLO = True
KLT_REFRESH_EVERY = 6
KLT_REFRESH_MIN_SCORE = 0.18
KLT_REFRESH_MIN_IOU = 0.25
KLT_REFRESH_MIN_QUALITY = 0.35
# YOLO safety
YOLO_NO_DET_LIMIT = 20
# Robust single-target logic
GAP_MAX_SECONDS = 1.2
ACQUIRE_CONFIRM_SCORE = 6
ACQUIRE_HIT_BONUS = 2
ACQUIRE_MISS_PENALTY = 1
ACQUIRE_MAX_MISS = 90
LOCK_MAX_MISS_FRAMES = 120
FULLSCAN_WHEN_MISS_GE = 16
# Template matching fallback
TM_ENABLE = True
TM_TEMPLATE_SIZE = 40
TM_SEARCH_SCALE_BASE = 2.5
TM_SEARCH_SCALE_PER_MISS = 0.20
TM_MIN_SCORE = 0.55
# Kalman safety limits
KALMAN_CLAMP_V_PX_S = 180.0
KALMAN_RESET_IF_OUT_OF_FRAME = True
YOLO_FRESH_SEC = 0.50
YOLO_FORCE_DET_WHEN_WEAK = True
KALMAN_Q_DT_BOOST_ENABLE = True
KALMAN_Q_DT_BOOST_START_SEC = 0.08
KALMAN_Q_DT_BOOST_SLOPE = 16.0
KALMAN_Q_DT_BOOST_MAX = 4.0
# Appearance gate
USE_HSV_GATE = False
HSV_HIST_BINS = (16, 16)
HSV_GATE_MIN_SIM = 0.06
HSV_UPDATE_EVERY = 8
# Async YOLO worker
YOLO_QUEUE_MAX = 1
# Debug / draw
DEBUG = True
DRAW_ALL_BOXES = True
DRAW_LOCK_BOX = True
DRAW_KALMAN = True
DRAW_KLT_POINTS = False
DRAW_BT_TRACKS = True
BT_DRAW_ONLY_CONFIRMED = False
# Output recording
SAVE_INFER_VIDEO = True
OUT_VIDEO_PATH = "out_infer.mp4"
TRACK_LOG_ENABLE = True
TRACK_LOG_PATH = "track_log.csv"
TRACK_SUMMARY_PATH = "track_summary.json"
TRACK_LOG_FLUSH_EVERY = 30
# Screen-space lock/guidance layer for simulator integration
GUIDANCE_ENABLE = True
DRAW_GUIDANCE = True
GUIDANCE_EXPORT_ENABLE = True
GUIDANCE_EXPORT_PATH = "guidance_state.json"
GUIDANCE_EXPORT_EVERY = 1
GUIDANCE_LEAD_SEC = 0.12
GUIDANCE_MAX_LEAD_PX = 90.0
GUIDANCE_BOX_BIAS_Y = 0.0
GUIDANCE_DEADZONE_NORM = 0.04
GUIDANCE_EXPO = 1.35
GUIDANCE_GAIN_X = 1.0
GUIDANCE_GAIN_Y = 1.0
GUIDANCE_CMD_SMOOTH = 0.70
GUIDANCE_POINT_SMOOTH = 0.55
GUIDANCE_CONF_MIN = 0.35
GUIDANCE_ON_TARGET_NORM = 0.12
GUIDANCE_LOOK_MAX_STEP_PX = 28.0
GUIDANCE_OVERRIDE_ENABLE = True
GUIDANCE_OVERRIDE_MISS_GE = 2
GUIDANCE_OVERRIDE_TTL = 2
# Trajectory drawing
DRAW_TRAJ = False
TRAIL_SECONDS = 1.2
TRAIL_ALPHA = 0.25
TRAIL_DRAW_EVERY_N = 2
TRAIL_MIN_STEP_PX = 3
CLEAR_TRAJ_ON_RECOVER = True
DRAW_TRAJ_ONLY_WHEN_LOCKED = True
DRAW_KALMAN_WHEN_MISS_LE = 8
# Camera motion compensation
USE_CAM_MOTION_COMP = True
CAM_MOTION_MAX_CORNERS = 500
CAM_MOTION_QL = 0.01
CAM_MOTION_MIN_DIST = 12
CAM_MOTION_RANSAC_THR = 3.0
CAM_MOTION_MAX_SHIFT_PX = 55.0
CAM_MOTION_SCALE_MIN = 0.90
CAM_MOTION_SCALE_MAX = 1.10
CAM_MOTION_MAX_ROT_DEG = 12.0
CAM_MOTION_EXCLUDE_NORM = [
(0.00, 0.00, 0.25, 0.85),
(0.75, 0.00, 1.00, 0.85),
(0.00, 0.00, 1.00, 0.12),
(0.30, 0.86, 0.70, 1.00),
]
# ByteTrack settings
BT_HIGH = 0.25
BT_LOW = 0.03
BT_NEW = 0.12
BT_MATCH_IOU = 0.15
BT_BUFFER = 140
BT_MIN_HITS = 1
BT_MAX_PREDICT_AGE = 6
YOLO_CONF_EFFECTIVE = min(CONF, BT_LOW)
KALMAN_HOLD_MAX = 10
# Single-target lock policy
TARGET_SWITCH_MISS_FRAMES = 1
TARGET_PICK_MIN_SCORE = 0.00
TARGET_REACQ_DIST_FACTOR = 7.5
TURN_MAX_ASPECT_RATIO = 6.0
TURN_MAX_AREA_RATIO = 9.0
TARGET_SWITCH_CONFIRM_HITS = 1
TARGET_STICKY_SCORE_BONUS = 0.45
TARGET_SWITCH_IOU_FLOOR = 0.0
STALE_LOCK_BREAK_ENABLE = False
STALE_LOCK_BREAK_DIST_DIAG = 3.5
STALE_LOCK_BREAK_MIN_MISS = 2
STALE_LOCK_BREAK_KLT_QUALITY = 0.35
STALE_LOCK_BREAK_KLT_IOU = 0.25
FAST_HANDOFF_ENABLE = False
FAST_HANDOFF_CONFIRM_HITS = 2
FAST_HANDOFF_GUIDANCE_CMD_DAMP = 0.0
CONFIRMED_NO_ID_NEAR_FACTOR = 2.6
CONFIRMED_NO_ID_NEAR_MIN = 26.0
APPROACH_MODE_ENABLE = True
ADAPTIVE_CHASE_ENABLE = True
ADAPTIVE_STAGE_MID_AREA = 260.0
APPROACH_CLOSE_AREA = 850.0
ADAPTIVE_STAGE_AREA_HYST = 120.0
APPROACH_MID_FORCE_DET_EVERY = 2
APPROACH_FORCE_DET_AREA = 850.0
APPROACH_FORCE_DET_EVERY = 1
APPROACH_MID_KF_ROI_SCALE = 1.15
APPROACH_KF_ROI_SCALE = 1.35
APPROACH_MID_MAX_AREA_RATIO = 14.0
APPROACH_MAX_AREA_RATIO = 24.0
APPROACH_MID_NEAR_DIST_DIAG = 1.35
APPROACH_NEAR_DIST_DIAG = 1.6
APPROACH_HSV_RELAX_GROW_RATIO = 2.5
APPROACH_MID_HSV_MIN_SCALE = 0.65
APPROACH_HSV_MIN_SCALE = 0.35
APPROACH_MID_SCORE_WEIGHT = 0.08
APPROACH_MID_SCORE_CLIP = 0.16
APPROACH_SCORE_WEIGHT = 0.18
APPROACH_SCORE_CLIP = 0.35
APPROACH_MID_SWITCH_EXTRA_MISS = 1
APPROACH_MID_SWITCH_EXTRA_HITS = 1
APPROACH_CLOSE_SWITCH_EXTRA_MISS = 2
APPROACH_CLOSE_SWITCH_EXTRA_HITS = 2
CLOSE_FORCE_FULLSCAN = True
PART_MERGE_ENABLE = True
PART_MERGE_MIN_PARTS = 2
PART_MERGE_MIN_REF_DIAG = 28.0
PART_MERGE_REF_DIST_DIAG = 2.2
PART_MERGE_CLUSTER_DIST_DIAG = 1.4
PART_MERGE_IOU_FLOOR = 0.02
PART_MERGE_MIN_UNION_GAIN = 1.35
PART_MERGE_MAX_UNION_RATIO = 40.0
PART_MERGE_MAX_ASPECT = 8.0
PART_MERGE_SCORE_BONUS = 0.03
SWITCH_FAST_MANEUVER_ENABLE = True
SWITCH_FAST_MANEUVER_SPEED = 60.0
SWITCH_FAST_MANEUVER_EXTRA_MISS = 2
SWITCH_FAST_MANEUVER_EXTRA_HITS = 2
# Switch-only trajectory gate (candidate must be kinematically plausible
# относительно направления цели)
SWITCH_TRAJ_GATE_ENABLE = True
SWITCH_TRAJ_MISS_GE = 1
SWITCH_TRAJ_MIN_SPEED = 1.2
SWITCH_TRAJ_COS_MIN = 0.10
SWITCH_TRAJ_PERP_DIAG = 0.35
SWITCH_TRAJ_PERP_MIN = 10.0
SWITCH_TRAJ_REQUIRE_RESIDUAL_BYPASS = True
# Switch-only anti-static gate (reject candidates that do not move over time)
SWITCH_STATIC_GUARD_ENABLE = True
SWITCH_TRACK_HIST_WINDOW = 8
SWITCH_STATIC_MIN_DISP = 4.0
SWITCH_STATIC_MIN_DIAG = 0.10
SWITCH_STATIC_REQUIRE_RESIDUAL_BYPASS = True
# Weak-reacquire guard (suppress one-frame turn false positives)
WEAK_REACQ_GUARD_ENABLE = True
WEAK_REACQ_MISS_GE = 6
WEAK_REACQ_MIN_HITS = 2
WEAK_REACQ_MIN_SCORE = 0.05
WEAK_REACQ_MAX_DIST_FACTOR = 4.0
WEAK_REACQ_MAX_DIST_MIN = 24.0
WEAK_REACQ_ADOPT_HITS = 3
# Separate score floors for actual target adoption.
# ByteTrack still receives low-score candidates, but lock/switch decisions
# require stronger track evidence.
TRACK_SCORE_MIN_ACQUIRE = 0.08
TRACK_SCORE_MIN_REACQUIRE = 0.07
TRACK_SCORE_MIN_SWITCH = 0.10
# Provisional reacquire memory (keep priority near last true micro-detection)
PROVISIONAL_HOLD_ENABLE = True
PROVISIONAL_HOLD_MAX = 8
PROVISIONAL_HIT_DECAY = 1
RECOVER_NEAR_DIST_FACTOR = 3.2
RECOVER_NEAR_DIST_MIN = 26.0
# Analog FPV hardening
ANALOG_FPV_MODE = True
APPLY_YOLO_PREPROC = True
PRE_CLAHE_CLIP = 2.2
PRE_CLAHE_TILE = (8, 8)
PRE_BLUR_K = 3
PRE_UNSHARP = 0.12
# OSD false positives rejection
REJECT_OSD_ZONES = True
REJECT_OSD_SMALL_AREA_MAX = 2600.0
REJECT_OSD_ZONES_NORM = [
(0.00, 0.00, 0.20, 0.80),
(0.80, 0.00, 1.00, 0.80),
(0.00, 0.00, 1.00, 0.08),
(0.35, 0.90, 0.65, 1.00),
]
# Additional lock-switch guard: do not switch to candidates inside OSD zones
# when they are far from predicted target position.
OSD_SWITCH_BLOCK_ENABLE = True
OSD_SWITCH_BLOCK_DIST_DIAG = 1.25
# Turn-safe recovery
TURN_SAFE_ENABLE = True
TURN_SAFE_UNC_LIMIT = 2800.0
TURN_SAFE_MISS_BEFORE_RESET = 12
TURN_SAFE_FORCE_FULLSCAN = True
TURN_SAFE_MIN_SCORE = 0.08
TURN_SAFE_REQUIRE_TRACK_ID = True
# Safety against drifting "CONFIRMED" state without a valid track anchor
CONFIRMED_NO_ID_MAX_MISS = 3
# Motion-zone recover assist (for tiny distant targets)
MOTION_ZONE_ENABLE = True
MOTION_ZONE_GRID = (8, 6)
MOTION_DIFF_THR = 16
MOTION_BLUR_K = 3
MOTION_MORPH_K = 3
MOTION_ZONE_MIN_PIXELS = 10
MOTION_ZONE_MIN_RATIO = 0.0012
MOTION_MAX_ACTIVE_ZONE_RATIO = 0.55
MOTION_ROI_MARGIN = 28
MOTION_ROI_MIN_SIZE = 80
DRAW_MOTION_ROI = False
MOTION_TURN_THR_GAIN = 2.0
MOTION_TURN_THR_MAX_BONUS = 10
MOTION_ZONE_HEAT_DECAY = 0.88
MOTION_ZONE_HEAT_BOOST = 1.0
MOTION_ZONE_HEAT_CLIP = 4.0
MOTION_ZONE_HEAT_MIN = 0.65
MOTION_ZONE_HOT_FAVOR_BONUS = 0.35
MOTION_ZONE_ENFORCE_HOT = True
MOTION_ZONE_ENFORCE_MISS_GE = 2
# Use motion ROI also in CONFIRMED state when target starts slipping.
MOTION_CONF_ENABLE = True
MOTION_CONF_MISS_GE = 2
MOTION_CONF_KLT_INVALID_ONLY = True
# Extra anti-jump guard for switching while using motion/wave ROI in CONFIRMED state.
MOTION_CONF_SWITCH_MISS_FRAMES = 3
MOTION_CONF_SWITCH_MIN_HITS = 2
MOTION_CONF_SWITCH_MIN_SCORE = 0.08
MOTION_CONF_SWITCH_IOU_FLOOR = 0.05
MOTION_CONF_SWITCH_DIST_DIAG = 0.90
MOTION_CONF_SWITCH_CONFIRM_HITS = 4
MOTION_CONF_SWITCH_REQUIRE_RESIDUAL = True
# While confirmed+miss, force periodic FULL scans so detector can reacquire globally.
CONF_MISS_FORCE_FULLSCAN_EVERY = 8
EGO_RESIDUAL_GATE_ENABLE = True
EGO_RESIDUAL_MISS_GE = 2
EGO_RESIDUAL_MIN_PIXELS = 2
EGO_RESIDUAL_MIN_RATIO = 0.006
# Wavelet assist (tiny distant target recover)
WAVELET_ASSIST_ENABLE = True
WAVELET_ACTIVE_MISS_GE = 2
WAVELET_ONLY_UNCONFIRMED = True
WAVELET_ONLY_RECOVER_PHASE = True
WAVELET_BOX_MARGIN = 8
WAVELET_MIN_SIDE = 20
WAVELET_GATE_TINY_AREA_MAX = 260.0
WAVELET_GATE_MISS_GE = 2
WAVELET_GATE_MIN_ENERGY = 0.14
WAVELET_ENERGY_BASE = 0.22
WAVELET_SCORE_WEIGHT = 0.28
WAVELET_SCORE_CLIP = 0.35
# Temporal M/N stabilization for wavelet (per track id)
WAVELET_MN_ENABLE = True
WAVELET_MN_WINDOW = 4
WAVELET_MN_MIN_HITS = 1
WAVELET_MN_MISS_GE = 2
# Wavelet-driven micro ROI for recover
WAVELET_ROI_ENABLE = True
WAVELET_ROI_MISS_GE = 2
WAVELET_ROI_CONF_MISS_GE = 6
WAVELET_ROI_TTL = 4
WAVELET_ROI_EVERY_N = 3
WAVELET_ROI_MARGIN = 20
WAVELET_ROI_MIN_SIDE = 84
WAVELET_ROI_PRED_SCALE = 3.0
WAVELET_ROI_MIN_PEAK_RATIO = 1.5
# AutoGaze assist (optional ROI prior for recover)
AUTOGAZE_ENABLE = False
AUTOGAZE_MODEL_ID = "nvidia/AutoGaze" # can be HF id or local folder
AUTOGAZE_USE_FLASH_ATTN = False # keep False unless flash-attn is installed and stable
AUTOGAZE_LOCAL_FILES_ONLY = True # avoids HF network retries; set False to download/update model
AUTOGAZE_CLIP_LEN = 16
AUTOGAZE_UPDATE_EVERY = 3
AUTOGAZE_GAZING_RATIO = 0.75
AUTOGAZE_TASK_LOSS_REQUIREMENT = 0.70
AUTOGAZE_RESULT_TTL = 12
AUTOGAZE_MISS_GE = 2
AUTOGAZE_CONF_MISS_GE = 2
AUTOGAZE_TOPK = 2
AUTOGAZE_MIN_ACTIVE_CELLS = 1
AUTOGAZE_ROI_MARGIN_CELLS = 1
AUTOGAZE_ROI_MIN_SIDE = 90
DRAW_AUTOGAZE_ROI = False
MODULE_TIME_BUDGET_MS = 30.0
AUTOGAZE_COOLDOWN_FRAMES = 12
WAVELET_COOLDOWN_FRAMES = 8
# Recover anti-noise gates for tiny distant target
RECOVER_FILTER_ENABLE = True
RECOVER_MIN_SCORE = 0.03
RECOVER_TINY_AREA_MAX = 180.0
RECOVER_TINY_MIN_SCORE = 0.045
RECOVER_TINY_MIN_MOTION_PIXELS = 1
RECOVER_TINY_MIN_MOTION_RATIO = 0.003
RECOVER_TARGET_MIN_HITS = 1
# Keep scanning around last brief detection to stabilize reacquire
FLASH_ROI_ENABLE = True
FLASH_ROI_TTL = 7
FLASH_ROI_MARGIN = 72
FLASH_ROI_MIN_SIDE = 90
FLASH_ROI_MIN_SCORE = 0.04
# Anti-stall recover (avoid getting stuck in wrong ROI-KF when detections disappear)
RECOVER_ROI_KF_DISABLE_MISS_GE = 6
RECOVER_FORCE_MOTION_FIRST_MISS_GE = 8
RECOVER_FORCE_FULLSCAN_MISS_GE = 18
# Pre-acquire for tiny distant target (M/N logic before stable track-id appears)
PREACQ_ENABLE = True
PREACQ_WINDOW = 7
PREACQ_MIN_HITS = 3
PREACQ_MIN_SCORE = 0.035
PREACQ_NEAR_FACTOR = 3.4
PREACQ_NEAR_MIN = 20.0
PREACQ_ACQ_BONUS = 2
PREACQ_INIT_KF_ON_MN = True
# Anti-false profile: "soft" (max recall), "medium", "hard", "hard_far"
ANTI_FP_PROFILE = "hard_far"
ACTIVE_ANTI_FP_PROFILE = "custom"
def apply_anti_fp_profile():
global CONFIRM_HITS, TARGET_SWITCH_CONFIRM_HITS
global BT_NEW, BT_MATCH_IOU, BT_LOW, YOLO_CONF_EFFECTIVE
global TRACK_SCORE_MIN_ACQUIRE, TRACK_SCORE_MIN_REACQUIRE, TRACK_SCORE_MIN_SWITCH
global RECOVER_MIN_SCORE, RECOVER_TINY_MIN_SCORE, RECOVER_TINY_MIN_MOTION_PIXELS
global RECOVER_TINY_MIN_MOTION_RATIO, RECOVER_TARGET_MIN_HITS
global WEAK_REACQ_MISS_GE, WEAK_REACQ_MIN_HITS, WEAK_REACQ_MIN_SCORE, WEAK_REACQ_ADOPT_HITS
global RECOVER_NEAR_DIST_FACTOR, PROVISIONAL_HOLD_MAX, PROVISIONAL_HIT_DECAY
global MOTION_DIFF_THR, MOTION_ZONE_MIN_RATIO, MOTION_MAX_ACTIVE_ZONE_RATIO
global MOTION_ZONE_HEAT_MIN, MOTION_ZONE_HOT_FAVOR_BONUS, MOTION_ZONE_ENFORCE_MISS_GE
global EGO_RESIDUAL_MISS_GE, EGO_RESIDUAL_MIN_PIXELS, EGO_RESIDUAL_MIN_RATIO
global ACTIVE_ANTI_FP_PROFILE
p = str(ANTI_FP_PROFILE).strip().lower()
if p not in ("soft", "medium", "hard", "hard_far"):
p = "medium"
ACTIVE_ANTI_FP_PROFILE = p
if p == "soft":
CONFIRM_HITS = 2
TARGET_SWITCH_CONFIRM_HITS = 1
BT_LOW = 0.03
BT_NEW = 0.12
BT_MATCH_IOU = 0.15
RECOVER_MIN_SCORE = 0.03
RECOVER_TINY_MIN_SCORE = 0.045
RECOVER_TINY_MIN_MOTION_PIXELS = 1
RECOVER_TINY_MIN_MOTION_RATIO = 0.003
RECOVER_TARGET_MIN_HITS = 1
TRACK_SCORE_MIN_ACQUIRE = 0.06
TRACK_SCORE_MIN_REACQUIRE = 0.05
TRACK_SCORE_MIN_SWITCH = 0.08
WEAK_REACQ_MISS_GE = 8
WEAK_REACQ_MIN_HITS = 1
WEAK_REACQ_MIN_SCORE = 0.045
WEAK_REACQ_ADOPT_HITS = 2
RECOVER_NEAR_DIST_FACTOR = 3.8
PROVISIONAL_HOLD_MAX = 10
PROVISIONAL_HIT_DECAY = 1
MOTION_DIFF_THR = 16
MOTION_ZONE_MIN_RATIO = 0.0012
MOTION_MAX_ACTIVE_ZONE_RATIO = 0.60
MOTION_ZONE_HEAT_MIN = 0.55
MOTION_ZONE_HOT_FAVOR_BONUS = 0.25
MOTION_ZONE_ENFORCE_MISS_GE = 3
EGO_RESIDUAL_MISS_GE = 4
EGO_RESIDUAL_MIN_PIXELS = 1
EGO_RESIDUAL_MIN_RATIO = 0.002
elif p == "medium":
CONFIRM_HITS = 3
TARGET_SWITCH_CONFIRM_HITS = 2
BT_LOW = 0.03
BT_NEW = 0.14
BT_MATCH_IOU = 0.17
RECOVER_MIN_SCORE = 0.04
RECOVER_TINY_MIN_SCORE = 0.060
RECOVER_TINY_MIN_MOTION_PIXELS = 2
RECOVER_TINY_MIN_MOTION_RATIO = 0.008
RECOVER_TARGET_MIN_HITS = 2
TRACK_SCORE_MIN_ACQUIRE = 0.08
TRACK_SCORE_MIN_REACQUIRE = 0.07
TRACK_SCORE_MIN_SWITCH = 0.10
WEAK_REACQ_MISS_GE = 5
WEAK_REACQ_MIN_HITS = 2
WEAK_REACQ_MIN_SCORE = 0.060
WEAK_REACQ_ADOPT_HITS = 3
RECOVER_NEAR_DIST_FACTOR = 2.9
PROVISIONAL_HOLD_MAX = 7
PROVISIONAL_HIT_DECAY = 1
MOTION_DIFF_THR = 17
MOTION_ZONE_MIN_RATIO = 0.0016
MOTION_MAX_ACTIVE_ZONE_RATIO = 0.50
MOTION_ZONE_HEAT_MIN = 0.70
MOTION_ZONE_HOT_FAVOR_BONUS = 0.35
MOTION_ZONE_ENFORCE_MISS_GE = 2
EGO_RESIDUAL_MISS_GE = 2
EGO_RESIDUAL_MIN_PIXELS = 2
EGO_RESIDUAL_MIN_RATIO = 0.006
else: # hard / hard_far
CONFIRM_HITS = 3
TARGET_SWITCH_CONFIRM_HITS = 3
BT_LOW = 0.035
BT_NEW = 0.11
BT_MATCH_IOU = 0.17
RECOVER_MIN_SCORE = 0.05
RECOVER_TINY_MIN_SCORE = 0.075
RECOVER_TINY_MIN_MOTION_PIXELS = 3
RECOVER_TINY_MIN_MOTION_RATIO = 0.015
RECOVER_TARGET_MIN_HITS = 3
TRACK_SCORE_MIN_ACQUIRE = 0.10
TRACK_SCORE_MIN_REACQUIRE = 0.09
TRACK_SCORE_MIN_SWITCH = 0.12
WEAK_REACQ_MISS_GE = 3
WEAK_REACQ_MIN_HITS = 3
WEAK_REACQ_MIN_SCORE = 0.080
WEAK_REACQ_ADOPT_HITS = 3
RECOVER_NEAR_DIST_FACTOR = 2.4
PROVISIONAL_HOLD_MAX = 5
PROVISIONAL_HIT_DECAY = 2
MOTION_DIFF_THR = 19
MOTION_ZONE_MIN_RATIO = 0.0022
MOTION_MAX_ACTIVE_ZONE_RATIO = 0.42
MOTION_ZONE_HEAT_MIN = 0.85
MOTION_ZONE_HOT_FAVOR_BONUS = 0.45
MOTION_ZONE_ENFORCE_MISS_GE = 1
EGO_RESIDUAL_MISS_GE = 1
EGO_RESIDUAL_MIN_PIXELS = 3
EGO_RESIDUAL_MIN_RATIO = 0.010
YOLO_CONF_EFFECTIVE = min(CONF, BT_LOW)
apply_anti_fp_profile()
# ===== Chase-drone preset overrides (applied after anti-fp profile) =====
# Ужесточаем переключение на альтернативный track, чтобы меньше липнуть на землю.
CONFIRM_HITS = 4
ACQUIRE_CONFIRM_SCORE = 8
PREACQ_MIN_HITS = 4
PREACQ_MIN_SCORE = 0.05
TARGET_SWITCH_MISS_FRAMES = 3
TARGET_SWITCH_CONFIRM_HITS = 4
TARGET_SWITCH_IOU_FLOOR = 0.10
TARGET_REACQ_DIST_FACTOR = 5.5
TRACK_SCORE_MIN_ACQUIRE = 0.10
TRACK_SCORE_MIN_REACQUIRE = 0.09
TRACK_SCORE_MIN_SWITCH = 0.14
# Switch gates preset for chase-scene
SWITCH_TRAJ_GATE_ENABLE = True
SWITCH_TRAJ_MISS_GE = 1
SWITCH_TRAJ_MIN_SPEED = 8.0
SWITCH_TRAJ_COS_MIN = 0.18
SWITCH_TRAJ_PERP_DIAG = 0.28
SWITCH_TRAJ_PERP_MIN = 9.0
SWITCH_TRAJ_REQUIRE_RESIDUAL_BYPASS = True
SWITCH_STATIC_GUARD_ENABLE = True
SWITCH_TRACK_HIST_WINDOW = 8
SWITCH_STATIC_MIN_DISP = 5.0
SWITCH_STATIC_MIN_DIAG = 0.12
SWITCH_STATIC_REQUIRE_RESIDUAL_BYPASS = True
WEAK_REACQ_MISS_GE = 4
WEAK_REACQ_MIN_HITS = 3
WEAK_REACQ_MIN_SCORE = 0.09
WEAK_REACQ_ADOPT_HITS = 5
MOTION_CONF_SWITCH_MIN_SCORE = 0.12
MOTION_CONF_SWITCH_CONFIRM_HITS = 6
MOTION_CONF_SWITCH_DIST_DIAG = 0.70
MOTION_CONF_SWITCH_IOU_FLOOR = 0.10
# Режем псевдодвижение земли.
EGO_RESIDUAL_MIN_PIXELS = 3
EGO_RESIDUAL_MIN_RATIO = 0.010
RECOVER_MIN_SCORE = 0.05
RECOVER_TINY_MIN_SCORE = 0.08
RECOVER_TARGET_MIN_HITS = 2
TURN_SAFE_MIN_SCORE = 0.12
# Appearance gate для подавления статичных ложняков.
USE_HSV_GATE = True
HSV_GATE_MIN_SIM = 0.10
HSV_UPDATE_EVERY = 4
# Wavelet чаще цепляет текстуру земли на chase-сценах.
WAVELET_ROI_ENABLE = False
# AutoGaze подключаем только на более явном срыве.
AUTOGAZE_MISS_GE = 4
AUTOGAZE_CONF_MISS_GE = 3
AUTOGAZE_TOPK = 1
AUTOGAZE_UPDATE_EVERY = 4
AUTOGAZE_RESULT_TTL = 8
# ===== Soft handoff patch for tiny FPV chase targets =====
# Lets YOLO refresh Kalman/KLT even when ByteTrack changes track_id.
SOFT_YOLO_HANDOFF_ENABLE = True
SOFT_YOLO_MIN_MISS = 1
SOFT_YOLO_MIN_ABSENT = 1
SOFT_YOLO_MIN_SCORE = 0.055
SOFT_YOLO_DIST_DIAG = 8.0
SOFT_YOLO_DIST_MIN = 48.0
SOFT_YOLO_IOU_FLOOR = 0.0
SOFT_YOLO_MAX_AREA_RATIO = 18.0
SOFT_YOLO_MAX_ASPECT_RATIO = 8.0
SOFT_YOLO_TRACK_IOU = 0.02
SOFT_YOLO_TRACK_DIST_DIAG = 2.2
SOFT_YOLO_TRACK_DIST_MIN = 32.0
SOFT_YOLO_REFRESH_KLT = True
# Keep a valid KLT anchor alive instead of letting prediction hold run to miss=10.
KLT_VALID_HOLD_ENABLE = True
KLT_VALID_HOLD_MAX_MISS = 3
# Make handoff less rigid. The old chase preset required several frames plus
# approach/fast extras, so swHit often stayed at 1 and the lock was lost.
TARGET_SWITCH_MISS_FRAMES = 1
TARGET_SWITCH_CONFIRM_HITS = 1
TARGET_SWITCH_IOU_FLOOR = 0.0
TRACK_SCORE_MIN_SWITCH = 0.07
WEAK_REACQ_MISS_GE = 2
WEAK_REACQ_MIN_HITS = 1
WEAK_REACQ_MIN_SCORE = 0.05
WEAK_REACQ_ADOPT_HITS = 1
MOTION_CONF_SWITCH_MIN_HITS = 1
MOTION_CONF_SWITCH_MIN_SCORE = 0.06
MOTION_CONF_SWITCH_CONFIRM_HITS = 1
MOTION_CONF_SWITCH_DIST_DIAG = 1.25
MOTION_CONF_SWITCH_IOU_FLOOR = 0.0
MOTION_CONF_SWITCH_REQUIRE_RESIDUAL = False
APPROACH_MID_SWITCH_EXTRA_MISS = 0
APPROACH_MID_SWITCH_EXTRA_HITS = 0
APPROACH_CLOSE_SWITCH_EXTRA_MISS = 0
APPROACH_CLOSE_SWITCH_EXTRA_HITS = 0
SWITCH_FAST_MANEUVER_EXTRA_MISS = 0
SWITCH_FAST_MANEUVER_EXTRA_HITS = 0
SWITCH_TRAJ_GATE_ENABLE = False
STALE_LOCK_BREAK_ENABLE = True
STALE_LOCK_BREAK_DIST_DIAG = 0.8
STALE_LOCK_BREAK_MIN_MISS = 1
FAST_HANDOFF_ENABLE = True
FAST_HANDOFF_CONFIRM_HITS = 1
FAST_HANDOFF_GUIDANCE_CMD_DAMP = 0.35
USE_HSV_GATE = False
CONFIRMED_NO_ID_MAX_MISS = 8
KALMAN_HOLD_MAX = 6
# ===== Anti-flicker handoff patch v2 =====
# Сохраняем мягкий handoff, но не даем ByteTrack/YOLO утащить Kalman
# на одиночный ложняк, пока KLT уверенно держит физическую цель.
BT_KLT_ANCHOR_GUARD_ENABLE = True
BT_KLT_ANCHOR_MIN_Q = 0.55
BT_KLT_ANCHOR_DIST_DIAG = 1.65
BT_KLT_ANCHOR_DIST_MIN = 34.0
BT_KLT_ANCHOR_IOU_FLOOR = 0.015
BT_KLT_ANCHOR_MAX_AREA_RATIO = 9.0
BT_KLT_ANCHOR_MAX_ASPECT_RATIO = 7.0
BT_KLT_ANCHOR_HOLD_ON_REJECT = True
BT_KLT_ANCHOR_DEBUG_EVERY = 30
# Не считаем постоянную смену ByteTrack id физическим переключением цели,
# если KLT якорь сильный и bbox принят рядом с ним.
BT_ID_STABILIZE_WHEN_KLT_VALID = True
# Soft YOLO handoff: широкий радиус оставляем только для реального восстановления.
# Когда KLT валидный, handoff обязан быть рядом с KLT-якорем.
SOFT_YOLO_KLT_MIN_Q = 0.55
SOFT_YOLO_KLT_DIST_DIAG = 1.85
SOFT_YOLO_KLT_DIST_MIN = 34.0
SOFT_YOLO_KLT_IOU_FLOOR = 0.015
SOFT_YOLO_KLT_MAX_AREA_RATIO = 9.0
SOFT_YOLO_LOST_DIST_DIAG = 7.0
SOFT_YOLO_LOST_DIST_MIN = 48.0
# Предыдущий hotfix был слишком быстрый: иногда принимал ложняк на 1 кадр.
TARGET_SWITCH_CONFIRM_HITS = 2
WEAK_REACQ_ADOPT_HITS = 2
FAST_HANDOFF_CONFIRM_HITS = 2
STALE_LOCK_BREAK_DIST_DIAG = 1.6
STALE_LOCK_BREAK_MIN_MISS = 2
GUIDANCE_OVERRIDE_MISS_GE = 3
# ===== Safe YOLO re-anchor patch v3 =====
# Fixes stale KLT/ByteTrack hold: if KLT is confident but stuck on the old
# position, a repeated YOLO candidate can re-anchor Kalman/KLT after M/N hits.
YOLO_REANCHOR_ENABLE = True
YOLO_REANCHOR_MISS_GE = 2
YOLO_REANCHOR_ABSENT_GE = 1
YOLO_REANCHOR_MIN_SCORE = 0.065
YOLO_REANCHOR_HITS = 2
YOLO_REANCHOR_TRACK_HITS = 2
YOLO_REANCHOR_WINDOW = 3
YOLO_REANCHOR_REPEAT_DIST_MIN = 46.0
YOLO_REANCHOR_REPEAT_DIST_DIAG = 2.8
YOLO_REANCHOR_PRED_DIST_MIN = 72.0
YOLO_REANCHOR_PRED_DIST_DIAG = 7.0
YOLO_REANCHOR_NEAR_PRED_ONE_SHOT_SCORE = 0.18
YOLO_REANCHOR_MAX_AREA_RATIO = 20.0
YOLO_REANCHOR_MAX_ASPECT_RATIO = 8.0
YOLO_REANCHOR_OSD_REJECT = True
YOLO_REANCHOR_OSD_MIN_SCORE = 0.12
YOLO_REANCHOR_RESET_KLT = True
# Let the re-anchor path do the recovery work before guidance is reset.
STALE_LOCK_BREAK_MIN_MISS = 3
FAST_HANDOFF_CONFIRM_HITS = 2
# Debug: draw only fresh ByteTrack boxes; predicted old BT boxes caused visual "sticking" confusion.
DRAW_BT_ONLY_FRESH = True
# ===== Multi-hypothesis trajectory prediction patch v4 =====
# Builds several short-term hypotheses when YOLO/ByteTrack lose the target:
# constant velocity, acceleration, damped velocity, left/right turn, up/down.
# These hypotheses expand the ROI and help YOLO re-anchor without accepting one-frame false positives.
TRAJ_PREDICT_ENABLE = True
TRAJ_PREDICT_MISS_GE = 1
TRAJ_HISTORY_LEN = 18
TRAJ_HISTORY_LOOKBACK = 8
TRAJ_HISTORY_KEEP_MISS_LE = 2
TRAJ_VEL_HIST_WEIGHT = 0.55
TRAJ_MAX_ACCEL_PX_S2 = 1200.0
TRAJ_HORIZON_MISS_OFFSET = 1
TRAJ_HORIZON_MIN_SEC = 0.08
TRAJ_HORIZON_MAX_SEC = 0.55
TRAJ_BOX_GROW_PER_MISS = 0.08
TRAJ_BOX_GROW_MAX = 1.75
TRAJ_MAX_HYPOTHESES = 7
TRAJ_DUP_CENTER_DIST = 8.0
TRAJ_USE_ACCEL = True
TRAJ_MIN_SPEED_FOR_MANEUVER = 8.0
TRAJ_LATERAL_ACCEL_MIN = 90.0
TRAJ_LATERAL_ACCEL_MAX = 620.0
TRAJ_LATERAL_ACCEL_SPEED_GAIN = 5.5
TRAJ_VERTICAL_ACCEL_MIN = 60.0
TRAJ_VERTICAL_ACCEL_MAX = 420.0
TRAJ_VERTICAL_ACCEL_SPEED_GAIN = 3.5
# Use prediction hypotheses for detector search and re-anchor scoring.
TRAJ_ROI_ENABLE = True
TRAJ_ROI_MISS_GE = 1
TRAJ_ROI_MARGIN = 70
TRAJ_ROI_MIN_SIDE = 170
TRAJ_REANCHOR_ENABLE = True
TRAJ_REANCHOR_MIN_SCORE = 0.055
TRAJ_REANCHOR_DIST_MIN = 64.0
TRAJ_REANCHOR_DIST_DIAG = 4.2
TRAJ_USE_PRIMARY_FOR_HOLD = True
TRAJ_HOLD_MISS_GE = 1
DRAW_TRAJ_PREDICTIONS = True
# Trajectory evidence may adopt faster than a generic far re-anchor, but still requires
# repeat confirmation unless the score is strong and close to a predicted hypothesis.
YOLO_REANCHOR_NEAR_PRED_ONE_SHOT_SCORE = 0.16
YOLO_REANCHOR_HITS = 2
YOLO_REANCHOR_TRACK_HITS = 1
# ===== Close-stage ROI priority patch v5 =====
# In close stage do not run full-screen YOLO on every detector tick.
# Use ROI-KF/ROI-TRAJ while lock is healthy; run FULL-CLOSE only as a periodic
# health-check or when the anchor is weak/missing. This reduces false positives
# entering ByteTrack while the real target is already locked.
CLOSE_PERIODIC_FULLSCAN_ENABLE = True
CLOSE_PERIODIC_FULLSCAN_EVERY = 12
CLOSE_FULLSCAN_MISS_GE = 2
CLOSE_FULLSCAN_WHEN_KLT_INVALID = True
CLOSE_FULLSCAN_TARGET_ABSENT_GE = 2
from runtime_env import apply_config_env_overrides
apply_config_env_overrides(globals())