Sivainti commited on
Commit
9692792
Β·
verified Β·
1 Parent(s): 9fe0485

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +127 -89
app.py CHANGED
@@ -27,6 +27,8 @@ class AttendanceSystem:
27
  self.recognition_thread = None
28
  self.last_recognition_time = {}
29
  self.recognition_cooldown = 5 # seconds between recognitions for same person
 
 
30
 
31
  # Create directories for data storage
32
  os.makedirs("data", exist_ok=True)
@@ -274,6 +276,9 @@ class AttendanceSystem:
274
  if self.is_streaming:
275
  return "⚠️ Video stream is already running!"
276
 
 
 
 
277
  self.video_capture = cv2.VideoCapture(camera_source)
278
  if not self.video_capture.isOpened():
279
  return "❌ Could not open camera/video source!"
@@ -302,15 +307,62 @@ class AttendanceSystem:
302
  self.recognition_thread.daemon = True
303
  self.recognition_thread.start()
304
 
305
- return "βœ… Video stream started successfully!"
306
 
307
  except Exception as e:
308
  return f"❌ Error starting video stream: {e}"
309
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  def stop_video_stream(self):
311
- """Stop video streaming"""
312
  try:
313
  self.is_streaming = False
 
314
 
315
  if self.video_capture:
316
  self.video_capture.release()
@@ -326,10 +378,10 @@ class AttendanceSystem:
326
  except queue.Empty:
327
  break
328
 
329
- return "βœ… Video stream stopped successfully!"
330
 
331
  except Exception as e:
332
- return f"❌ Error stopping video stream: {e}"
333
 
334
  def get_current_frame(self):
335
  """Get current frame for display"""
@@ -434,7 +486,7 @@ attendance_system = AttendanceSystem()
434
 
435
  def create_interface():
436
  with gr.Blocks(
437
- title="🎯 Advanced Attendance System with Live Recognition",
438
  theme=gr.themes.Soft(),
439
  css="""
440
  .gradio-container {
@@ -448,57 +500,72 @@ def create_interface():
448
  border-radius: 5px;
449
  margin: 5px 0;
450
  }
 
 
 
451
  """
452
  ) as demo:
453
 
454
  gr.Markdown(
455
  """
456
- # 🎯 Advanced Attendance System with Live Face Recognition
457
 
458
- **Comprehensive facial recognition system with automatic worker registration and attendance tracking**
459
 
460
  ## πŸš€ **Key Features:**
461
- - **πŸŽ₯ Live Video Stream Recognition** - Real-time face detection from camera/CCTV
 
462
  - **πŸ€– Automatic Worker Registration** - Auto-register unknown faces with unique IDs
463
  - **πŸ‘€ Manual Registration** - Register workers manually with photos
464
  - **πŸ“… 24-Hour Attendance Rule** - One attendance mark per worker per day
465
  - **πŸ“Š Advanced Analytics** - Detailed reports and data export
466
- - **πŸ’Ύ Persistent Data Storage** - All data saved locally in `/data` folder
467
-
468
- ## πŸ“ **Data Storage Location:**
469
- - **Worker Database:** `/data/workers.pkl`
470
- - **Attendance Records:** `/data/attendance.json`
471
- - **Face Images:** `/data/faces/` folder
472
  """
473
  )
474
 
475
  with gr.Tabs():
476
- # Live Recognition Tab
477
- with gr.Tab("πŸŽ₯ Live Recognition", elem_classes="tab-nav"):
478
- gr.Markdown("### Real-time Face Recognition and Attendance")
479
 
480
  with gr.Row():
481
  with gr.Column(scale=1):
