Files
PeopleCounter/face_detector.py
eroncero 432f0378bf feat: initial implementation of People Counter web app
- Add Flask application with MJPEG video streaming
- Implement OpenCV DNN face detection module
- Add zone-based entry/exit tracking with cooldown mechanism
- Create web interface with real-time WebSocket updates
- Add model download script and comprehensive README
- Include OpenCV DNN model files for face detection
2026-01-20 00:44:06 +01:00

119 lines
3.9 KiB
Python

"""
Face Detection Module using OpenCV DNN Face Detector
Uses pre-trained models for accurate face detection.
"""
import cv2
import numpy as np
import os
class FaceDetector:
def __init__(self, model_dir="models", confidence_threshold=0.5):
"""
Initialize the face detector with OpenCV DNN models.
Args:
model_dir: Directory containing the model files
confidence_threshold: Minimum confidence for face detection (0.0-1.0)
"""
self.confidence_threshold = confidence_threshold
self.model_dir = model_dir
# Paths to model files
self.prototxt_path = os.path.join(model_dir, "deploy.prototxt")
self.model_path = os.path.join(model_dir, "res10_300x300_ssd_iter_140000.caffemodel")
# Load the DNN face detector
self.net = None
self._load_model()
def _load_model(self):
"""Load the OpenCV DNN face detection model."""
if not os.path.exists(self.prototxt_path):
raise FileNotFoundError(
f"Model prototxt file not found: {self.prototxt_path}\n"
"Please download the model files first."
)
if not os.path.exists(self.model_path):
raise FileNotFoundError(
f"Model weights file not found: {self.model_path}\n"
"Please download the model files first."
)
self.net = cv2.dnn.readNetFromCaffe(self.prototxt_path, self.model_path)
def detect_faces(self, frame):
"""
Detect faces in a frame.
Args:
frame: BGR image frame from OpenCV
Returns:
List of tuples (x, y, w, h, confidence) for each detected face
where (x, y) is top-left corner, w and h are width and height
"""
if self.net is None:
return []
# Get frame dimensions
(h, w) = frame.shape[:2]
# Create blob from frame (preprocessing for DNN)
blob = cv2.dnn.blobFromImage(
cv2.resize(frame, (300, 300)),
1.0,
(300, 300),
(104.0, 177.0, 123.0)
)
# Pass blob through network
self.net.setInput(blob)
detections = self.net.forward()
faces = []
# Process detections
for i in range(0, detections.shape[2]):
confidence = detections[0, 0, i, 2]
# Filter weak detections
if confidence > self.confidence_threshold:
# Get bounding box coordinates
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(x1, y1, x2, y2) = box.astype("int")
# Ensure coordinates are within frame bounds
x1 = max(0, x1)
y1 = max(0, y1)
x2 = min(w, x2)
y2 = min(h, y2)
# Convert to (x, y, w, h) format
faces.append((x1, y1, x2 - x1, y2 - y1, confidence))
return faces
def draw_faces(self, frame, faces, color=(0, 255, 0), thickness=2):
"""
Draw bounding boxes around detected faces.
Args:
frame: Frame to draw on
faces: List of face detections from detect_faces()
color: BGR color tuple for bounding boxes
thickness: Line thickness
Returns:
Frame with bounding boxes drawn
"""
result_frame = frame.copy()
for (x, y, w, h, confidence) in faces:
cv2.rectangle(result_frame, (x, y), (x + w, y + h), color, thickness)
# Optionally draw confidence score
label = f"{confidence:.2f}"
cv2.putText(result_frame, label, (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
return result_frame