blackmamba2408 commited on
Commit
814a4c2
ยท
verified ยท
1 Parent(s): 15747d5

๐Ÿš€ Simplified, robust app for HF Spaces compatibility

Browse files
Files changed (1) hide show
  1. app.py +122 -181
app.py CHANGED
@@ -1,82 +1,89 @@
1
  import gradio as gr
2
  import numpy as np
3
- import cv2
4
  from PIL import Image
5
  import os
6
  import json
7
  from datetime import datetime
8
- import logging
9
 
10
- # Configure logging
11
- logging.basicConfig(level=logging.INFO)
12
- logger = logging.getLogger(__name__)
13
-
14
- # Import InsightFace components
15
  try:
16
  from insightface.app.face_analysis import FaceAnalysis
17
  import onnxruntime as ort
18
- except ImportError as e:
19
- logger.error(f"Import error: {e}")
20
- FaceAnalysis = None
 
 
21
 
22
  class FaceMatchingSystem:
23
  def __init__(self):
24
- """Initialize the professional face matching system"""
25
  self.app = None
26
  self.face_database = {}
 
27
  self.setup_models()
28
 
29
  def setup_models(self):
30
  """Setup the face recognition models"""
31
  try:
32
- logger.info("Initializing face recognition models...")
33
-
34
- try:
35
- if FaceAnalysis is not None:
36
- logger.info("Attempting to load InsightFace models...")
37
  self.app = FaceAnalysis(
38
  name='buffalo_l',
39
  providers=['CPUExecutionProvider']
40
  )
41
  self.app.prepare(ctx_id=0, det_thresh=0.5, det_size=(640, 640))
42
- logger.info("โœ“ Real InsightFace models loaded successfully")
 
43
  return
44
- except Exception as e:
45
- logger.warning(f"Failed to load real models: {e}")
46
 
47
- # Fall back to demo mode
48
- logger.info("Using demo mode for deployment")
49
  self.app = MockFaceApp()
50
- logger.info("โœ“ Demo face recognition system loaded successfully")
 
51
 
52
  except Exception as e:
53
- logger.error(f"Failed to initialize models: {e}")
54
  self.app = MockFaceApp()
 
55
 
56
  def extract_face_embedding(self, image):
57
  """Extract face embedding from image"""
58
  try:
 
 
 
 
59
  if isinstance(image, Image.Image):
60
- image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
 
 
61
 
 
62
  if hasattr(self.app, 'get'):
63
- faces = self.app.get(image)
64
  else:
65
- return np.random.rand(512), "Mock face detected (demo mode)"
66
 
67
  if len(faces) == 0:
68
  return None, "No face detected in the image"
69
 
 
70
  if len(faces) > 1:
71
  faces = sorted(faces, key=lambda x: (x.bbox[2] - x.bbox[0]) * (x.bbox[3] - x.bbox[1]), reverse=True)
72
 
73
  face = faces[0]
74
  embedding = face.embedding
 
75
 
76
- return embedding, f"Face detected successfully (confidence: {face.det_score:.3f})"
77
 
78
  except Exception as e:
79
- logger.error(f"Error extracting face embedding: {e}")
80
  return None, f"Error processing image: {str(e)}"
81
 
82
  def add_face_to_database(self, image, person_name):
@@ -145,7 +152,7 @@ class FaceMatchingSystem:
145
  with open('face_database.json', 'w') as f:
146
  json.dump(self.face_database, f, indent=2)
147
  except Exception as e:
148
- logger.error(f"Failed to save database: {e}")
149
 
150
  def load_database(self):
151
  """Load the face database"""
@@ -153,9 +160,9 @@ class FaceMatchingSystem:
153
  if os.path.exists('face_database.json'):
154
  with open('face_database.json', 'r') as f:
155
  self.face_database = json.load(f)
156
- logger.info(f"Loaded {len(self.face_database)} faces from database")
157
  except Exception as e:
158
- logger.error(f"Failed to load database: {e}")
159
  self.face_database = {}
160
 
161
  def get_database_info(self):
@@ -199,166 +206,100 @@ class MockFaceApp:
199
  return [MockFace(image_hash)]
200
 
201
  # Initialize the system
202
- logger.info("Initializing Face Matching System...")
203
  face_system = FaceMatchingSystem()
204
  face_system.load_database()
205
 
206
- def create_interface():
207
- """Create the Gradio interface"""
208
 
