reagvis commited on
Commit
f076a0b
·
verified ·
1 Parent(s): 3b59057

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +220 -0
app.py CHANGED
@@ -125,6 +125,226 @@ async def health_check():
125
  """
126
  return {"status": "healthy", "tools_initialized": TOOLS_INITIALIZED_SUCCESSFULLY}
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
  # Create the Gradio interface
130
  def create_interface():
 
125
  """
126
  return {"status": "healthy", "tools_initialized": TOOLS_INITIALIZED_SUCCESSFULLY}
127
 
128
+ def process_kyc_verification(user_image: Image.Image, id_card_image: Image.Image):
129
+ """
130
+ Main KYC verification function that processes both images and returns comprehensive results
131
+
132
+ Args:
133
+ user_image: PIL Image of the user's face photo
134
+ id_card_image: PIL Image of the ID card/document
135
+
136
+ Returns:
137
+ dict: Comprehensive verification results with scores and analysis
138
+ """
139
+ start_time = time.time()
140
+
141
+ try:
142
+ # Validate inputs
143
+ if user_image is None:
144
+ return {
145
+ "error": "User image is required",
146
+ "liveness_score": 0.0,
147
+ "face_similarity": 0.0,
148
+ "deepfake_score": 1.0,
149
+ "overall_decision": "REJECTED",
150
+ "processing_time": 0.0
151
+ }
152
+
153
+ if id_card_image is None:
154
+ return {
155
+ "error": "ID card image is required",
156
+ "liveness_score": 0.0,
157
+ "face_similarity": 0.0,
158
+ "deepfake_score": 1.0,
159
+ "overall_decision": "REJECTED",
160
+ "processing_time": 0.0
161
+ }
162
+
163
+ if not TOOLS_INITIALIZED_SUCCESSFULLY:
164
+ return {
165
+ "error": "KYC tools failed to initialize",
166
+ "liveness_score": 0.0,
167
+ "face_similarity": 0.0,
168
+ "deepfake_score": 1.0,
169
+ "overall_decision": "ERROR",
170
+ "processing_time": 0.0
171
+ }
172
+
173
+ print("Starting KYC verification process...")
174
+
175
+ # Initialize scores
176
+ liveness_score = 0.0
177
+ face_similarity = 0.0
178
+ deepfake_score = 1.0
179
+
180
+ # Save images to temporary files for tool processing
181
+ with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as temp_user:
182
+ user_image.save(temp_user.name, format='JPEG')
183
+ user_image_path = temp_user.name
184
+
185
+ with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as temp_id:
186
+ id_card_image.save(temp_id.name, format='JPEG')
187
+ id_card_path = temp_id.name
188
+
189
+ temp_files_to_clean = [user_image_path, id_card_path]
190
+
191
+ try:
192
+ # 1. ID Document Analysis
193
+ print("Analyzing ID document...")
194
+ try:
195
+ id_analysis = image_description_tool_instance.apply(id_card_path)
196
+ except Exception as e:
197
+ id_analysis = f"Error analyzing ID document: {str(e)}"
198
+
199
+ # 2. Liveness Detection
200
+ print("Performing liveness detection...")
201
+ try:
202
+ liveness_result_str = liveness_detection_tool_instance.apply(user_image_path)
203
+ confidence_match = re.search(r"Confidence:\s*([0-9.]+)", liveness_result_str, re.IGNORECASE)
204
+ if confidence_match:
205
+ liveness_score = float(confidence_match.group(1))
206
+ else:
207
+ liveness_score = 0.85 if "real" in liveness_result_str.lower() or "live" in liveness_result_str.lower() else 0.25
208
+ liveness_details = liveness_result_str
209
+ except Exception as e:
210
+ liveness_score = 0.0
211
+ liveness_details = f"Error in liveness detection: {str(e)}"
212
+
213
+ # 3. Face Comparison
214
+ print("Comparing faces...")
215
+ try:
216
+ face_sim_result_str = face_similarity_tool_instance.apply(user_image_path, id_card_path)
217
+ score_match = re.search(r"similarity score:\s*([0-9.]+)", face_sim_result_str, re.IGNORECASE)
218
+ if score_match:
219
+ face_similarity = float(score_match.group(1))
220
+ else:
221
+ try:
222
+ potential_score_str = face_sim_result_str.split(":")[-1].strip().split(" ")[0].replace(')', '').replace('(', '')
223
+ face_similarity = float(re.sub(r"[^0-9.]", "", potential_score_str))
224
+ except:
225
+ face_similarity = 0.75 if "match" in face_sim_result_str.lower() or "true" in face_sim_result_str.lower() else 0.35
226
+ face_details = face_sim_result_str
227
+ except Exception as e:
228
+ face_similarity = 0.0
229
+ face_details = f"Error in face similarity: {str(e)}"
230
+
231
+ # 4. Deepfake Detection
232
+ print("Detecting deepfakes...")
233
+ try:
234
+ img_df_result = image_deepfake_tool_instance.apply(user_image_path)
235
+ if img_df_result.get("label", "").lower() == "error":
236
+ deepfake_score = 1.0
237
+ deepfake_details = img_df_result.get('error_message', 'Unknown error during deepfake detection.')
238
+ else:
239
+ label = img_df_result.get("label", "AI").lower()
240
+ confidence = img_df_result.get("confidence", 0.0)
241
+ if label == "human":
242
+ deepfake_score = 1.0 - confidence
243
+ elif label == "ai":
244
+ deepfake_score = confidence
245
+ else:
246
+ deepfake_score = 1.0
247
+ deepfake_details = f"Prediction: '{label.capitalize()}' with confidence {confidence:.4f}"
248
+ except Exception as e:
249
+ deepfake_score = 1.0
250
+ deepfake_details = f"Error in deepfake detection: {str(e)}"
251
+
252
+ # 5. Overall Decision Logic
253
+ processing_time = time.time() - start_time
254
+
255
+ # Decision criteria
256
+ liveness_pass = liveness_score >= LIVENESS_THRESHOLD
257
+ face_match_pass = face_similarity >= FACE_MATCH_THRESHOLD
258
+ deepfake_pass = deepfake_score <= DEEPFAKE_THRESHOLD
259
+
260
+ overall_decision = "APPROVED" if (liveness_pass and face_match_pass and deepfake_pass) else "REJECTED"
261
+ confidence_overall = min(liveness_score, face_similarity, 1 - deepfake_score)
262
+
263
+ # Generate recommendations
264
+ recommendations = []
265
+ if liveness_pass:
266
+ recommendations.append("✅ Liveness check passed - Live person detected")
267
+ else:
268
+ recommendations.append("❌ Liveness check failed - Manual review required")
269
+
270
+ if face_match_pass:
271
+ recommendations.append("✅ Face similarity acceptable - Identity match confirmed")
272
+ else:
273
+ recommendations.append("❌ Face similarity below threshold - Identity mismatch")
274
+
275
+ if deepfake_pass:
276
+ recommendations.append("✅ No deepfake detected - Image appears authentic")
277
+ else:
278
+ recommendations.append("❌ Potential manipulation detected - Manual verification needed")
279
+
280
+ # Compile comprehensive results
281
+ result = {
282
+ # Main scores
283
+ "liveness_score": round(float(liveness_score), 3),
284
+ "face_similarity": round(float(face_similarity), 3),
285
+ "deepfake_score": round(float(deepfake_score), 3),
286
+
287
+ # Overall assessment
288
+ "overall_decision": overall_decision,
289
+ "confidence_overall": round(float(confidence_overall), 3),
290
+
291
+ # Individual check results
292
+ "liveness_passed": liveness_pass,
293
+ "face_match_passed": face_match_pass,
294
+ "deepfake_passed": deepfake_pass,
295
+
296
+ # Detailed analysis
297
+ "id_analysis": id_analysis,
298
+ "analysis_details": {
299
+ "liveness_analysis": liveness_details,
300
+ "face_comparison": face_details,
301
+ "deepfake_analysis": deepfake_details,
302
+ "document_analysis": id_analysis
303
+ },
304
+
305
+ # Recommendations and metadata
306
+ "recommendations": recommendations,
307
+ "processing_time": round(processing_time, 2),
308
+ "model_version": MODEL_VERSION,
309
+ "timestamp": time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime()),
310
+
311
+ # Thresholds used
312
+ "thresholds": {
313
+ "liveness_threshold": LIVENESS_THRESHOLD,
314
+ "face_similarity_threshold": FACE_MATCH_THRESHOLD,
315
+ "deepfake_threshold": DEEPFAKE_THRESHOLD
316
+ }
317
+ }
318
+
319
+ print(f"KYC verification completed in {processing_time:.2f}s - Decision: {overall_decision}")
320
+ return result
321
+
322
+ finally:
323
+ # Clean up temporary files
324
+ for temp_path in temp_files_to_clean:
325
+ try:
326
+ if os.path.exists(temp_path):
327
+ os.remove(temp_path)
328
+ except Exception as e_clean:
329
+ print(f"Error cleaning up temp file {temp_path}: {e_clean}")
330
+
331
+ except Exception as e:
332
+ error_msg = f"KYC verification failed: {str(e)}"
333
+ print(error_msg)
334
+
335
+ return {
336
+ "error": error_msg,
337
+ "liveness_score": 0.0,
338
+ "face_similarity": 0.0,
339
+ "deepfake_score": 1.0,
340
+ "overall_decision": "ERROR",
341
+ "confidence_overall": 0.0,
342
+ "analysis_details": {"error": str(e)},
343
+ "recommendations": ["Manual review required due to processing error"],
344
+ "processing_time": time.time() - start_time,
345
+ "model_version": MODEL_VERSION,
346
+ "timestamp": time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime())
347
+ }
348
 
349
  # Create the Gradio interface
350
  def create_interface():