# signature_verification/signature_siamese.py import cv2 import numpy as np import tensorflow as tf from config import SIA_MODEL_PATH, SIG_THRESH class SignatureSiamese: def __init__(self, model_path: str = SIA_MODEL_PATH): try: self.interp = tf.lite.Interpreter(model_path=model_path) self.interp.allocate_tensors() ids = self.interp.get_input_details() self.in1, self.in2 = ids[0]['index'], ids[1]['index'] self.out_idx = self.interp.get_output_details()[0]['index'] print(f"✅ Loaded TFLite Siamese model from {model_path}") except Exception as e: self.interp = None print(f"❌ Failed to load Siamese model from {model_path}: {e}") def _prep(self, img: np.ndarray) -> np.ndarray: gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) if img.ndim == 3 else img r = cv2.resize(gray, (224, 224)) return r.reshape(1, 224, 224, 1).astype(np.float32) / 255.0 def verify(self, img1: np.ndarray, img2: np.ndarray) -> tuple[bool, float]: if not self.interp: return False, float('inf') inp1, inp2 = self._prep(img1), self._prep(img2) self.interp.set_tensor(self.in1, inp1) self.interp.set_tensor(self.in2, inp2) self.interp.invoke() diff = self.interp.get_tensor(self.out_idx) dist = np.linalg.norm(diff) return dist < SIG_THRESH, dist