roseyshi commited on
Commit
6f2dcbc
·
verified ·
1 Parent(s): b2a30a5

Upload 16 files

Browse files
Dockerfile.dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile.backend
2
+ FROM python:3.9-slim
3
+
4
+ WORKDIR /app
5
+
6
+ COPY requirements.txt .
7
+ RUN pip install --no-cache-dir -r requirements.txt
8
+
9
+ COPY . .
10
+
11
+ CMD ["uvicorn", "backend.api.main:app", "--host", "0.0.0.0", "--port", "8000"]
analytics_service.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # backend/services/analytics_service.py
2
+ from datetime import datetime, timedelta
3
+ from sqlalchemy import func, and_
4
+ from database.models import Attendance, Employee
5
+ import pandas as pd
6
+
7
+ class AnalyticsService:
8
+ def __init__(self, db_session):
9
+ self.db = db_session
10
+
11
+ def get_personnel_present(self, date=None):
12
+ """Get number of personnel present today"""
13
+ if date is None:
14
+ date = datetime.now().date()
15
+
16
+ count = self.db.query(Attendance).filter(
17
+ Attendance.date == date,
18
+ Attendance.status.in_(['present', 'early', 'on_time', 'late'])
19
+ ).count()
20
+ return count
21
+
22
+ def get_shift_coverage(self):
23
+ """Calculate shift coverage percentage"""
24
+ total_employees = self.db.query(Employee).count()
25
+ present_today = self.get_personnel_present()
26
+
27
+ if total_employees == 0:
28
+ return 0
29
+ return (present_today / total_employees) * 100
30
+
31
+ def get_staffing_trends(self, days=30):
32
+ """Get staffing trends for last N days"""
33
+ end_date = datetime.now().date()
34
+ start_date = end_date - timedelta(days=days)
35
+
36
+ results = self.db.query(
37
+ Attendance.date,
38
+ func.count(Attendance.id).label('present_count')
39
+ ).filter(
40
+ Attendance.date.between(start_date, end_date),
41
+ Attendance.status.in_(['present', 'early', 'on_time', 'late'])
42
+ ).group_by(Attendance.date).all()
43
+
44
+ return pd.DataFrame(results, columns=['date', 'present_count'])
45
+
46
+ def get_missing_personnel(self):
47
+ """Get list of employees who haven't checked in today"""
48
+ today = datetime.now().date()
49
+
50
+ # Get all employees
51
+ all_employees = self.db.query(Employee).all()
52
+ all_ids = [e.id for e in all_employees]
53
+
54
+ # Get present employees today
55
+ present = self.db.query(Attendance.employee_id).filter(
56
+ Attendance.date == today,
57
+ Attendance.status.in_(['present', 'early', 'on_time', 'late'])
58
+ ).distinct().all()
59
+ present_ids = [p[0] for p in present]
60
+
61
+ # Find missing
62
+ missing_ids = set(all_ids) - set(present_ids)
63
+
64
+ return self.db.query(Employee).filter(
65
+ Employee.id.in_(missing_ids)
66
+ ).all()
app.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # frontend/app.py (Streamlit version)
2
+ import streamlit as st
3
+ import requests
4
+ import websocket
5
+ import json
6
+ import base64
7
+ from PIL import Image
8
+ import io
9
+ import numpy as np
10
+ import cv2
11
+
12
+ st.set_page_config(
13
+ page_title="AI Personnel Dashboard",
14
+ page_icon="👥",
15
+ layout="wide"
16
+ )
17
+
18
+ # Sidebar
19
+ st.sidebar.title("🔍 Navigation")
20
+ page = st.sidebar.selectbox(
21
+ "Select Page",
22
+ ["Live Feed", "Dashboard", "Analytics", "Employee Management"]
23
+ )
24
+
25
+ if page == "Live Feed":
26
+ st.title("📹 Live Personnel Monitoring")
27
+
28
+ # Video feed placeholder
29
+ video_placeholder = st.empty()
30
+ metrics_placeholder = st.empty()
31
+
32
+ # Connect to WebSocket
33
+ # ... WebSocket implementation for real-time feed
34
+
35
+ elif page == "Dashboard":
36
+ st.title("📊 Dashboard")
37
+
38
+ # Fetch analytics
39
+ response = requests.get("http://localhost:8000/api/analytics/dashboard")
40
+ data = response.json()
41
+
42
+ col1, col2, col3, col4 = st.columns(4)
43
+
44
+ with col1:
45
+ st.metric("👥 Personnel Present", data['personnel_present'])
46
+
47
+ with col2:
48
+ st.metric("📈 Shift Coverage", f"{data['shift_coverage']:.1f}%")
49
+
50
+ with col3:
51
+ st.metric("📅 Total Employees", 50) # Fetch from DB
52
+
53
+ with col4:
54
+ missing_count = len(data['missing_personnel'])
55
+ st.metric("⚠️ Missing Personnel", missing_count)
56
+
57
+ # Staffing trends chart
58
+ st.subheader("Staffing Trends (Last 30 Days)")
59
+ # ... Plot trends using matplotlib/plotly
60
+
61
+ # Missing personnel alerts
62
+ if missing_count > 0:
63
+ st.warning(f"⚠️ {missing_count} employees haven't checked in today!")
64
+ for employee in data['missing_personnel']:
65
+ st.write(f"- {employee['name']}")
attendance_manager.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # backend/core/attendance_manager.py
2
+ from datetime import datetime, timedelta
3
+ from sqlalchemy.orm import Session
4
+ from database.models import Attendance, Employee
5
+ import logging
6
+
7
+ class AttendanceManager:
8
+ def __init__(self, db_session: Session):
9
+ self.db = db_session
10
+ self.attendance_cache = {}
11
+ self.grace_period_minutes = 15
12
+
13
+ def mark_attendance(self, employee_id, timestamp=None):
14
+ """Mark attendance for an employee"""
15
+ if timestamp is None:
16
+ timestamp = datetime.now()
17
+
18
+ # Check if already marked today
19
+ today = timestamp.date()
20
+ existing = self.db.query(Attendance).filter(
21
+ Attendance.employee_id == employee_id,
22
+ Attendance.date == today
23
+ ).first()
24
+
25
+ if existing:
26
+ existing.check_out = timestamp
27
+ existing.status = 'present'
28
+ else:
29
+ # Determine if early/late/on-time
30
+ status = self._determine_status(timestamp)
31
+ attendance = Attendance(
32
+ employee_id=employee_id,
33
+ date=today,
34
+ check_in=timestamp,
35
+ status=status
36
+ )
37
+ self.db.add(attendance)
38
+
39
+ self.db.commit()
40
+ return True
41
+
42
+ def _determine_status(self, timestamp):
43
+ """Determine if employee is on-time, late, or early"""
44
+ shift_start = timestamp.replace(hour=9, minute=0, second=0)
45
+ if timestamp < shift_start:
46
+ return 'early'
47
+ elif timestamp <= shift_start + timedelta(minutes=self.grace_period_minutes):
48
+ return 'on_time'
49
+ else:
50
+ return 'late'
capture_screenshots.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # capture_screenshots.py
2
+ import cv2
3
+ import numpy as np
4
+
5
+ def create_demo_screenshot():
6
+ """Generate visual screenshots for portfolio"""
7
+
8
+ # Create simulated dashboard images
9
+ dashboard = np.zeros((800, 1200, 3), dtype=np.uint8)
10
+
11
+ # Add simulated metrics
12
+ cv2.rectangle(dashboard, (50, 50), (250, 150), (30, 30, 30), -1)
13
+ cv2.putText(dashboard, "👥 8 Personnel Present", (70, 110),
14
+ cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
15
+
16
+ # Save
17
+ cv2.imwrite('dashboard_screenshot.jpg', dashboard)
18
+
19
+ create_demo_screenshot()
create_demo.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # create_demo_gif.py
2
+ import imageio
3
+ import cv2
4
+ import os
5
+
6
+ def create_demo_gif(video_path, output_path='demo.gif', duration=0.5):
7
+ """Create GIF from video for portfolio"""
8
+ reader = imageio.get_reader(video_path)
9
+ fps = reader.get_meta_data()['fps']
10
+
11
+ # Extract frames (every 3rd frame)
12
+ frames = []
13
+ for i, frame in enumerate(reader):
14
+ if i % 3 == 0:
15
+ # Convert to RGB
16
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
17
+ frames.append(frame_rgb)
18
+ if len(frames) >= 20: # Limit GIF length
19
+ break
20
+
21
+ # Save as GIF
22
+ imageio.mimsave(output_path, frames, duration=duration)
23
+ print(f"✅ GIF saved to {output_path}")
24
+
25
+ # Usage
26
+ create_demo_gif('demo_video.mp4')
demo_live.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # demo_live.py - Simple script to run a live demo
2
+ import cv2
3
+ from core.face_detection import FaceDetector
4
+ from core.face_recognition import FaceRecognizer
5
+ from core.attendance_manager import AttendanceManager
6
+ import time
7
+
8
+ def run_live_demo():
9
+ """Run live demo with webcam"""
10
+ # Initialize components
11
+ detector = FaceDetector()
12
+ recognizer = FaceRecognizer()
13
+
14
+ # Open webcam
15
+ cap = cv2.VideoCapture(0)
16
+
17
+ print("🎥 Live Demo Started - Press 'q' to quit")
18
+ print("👤 Show your face to the camera")
19
+
20
+ while True:
21
+ ret, frame = cap.read()
22
+ if not ret:
23
+ break
24
+
25
+ # Detect and recognize
26
+ faces = detector.detect_faces(frame)
27
+ for face_data in faces:
28
+ name = recognizer.recognize_face(face_data['face_img'])
29
+
30
+ # Draw results
31
+ x1, y1, x2, y2 = face_data['bbox']
32
+ color = (0, 255, 0) if name else (0, 0, 255)
33
+ label = name if name else "Unknown"
34
+
35
+ cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2)
36
+ cv2.putText(frame, label, (x1, y1-10),
37
+ cv2.FONT_HERSHEY_SIMPLEX, 0.9, color, 2)
38
+
39
+ # Show confidence
40
+ cv2.putText(frame, f"Conf: {face_data['confidence']:.2f}",
41
+ (x1, y2+20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1)
42
+
43
+ # Display stats
44
+ cv2.putText(frame, f"Faces Detected: {len(faces)}", (10, 30),
45
+ cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
46
+
47
+ cv2.imshow('AI Attendance Demo', frame)
48
+
49
+ if cv2.waitKey(1) & 0xFF == ord('q'):
50
+ break
51
+
52
+ cap.release()
53
+ cv2.destroyAllWindows()
54
+
55
+ if __name__ == "__main__":
56
+ run_live_demo()
demo_simulated.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # demo_simulated.py - Generate realistic demo data
2
+ import pandas as pd
3
+ import numpy as np
4
+ from datetime import datetime, timedelta
5
+ import random
6
+
7
+ class SimulatedDemo:
8
+ """Generate simulated attendance data for dashboard demo"""
9
+
10
+ def __init__(self):
11
+ self.employees = self._create_employees()
12
+ self.attendance_log = []
13
+
14
+ def _create_employees(self):
15
+ """Create employee database"""
16
+ names = [
17
+ "Alice Johnson", "Bob Smith", "Carol White",
18
+ "David Brown", "Eve Davis", "Frank Wilson",
19
+ "Grace Lee", "Henry Kim", "Ivy Chen", "Jack Taylor"
20
+ ]
21
+
22
+ employees = []
23
+ for i, name in enumerate(names, 1):
24
+ employees.append({
25
+ 'id': i,
26
+ 'name': name,
27
+ 'department': random.choice(['Engineering', 'Sales', 'HR', 'Marketing']),
28
+ 'shift_start': '09:00',
29
+ 'shift_end': '18:00'
30
+ })
31
+ return employees
32
+
33
+ def generate_attendance(self, days=30):
34
+ """Generate simulated attendance data"""
35
+ end_date = datetime.now()
36
+ start_date = end_date - timedelta(days=days)
37
+
38
+ attendance = []
39
+
40
+ for day in range(days):
41
+ current_date = start_date + timedelta(days=day)
42
+ # Skip weekends
43
+ if current_date.weekday() >= 5:
44
+ continue
45
+
46
+ for employee in self.employees:
47
+ # 90% attendance rate
48
+ if random.random() < 0.9:
49
+ check_in = self._random_time(current_date, 8, 10)
50
+ check_out = self._random_time(current_date, 17, 19)
51
+
52
+ status = self._determine_status(check_in, '09:00')
53
+
54
+ attendance.append({
55
+ 'employee_name': employee['name'],
56
+ 'date': current_date.strftime('%Y-%m-%d'),
57
+ 'check_in': check_in.strftime('%H:%M'),
58
+ 'check_out': check_out.strftime('%H:%M'),
59
+ 'status': status,
60
+ 'department': employee['department']
61
+ })
62
+
63
+ self.attendance_log = pd.DataFrame(attendance)
64
+ return self.attendance_log
65
+
66
+ def _random_time(self, date, hour_start, hour_end):
67
+ """Generate random time within range"""
68
+ hour = random.randint(hour_start, hour_end)
69
+ minute = random.randint(0, 59)
70
+ return date.replace(hour=hour, minute=minute)
71
+
72
+ def _determine_status(self, check_in, shift_start):
73
+ """Determine attendance status"""
74
+ shift_hour, shift_min = map(int, shift_start.split(':'))
75
+ shift_start_time = check_in.replace(hour=shift_hour, minute=shift_min)
76
+
77
+ if check_in < shift_start_time:
78
+ return 'early'
79
+ elif check_in <= shift_start_time + timedelta(minutes=15):
80
+ return 'on_time'
81
+ else:
82
+ return 'late'
83
+
84
+ # Generate and save demo data
85
+ demo = SimulatedDemo()
86
+ attendance_data = demo.generate_attendance()
87
+
88
+ # Save as CSV for dashboard
89
+ attendance_data.to_csv('demo_attendance_data.csv', index=False)
90
+ print("✅ Demo data generated and saved to 'demo_attendance_data.csv'")
demo_video.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # demo_video.py - Process a video file
2
+ def process_video_demo(video_path='sample_video.mp4'):
3
+ """Process a pre-recorded video for demo"""
4
+ cap = cv2.VideoCapture(video_path)
5
+
6
+ # Setup video writer for output
7
+ output_path = 'demo_output.mp4'
8
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
9
+ out = cv2.VideoWriter(output_path, fourcc, 30.0,
10
+ (int(cap.get(3)), int(cap.get(4))))
11
+
12
+ detector = FaceDetector()
13
+ recognizer = FaceRecognizer()
14
+
15
+ frame_count = 0
16
+ recognition_results = []
17
+
18
+ while cap.isOpened():
19
+ ret, frame = cap.read()
20
+ if not ret:
21
+ break
22
+
23
+ frame_count += 1
24
+
25
+ # Process every 3rd frame for speed
26
+ if frame_count % 3 == 0:
27
+ faces = detector.detect_faces(frame)
28
+
29
+ for face_data in faces:
30
+ name = recognizer.recognize_face(face_data['face_img'])
31
+ recognition_results.append({
32
+ 'frame': frame_count,
33
+ 'name': name,
34
+ 'confidence': float(face_data['confidence'])
35
+ })
36
+
37
+ # Draw on frame
38
+ x1, y1, x2, y2 = face_data['bbox']
39
+ if name:
40
+ cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 3)
41
+ cv2.putText(frame, f"✅ {name}", (x1, y1-10),
42
+ cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
43
+ else:
44
+ cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2)
45
+ cv2.putText(frame, "❌ Unknown", (x1, y1-10),
46
+ cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
47
+
48
+ out.write(frame)
49
+
50
+ cap.release()
51
+ out.release()
52
+
53
+ # Generate demo report
54
+ generate_demo_report(recognition_results)
55
+ print(f"✅ Demo video saved to {output_path}")
56
+
57
+ def generate_demo_report(results):
58
+ """Create a report showing recognition accuracy"""
59
+ recognized = [r for r in results if r['name']]
60
+ unknown = [r for r in results if not r['name']]
61
+
62
+ report = f"""
63
+ 📊 Demo Results Report
64
+ {'='*40}
65
+ Total Faces Processed: {len(results)}
66
+ Successfully Recognized: {len(recognized)} ({len(recognized)/len(results)*100:.1f}%)
67
+ Unknown Faces: {len(unknown)}
68
+ Average Confidence: {sum(r['confidence'] for r in recognized)/len(recognized):.2f}
69
+
70
+ Recognized Personnel:
71
+ """
72
+ # Group by name
73
+ from collections import Counter
74
+ name_counts = Counter(r['name'] for r in recognized)
75
+ for name, count in name_counts.items():
76
+ report += f" - {name}: {count} detections\n"
77
+
78
+ with open('demo_report.txt', 'w') as f:
79
+ f.write(report)
80
+ print(report)
face_detection.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # backend/core/face_detection.py
2
+ import cv2
3
+ from ultralytics import YOLO
4
+ import numpy as np
5
+
6
+ class FaceDetector:
7
+ def __init__(self, model_path='yolov8n-face.pt'):
8
+ self.model = YOLO(model_path)
9
+ self.confidence_threshold = 0.5
10
+
11
+ def detect_faces(self, frame):
12
+ """Detect faces in a frame using YOLO"""
13
+ results = self.model(frame)
14
+ faces = []
15
+
16
+ for result in results:
17
+ boxes = result.boxes
18
+ for box in boxes:
19
+ if box.conf > self.confidence_threshold:
20
+ x1, y1, x2, y2 = box.xyxy[0].cpu().numpy().astype(int)
21
+ face = frame[y1:y2, x1:x2]
22
+ faces.append({
23
+ 'bbox': (x1, y1, x2, y2),
24
+ 'face_img': face,
25
+ 'confidence': box.conf
26
+ })
27
+ return faces
face_recognition.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # backend/core/face_recognition.py
2
+ import face_recognition
3
+ import numpy as np
4
+ import pickle
5
+ import os
6
+
7
+ class FaceRecognizer:
8
+ def __init__(self, encodings_path='models/face_encodings.pkl'):
9
+ self.known_face_encodings = []
10
+ self.known_face_names = []
11
+ self.load_encodings(encodings_path)
12
+
13
+ def load_encodings(self, path):
14
+ """Load pre-computed face encodings"""
15
+ if os.path.exists(path):
16
+ with open(path, 'rb') as f:
17
+ data = pickle.load(f)
18
+ self.known_face_encodings = data['encodings']
19
+ self.known_face_names = data['names']
20
+
21
+ def recognize_face(self, face_img):
22
+ """Recognize a single face"""
23
+ if face_img is None or face_img.size == 0:
24
+ return None
25
+
26
+ # Get face encoding
27
+ face_locations = face_recognition.face_locations(face_img)
28
+ if not face_locations:
29
+ return None
30
+
31
+ face_encoding = face_recognition.face_encodings(face_img, face_locations)[0]
32
+
33
+ # Compare with known faces
34
+ matches = face_recognition.compare_faces(
35
+ self.known_face_encodings,
36
+ face_encoding
37
+ )
38
+
39
+ if True in matches:
40
+ matched_index = matches.index(True)
41
+ return self.known_face_names[matched_index]
42
+ return None
interview_demo.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # interview_demo.py - Streamlit app for interviews
2
+ import streamlit as st
3
+ import cv2
4
+ import tempfile
5
+ import numpy as np
6
+ from PIL import Image
7
+
8
+ def interview_demo_app():
9
+ st.set_page_config(page_title="Live Demo", layout="wide")
10
+
11
+ st.title("🎯 Live Demo - AI Attendance System")
12
+
13
+ st.info("""
14
+ **How to demonstrate:**
15
+ 1. Click 'Start Camera' below
16
+ 2. Show your face to the camera
17
+ 3. See real-time detection and recognition
18
+ 4. Watch attendance log update automatically
19
+ """)
20
+
21
+ # Sidebar with status
22
+ with st.sidebar:
23
+ st.header("🔴 System Status")
24
+ st.success("✅ Camera Ready")
25
+ st.success("✅ Model Loaded")
26
+ st.success("✅ Database Connected")
27
+
28
+ st.header("📊 Session Stats")
29
+ if 'detections' not in st.session_state:
30
+ st.session_state.detections = []
31
+
32
+ st.metric("Faces Detected", len(st.session_state.detections))
33
+
34
+ # Camera feed
35
+ col1, col2 = st.columns([2, 1])
36
+
37
+ with col1:
38
+ st.subheader("📹 Live Feed")
39
+ camera_placeholder = st.empty()
40
+
41
+ # Start camera button
42
+ if st.button("🚀 Start Camera", use_container_width=True):
43
+ cap = cv2.VideoCapture(0)
44
+
45
+ if not cap.isOpened():
46
+ st.error("⚠️ Could not access camera")
47
+ else:
48
+ # Process frames
49
+ frame_count = 0
50
+ while True:
51
+ ret, frame = cap.read()
52
+ if not ret:
53
+ break
54
+
55
+ # Your detection code here
56
+ # For demo, just show frame with overlay
57
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
58
+ frame = cv2.putText(frame, "🟢 Live Demo", (10, 30),
59
+ cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
60
+
61
+ camera_placeholder.image(frame, use_container_width=True)
62
+
63
+ # Simulate detections
64
+ if frame_count % 30 == 0:
65
+ st.session_state.detections.append({
66
+ 'time': datetime.now(),
67
+ 'name': 'Demo User'
68
+ })
69
+
70
+ frame_count += 1
71
+
72
+ with col2:
73
+ st.subheader("📋 Live Attendance")
74
+ attendance_table = st.empty()
75
+
76
+ # Show attendance log
77
+ if st.session_state.detections:
78
+ df = pd.DataFrame(st.session_state.detections)
79
+ attendance_table.dataframe(df.tail(10))
80
+ else:
81
+ st.info("Waiting for detections...")
82
+
83
+ # Demo controls
84
+ col3, col4 = st.columns(2)
85
+ with col3:
86
+ if st.button("🧹 Clear Log", use_container_width=True):
87
+ st.session_state.detections = []
88
+ st.rerun()
89
+ with col4:
90
+ if st.button("📥 Export Demo Data", use_container_width=True):
91
+ # Export functionality
92
+ st.success("✅ Demo data exported!")
93
+
94
+ if __name__ == "__main__":
95
+ interview_demo_app()
mock_dashboard.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mock_dashboard.py - Show dashboard working without webcam
2
+ import streamlit as st
3
+ import pandas as pd
4
+ from datetime import datetime
5
+ import plotly.express as px
6
+
7
+ # Load demo data
8
+ df = pd.read_csv('demo_attendance_data.csv')
9
+
10
+ def show_mock_dashboard():
11
+ """Display dashboard with mock data"""
12
+ st.title("👥 AI Personnel Dashboard - Demo")
13
+
14
+ # Add watermark
15
+ st.markdown("""
16
+ <div style='position: fixed; bottom: 0; right: 0;
17
+ background: rgba(255,255,255,0.8); padding: 10px;'>
18
+ 🎯 Demo Data - Not Live
19
+ </div>
20
+ """, unsafe_allow_html=True)
21
+
22
+ # Metrics
23
+ col1, col2, col3, col4 = st.columns(4)
24
+
25
+ today = datetime.now().strftime('%Y-%m-%d')
26
+ today_data = df[df['date'] == today]
27
+
28
+ with col1:
29
+ st.metric("👥 Present Today", len(today_data))
30
+
31
+ with col2:
32
+ total_employees = 50
33
+ coverage = (len(today_data) / total_employees) * 100
34
+ st.metric("📈 Coverage", f"{coverage:.1f}%")
35
+
36
+ with col3:
37
+ late = len(today_data[today_data['status'] == 'late'])
38
+ st.metric("⏰ Late Arrivals", late)
39
+
40
+ with col4:
41
+ missing = total_employees - len(today_data)
42
+ st.metric("⚠️ Missing", missing)
43
+
44
+ # Charts
45
+ st.subheader("📊 Attendance Trends")
46
+
47
+ daily_attendance = df.groupby('date').size().reset_index(name='count')
48
+ fig = px.line(daily_attendance, x='date', y='count',
49
+ title='Daily Attendance Trend')
50
+ st.plotly_chart(fig, use_container_width=True)
51
+
52
+ # Department breakdown
53
+ st.subheader("🏢 Department-wise Attendance")
54
+ dept_data = today_data.groupby('department').size().reset_index(name='count')
55
+ fig = px.bar(dept_data, x='department', y='count',
56
+ title='Today\'s Attendance by Department')
57
+ st.plotly_chart(fig, use_container_width=True)
58
+
59
+ # Missing personnel
60
+ st.subheader("⚠️ Missing Personnel Alert")
61
+ missing_emps = ['Alice Johnson', 'Bob Smith', 'Carol White']
62
+ for emp in missing_emps:
63
+ st.warning(f"🔴 {emp} has not checked in today")
64
+
65
+ if __name__ == "__main__":
66
+ show_mock_dashboard()
sql.sql ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- PostgreSQL Schema
2
+ CREATE TABLE employees (
3
+ id SERIAL PRIMARY KEY,
4
+ employee_id VARCHAR(50) UNIQUE NOT NULL,
5
+ name VARCHAR(100) NOT NULL,
6
+ department VARCHAR(100),
7
+ position VARCHAR(100),
8
+ shift_start TIME,
9
+ shift_end TIME,
10
+ email VARCHAR(100),
11
+ face_encoding BYTEA,
12
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
13
+ );
14
+
15
+ CREATE TABLE attendance (
16
+ id SERIAL PRIMARY KEY,
17
+ employee_id INTEGER REFERENCES employees(id),
18
+ date DATE NOT NULL,
19
+ check_in TIMESTAMP,
20
+ check_out TIMESTAMP,
21
+ status VARCHAR(20),
22
+ location VARCHAR(100),
23
+ device_id VARCHAR(50),
24
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
25
+ );
26
+
27
+ CREATE TABLE alerts (
28
+ id SERIAL PRIMARY KEY,
29
+ type VARCHAR(50),
30
+ employee_id INTEGER REFERENCES employees(id),
31
+ message TEXT,
32
+ severity VARCHAR(20),
33
+ read BOOLEAN DEFAULT FALSE,
34
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
35
+ );
video_processor.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # backend/core/video_processor.py
2
+ import cv2
3
+ import asyncio
4
+ from datetime import datetime
5
+ from core.face_detection import FaceDetector
6
+ from core.face_recognition import FaceRecognizer
7
+ from core.attendance_manager import AttendanceManager
8
+
9
+ class VideoProcessor:
10
+ def __init__(self, detector, recognizer, attendance_manager):
11
+ self.detector = detector
12
+ self.recognizer = recognizer
13
+ self.attendance_manager = attendance_manager
14
+ self.frame_buffer = []
15
+ self.processing_interval = 0.5 # Process every 0.5 seconds
16
+
17
+ async def process_video(self, video_source=0):
18
+ """Process video stream from camera or file"""
19
+ cap = cv2.VideoCapture(video_source)
20
+
21
+ if not cap.isOpened():
22
+ raise ValueError("Could not open video source")
23
+
24
+ last_process_time = datetime.now()
25
+
26
+ while True:
27
+ ret, frame = cap.read()
28
+ if not ret:
29
+ break
30
+
31
+ # Process at intervals for efficiency
32
+ current_time = datetime.now()
33
+ if (current_time - last_process_time).total_seconds() >= self.processing_interval:
34
+ # Detect faces
35
+ faces = self.detector.detect_faces(frame)
36
+
37
+ for face_data in faces:
38
+ # Recognize face
39
+ name = self.recognizer.recognize_face(face_data['face_img'])
40
+ if name:
41
+ # Mark attendance
42
+ employee_id = self._get_employee_id(name)
43
+ if employee_id:
44
+ self.attendance_manager.mark_attendance(employee_id)
45
+ # Draw bounding box with name
46
+ x1, y1, x2, y2 = face_data['bbox']
47
+ cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
48
+ cv2.putText(frame, name, (x1, y1-10),
49
+ cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,255,0), 2)
50
+
51
+ last_process_time = current_time
52
+
53
+ yield frame
54
+
55
+ cap.release()
web_socket.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # backend/api/websocket.py
2
+ from fastapi import FastAPI, WebSocket, WebSocketDisconnect
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ import asyncio
5
+ import json
6
+ import cv2
7
+ import base64
8
+
9
+ app = FastAPI()
10
+
11
+ app.add_middleware(
12
+ CORSMiddleware,
13
+ allow_origins=["*"],
14
+ allow_credentials=True,
15
+ allow_methods=["*"],
16
+ allow_headers=["*"],
17
+ )
18
+
19
+ @app.websocket("/ws/video")
20
+ async def video_websocket(websocket: WebSocket):
21
+ await websocket.accept()
22
+
23
+ # Initialize components
24
+ detector = FaceDetector()
25
+ recognizer = FaceRecognizer()
26
+ attendance_manager = AttendanceManager(db_session)
27
+ processor = VideoProcessor(detector, recognizer, attendance_manager)
28
+
29
+ try:
30
+ async for frame in processor.process_video():
31
+ # Encode frame to JPEG
32
+ _, buffer = cv2.imencode('.jpg', frame)
33
+ frame_b64 = base64.b64encode(buffer).decode('utf-8')
34
+
35
+ # Send to client
36
+ await websocket.send_json({
37
+ 'frame': frame_b64,
38
+ 'timestamp': datetime.now().isoformat()
39
+ })
40
+
41
+ except WebSocketDisconnect:
42
+ print("Client disconnected")
43
+
44
+ @app.get("/api/analytics/dashboard")
45
+ async def get_dashboard_data():
46
+ """Get all dashboard metrics"""
47
+ analytics = AnalyticsService(db_session)
48
+
49
+ return {
50
+ 'personnel_present': analytics.get_personnel_present(),
51
+ 'shift_coverage': analytics.get_shift_coverage(),
52
+ 'staffing_trends': analytics.get_staffing_trends().to_dict(),
53
+ 'missing_personnel': [
54
+ {'id': e.id, 'name': e.name}
55
+ for e in analytics.get_missing_personnel()
56
+ ],
57
+ 'timestamp': datetime.now().isoformat()
58
+ }