import cv2 from config import * from helpers import clamp, box_center, box_wh # Template matching fallback # ========================= def _crop_safe(img, x1, y1, x2, y2): h, w = img.shape[:2] x1 = int(clamp(x1, 0, w - 1)) y1 = int(clamp(y1, 0, h - 1)) x2 = int(clamp(x2, 0, w)) y2 = int(clamp(y2, 0, h)) if x2 <= x1 + 1 or y2 <= y1 + 1: return None return img[y1:y2, x1:x2] def tm_update_template(gray_eff, box_eff): if gray_eff is None or box_eff is None: return None cx, cy = box_center(box_eff) half = TM_TEMPLATE_SIZE // 2 patch = _crop_safe(gray_eff, cx - half, cy - half, cx + half, cy + half) if patch is None: return None if patch.shape[0] < 12 or patch.shape[1] < 12: return None return patch.copy() def tm_search(gray_eff, template, pred_center, miss_streak): if (not TM_ENABLE) or gray_eff is None or template is None or pred_center is None: return None h, w = gray_eff.shape[:2] cx, cy = float(pred_center[0]), float(pred_center[1]) scale = TM_SEARCH_SCALE_BASE + TM_SEARCH_SCALE_PER_MISS * float(miss_streak) th, tw = template.shape[:2] win_w = int(max(tw * scale, tw + 20)) win_h = int(max(th * scale, th + 20)) x1 = int(cx - win_w / 2) y1 = int(cy - win_h / 2) x2 = int(cx + win_w / 2) y2 = int(cy + win_h / 2) roi = _crop_safe(gray_eff, x1, y1, x2, y2) if roi is None or roi.shape[0] < th + 2 or roi.shape[1] < tw + 2: return None res = cv2.matchTemplate(roi, template, cv2.TM_CCOEFF_NORMED) _, maxv, _, maxl = cv2.minMaxLoc(res) if maxv < TM_MIN_SCORE: return None bx = x1 + maxl[0] by = y1 + maxl[1] mcx = bx + tw / 2 mcy = by + th / 2 return (mcx, mcy, float(maxv), tw, th) # =========================