209
- with gr.Blocks(
210
- title="FaceMatch Pro - Professional Face Recognition",
211
- theme=gr.themes.Soft()
212
- ) as demo:
213
-
214
- # Header
215
- gr.HTML("""
216
- <div style="text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 2rem; border-radius: 15px; margin-bottom: 2rem;">
217
- <h1>๐ŸŽฏ FaceMatch Pro</h1>
218
- <p style="font-size: 1.2rem;">Advanced AI-Powered Face Recognition & Matching System</p>
219
- <div style="display: flex; justify-content: center; gap: 2rem; margin: 1rem 0;">
220
- <div style="text-align: center;">
221
- <div style="font-size: 1.5rem; font-weight: bold;">99%+</div>
222
- <div style="font-size: 0.9rem; opacity: 0.9;">Accuracy</div>
223
- </div>
224
- <div style="text-align: center;">
225
- <div style="font-size: 1.5rem; font-weight: bold;">&lt;50ms</div>
226
- <div style="font-size: 0.9rem; opacity: 0.9;">Response Time</div>
227
- </div>
228
- <div style="text-align: center;">
229
- <div style="font-size: 1.5rem; font-weight: bold;">512D</div>
230
- <div style="font-size: 0.9rem; opacity: 0.9;">Feature Vector</div>
231
- </div>
232
- </div>
233
- <p style="margin: 1rem 0; opacity: 0.9;">๐Ÿ”’ Privacy-First โ€ข โšก Real-Time Processing โ€ข ๐ŸŽฏ Enterprise-Grade Accuracy</p>
234
- </div>
235
- """)
236
-
237
- with gr.Tabs():
238
- # Tab 1: Add Face to Database
239
- with gr.Tab("๐Ÿ“ฅ Add Face to Database"):
240
- gr.HTML("<h3>๐Ÿ‘ค Register New Face</h3>")
241
-
242
- with gr.Row():
243
- with gr.Column():
244
- add_image = gr.Image(label="Upload Photo", type="pil", height=300)
245
- person_name = gr.Textbox(label="Person Name", placeholder="Enter name...")
246
- add_btn = gr.Button("Add to Database", variant="primary")
247
-
248
- with gr.Column():
249
- add_result = gr.Textbox(label="Result", lines=3)
250
- database_info = gr.Textbox(
251
- label="Database Info",
252
- lines=8,
253
- value=face_system.get_database_info()
254
- )
255
-
256
- add_btn.click(
257
- face_system.add_face_to_database,
258
- inputs=[add_image, person_name],
259
- outputs=[add_result, database_info]
260
- )
261
 
262
- # Tab 2: Match Face
263
- with gr.Tab("๐Ÿ” Face Recognition"):
264
- gr.HTML("<h3>๐Ÿ” Find Face Matches</h3>")
265
-
266
- with gr.Row():
267
- with gr.Column():
268
- match_image = gr.Image(label="Upload Photo to Match", type="pil", height=300)
269
- threshold = gr.Slider(
270
- minimum=0.3,
271
- maximum=0.9,
272
- value=0.6,
273
- step=0.05,
274
- label="Matching Threshold"
275
- )
276
- match_btn = gr.Button("Find Matches", variant="primary")
277
-
278
- with gr.Column():
279
- match_result = gr.Textbox(label="Match Result", lines=2)
280
- confidence_text = gr.Textbox(label="Confidence Details", lines=2)
281
- confidence_score = gr.Number(label="Confidence Score (%)", precision=1)
282
 
283
- match_btn.click(
284
- face_system.match_face,
285
- inputs=[match_image, threshold],
286
- outputs=[match_result, confidence_text, confidence_score]
287
- )
 
 
288
 
289
- # Tab 3: Database Management
290
- with gr.Tab("๐Ÿ—„๏ธ Database Management"):
291
- gr.HTML("<h3>๐Ÿ—„๏ธ Database Administration</h3>")
292
-
293
- with gr.Row():
294
- with gr.Column():
295
- db_stats = gr.Textbox(
296
- label="Database Contents",
297
- lines=10,
298
- value=face_system.get_database_info()
299
- )
300
-
301
- with gr.Row():
302
- refresh_btn = gr.Button("Refresh Info", variant="secondary")
303
- clear_btn = gr.Button("Clear Database", variant="stop")
304
-
305
- clear_result = gr.Textbox(label="Action Result", lines=2)
306
-
307
- refresh_btn.click(
308
- lambda: face_system.get_database_info(),
309
- outputs=[db_stats]
310
- )
311
 
312
- clear_btn.click(
313
- face_system.clear_database,
314
- outputs=[clear_result, db_stats]
315
- )
316
 