482
- camera_source = gr.Number(
483
- label="Camera Source (0 for default camera, or RTSP URL)",
484
- value=0,
485
- precision=0
486
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
487
 
488
- with gr.Row():
489
- start_stream_btn = gr.Button(
490
- "πŸŽ₯ Start Live Recognition",
491
- variant="primary",
492
- size="lg"
493
- )
494
- stop_stream_btn = gr.Button(
495
- "⏹️ Stop Stream",
496
- variant="secondary",
497
- size="lg"
498
- )
499
 
500
  stream_status = gr.Textbox(
501
- label="Stream Status",
502
  value="Ready to start...",
503
  interactive=False,
504
  lines=2
@@ -507,10 +574,9 @@ def create_interface():
507
  gr.Markdown(
508
  """
509
  **πŸ“‹ Instructions:**
510
- 1. Click "Start Live Recognition" to begin
511
- 2. System will automatically detect and register new faces
512
- 3. Known workers will be marked present (once per day)
513
- 4. New workers get auto-assigned IDs (W0001, W0002, etc.)
514
 
515
  **🎨 Color Coding:**
516
  - 🟒 **Green:** Known worker (attendance marked)
@@ -520,6 +586,12 @@ def create_interface():
520
  )
521
 
522
  with gr.Column(scale=1):
 
 
 
 
 
 
523
  live_attendance_display = gr.Markdown(
524
  value=attendance_system.get_today_attendance(),
525
  label="Live Attendance Updates"
@@ -603,55 +675,6 @@ def create_interface():
603
  value="Select date range and click 'Generate Report' to view attendance analytics.",
604
  label="Attendance Report"
605
  )
606
-
607
- # System Info Tab
608
- with gr.Tab("ℹ️ System Information", elem_classes="tab-nav"):
609
- gr.Markdown(
610
- """
611
- ## πŸ“– System Guide
612
-
613
- ### πŸŽ₯ Live Recognition System
614
- - **Camera Setup:** Use camera index (0, 1, 2...) or RTSP URL for IP cameras
615
- - **Auto Registration:** Unknown faces automatically get worker IDs (W0001, W0002...)
616
- - **24-Hour Rule:** Each worker can only be marked present once per day
617
- - **Real-time Processing:** Continuous face detection and recognition
618
-
619
- ### πŸ‘€ Manual Registration
620
- - Upload clear, front-facing photos for best results
621
- - One face per image for registration
622
- - Workers get unique IDs automatically assigned
623
-
624
- ### πŸ“ Data Storage Structure
625
- ```
626
- /data/
627
- β”œβ”€β”€ workers.pkl # Worker database (embeddings, names, IDs)
628
- β”œβ”€β”€ attendance.json # All attendance records
629
- └── faces/ # Saved face images
630
- β”œβ”€β”€ W0001_John_Doe.jpg
631
- β”œβ”€β”€ W0002_Jane_Smith.jpg
632
- └── ...
633
- ```
634
-
635
- ### πŸ”§ Technical Features
636
- - **Face Recognition:** Uses DeepFace with Facenet embeddings
637
- - **Distance Threshold:** 10 for face matching accuracy
638
- - **Threading:** Separate threads for video processing and UI
639
- - **Queue Management:** Efficient frame processing with queue system
640
- - **Error Handling:** Robust error handling and recovery
641
-
642
- ### 🚨 Troubleshooting
643
- - **Camera Issues:** Check camera permissions and connections
644
- - **Poor Recognition:** Ensure good lighting and clear face visibility
645
- - **Performance:** Reduce video resolution for better performance
646
- - **Storage:** Check disk space for face image storage
647
-
648
- ### πŸ”’ Privacy & Security
649
- - All data stored locally in `/data` folder
650
- - No external API calls or data transmission
651
- - Face images saved securely with worker IDs
652
- - Attendance records in JSON format for easy backup
653
- """
654
- )
655
 
656
  # Event handlers
657
  start_stream_btn.click(
@@ -660,6 +683,12 @@ def create_interface():
660
  outputs=[stream_status]
661
  )
662
 
 
 
 
 
 
 
663
  stop_stream_btn.click(
664
  fn=attendance_system.stop_video_stream,
665
  outputs=[stream_status]
@@ -694,8 +723,17 @@ def create_interface():
694
  outputs=[export_status, export_file]
695
  )
696
 
697
- # Remove the problematic auto-refresh implementation
698
- # Users will need to manually click the refresh button
 
 
 
 
 
 
 
 
 
699
 
700
  return demo
701
 
 
27
  self.recognition_thread = None
28
  self.last_recognition_time = {}
29
  self.recognition_cooldown = 5 # seconds between recognitions for same person
30
+ self.video_file_path = None
31
+ self.video_processing = False
32
 
33
  # Create directories for data storage
34
  os.makedirs("data", exist_ok=True)
 
276
  if self.is_streaming:
277
  return "⚠️ Video stream is already running!"
278
 
279
+ # Clear previous video file if switching from file to camera
280
+ self.video_file_path = None
281
+
282
  self.video_capture = cv2.VideoCapture(camera_source)
283
  if not self.video_capture.isOpened():
284
  return "❌ Could not open camera/video source!"
 
307
  self.recognition_thread.daemon = True
308
  self.recognition_thread.start()
309
 
310
+ return "βœ… Live camera stream started successfully!"
311
 
312
  except Exception as e:
313
  return f"❌ Error starting video stream: {e}"
314
 
315
+ def process_uploaded_video(self, video_path):
316
+ """Process an uploaded video file for face recognition"""
317
+ try:
318
+ if self.is_streaming:
319
+ return "⚠️ Please stop current stream before processing a video file!"
320
+
321
+ if not os.path.exists(video_path):
322
+ return "❌ Video file not found!"
323
+
324
+ self.video_file_path = video_path
325
+ self.video_processing = True
326
+
327
+ def video_processing_loop():
328
+ cap = cv2.VideoCapture(video_path)
329
+ fps = cap.get(cv2.CAP_PROP_FPS)
330
+ frame_delay = 1.0 / fps if fps > 0 else 0.03
331
+
332
+ while self.video_processing and cap.isOpened():
333
+ ret, frame = cap.read()
334
+ if not ret:
335
+ break
336
+
337
+ # Process frame for face recognition
338
+ processed_frame = self.process_video_frame(frame)
339
+
340
+ # Add to queue for display
341
+ if not self.frame_queue.full():
342
+ try:
343
+ self.frame_queue.put_nowait(processed_frame)
344
+ except queue.Full:
345
+ pass
346
+
347
+ time.sleep(frame_delay)
348
+
349
+ cap.release()
350
+ self.video_processing = False
351
+
352
+ self.recognition_thread = threading.Thread(target=video_processing_loop)
353
+ self.recognition_thread.daemon = True
354
+ self.recognition_thread.start()
355
+
356
+ return f"βœ… Video processing started successfully! ({os.path.basename(video_path)})"
357
+
358
+ except Exception as e:
359
+ return f"❌ Error processing video: {e}"
360
+
361
  def stop_video_stream(self):
362
+ """Stop video streaming or processing"""
363
  try:
364
  self.is_streaming = False
365
+ self.video_processing = False
366
 
367
  if self.video_capture:
368
  self.video_capture.release()
 
378
  except queue.Empty:
379
  break
380
 
381
+ return "βœ… Video stream/processing stopped successfully!"
382
 
383
  except Exception as e:
384
+ return f"❌ Error stopping video: {e}"
385
 
386
  def get_current_frame(self):
387
  """Get current frame for display"""
 
486
 
487
  def create_interface():
488
  with gr.Blocks(
489
+ title="🎯 Advanced Attendance System with Video Recognition",
490
  theme=gr.themes.Soft(),
491
  css="""
492
  .gradio-container {
 
500
  border-radius: 5px;
501
  margin: 5px 0;
502
  }
503
+ .video-option-tabs {
504
+ margin-bottom: 15px;
505
+ }
506
  """
507
  ) as demo:
508
 
509
  gr.Markdown(
510
  """
511
+ # 🎯 Advanced Attendance System with Face Recognition
512
 
513
+ **Comprehensive facial recognition system with live camera and video file processing**
514
 
515
  ## πŸš€ **Key Features:**
516
+ - **πŸŽ₯ Live Camera Recognition** - Real-time face detection from camera/CCTV
517
+ - **πŸ“Ή Video File Processing** - Process pre-recorded videos for attendance
518
  - **πŸ€– Automatic Worker Registration** - Auto-register unknown faces with unique IDs
519
  - **πŸ‘€ Manual Registration** - Register workers manually with photos
520
  - **πŸ“… 24-Hour Attendance Rule** - One attendance mark per worker per day
521
  - **πŸ“Š Advanced Analytics** - Detailed reports and data export
 
 
 
 
 
 
522
  """
523
  )
524
 
525
  with gr.Tabs():
526
+ # Video Recognition Tab
527
+ with gr.Tab("πŸŽ₯ Video Recognition", elem_classes="tab-nav"):
528
+ gr.Markdown("### Face Recognition from Live Camera or Video File")
529
 
530
  with gr.Row():
531
  with gr.Column(scale=1):
532
+ with gr.Tabs(selected="live", elem_classes="video-option-tabs") as video_tabs:
533
+ with gr.Tab("Live Camera", id="live"):
534
+ camera_source = gr.Number(
535
+ label="Camera Source (0 for default camera, or RTSP URL)",
536
+ value=0,
537
+ precision=0
538
+ )
539
+
540
+ with gr.Row():
541
+ start_stream_btn = gr.Button(
542
+ "πŸŽ₯ Start Live Recognition",
543
+ variant="primary",
544
+ size="lg"
545
+ )
546
+
547
+ with gr.Tab("Upload Video", id="upload"):
548
+ video_file = gr.Video(
549
+ label="Upload Video File",
550
+ sources=["upload"],
551
+ type="filepath"
552
+ )
553
+
554
+ with gr.Row():
555
+ process_video_btn = gr.Button(
556
+ "πŸ“Ή Process Video File",
557
+ variant="primary",
558
+ size="lg"
559
+ )
560
 
561
+ stop_stream_btn = gr.Button(
562
+ "⏹️ Stop Processing",
563
+ variant="stop",
564
+ size="lg"
565
+ )
 
 
 
 
 
 
566
 
567
  stream_status = gr.Textbox(
568
+ label="Processing Status",
569
  value="Ready to start...",
570
  interactive=False,
571
  lines=2
 
574
  gr.Markdown(
575
  """
576
  **πŸ“‹ Instructions:**
577
+ - **Live Camera:** Select camera source and click "Start Live Recognition"
578
+ - **Video File:** Upload a video file and click "Process Video File"
579
+ - Click "Stop Processing" to stop current session
 
580
 
581
  **🎨 Color Coding:**
582
  - 🟒 **Green:** Known worker (attendance marked)
 
586
  )
587
 
588
  with gr.Column(scale=1):
589
+ video_output = gr.Image(
590
+ label="Recognition Output",
591
+ streaming=True,
592
+ interactive=False
593
+ )
594
+
595
  live_attendance_display = gr.Markdown(
596
  value=attendance_system.get_today_attendance(),
597
  label="Live Attendance Updates"
 
675
  value="Select date range and click 'Generate Report' to view attendance analytics.",
676
  label="Attendance Report"
677
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
678
 
679
  # Event handlers
680
  start_stream_btn.click(
 
683
  outputs=[stream_status]
684
  )
685
 
686
+ process_video_btn.click(
687
+ fn=attendance_system.process_uploaded_video,
688
+ inputs=[video_file],
689
+ outputs=[stream_status]
690
+ )
691
+
692
  stop_stream_btn.click(
693
  fn=attendance_system.stop_video_stream,
694
  outputs=[stream_status]
 
723
  outputs=[export_status, export_file]
724
  )
725
 
726
+ # Video frame update
727
+ def update_video_frame():
728
+ while True:
729
+ frame = attendance_system.get_current_frame()
730
+ if frame is not None:
731
+ # Convert BGR to RGB
732
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
733
+ yield frame
734
+ time.sleep(0.03)
735
+
736
+ demo.load(update_video_frame, None, video_output, every=0.03)
737
 
738
  return demo
739