hardiksharma6555 commited on
Commit
0a020e2
Β·
verified Β·
1 Parent(s): 6efad2a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -44
app.py CHANGED
@@ -1,4 +1,6 @@
1
- # app.py
 
 
2
 
3
  import os
4
  import warnings
@@ -15,46 +17,102 @@ from typing import Optional, Tuple, Any
15
  # Suppress warnings for a cleaner output
16
  warnings.filterwarnings("ignore")
17
 
18
- # --- Configuration: Model Paths and Thresholds ---
19
- # NOTE: The user must ensure these files are downloaded to the same directory
20
- # before running the script (e.g., using a separate gdown script or Colab cell).
21
- TARGET_DIR = '.' # Current directory for a local setup
 
 
 
22
 
23
- # Deepfake Model Paths
 
 
 
24
  MODEL_PATHS = {
25
- "mobilenetv3": os.path.join(TARGET_DIR, "mobilenetv3_small_100_final.onnx"),
26
- "efficientnet_b0": os.path.join(TARGET_DIR, "efficientnet_b0_final.onnx"),
27
- "edgenext": os.path.join(TARGET_DIR, "edgenext_small_final.onnx"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  }
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  # --- 2A. CONFIGURATION ---
31
- # We use the built-in insightface model 'buffalo_l' for better alignment/embedding
32
- SIM_MODEL_NAME = 'buffalo_l'
33
  CTX_ID = -1 # CPU
34
  ID_MATCH_THRESHOLD = 0.50 # Similarity Threshold
35
  FAKE_SCORE_THRESHOLD = 0.5 # Deepfake Score Threshold
36
 
37
- # Fixed paths for shared Deepfake models (Caffe files are no longer used for detection,
38
- # as we switch to the more robust insightface detector)
39
- # NOTE: We keep the ONNX paths as they are the deepfake models.
40
  ONNX_SESSIONS = {}
 
41
 
42
  # --- 2B. INITIALIZE MODELS ---
43
- app: Optional[FaceAnalysis] = None
44
 
45
- print("\n--- 1. Initializing Models ---")
46
  try:
47
- # Use 'buffalo_l' for higher accuracy, which also provides the 5-point landmarks
 
48
  app = FaceAnalysis(name=SIM_MODEL_NAME, providers=['CPUExecutionProvider'])
49
- # Customize the detector to get landmarks ('lmk') along with the usual attributes
 
 
50
  app.prepare(ctx_id=CTX_ID, det_size=(640, 640), det_thresh=0.5,
51
- det_model="retinaface_r50_v1", allowed_modules=['detection', 'landmark', 'recognition'])
52
 
53
  # Initialize ONNX Deepfake Classification Models
54
  for model_name, path in MODEL_PATHS.items():
55
  if os.path.exists(path):
56
  ONNX_SESSIONS[model_name] = ort.InferenceSession(path, providers=['CPUExecutionProvider'])
57
- print(f"Loaded {model_name.upper()} model.")
58
  else:
59
  print(f"Warning: Deepfake model {model_name.upper()} not found at {path}")
60
 
@@ -64,7 +122,8 @@ try:
64
  except Exception as e:
65
  print(f"❌ FATAL ERROR: Failed to load models. Detail: {e}")
66
  app = None
67
- sys.exit(1) # Exit if models fail to load
 
68
 
69
  print("βœ… Model initialization complete.")
70
 
@@ -86,7 +145,7 @@ def get_face_data(img_array_rgb: np.ndarray) -> Tuple[Optional[np.ndarray], Opti
86
  if not all_faces:
87
  return None, None, img_bgr, None
88
  face = get_largest_face(all_faces)
89
- # The 'face' object from FaceAnalysis now contains embedding and 5-point landmarks ('lmk')
90
  return face.embedding, face.lmk, img_bgr, face.bbox
91
 
92
  def calculate_similarity(embedding1: Optional[np.ndarray], embedding2: Optional[np.ndarray]) -> float:
@@ -98,22 +157,20 @@ def calculate_similarity(embedding1: Optional[np.ndarray], embedding2: Optional[
98
  similarity = np.dot(e1_norm, e2_norm)
99
  return float(similarity)
100
 
101
- # --- 2D. DEEPFAKE DETECTION HELPER FUNCTIONS (Liveness Check) ---
102
 
103
  def align_face_insightface(img_bgr: np.ndarray, landmarks_5pt: np.ndarray, output_size: int = 160) -> np.ndarray:
104
  """
105
- Simplified alignment using 5-point landmarks for deepfake model input.
106
- This replaces the complex dlib/81-point alignment.
107
- The goal is a centered, roughly aligned 160x160 face crop.
108
  """
109
- # Standard 5-point template for InsightFace's alignment for deepfake models
110
  dst = np.array([
111
  [30.2946, 51.6963], # Left Eye
112
  [65.5318, 51.6963], # Right Eye
113
  [48.0252, 71.7366], # Nose Tip
114
  [33.5493, 92.3655], # Left Mouth Corner
115
  [62.7299, 92.3655] # Right Mouth Corner
116
- ], dtype=np.float32) * (output_size / 96) # Scale for 160x160 output
117
 
118
  src = landmarks_5pt.astype(np.float32)
119
 
@@ -135,18 +192,17 @@ def get_liveness_score(img_array_rgb: np.ndarray, landmarks_5pt: np.ndarray, mod
135
  # Align the face using the 5-point landmarks
136
  face_crop_bgr = align_face_insightface(img_bgr, landmarks_5pt, output_size=160)
137
 
138
- # Pre-process for ONNX model
139
  face_crop_rgb = cv2.cvtColor(face_crop_bgr, cv2.COLOR_BGR2RGB)
140
- # Assuming the deepfake model expects a [-1, 1] normalization
141
  normalized_img = (face_crop_rgb / 255.0 - 0.5) / 0.5
142
- input_tensor = np.transpose(normalized_img, (2, 0, 1)) # C, H, W
143
- input_tensor = np.expand_dims(input_tensor, axis=0).astype("float32") # 1, C, H, W
144
 
145
  input_name = session.get_inputs()[0].name
146
  output_name = session.get_outputs()[0].name
147
  logit = session.run([output_name], {input_name: input_tensor})[0]
148
 
149
- # Convert logit to probability (Fake Confidence Score) using sigmoid: 1 / (1 + exp(-x))
150
  probability = 1 / (1 + np.exp(-logit))
151
  score = float(np.ravel(probability)[0]) if probability.size > 0 else 0.0
152
 
@@ -165,7 +221,7 @@ def unified_ekyc_analysis(model_choice: str, img_A_pil: Image.Image, img_B_pil:
165
  Performs Identity Verification (Step 1) then Forgery Check (Step 2).
166
  """
167
  if app is None or not ONNX_SESSIONS or model_choice not in ONNX_SESSIONS:
168
- error_msg = f"""# ❌ CRITICAL FAILURE: Models failed to load. Please ensure all ONNX models are in the current directory and dependencies are installed."""
169
  return None, None, error_msg
170
 
171
  start_time = time.time()
@@ -174,15 +230,12 @@ def unified_ekyc_analysis(model_choice: str, img_A_pil: Image.Image, img_B_pil:
174
  img_A_array = np.array(img_A_pil.convert('RGB'))
175
  img_B_array = np.array(img_B_pil.convert('RGB'))
176
 
177
- # e1, e2: Face Embeddings for Similarity
178
- # lmk_A, lmk_B: 5-point Landmarks for Alignment
179
- # vis_A_bgr, vis_B_bgr: BGR images for visualization
180
- # bbox_A, bbox_B: Bounding Boxes
181
  e1, lmk_A, vis_A_bgr, bbox_A = get_face_data(img_A_array)
182
  e2, lmk_B, vis_B_bgr, bbox_B = get_face_data(img_B_array)
183
 
184
  # 1. Basic Face Detection Check (Pre-Step)
185
- if e1 is None or e2 is None:
186
  report = "πŸ›‘ **PRE-CHECK FAILED:** Face detection failed on one or both images. Cannot proceed."
187
  return Image.fromarray(img_A_array), Image.fromarray(img_B_array), report
188
 
@@ -288,13 +341,12 @@ def unified_ekyc_analysis(model_choice: str, img_A_pil: Image.Image, img_B_pil:
288
 
289
 
290
  # --- GRADIO FRONTEND ---
291
- print("\n--- 2. Initializing Gradio interface ---")
292
 
293
  available_models = list(ONNX_SESSIONS.keys())
294
- # Prioritize EdgeNeXt if available
295
- default_model = "edgenext" if "edgenext" in available_models else ("efficientnet_b0" if "efficientnet_b0" in available_models else (available_models[0] if available_models else ""))
296
 
297
- if not available_models:
298
  print("FATAL: No deepfake models were loaded. Cannot launch Gradio.")
299
  else:
300
  iface = gr.Interface(
@@ -319,7 +371,7 @@ else:
319
  gr.Markdown(label="Final eKYC Report")
320
  ],
321
  title="Deepfake-Proof eKYC System (Unified Analysis)",
322
- description="Performs two-step conditional verification: Step 1: Identity Match. Step 2 (if Match): Forgery/Liveness Check on both images. NOTE: Ensure all ONNX models are in the same directory.",
323
  )
324
 
325
  iface.launch(debug=False)
 
1
+ # Combined Script for Colab/Notebook Execution
2
+ # This script handles installation, model download via gdown,
3
+ # and runs the dlib-free eKYC application with the buffalo_l model.
4
 
5
  import os
6
  import warnings
 
17
  # Suppress warnings for a cleaner output
18
  warnings.filterwarnings("ignore")
19
 
20
+ # ==============================================================================
21
+ # 1. SETUP, INSTALLATION, AND MODEL DOWNLOAD (Combined Cell)
22
+ # ==============================================================================
23
+
24
+ print("--- 1. Installing Required Libraries ---")
25
+ # Install core libraries and gdown, gradio. dlib is removed from the requirements
26
+ !pip install insightface==0.7.3 numpy onnxruntime opencv-python matplotlib tqdm gdown gradio --quiet
27
 
28
+ # --- Configuration: Model File IDs and Target Paths ---
29
+ TARGET_DIR = '/content/'
30
+
31
+ # Deepfake Model Paths (All ONNX models are downloaded for runtime switching)
32
  MODEL_PATHS = {
33
+ "mobilenetv3": "/content/mobilenetv3_small_100_final.onnx",
34
+ "efficientnet_b0": "/content/efficientnet_b0_final.onnx",
35
+ "edgenext": "/content/edgenext_small_final.onnx",
36
+ }
37
+
38
+ # Mapping of file names to their corresponding Google Drive File IDs
39
+ # NOTE: The DLIB and Caffe files are kept for download continuity,
40
+ # but are NOT used in the dlib-free logic.
41
+ MODEL_FILES = {
42
+ # Deepfake Detector Components (Downloaded but not used in final logic)
43
+ "deploy.prototxt": "1V02QA7eOnrkKixTdnP6cvIBx4Qxqwhmw",
44
+ "res10_300x300_ssd_iter_140000_fp16.caffemodel": "14n7DryxHqwqac9z0HzpIqtipBp5EfRvA",
45
+ "shape_predictor_81_face_landmarks.dat": "1sixwbA4oOn7Ijmm85sAODL8AtwjCq6a9",
46
+
47
+ # Deepfake Classification ONNX Models
48
+ "mobilenetv3_small_100_final.onnx": "1spFbTIL8nRmIBG_F6j6-aF01fWGVGo_f",
49
+ "efficientnet_b0_final.onnx": "1TsHUbx0cd-55XDygQIAmEbXFUGHxBT_x",
50
+ "edgenext_small_final.onnx": "15hnhznZVyASYhSOYOFSsgMGEfsyh1MBY"
51
  }
52
 
53
+ def download_models_from_drive():
54
+ """Downloads all required model files from the provided Drive IDs."""
55
+ print(f"\n--- 2. Starting Deepfake Model Download to {TARGET_DIR} ---")
56
+
57
+ try:
58
+ import gdown
59
+ except ImportError:
60
+ # Should be installed by pip above, but double check
61
+ !pip install gdown --quiet
62
+ import gdown
63
+
64
+ os.makedirs(TARGET_DIR, exist_ok=True)
65
+ downloaded_files = 0
66
+
67
+ for filename, file_id in MODEL_FILES.items():
68
+ local_path = os.path.join(TARGET_DIR, filename)
69
+
70
+ if os.path.exists(local_path) and os.path.getsize(local_path) > 0:
71
+ # print(f"Skipping download, {filename} already exists.")
72
+ downloaded_files += 1
73
+ continue
74
+
75
+ try:
76
+ print(f"Downloading {filename}...")
77
+ gdown.download(id=file_id, output=local_path, quiet=True, fuzzy=True)
78
+ if os.path.exists(local_path) and os.path.getsize(local_path) > 0:
79
+ downloaded_files += 1
80
+ except Exception as e:
81
+ print(f"Warning: Failed to download {filename}. Error: {e}", file=sys.stderr)
82
+
83
+ download_models_from_drive()
84
+ print("βœ… Initial setup complete. Proceeding to model initialization.")
85
+
86
+ # --- 2. MODEL INITIALIZATION AND CORE HELPER FUNCTIONS ---
87
+
88
  # --- 2A. CONFIGURATION ---
89
+ # IMPORTANT: Using 'buffalo_l' as requested, which provides 5-point landmarks (lmk)
90
+ SIM_MODEL_NAME = 'buffalo_l'
91
  CTX_ID = -1 # CPU
92
  ID_MATCH_THRESHOLD = 0.50 # Similarity Threshold
93
  FAKE_SCORE_THRESHOLD = 0.5 # Deepfake Score Threshold
94
 
 
 
 
95
  ONNX_SESSIONS = {}
96
+ app: Optional[FaceAnalysis] = None
97
 
98
  # --- 2B. INITIALIZE MODELS ---
 
99
 
100
+ print("\n--- 3. Initializing Models ---")
101
  try:
102
+ # Face Analysis/Recognition Model (downloads buffalo_l)
103
+ print(f"Initializing FaceAnalysis model: {SIM_MODEL_NAME}")
104
  app = FaceAnalysis(name=SIM_MODEL_NAME, providers=['CPUExecutionProvider'])
105
+
106
+ # Configure app to get detection, 5-point landmark (lmk), and recognition (embedding)
107
+ # The 'det_model' argument is removed for compatibility with insightface==0.7.3
108
  app.prepare(ctx_id=CTX_ID, det_size=(640, 640), det_thresh=0.5,
109
+ allowed_modules=['detection', 'landmark', 'recognition'])
110
 
111
  # Initialize ONNX Deepfake Classification Models
112
  for model_name, path in MODEL_PATHS.items():
113
  if os.path.exists(path):
114
  ONNX_SESSIONS[model_name] = ort.InferenceSession(path, providers=['CPUExecutionProvider'])
115
+ print(f"Loaded {model_name.upper()} deepfake model.")
116
  else:
117
  print(f"Warning: Deepfake model {model_name.upper()} not found at {path}")
118
 
 
122
  except Exception as e:
123
  print(f"❌ FATAL ERROR: Failed to load models. Detail: {e}")
124
  app = None
125
+ # We don't sys.exit(1) here to allow Gradio to show the error, but the function will handle it.
126
+
127
 
128
  print("βœ… Model initialization complete.")
129
 
 
145
  if not all_faces:
146
  return None, None, img_bgr, None
147
  face = get_largest_face(all_faces)
148
+ # The 'face' object from FaceAnalysis provides embedding and 5-point landmarks ('lmk')
149
  return face.embedding, face.lmk, img_bgr, face.bbox
150
 
151
  def calculate_similarity(embedding1: Optional[np.ndarray], embedding2: Optional[np.ndarray]) -> float:
 
157
  similarity = np.dot(e1_norm, e2_norm)
158
  return float(similarity)
159
 
160
+ # --- 2D. DEEPFAKE DETECTION HELPER FUNCTIONS (Liveness Check - DLIB FREE) ---
161
 
162
  def align_face_insightface(img_bgr: np.ndarray, landmarks_5pt: np.ndarray, output_size: int = 160) -> np.ndarray:
163
  """
164
+ Alignment using 5-point landmarks provided by insightface.
 
 
165
  """
166
+ # Standard 5-point template for alignment scaled for 160x160 output
167
  dst = np.array([
168
  [30.2946, 51.6963], # Left Eye
169
  [65.5318, 51.6963], # Right Eye
170
  [48.0252, 71.7366], # Nose Tip
171
  [33.5493, 92.3655], # Left Mouth Corner
172
  [62.7299, 92.3655] # Right Mouth Corner
173
+ ], dtype=np.float32) * (output_size / 96)
174
 
175
  src = landmarks_5pt.astype(np.float32)
176
 
 
192
  # Align the face using the 5-point landmarks
193
  face_crop_bgr = align_face_insightface(img_bgr, landmarks_5pt, output_size=160)
194
 
195
+ # Pre-process for ONNX model (C, H, W, normalization [-1, 1])
196
  face_crop_rgb = cv2.cvtColor(face_crop_bgr, cv2.COLOR_BGR2RGB)
 
197
  normalized_img = (face_crop_rgb / 255.0 - 0.5) / 0.5
198
+ input_tensor = np.transpose(normalized_img, (2, 0, 1))
199
+ input_tensor = np.expand_dims(input_tensor, axis=0).astype("float32")
200
 
201
  input_name = session.get_inputs()[0].name
202
  output_name = session.get_outputs()[0].name
203
  logit = session.run([output_name], {input_name: input_tensor})[0]
204
 
205
+ # Convert logit to probability (Fake Confidence Score) using sigmoid
206
  probability = 1 / (1 + np.exp(-logit))
207
  score = float(np.ravel(probability)[0]) if probability.size > 0 else 0.0
208
 
 
221
  Performs Identity Verification (Step 1) then Forgery Check (Step 2).
222
  """
223
  if app is None or not ONNX_SESSIONS or model_choice not in ONNX_SESSIONS:
224
+ error_msg = f"""# ❌ CRITICAL FAILURE: Models failed to load. Please check console output and ensure all ONNX models are present and FaceAnalysis initialized successfully."""
225
  return None, None, error_msg
226
 
227
  start_time = time.time()
 
230
  img_A_array = np.array(img_A_pil.convert('RGB'))
231
  img_B_array = np.array(img_B_pil.convert('RGB'))
232
 
233
+ # e1, e2: Embeddings; lmk_A, lmk_B: Landmarks (5-point); vis_A_bgr, vis_B_bgr: BGR images; bbox_A, bbox_B: Bounding Boxes
 
 
 
234
  e1, lmk_A, vis_A_bgr, bbox_A = get_face_data(img_A_array)
235
  e2, lmk_B, vis_B_bgr, bbox_B = get_face_data(img_B_array)
236
 
237
  # 1. Basic Face Detection Check (Pre-Step)
238
+ if e1 is None or e2 is None or lmk_A is None or lmk_B is None:
239
  report = "πŸ›‘ **PRE-CHECK FAILED:** Face detection failed on one or both images. Cannot proceed."
240
  return Image.fromarray(img_A_array), Image.fromarray(img_B_array), report
241
 
 
341
 
342
 
343
  # --- GRADIO FRONTEND ---
344
+ print("\n--- 4. Initializing Gradio interface ---")
345
 
346
  available_models = list(ONNX_SESSIONS.keys())
347
+ default_model = "edgenext" if "edgenext" in available_models else (available_models[0] if available_models else None)
 
348
 
349
+ if default_model is None:
350
  print("FATAL: No deepfake models were loaded. Cannot launch Gradio.")
351
  else:
352
  iface = gr.Interface(
 
371
  gr.Markdown(label="Final eKYC Report")
372
  ],
373
  title="Deepfake-Proof eKYC System (Unified Analysis)",
374
+ description="Performs two-step conditional verification: Step 1: Identity Match. Step 2 (if Match): Forgery/Liveness Check on both images. Includes automatic model download and is DLIB-free.",
375
  )
376
 
377
  iface.launch(debug=False)