317
- # Tab 4: About
318
- with gr.Tab("โ„น๏ธ About"):
319
- gr.HTML("""
320
- <div style="padding: 2rem;">
321
- <h2>๐ŸŽฏ FaceMatch Pro</h2>
322
- <p>Professional-grade face recognition system powered by state-of-the-art AI technology.</p>
323
-
324
- <h3>๐Ÿš€ Key Features</h3>
325
- <ul>
326
- <li>99%+ accuracy face detection & recognition</li>
327
- <li>Real-time processing with &lt;50ms response</li>
328
- <li>Privacy-first local processing</li>
329
- <li>Confidence scoring & similarity metrics</li>
330
- <li>Persistent database storage</li>
331
- <li>Professional web interface</li>
332
- </ul>
333
-
334
- <h3>โš™๏ธ Technical Specifications</h3>
335
- <ul>
336
- <li>Deep Convolutional Neural Networks</li>
337
- <li>512-dimensional feature vectors</li>
338
- <li>ONNX Runtime CPU optimization</li>
339
- <li>Cosine similarity matching</li>
340
- <li>RetinaFace detection architecture</li>
341
- <li>JSON-based database storage</li>
342
- </ul>
343
-
344
- <h3>๐Ÿ”’ Privacy & Security</h3>
345
- <p><strong>Local Processing:</strong> All face recognition processing happens locally on the server. No data is transmitted to external services.</p>
346
- <p><strong>Secure Storage:</strong> Face embeddings are stored locally in JSON format.</p>
347
- <p><strong>Privacy-First:</strong> Original images are not stored permanently, only mathematical representations.</p>
348
- </div>
349
- """)
350
 
351
- # Footer
352
- gr.HTML("""
353
- <div style="text-align: center; margin-top: 2rem; padding: 1rem; background: #f8f9fa; border-radius: 10px;">
354
- <p>๐Ÿ”’ All processing happens locally. Your images are never stored or transmitted externally.</p>
355
- <p>๐Ÿ’ก This is a demonstration of professional face recognition capabilities.</p>
356
- </div>
357
- """)
358
-
359
- return demo
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
 
361
- # Create and launch the interface
362
  if __name__ == "__main__":
363
- demo = create_interface()
364
  demo.launch()
 
1
  import gradio as gr
2
  import numpy as np
 
3
  from PIL import Image
4
  import os
5
  import json
6
  from datetime import datetime
 
7
 
8
+ # Try to import InsightFace, fallback gracefully if not available
9
+ INSIGHTFACE_AVAILABLE = False
 
 
 
10
  try:
11
  from insightface.app.face_analysis import FaceAnalysis
12
  import onnxruntime as ort
13
+ INSIGHTFACE_AVAILABLE = True
14
+ print("โœ“ InsightFace available")
15
+ except Exception as e:
16
+ print(f"InsightFace not available: {e}")
17
+ print("Will use demo mode")
18
 
19
  class FaceMatchingSystem:
20
  def __init__(self):
21
+ """Initialize the face matching system"""
22
  self.app = None
23
  self.face_database = {}
24
+ self.model_status = "Initializing..."
25
  self.setup_models()
26
 
27
  def setup_models(self):
28
  """Setup the face recognition models"""
29
  try:
30
+ if INSIGHTFACE_AVAILABLE:
31
+ print("Attempting to load InsightFace models...")
32
+ try:
 
 
33
  self.app = FaceAnalysis(
34
  name='buffalo_l',
35
  providers=['CPUExecutionProvider']
36
  )
37
  self.app.prepare(ctx_id=0, det_thresh=0.5, det_size=(640, 640))
38
+ self.model_status = "โœ“ InsightFace models loaded successfully"
39
+ print(self.model_status)
40
  return
41
+ except Exception as e:
42
+ print(f"Failed to load InsightFace models: {e}")
43
 
44
+ # Fallback to demo mode
 
45
  self.app = MockFaceApp()
46
+ self.model_status = "Demo mode active (InsightFace not available)"
47
+ print(self.model_status)
48
 
49
  except Exception as e:
50
+ print(f"Error in model setup: {e}")
51
  self.app = MockFaceApp()
52
+ self.model_status = f"Demo mode (Error: {str(e)})"
53
 
54
  def extract_face_embedding(self, image):
55
  """Extract face embedding from image"""
56
  try:
57
+ if image is None:
58
+ return None, "No image provided"
59
+
60
+ # Convert PIL to numpy array (RGB format)
61
  if isinstance(image, Image.Image):
62
+ image_array = np.array(image.convert('RGB'))
63
+ else:
64
+ image_array = image
65
 
66
+ # Use the face analysis app
67
  if hasattr(self.app, 'get'):
68
+ faces = self.app.get(image_array)
69
  else:
70
+ return np.random.rand(512), "Demo mode: mock embedding generated"
71
 
72
  if len(faces) == 0:
73
  return None, "No face detected in the image"
74
 
75
+ # Use the largest face if multiple detected
76
  if len(faces) > 1:
77
  faces = sorted(faces, key=lambda x: (x.bbox[2] - x.bbox[0]) * (x.bbox[3] - x.bbox[1]), reverse=True)
78
 
79
  face = faces[0]
80
  embedding = face.embedding
81
+ confidence = getattr(face, 'det_score', 0.95)
82
 
83
+ return embedding, f"Face detected (confidence: {confidence:.3f})"
84
 
85
  except Exception as e:
86
+ print(f"Error extracting face embedding: {e}")
87
  return None, f"Error processing image: {str(e)}"
88
 
89
  def add_face_to_database(self, image, person_name):
 
152
  with open('face_database.json', 'w') as f:
153
  json.dump(self.face_database, f, indent=2)
154
  except Exception as e:
155
+ print(f"Failed to save database: {e}")
156
 
157
  def load_database(self):
158
  """Load the face database"""
 
160
  if os.path.exists('face_database.json'):
161
  with open('face_database.json', 'r') as f:
162
  self.face_database = json.load(f)
163
+ print(f"Loaded {len(self.face_database)} faces from database")
164
  except Exception as e:
165
+ print(f"Failed to load database: {e}")
166
  self.face_database = {}
167
 
168
  def get_database_info(self):
 
206
  return [MockFace(image_hash)]
207
 
208
  # Initialize the system
209
+ print("Initializing Face Matching System...")
210
  face_system = FaceMatchingSystem()
211
  face_system.load_database()
212
 
213
+ # Create a simple, robust Gradio interface
214
+ with gr.Blocks(title="FaceMatch Pro") as demo:
215
 
216
+ gr.Markdown("# ๐ŸŽฏ FaceMatch Pro")
217
+ gr.Markdown("### Professional Face Recognition System")
218
+
219
+ # Status display
220
+ status_display = gr.Textbox(
221
+ label="System Status",
222
+ value=face_system.model_status,
223
+ interactive=False
224
+ )
225
+
226
+ with gr.Tabs():
227
+ # Tab 1: Add Face
228
+ with gr.Tab("Add Face"):
229
+ gr.Markdown("### Add a face to the database")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
 
231
+ with gr.Row():
232
+ with gr.Column():
233
+ add_image = gr.Image(label="Upload Photo", type="pil")
234
+ person_name = gr.Textbox(label="Person Name", placeholder="Enter name...")
235
+ add_btn = gr.Button("Add to Database", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
 
237
+ with gr.Column():
238
+ add_result = gr.Textbox(label="Result", lines=3)
239
+ database_info = gr.Textbox(
240
+ label="Database Info",
241
+ lines=6,
242
+ value=face_system.get_database_info()
243
+ )
244
 
245
+ add_btn.click(
246
+ face_system.add_face_to_database,
247
+ inputs=[add_image, person_name],
248
+ outputs=[add_result, database_info]
249
+ )
250
+
251
+ # Tab 2: Match Face
252
+ with gr.Tab("Match Face"):
253
+ gr.Markdown("### Find face matches")
254
+
255
+ with gr.Row():
256
+ with gr.Column():
257
+ match_image = gr.Image(label="Upload Photo to Match", type="pil")
258
+ threshold = gr.Slider(
259
+ minimum=0.3,
260
+ maximum=0.9,
261
+ value=0.6,
262
+ step=0.05,
263
+ label="Matching Threshold"
264
+ )
265
+ match_btn = gr.Button("Find Matches", variant="primary")
 
266
 
267
+ with gr.Column():
268
+ match_result = gr.Textbox(label="Match Result", lines=2)
269
+ confidence_text = gr.Textbox(label="Confidence Details", lines=2)
270
+ confidence_score = gr.Number(label="Confidence Score (%)", precision=1)
271
 
272
+ match_btn.click(
273
+ face_system.match_face,
274
+ inputs=[match_image, threshold],
275
+ outputs=[match_result, confidence_text, confidence_score]
276
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
 
278
+ # Tab 3: Database Management
279
+ with gr.Tab("Database"):
280
+ gr.Markdown("### Database Management")
281
+
282
+ db_stats = gr.Textbox(
283
+ label="Database Contents",
284
+ lines=8,
285
+ value=face_system.get_database_info()
286
+ )
287
+
288
+ with gr.Row():
289
+ refresh_btn = gr.Button("Refresh Info", variant="secondary")
290
+ clear_btn = gr.Button("Clear Database", variant="stop")
291
+
292
+ clear_result = gr.Textbox(label="Action Result", lines=2)
293
+
294
+ refresh_btn.click(
295
+ lambda: face_system.get_database_info(),
296
+ outputs=[db_stats]
297
+ )
298
+
299
+ clear_btn.click(
300
+ face_system.clear_database,
301
+ outputs=[clear_result, db_stats]
302
+ )
303
 
 
304
  if __name__ == "__main__":
 
305
  demo.launch()