-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
129 lines (105 loc) · 5.07 KB
/
Copy pathmain.py
File metadata and controls
129 lines (105 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
## ====================================================================
## ADVANCED HUB ATTENDANCE (Gender Voting + Blur Filter)
## ====================================================================
from ultralytics import YOLO
import cv2
import os
import csv
from datetime import datetime
from deepface import DeepFace
import numpy as np
import warnings
from collections import Counter
# Suppress TensorFlow noise
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
warnings.filterwarnings("ignore")
# --- Config ---
SNAPSHOTS_DIR = "people_snapshots"
LOG_FILE = "attendance_gender.csv"
VOTES_REQUIRED = 5 # We need 5 good samples before we "confirm" a person
os.makedirs(SNAPSHOTS_DIR, exist_ok=True)
# Load YOLO model (Small is better for movement)
model = YOLO('yolov8s.pt')
def find_camera():
for index in range(10):
cap = cv2.VideoCapture(index)
if cap.isOpened():
print(f"[#] Camera found at index {index}")
return cap
cap.release()
return None
def is_blurry(image, threshold=50):
"""Returns True if the image is too blurry for accurate analysis."""
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
score = cv2.Laplacian(gray, cv2.CV_64F).var()
return score < threshold
cap = find_camera()
if not cap:
print("[!] Error: Could not access webcam")
exit()
# State Management
gender_votes = {} # track_id -> [list of gender guesses]
final_results = {} # track_id -> confirmed gender
processed_ids = set() # track_id -> bool (logged to CSV)
# CSV Setup
with open(LOG_FILE, "a", newline="") as f:
f.seek(0, 2)
if f.tell() == 0:
csv.writer(f).writerow(["timestamp", "person_id", "gender", "snapshot"])
print("-" * 50)
print(" GENDER ANALYSIS (Voting System enabled) ")
print(" Analysis will confirm after 5 clear frames ")
print(" Press 'q' to quit ")
print("-" * 50)
while True:
ret, frame = cap.read()
if not ret: break
# Track bodies
results = model.track(frame, persist=True, classes=[0], conf=0.3, tracker="bytetrack.yaml", verbose=False)
for r in results:
if r.boxes.id is None: continue
boxes = r.boxes.xyxy.cpu().numpy().astype(int)
track_ids = r.boxes.id.cpu().numpy().astype(int)
for box, track_id in zip(boxes, track_ids):
x1, y1, x2, y2 = box
# 1. Skip if already finalized
if track_id in final_results and track_id in processed_ids:
color, label = (0, 255, 0), f"ID:{track_id} | {final_results[track_id]}"
else:
color, label = (0, 255, 255), f"Analyzing ID:{track_id}..."
# 2. Try to analyze this person's gender
person_crop = frame[max(0, y1):y2, max(0, x1):x2]
# Check quality before analyzing
if person_crop.size > 1000 and not is_blurry(person_crop, threshold=40):
try:
# Analyze Gender
# Use RetinaFace for detection inside DeepFace for better small-face results
res = DeepFace.analyze(person_crop, actions=['gender'], enforce_detection=True, detector_backend='opencv', silent=True)
gender = res[0]['dominant_gender']
# Add to voting pool
if track_id not in gender_votes: gender_votes[track_id] = []
gender_votes[track_id].append(gender)
# 3. If we have enough votes, finalize!
if len(gender_votes[track_id]) >= VOTES_REQUIRED:
# Take the most frequent result
vote_counts = Counter(gender_votes[track_id])
confirmed_gender = vote_counts.most_common(1)[0][0]
final_results[track_id] = confirmed_gender
# Log and Snapshot
if track_id not in processed_ids:
ts = datetime.now().strftime("%H%M%S")
snap_name = f"person_{track_id}_{confirmed_gender}_{ts}.jpg"
cv2.imwrite(os.path.join(SNAPSHOTS_DIR, snap_name), person_crop)
with open(LOG_FILE, "a", newline="") as f:
csv.writer(f).writerow([datetime.now().strftime("%Y-%m-%d %H:%M:%S"), track_id, confirmed_gender, snap_name])
print(f" [✓] Finalized ID {track_id}: {confirmed_gender}")
processed_ids.add(track_id)
except:
pass # No face found or blurry - wait for a better frame
# Drawing
cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2)
cv2.putText(frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
cv2.imshow("Hub Attendance Analysis", frame)
if cv2.waitKey(1) & 0xFF == ord("q"): break
cap.release()
cv2.destroyAllWindows()