-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathjose.py
More file actions
301 lines (231 loc) · 10.6 KB
/
jose.py
File metadata and controls
301 lines (231 loc) · 10.6 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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
import cv2
import dlib
# Load HOG + SVM-based face detector from dlib
hog_detector = dlib.get_frontal_face_detector()
# Open webcam (0 is usually the default camera)
cap = cv2.VideoCapture(0)
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Error: Cannot open webcam.")
else:
print("Webcam is successfully opened!")
print("Press 'q' to exit.")
while True:
# Read frame from webcam
ret, frame = cap.read()
if not ret:
print("Failed to grab frame.")
break
# Convert frame to grayscale and equalize histogram
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.equalizeHist(gray)
# Detect faces
detected_faces = hog_detector(gray)
# Draw bounding boxes
for face in detected_faces:
x, y, w, h = face.left(), face.top(), face.width(), face.height()
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
# Show the frame
cv2.imshow("Live Face Detection (Press 'q' to quit)", frame)
# Press 'q' to quit
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Release resources
cap.release()
cv2.destroyAllWindows()
import cv2
import dlib
import os
import numpy as np
from PIL import Image # Used for easier image handling during training
# --- Configuration ---
dataset_path = 'dataset' # Path to the folder containing training images
output_trainer_file = 'trainer/trainer.yml' # Where to save the trained model
confidence_threshold = 75 # LBPH confidence threshold (lower value means better match) Adjust as needed.
# --- Initialization ---
# Initialize dlib's HOG-based face detector
print("[INFO] Initializing dlib face detector...")
detector = dlib.get_frontal_face_detector()
# Initialize OpenCV's LBPH Face Recognizer
# Make sure the directory for the trainer file exists
output_dir = os.path.dirname(output_trainer_file)
if not os.path.exists(output_dir):
print(f"[INFO] Creating directory: {output_dir}")
os.makedirs(output_dir)
# Create LBPH Recognizer instance
# Note: cv2.face was moved in OpenCV 4. If you have issues, try cv2.face.LBPHFaceRecognizer_create()
try:
recognizer = cv2.face.LBPHFaceRecognizer_create()
print("[INFO] Initializing LBPH Recognizer (cv2.face.LBPHFaceRecognizer_create)...")
except AttributeError:
try:
recognizer = cv2.face_LBPHFaceRecognizer.create() # Older OpenCV versions
print("[INFO] Initializing LBPH Recognizer (cv2.face_LBPHFaceRecognizer.create)...")
except AttributeError:
print("[ERROR] Could not find LBPHFaceRecognizer_create. Check your OpenCV installation and version (ensure opencv-contrib-python is installed if needed).")
exit()
# --- Training Phase ---
# Function to get images and labels from the dataset directory
def get_images_and_labels(path):
print(f"[INFO] Reading training images from: {path}")
image_paths = [os.path.join(path, f) for f in os.listdir(path) if not f.startswith('.')] # Ignore hidden files
face_samples = []
ids = []
names = {} # Dictionary to map ID -> Name
current_id = 0
label_ids = {} # Dictionary to map Name -> ID
if not image_paths:
print(f"[ERROR] No images found in the dataset path: {path}")
print("Please ensure the 'dataset' folder exists and contains images named like 'SubjectName.UserID.ImageNumber.jpg'")
return [], [], {}
print(f"[INFO] Found {len(image_paths)} potential image files.")
processed_image_count = 0
face_detected_count = 0
for image_path in image_paths:
try:
# Use PIL to open image (handles various formats robustly)
pil_img = Image.open(image_path).convert('L') # Convert to grayscale
img_numpy = np.array(pil_img, 'uint8')
# Extract name and ID from filename (e.g., "Alice.1.1.jpg")
filename = os.path.basename(image_path)
parts = filename.split('.')
if len(parts) < 3:
print(f"[WARNING] Skipping file with unexpected format: {filename}. Expected 'Name.ID.Num.jpg'")
continue
name = parts[0]
try:
img_id = int(parts[1])
except ValueError:
print(f"[WARNING] Skipping file - could not parse ID as integer from: {filename}. Expected 'Name.ID.Num.jpg'")
continue
# Assign unique integer ID if needed (optional, using ID from filename is preferred)
# if name not in label_ids:
# label_ids[name] = current_id
# names[current_id] = name
# current_id += 1
# img_id = label_ids[name]
# Store Name mapping if not already present for this ID
if img_id not in names:
names[img_id] = name
print(f"[INFO] Mapping ID {img_id} to Name '{name}'")
processed_image_count += 1
# Detect faces using dlib HOG detector
# The '1' indicates upsampling the image 1 time, making it larger and potentially finding more faces.
dets = detector(img_numpy, 1)
# print(f"[DEBUG] Detected {len(dets)} faces in {filename}")
if not dets:
print(f"[WARNING] No face detected in training image: {filename}")
for k, d in enumerate(dets):
# dlib returns a rectangle object (left, top, right, bottom)
x1, y1, x2, y2 = d.left(), d.top(), d.right(), d.bottom()
# Ensure coordinates are valid
if x1 < 0 or y1 < 0 or x2 > img_numpy.shape[1] or y2 > img_numpy.shape[0]:
print(f"[WARNING] Skipping face with out-of-bounds coordinates in {filename}")
continue
if x1 >= x2 or y1 >= y2:
print(f"[WARNING] Skipping face with invalid dimensions (w or h <= 0) in {filename}")
continue
# Extract the face ROI (Region of Interest)
face_roi = img_numpy[y1:y2, x1:x2]
# --- Optional: Display face being trained ---
# cv2.imshow("Training on image...", face_roi)
# cv2.waitKey(10) # wait 10ms
# --- End Optional ---
face_samples.append(face_roi)
ids.append(img_id)
face_detected_count += 1
except Exception as e:
print(f"[ERROR] Failed to process image {image_path}: {e}")
# cv2.destroyAllWindows() # Close the optional training window
print(f"[INFO] Processed {processed_image_count} images.")
print(f"[INFO] Extracted {face_detected_count} faces for training.")
if not face_samples:
print("[ERROR] No faces were extracted from the dataset. Cannot train the recognizer.")
print("Please check dataset images and dlib detection.")
return [], [], {}
return face_samples, ids, names
# --- Train the Recognizer ---
if not os.path.exists(dataset_path):
print(f"[ERROR] Dataset path does not exist: {dataset_path}")
print("Please create the 'dataset' folder and add training images.")
exit()
faces, ids, names_map = get_images_and_labels(dataset_path)
if faces and ids:
print("\n[INFO] Training LBPH recognizer...")
recognizer.train(faces, np.array(ids))
# Save the trained model
recognizer.write(output_trainer_file)
print(f"[INFO] Trained model saved to {output_trainer_file}")
print(f"[INFO] Names mapped: {names_map}")
else:
print("[ERROR] Training failed due to lack of training data.")
exit()
# --- Real-time Detection and Identification ---
# Load the trained recognizer if not just trained (useful if running separately)
# recognizer.read(output_trainer_file)
print("\n[INFO] Starting video capture...")
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("[ERROR] Cannot open webcam.")
exit()
print("[INFO] Press 'q' to quit.")
font = cv2.FONT_HERSHEY_SIMPLEX
while True:
ret, frame = cap.read()
if not ret:
print("[ERROR] Failed to capture frame from webcam.")
break
# Convert frame to grayscale for detection and recognition
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Detect faces using dlib HOG detector
# Again, '1' is the upsample factor. Use '0' for faster but potentially less sensitive detection.
dets = detector(gray, 1)
# print(f"[DEBUG] Detected {len(dets)} faces in current frame.")
# Loop over the detected faces
for k, d in enumerate(dets):
x1, y1, x2, y2 = d.left(), d.top(), d.right(), d.bottom()
# Ensure coordinates are valid before drawing/cropping
if x1 < 0: x1 = 0
if y1 < 0: y1 = 0
if x2 > frame.shape[1]: x2 = frame.shape[1]
if y2 > frame.shape[0]: y2 = frame.shape[0]
if x1 >= x2 or y1 >= y2: # Skip invalid boxes
continue
# Draw rectangle around the face in the original color frame
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
# --- Identification using LBPH ---
# Extract the grayscale face ROI for recognition
face_roi_gray = gray[y1:y2, x1:x2]
try:
# Predict the ID and confidence
id_, confidence = recognizer.predict(face_roi_gray)
# Check if the prediction is confident enough (lower confidence is better)
if confidence < confidence_threshold:
# Map the predicted ID back to a name
name = names_map.get(id_, "Unknown") # Get name or default to Unknown
display_text = f"{name} ({confidence:.2f})"
text_color = (255, 255, 255) # White text for known faces
else:
# If confidence is too high, label as Unknown
name = "Unknown"
display_text = f"{name} ({confidence:.2f})"
text_color = (0, 0, 255) # Red text for unknown faces
# Display the name and confidence
text_y = y1 - 10 if y1 - 10 > 10 else y1 + 10 # Position text above or below box
cv2.putText(frame, display_text, (x1, text_y), font, 0.7, text_color, 2)
except cv2.error as e:
# This can happen if the face ROI is too small or invalid
print(f"[WARNING] Could not predict face ROI: {e}")
cv2.putText(frame, "Error", (x1, y1 - 5), font, 0.7, (0, 0, 255), 2)
except Exception as e:
print(f"[ERROR] Unexpected error during prediction: {e}")
# Display the resulting frame
cv2.imshow('Real-Time Face Detection and Identification (dlib HOG + LBPH)', frame)
# Break loop on 'q' key press
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# --- Cleanup ---
print("\n[INFO] Cleaning up...")
cap.release()
cv2.destroyAllWindows()
print("[INFO] Application finished.")