Real-Time Face Recognition Systems with OpenCV and Deep Learning

Published on December 10, 2025

Face recognition has evolved from a research curiosity to a practical technology used in security, attendance systems, and photo organization. In this post, I'll walk through building a real-time face recognition system that processes 200+ students per session—achieving an 80% reduction in attendance processing time.

System Architecture

Our system uses a three-stage pipeline:

  1. Face Detection: Locate faces in video frames
  2. Face Encoding: Convert faces to numerical representations
  3. Face Recognition: Match encodings against a database

1. Face Detection with Haar Cascades

import cv2
import numpy as np

class FaceDetector:
    def __init__(self):
        # Load pre-trained Haar cascade
        self.face_cascade = cv2.CascadeClassifier(
            cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
        )
    
    def detect_faces(self, frame):
        """Detect faces in a frame."""
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        
        faces = self.face_cascade.detectMultiScale(
            gray,
            scaleFactor=1.1,
            minNeighbors=5,
            minSize=(30, 30)
        )
        
        return faces  # Returns (x, y, w, h) for each face

# For better accuracy, use dlib's HOG or CNN detector
import dlib

class DlibFaceDetector:
    def __init__(self, use_cnn=False):
        if use_cnn:
            self.detector = dlib.cnn_face_detection_model_v1(
                'mmod_human_face_detector.dat'
            )
        else:
            self.detector = dlib.get_frontal_face_detector()
    
    def detect_faces(self, frame):
        rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        return self.detector(rgb, 1)

2. Face Encoding with Deep Learning

import face_recognition

class FaceEncoder:
    def __init__(self):
        self.known_encodings = {}
        self.known_names = []
    
    def encode_face(self, image, face_location=None):
        """Generate 128-dimensional face encoding."""
        rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        
        if face_location:
            encodings = face_recognition.face_encodings(
                rgb, 
                known_face_locations=[face_location]
            )
        else:
            encodings = face_recognition.face_encodings(rgb)
        
        return encodings[0] if encodings else None
    
    def register_face(self, name, images):
        """Register a person with multiple face images."""
        encodings = []
        for img in images:
            encoding = self.encode_face(img)
            if encoding is not None:
                encodings.append(encoding)
        
        if encodings:
            # Store average encoding for robustness
            self.known_encodings[name] = np.mean(encodings, axis=0)
            self.known_names.append(name)
            return True
        return False

3. Face Recognition and Matching

class FaceRecognizer:
    def __init__(self, encoder, threshold=0.6):
        self.encoder = encoder
        self.threshold = threshold
    
    def recognize(self, frame, face_locations):
        """Recognize faces in frame."""
        results = []
        rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        
        # Get encodings for detected faces
        encodings = face_recognition.face_encodings(rgb, face_locations)
        
        for encoding, location in zip(encodings, face_locations):
            # Compare against known faces
            distances = face_recognition.face_distance(
                list(self.encoder.known_encodings.values()),
                encoding
            )
            
            if len(distances) > 0:
                min_idx = np.argmin(distances)
                min_distance = distances[min_idx]
                
                if min_distance < self.threshold:
                    name = self.encoder.known_names[min_idx]
                    confidence = 1 - min_distance
                else:
                    name = "Unknown"
                    confidence = 0
            else:
                name = "Unknown"
                confidence = 0
            
            results.append({
                'name': name,
                'confidence': confidence,
                'location': location
            })
        
        return results

4. Complete Attendance System

import datetime
import csv

class AttendanceSystem:
    def __init__(self, encoder_path='encodings.pkl'):
        self.detector = FaceDetector()
        self.encoder = FaceEncoder()
        self.recognizer = FaceRecognizer(self.encoder)
        self.attendance_log = {}
        
        # Load pre-computed encodings
        self.load_encodings(encoder_path)
    
    def mark_attendance(self, name):
        """Mark attendance for recognized person."""
        if name not in self.attendance_log:
            timestamp = datetime.datetime.now()
            self.attendance_log[name] = timestamp
            print(f"✓ {name} marked present at {timestamp.strftime('%H:%M:%S')}")
            return True
        return False
    
    def run_camera(self):
        """Run real-time recognition from camera."""
        cap = cv2.VideoCapture(0)
        
        while True:
            ret, frame = cap.read()
            if not ret:
                break
            
            # Detect faces
            face_locations = self.detector.detect_faces(frame)
            
            # Recognize faces
            results = self.recognizer.recognize(frame, face_locations)
            
            # Draw results and mark attendance
            for result in results:
                name = result['name']
                confidence = result['confidence']
                x, y, w, h = result['location']
                
                # Mark attendance
                if name != "Unknown":
                    self.mark_attendance(name)
                
                # Draw bounding box
                color = (0, 255, 0) if name != "Unknown" else (0, 0, 255)
                cv2.rectangle(frame, (x, y), (x+w, y+h), color, 2)
                cv2.putText(
                    frame, 
                    f"{name} ({confidence:.2f})",
                    (x, y-10),
                    cv2.FONT_HERSHEY_SIMPLEX,
                    0.5, color, 2
                )
            
            cv2.imshow('Attendance System', frame)
            
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        
        cap.release()
        cv2.destroyAllWindows()
    
    def export_attendance(self, filename='attendance.csv'):
        """Export attendance log to CSV."""
        with open(filename, 'w', newline='') as f:
            writer = csv.writer(f)
            writer.writerow(['Name', 'Timestamp'])
            for name, timestamp in self.attendance_log.items():
                writer.writerow([name, timestamp.isoformat()])

Performance Optimization

For real-time performance with 200+ students:

Results

Our deployed system achieved: