Sivainti commited on
Commit
ad84de9
Β·
verified Β·
1 Parent(s): 8a6b406

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +205 -17
app.py CHANGED
@@ -13,10 +13,24 @@ import json
13
  import threading
14
  import time
15
  import queue
 
 
 
16
 
17
  # Suppress TensorFlow oneDNN warning
18
  os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
19
 
 
 
 
 
 
 
 
 
 
 
 
20
  class AttendanceSystem:
21
  def __init__(self):
22
  self.known_face_embeddings = []
@@ -33,6 +47,19 @@ class AttendanceSystem:
33
  self.video_file_path = None
34
  self.video_processing = False
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  # Create directories for data storage
37
  os.makedirs("data", exist_ok=True)
38
  os.makedirs("data/faces", exist_ok=True)
@@ -84,21 +111,46 @@ class AttendanceSystem:
84
  except Exception as e:
85
  print(f"Error saving data: {e}")
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  def register_worker_manual(self, image, name):
88
- """Manual worker registration"""
89
  if image is None or not name.strip():
90
  return "❌ Please provide both image and name!", self.get_registered_workers_info()
91
 
92
  # Convert PIL image to RGB array
93
  if isinstance(image, Image.Image):
94
- image = np.array(image)
95
 
96
  try:
97
  # Verify the image contains a face
98
- face_analysis = DeepFace.analyze(img_path=image, actions=['emotion'], enforce_detection=True, detector_backend='opencv')
99
 
100
  # Get face embedding
101
- embedding = DeepFace.represent(img_path=image, model_name='Facenet')[0]['embedding']
102
 
103
  # Check if person already exists
104
  name = name.strip().title()
@@ -108,6 +160,9 @@ class AttendanceSystem:
108
  # Generate new worker ID
109
  worker_id = f"W{self.next_worker_id:04d}"
110
 
 
 
 
111
  # Add the face embedding, name, and ID
112
  self.known_face_embeddings.append(embedding)
113
  self.known_face_names.append(name)
@@ -115,12 +170,25 @@ class AttendanceSystem:
115
  self.next_worker_id += 1
116
 
117
  # Save face image
118
- face_image = Image.fromarray(image)
119
  face_image.save(f"data/faces/{worker_id}_{name.replace(' ', '_')}.jpg")
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  self.save_data()
122
 
123
- return f"βœ… {name} has been successfully registered with ID: {worker_id}!", self.get_registered_workers_info()
124
 
125
  except ValueError as e:
126
  if "Face could not be detected" in str(e):
@@ -139,6 +207,10 @@ class AttendanceSystem:
139
  # Get face embedding
140
  embedding = DeepFace.represent(img_path=face_image, model_name='Facenet')[0]['embedding']
141
 
 
 
 
 
142
  # Add to database
143
  self.known_face_embeddings.append(embedding)
144
  self.known_face_names.append(worker_name)
@@ -146,9 +218,21 @@ class AttendanceSystem:
146
  self.next_worker_id += 1
147
 
148
  # Save face image
149
- face_pil = Image.fromarray(cv2.cvtColor(face_image, cv2.COLOR_BGR2RGB))
150
  face_pil.save(f"data/faces/{worker_id}_{worker_name}.jpg")
151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  self.save_data()
153
 
154
  return worker_id, worker_name
@@ -158,7 +242,7 @@ class AttendanceSystem:
158
  return None, None
159
 
160
  def mark_attendance(self, worker_id, worker_name):
161
- """Mark attendance for a worker"""
162
  try:
163
  today = date.today().isoformat()
164
  current_time = datetime.now()
@@ -170,8 +254,8 @@ class AttendanceSystem:
170
  )
171
 
172
  if not already_marked:
173
- # Mark attendance
174
- self.attendance_records.append({
175
  "worker_id": worker_id,
176
  "name": worker_name,
177
  "date": today,
@@ -179,7 +263,25 @@ class AttendanceSystem:
179
  "timestamp": current_time.isoformat(),
180
  "status": "Present",
181
  "method": "Auto"
182
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  self.save_data()
184
  return True
185
  return False
@@ -397,7 +499,25 @@ class AttendanceSystem:
397
  return None
398
 
399
  def get_registered_workers_info(self):
400
- """Get information about registered workers"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  if not self.known_face_names:
402
  return "No workers registered yet."
403
 
@@ -407,7 +527,30 @@ class AttendanceSystem:
407
  return info
408
 
409
  def get_today_attendance(self):
410
- """Get today's attendance records"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
411
  today = date.today().isoformat()
412
  today_records = [r for r in self.attendance_records if r["date"] == today]
413
 
@@ -418,11 +561,10 @@ class AttendanceSystem:
418
  for record in today_records:
419
  method_icon = "πŸ€–" if record.get("method") == "Auto" else "πŸ‘€"
420
  info += f"{method_icon} **{record['name']}** (ID: {record['worker_id']}) - {record['time']}\n"
421
-
422
  return info
423
 
424
  def get_attendance_report(self, start_date, end_date):
425
- """Generate attendance report for date range"""
426
  if not start_date or not end_date:
427
  return "Please select both start and end dates."
428
 
@@ -433,6 +575,50 @@ class AttendanceSystem:
433
  except ValueError:
434
  return "Invalid date format. Please use YYYY-MM-DD."
435
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
436
  # Filter records by date range
437
  filtered_records = [
438
  r for r in self.attendance_records
@@ -513,15 +699,17 @@ def create_interface():
513
  """
514
  # 🎯 Advanced Attendance System with Face Recognition
515
 
516
- **Comprehensive facial recognition system with live camera and video file processing**
517
 
518
  ## πŸš€ **Key Features:**
519
  - **πŸŽ₯ Live Camera Recognition** - Real-time face detection from camera/CCTV
520
  - **πŸ“Ή Video File Processing** - Process pre-recorded videos for attendance
521
  - **πŸ€– Automatic Worker Registration** - Auto-register unknown faces with unique IDs
522
- - **πŸ‘€ Manual Registration** - Register workers manually with photos
523
  - **πŸ“… 24-Hour Attendance Rule** - One attendance mark per worker per day
524
  - **πŸ“Š Advanced Analytics** - Detailed reports and data export
 
 
525
  """
526
  )
527
 
 
13
  import threading
14
  import time
15
  import queue
16
+ import requests
17
+ from simple_salesforce import Salesforce
18
+ import os
19
 
20
  # Suppress TensorFlow oneDNN warning
21
  os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
22
 
23
+ # Hugging Face API configuration
24
+ HF_API_URL = "https://api-inference.huggingface.co/models/Salesforce/blip-image-captioning-base"
25
+ HF_API_TOKEN = os.getenv("HUGGINGFACE_API_TOKEN")
26
+
27
+ # Salesforce configuration
28
+ SF_CLIENT_ID = os.getenv("SF_CLIENT_ID")
29
+ SF_CLIENT_SECRET = os.getenv("SF_CLIENT_SECRET")
30
+ SF_USERNAME = os.getenv("smartlabour@attendance.system")
31
+ SF_PASSWORD = os.getenv("#Prashanth@123")
32
+ SF_SECURITY_TOKEN = os.getenv("pasQDqmWApzD0skgbv76gVgIs")
33
+
34
  class AttendanceSystem:
35
  def __init__(self):
36
  self.known_face_embeddings = []
 
47
  self.video_file_path = None
48
  self.video_processing = False
49
 
50
+ # Initialize Salesforce connection
51
+ try:
52
+ self.sf = Salesforce(
53
+ username=SF_USERNAME,
54
+ password=SF_PASSWORD,
55
+ security_token=SF_SECURITY_TOKEN,
56
+ client_id=SF_CLIENT_ID,
57
+ client_secret=SF_CLIENT_SECRET
58
+ )
59
+ except Exception as e:
60
+ print(f"Error connecting to Salesforce: {e}")
61
+ self.sf = None
62
+
63
  # Create directories for data storage
64
  os.makedirs("data", exist_ok=True)
65
  os.makedirs("data/faces", exist_ok=True)
 
111
  except Exception as e:
112
  print(f"Error saving data: {e}")
113
 
114
+ def get_image_caption(self, image):
115
+ """Generate image caption using Hugging Face API"""
116
+ try:
117
+ # Convert PIL image to bytes
118
+ if isinstance(image, Image.Image):
119
+ img_byte_arr = BytesIO()
120
+ image.save(img_byte_arr, format='JPEG')
121
+ img_data = img_byte_arr.getvalue()
122
+
123
+ # Make API request to Hugging Face
124
+ headers = {"Authorization": f"Bearer {HF_API_TOKEN}"}
125
+ response = requests.post(HF_API_URL, headers=headers, data=img_data)
126
+
127
+ if response.status_code == 200:
128
+ result = response.json()
129
+ if isinstance(result, list) and len(result) > 0:
130
+ return result[0].get("generated_text", "No caption generated")
131
+ return "No caption generated"
132
+ else:
133
+ print(f"Hugging Face API error: {response.status_code} - {response.text}")
134
+ return "Error generating caption"
135
+ except Exception as e:
136
+ print(f"Error in Hugging Face API call: {e}")
137
+ return "Error generating caption"
138
+
139
  def register_worker_manual(self, image, name):
140
+ """Manual worker registration with Hugging Face and Salesforce integration"""
141
  if image is None or not name.strip():
142
  return "❌ Please provide both image and name!", self.get_registered_workers_info()
143
 
144
  # Convert PIL image to RGB array
145
  if isinstance(image, Image.Image):
146
+ image_array = np.array(image)
147
 
148
  try:
149
  # Verify the image contains a face
150
+ face_analysis = DeepFace.analyze(img_path=image_array, actions=['emotion'], enforce_detection=True, detector_backend='opencv')
151
 
152
  # Get face embedding
153
+ embedding = DeepFace.represent(img_path=image_array, model_name='Facenet')[0]['embedding']
154
 
155
  # Check if person already exists
156
  name = name.strip().title()
 
160
  # Generate new worker ID
161
  worker_id = f"W{self.next_worker_id:04d}"
162
 
163
+ # Generate image caption using Hugging Face
164
+ caption = self.get_image_caption(image)
165
+
166
  # Add the face embedding, name, and ID
167
  self.known_face_embeddings.append(embedding)
168
  self.known_face_names.append(name)
 
170
  self.next_worker_id += 1
171
 
172
  # Save face image
173
+ face_image = Image.fromarray(image_array)
174
  face_image.save(f"data/faces/{worker_id}_{name.replace(' ', '_')}.jpg")
175
 
176
+ # Save to Salesforce
177
+ if self.sf:
178
+ try:
179
+ self.sf.Worker__c.create({
180
+ 'Name': name,
181
+ 'Worker_ID__c': worker_id,
182
+ 'Face_Embedding__c': json.dumps(embedding),
183
+ 'Image_Caption__c': caption
184
+ })
185
+ print(f"βœ… Worker {name} ({worker_id}) saved to Salesforce with caption: {caption}")
186
+ except Exception as e:
187
+ print(f"Error saving to Salesforce: {e}")
188
+
189
  self.save_data()
190
 
191
+ return f"βœ… {name} has been successfully registered with ID: {worker_id}! Caption: {caption}", self.get_registered_workers_info()
192
 
193
  except ValueError as e:
194
  if "Face could not be detected" in str(e):
 
207
  # Get face embedding
208
  embedding = DeepFace.represent(img_path=face_image, model_name='Facenet')[0]['embedding']
209
 
210
+ # Generate image caption
211
+ face_pil = Image.fromarray(cv2.cvtColor(face_image, cv2.COLOR_BGR2RGB))
212
+ caption = self.get_image_caption(face_pil)
213
+
214
  # Add to database
215
  self.known_face_embeddings.append(embedding)
216
  self.known_face_names.append(worker_name)
 
218
  self.next_worker_id += 1
219
 
220
  # Save face image
 
221
  face_pil.save(f"data/faces/{worker_id}_{worker_name}.jpg")
222
 
223
+ # Save to Salesforce
224
+ if self.sf:
225
+ try:
226
+ self.sf.Worker__c.create({
227
+ 'Name': worker_name,
228
+ 'Worker_ID__c': worker_id,
229
+ 'Face_Embedding__c': json.dumps(embedding),
230
+ 'Image_Caption__c': caption
231
+ })
232
+ print(f"βœ… Worker {worker_name} ({worker_id}) saved to Salesforce with caption: {caption}")
233
+ except Exception as e:
234
+ print(f"Error saving to Salesforce: {e}")
235
+
236
  self.save_data()
237
 
238
  return worker_id, worker_name
 
242
  return None, None
243
 
244
  def mark_attendance(self, worker_id, worker_name):
245
+ """Mark attendance for a worker and save to Salesforce"""
246
  try:
247
  today = date.today().isoformat()
248
  current_time = datetime.now()
 
254
  )
255
 
256
  if not already_marked:
257
+ # Create attendance record
258
+ attendance_record = {
259
  "worker_id": worker_id,
260
  "name": worker_name,
261
  "date": today,
 
263
  "timestamp": current_time.isoformat(),
264
  "status": "Present",
265
  "method": "Auto"
266
+ }
267
+ self.attendance_records.append(attendance_record)
268
+
269
+ # Save to Salesforce
270
+ if self.sf:
271
+ try:
272
+ self.sf.Attendance__c.create({
273
+ 'Worker_ID__c': worker_id,
274
+ 'Name__c': worker_name,
275
+ 'Date__c': today,
276
+ 'Time__c': current_time.strftime("%H:%M:%S"),
277
+ 'Timestamp__c': current_time.isoformat(),
278
+ 'Status__c': "Present",
279
+ 'Method__c': "Auto"
280
+ })
281
+ print(f"βœ… Attendance for {worker_name} ({worker_id}) saved to Salesforce")
282
+ except Exception as e:
283
+ print(f"Error saving attendance to Salesforce: {e}")
284
+
285
  self.save_data()
286
  return True
287
  return False
 
499
  return None
500
 
501
  def get_registered_workers_info(self):
502
+ """Get information about registered workers from Salesforce"""
503
+ if not self.sf:
504
+ return "❌ Salesforce connection not established."
505
+
506
+ try:
507
+ workers = self.sf.query_all("SELECT Name, Worker_ID__c, Image_Caption__c FROM Worker__c")['records']
508
+ if not workers:
509
+ return "No workers registered yet."
510
+
511
+ info = f"**Registered Workers ({len(workers)}):**\n\n"
512
+ for i, worker in enumerate(workers, 1):
513
+ info += f"{i}. **{worker['Name']}** (ID: {worker['Worker_ID__c']}) - Caption: {worker['Image_Caption__c'] or 'N/A'}\n"
514
+ return info
515
+ except Exception as e:
516
+ print(f"Error fetching workers from Salesforce: {e}")
517
+ return self._get_local_workers_info()
518
+
519
+ def _get_local_workers_info(self):
520
+ """Fallback to local worker info if Salesforce query fails"""
521
  if not self.known_face_names:
522
  return "No workers registered yet."
523
 
 
527
  return info
528
 
529
  def get_today_attendance(self):
530
+ """Get today's attendance records from Salesforce"""
531
+ if not self.sf:
532
+ return "❌ Salesforce connection not established."
533
+
534
+ today = date.today().isoformat()
535
+ try:
536
+ records = self.sf.query_all(
537
+ f"SELECT Name__c, Worker_ID__c, Time__c, Method__c FROM Attendance__c WHERE Date__c = '{today}'"
538
+ )['records']
539
+
540
+ if not records:
541
+ return f"**Today's Attendance ({today}):**\n\nNo attendance marked yet."
542
+
543
+ info = f"**Today's Attendance ({today}):**\n\n"
544
+ for record in records:
545
+ method_icon = "πŸ€–" if record['Method__c'] == "Auto" else "πŸ‘€"
546
+ info += f"{method_icon} **{record['Name__c']}** (ID: {record['Worker_ID__c']}) - {record['Time__c']}\n"
547
+ return info
548
+ except Exception as e:
549
+ print(f"Error fetching attendance from Salesforce: {e}")
550
+ return self._get_local_today_attendance()
551
+
552
+ def _get_local_today_attendance(self):
553
+ """Fallback to local attendance records if Salesforce query fails"""
554
  today = date.today().isoformat()
555
  today_records = [r for r in self.attendance_records if r["date"] == today]
556
 
 
561
  for record in today_records:
562
  method_icon = "πŸ€–" if record.get("method") == "Auto" else "πŸ‘€"
563
  info += f"{method_icon} **{record['name']}** (ID: {record['worker_id']}) - {record['time']}\n"
 
564
  return info
565
 
566
  def get_attendance_report(self, start_date, end_date):
567
+ """Generate attendance report for date range from Salesforce"""
568
  if not start_date or not end_date:
569
  return "Please select both start and end dates."
570
 
 
575
  except ValueError:
576
  return "Invalid date format. Please use YYYY-MM-DD."
577
 
578
+ if not self.sf:
579
+ return "❌ Salesforce connection not established."
580
+
581
+ try:
582
+ # Query Salesforce for attendance records
583
+ records = self.sf.query_all(
584
+ f"SELECT Worker_ID__c, Name__c, Date__c, Time__c, Method__c FROM Attendance__c "
585
+ f"WHERE Date__c >= '{start_date}' AND Date__c <= '{end_date}'"
586
+ )['records']
587
+
588
+ if not records:
589
+ return f"No attendance records found between {start_date} and {end_date}."
590
+
591
+ # Create DataFrame for analysis
592
+ df = pd.DataFrame(records)
593
+
594
+ # Summary statistics
595
+ total_days = (pd.to_datetime(end_date) - pd.to_datetime(start_date)).days + 1
596
+ unique_workers = df['Worker_ID__c'].nunique()
597
+ total_attendances = len(df)
598
+ auto_registrations = len(df[df['Method__c'] == 'Auto'])
599
+
600
+ report = f"**πŸ“Š Attendance Report ({start_date} to {end_date})**\n\n"
601
+ report += f"**Summary:**\n"
602
+ report += f"β€’ Total Days: {total_days}\n"
603
+ report += f"β€’ Unique Workers: {unique_workers}\n"
604
+ report += f"β€’ Total Attendances: {total_attendances}\n"
605
+ report += f"β€’ Auto Detections: {auto_registrations}\n\n"
606
+
607
+ # Individual attendance counts
608
+ if not df.empty:
609
+ attendance_counts = df.groupby(['Worker_ID__c', 'Name__c']).size().reset_index(name='count')
610
+ report += f"**πŸ‘₯ Individual Attendance:**\n"
611
+ for _, row in attendance_counts.iterrows():
612
+ percentage = (row['count'] / total_days) * 100
613
+ report += f"β€’ **{row['Name__c']}** ({row['Worker_ID__c']}): {row['count']} days ({percentage:.1f}%)\n"
614
+
615
+ return report
616
+ except Exception as e:
617
+ print(f"Error generating report from Salesforce: {e}")
618
+ return self._get_local_attendance_report(start_date, end_date)
619
+
620
+ def _get_local_attendance_report(self, start_date, end_date):
621
+ """Fallback to local attendance report if Salesforce query fails"""
622
  # Filter records by date range
623
  filtered_records = [
624
  r for r in self.attendance_records
 
699
  """
700
  # 🎯 Advanced Attendance System with Face Recognition
701
 
702
+ **Comprehensive facial recognition system with live camera and video file processing, integrated with Hugging Face and Salesforce**
703
 
704
  ## πŸš€ **Key Features:**
705
  - **πŸŽ₯ Live Camera Recognition** - Real-time face detection from camera/CCTV
706
  - **πŸ“Ή Video File Processing** - Process pre-recorded videos for attendance
707
  - **πŸ€– Automatic Worker Registration** - Auto-register unknown faces with unique IDs
708
+ - **πŸ‘€ Manual Registration** - Register workers manually with photos and AI-generated captions
709
  - **πŸ“… 24-Hour Attendance Rule** - One attendance mark per worker per day
710
  - **πŸ“Š Advanced Analytics** - Detailed reports and data export
711
+ - **πŸ€— Hugging Face Integration** - AI-powered image captioning
712
+ - **☁️ Salesforce Integration** - Store worker and attendance data in Salesforce
713
  """
714
  )
715