Last updated: February 4, 2025

<span aria-hidden="true" id="real-time-face-detection-with-opencvs-yunet"></span>

# Real-time face detection with OpenCV's YuNet

![Kevin van Zonneveld](/assets/images/teammates/avatar-kvz-4.jpg?dpl=dpl_EaRBV7VUa5qo1qfBKDnoq2VsKW7d)

**Kevin van Zonneveld**

Co-founder · Amsterdam, The Netherlands · Show bio

[](https://x.com/kvz)[](https://github.com/kvz)

Real-time face detection is a powerful tool for a variety of applications, from security monitoring to interactive user experiences. In this post, we explore how to set up a streaming face detection pipeline in Python using OpenCV's YuNet detector, a state-of-the-art solution that offers excellent performance on CPU hardware.

<span aria-hidden="true" id="why-real-time-face-detection"></span>

## Why real-time face detection?

Detecting faces in real time enables various applications, from security systems to interactive installations. Modern face detection algorithms like YuNet provide robust detection capabilities while maintaining high performance, making them suitable for production environments.

<span aria-hidden="true" id="setting-up-your-environment"></span>

## Setting up your environment

Before implementing face detection, set up your development environment:

```bash
# Install required packages
pip install opencv-python numpy

# Download YuNet model
git clone https://github.com/opencv/opencv_zoo.git
cd opencv_zoo/models/face_detection_yunet/

```

<span aria-hidden="true" id="building-a-basic-streaming-face-detection-pipeline"></span>

## Building a basic streaming face detection pipeline

Here's a complete example that captures video from your webcam and processes each frame using YuNet:

```python
import cv2
import numpy as np

# Initialize YuNet face detector
face_detector = cv2.FaceDetectorYN.create(
    'face_detection_yunet_2023mar.onnx',
    "",
    (320, 320),
    0.9,  # score threshold
    0.3,  # nms threshold
    5000  # top k
)

# Initialize webcam
cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # Set input size
    height, width, _ = frame.shape
    face_detector.setInputSize((width, height))

    # Detect faces
    _, faces = face_detector.detect(frame)

    # Draw results
    if faces is not None:
        for face in faces:
            box = face[0:4].astype(np.int32)
            cv2.rectangle(frame, (box[0], box[1]),
                         (box[0] + box[2], box[1] + box[3]),
                         (0, 255, 0), 2)

    cv2.imshow('Real-time Face Detection', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

```

This script initializes the YuNet detector, captures video frames, and draws bounding boxes around detected faces in real-time.

<span aria-hidden="true" id="advanced-usage-handling-multiple-faces-and-parameter-adjustments"></span>

## Advanced usage: handling multiple faces and parameter adjustments

YuNet offers several parameters to fine-tune detection performance:

```python
# Advanced configuration
face_detector = cv2.FaceDetectorYN.create(
    'face_detection_yunet_2023mar.onnx',
    "",
    (320, 320),
    0.7,    # Lower threshold for higher sensitivity
    0.4,    # Adjusted NMS threshold
    10000   # Increased top k for more faces
)

# Error handling and face processing
try:
    _, faces = face_detector.detect(frame)
    if faces is not None:
        for face in faces:
            confidence = face[4]
            if confidence > 0.7:  # Additional confidence filter
                box = face[0:4].astype(np.int32)
                landmarks = face[5:15].astype(np.int32).reshape(-1, 2)

                # Draw face box
                cv2.rectangle(frame, (box[0], box[1]),
                             (box[0] + box[2], box[1] + box[3]),
                             (0, 255, 0), 2)

                # Draw landmarks
                for landmark in landmarks:
                    cv2.circle(frame, landmark, 2, (0, 255, 255), -1)
except Exception as e:
    print(f"Detection error: {e}")

```

This enhanced version includes landmark detection and proper error handling.

<span aria-hidden="true" id="optimizing-performance"></span>

## Optimizing performance

To achieve optimal performance in real-time applications:

1. Resize input frames:

```python
scale = 0.5  
resized = cv2.resize(frame, None, fx=scale, fy=scale)  
face_detector.setInputSize((resized.shape[1], resized.shape[0]))  
```

2. Process frames asynchronously:

```python
from concurrent.futures import ThreadPoolExecutor  
def process_frame(frame):  
    _, faces = face_detector.detect(frame)  
    return faces  
with ThreadPoolExecutor(max_workers=2) as executor:  
    future = executor.submit(process_frame, frame)  
    faces = future.result()  
```

3. Implement frame skipping when needed:

```python
frame_count = 0  
process_every = 2  # Process every second frame  
while True:  
    ret, frame = cap.read()  
    frame_count += 1  
    if frame_count % process_every == 0:  
        # Process frame  
        _, faces = face_detector.detect(frame)  
```

<span aria-hidden="true" id="practical-use-case-security-monitoring"></span>

## Practical use case: security monitoring

Here's a practical example of a security monitoring system that logs face detections:

```python
from datetime import datetime
import json

class FaceMonitor:
    def __init__(self, log_file='face_detections.json'):
        self.log_file = log_file
        self.face_detector = cv2.FaceDetectorYN.create(
            'face_detection_yunet_2023mar.onnx',
            "",
            (320, 320),
            0.9,
            0.3,
            5000
        )

    def log_detection(self, num_faces):
        entry = {
            'timestamp': datetime.now().isoformat(),
            'faces_detected': num_faces
        }
        with open(self.log_file, 'a') as f:
            json.dump(entry, f)
            f.write('\n')

    def monitor(self, frame):
        _, faces = self.face_detector.detect(frame)
        if faces is not None:
            self.log_detection(len(faces))
        return faces

```

<span aria-hidden="true" id="performance-considerations"></span>

## Performance considerations

YuNet offers impressive performance metrics:

* CPU performance: 30-50 FPS on modern processors
* Memory usage: Approximately 30MB
* Detection accuracy: 95%+ on standard benchmarks

These metrics make it suitable for most real-time applications without requiring specialized hardware.

<span aria-hidden="true" id="conclusion"></span>

## Conclusion

Implementing real-time face detection has become more accessible with modern tools like OpenCV's YuNet detector. The combination of high performance and accuracy makes it an excellent choice for various applications. For those interested in exploring automated image analysis solutions at scale, check out Transloadit's AI service documentation.

\#face-detection#image-processing#python#artificial-intelligence-service

### 👩‍💻 Join 20k+ developers

Sign up for our [monthly newsletter](/newsletters.md) to receive direct links to 3 exclusive tech — and 2 product updates. No less, no more.

Your email:

Get access

## File uploading and encoding. Made simple.

Transloadit streamlines file handling for developers, trusted by brands like Coursera and The New York Times. We’re known for a reliable API, top-notch support, and a strong commitment to open source, with projects like [Uppy⁠](https://uppy.io) and [Tus⁠](https://tus.io) setting standards in file processing.

[Sign up](/c/)[Book a Demo](https://survey.typeform.com/to/kRg47Xi5)

No credit card needed

Cancel anytime
