Skip to content

add real time face blurring script #411

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions README.md

Large diffs are not rendered by default.

82 changes: 82 additions & 0 deletions Real-Time-Face-Blurring-Tool/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Real-Time Face Blurring Tool

A robust Python application for anonymizing faces in images, videos, and live webcam feeds using OpenCV's deep neural network (DNN) module.

## Features

- **Multi-source processing**:
- 📷 Single image processing
- 🎥 Video file processing
- 🌐 Live webcam feed processing
- **Advanced face detection** using Caffe-based DNN model
- **Adjustable parameters**:
- Blur strength (kernel size)
- Detection confidence threshold
- **Automatic output organization**:
- `./output_images/` for processed images
- `./output_videos/` for processed videos
- **Progress tracking** for video processing
- **Graceful resource handling** with proper cleanup

## Requirements

- Python 3.6+
- Required packages:
```bash
pip install opencv-python numpy
```

## Installation

Clone the repository and install dependencies:

```bash
git clone https://github.com/yourusername/Real-Time-Face-Blurring-Tool.git
cd Real-Time-Face-Blurring-Tool
pip install -r requirements.txt
```

## Model Files

Download the following files and place them in the correct folders:

- `deploy.prototxt.txt` → `protocol/` folder
- `res10_300x300_ssd_iter_140000_fp16.caffemodel` → `model/` folder

You can download them from [OpenCV's GitHub repository](https://github.com/opencv/opencv/tree/master/samples/dnn/face_detector).

## Usage

Process an image:

```bash
python main.py --image path/to/image.jpg
```

Process a video:

```bash
python main.py --video path/to/video.mp4
```

Process webcam feed:

```bash
python main.py --webcam
```

### Optional Arguments

- `--blur` Blur kernel size (odd integer, default: 61)
- `--confidence` Face detection confidence threshold (default: 0.5)

## Output

- Processed images are saved in `./output_images/` with `_blurred` appended to the filename.
- Processed videos are saved in `./output_videos/` with `_blurred` appended to the filename.

## Troubleshooting

- **Model file not found:** Make sure you downloaded the model files and placed them in the correct folders.
- **Webcam not detected:** Ensure your webcam is connected and not used by another application.
- **Permission errors:** Run your terminal or IDE as administrator if you encounter permission issues writing output files.
241 changes: 241 additions & 0 deletions Real-Time-Face-Blurring-Tool/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
import os
import cv2
import numpy as np
import logging
from pathlib import Path

# Configuration
DEFAULT_BLUR_STRENGTH = 61 # Must be odd
DEFAULT_CONFIDENCE_THRESHOLD = 0.5
OUTPUT_IMAGE_FOLDER = "./output_images/"
OUTPUT_VIDEO_FOLDER = "./output_videos/"
WEBCAM_RESOLUTION = (640, 480)
INPUT_SIZE = (300, 300)
MEAN_VALUES = (104.0, 177.0, 123.0)
MODEL_PROTOTXT = "deploy.prototxt.txt"
MODEL_WEIGHTS = "res10_300x300_ssd_iter_140000_fp16.caffemodel"

# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Load DNN model once
def load_face_detection_model():
"""Loads the pre-trained face detection model."""
try:
base_dir = Path(__file__).parent
prototxt_path = str(base_dir / "protocol" / MODEL_PROTOTXT)
model_path = str(base_dir / "model" / MODEL_WEIGHTS)

if not os.path.exists(prototxt_path):
raise FileNotFoundError(f"Prototxt file not found at {prototxt_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model weights not found at {model_path}")

return cv2.dnn.readNetFromCaffe(prototxt_path, model_path)
except Exception as e:
logger.error(f"Failed to load model: {e}")
raise

face_net = load_face_detection_model()
Copy link
Preview

Copilot AI Jul 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loading the model at module level without error handling could cause the entire module to fail if model files are missing. Consider adding try-catch blocks and proper error handling.

Copilot uses AI. Check for mistakes.


def save_video(video, output_path, default_fps=30, default_res=WEBCAM_RESOLUTION):
"""
Initializes a video writer object to save processed video frames.

Args:
video: OpenCV video capture object
output_path: Path to save the output video
default_fps: Fallback FPS if not detected
default_res: Fallback resolution if not detected

Returns:
cv2.VideoWriter object
"""
try:
fps = video.get(cv2.CAP_PROP_FPS)
if not fps or fps <= 1:
fps = default_fps
width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) or default_res[0]
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) or default_res[1]

fourcc = cv2.VideoWriter_fourcc(*'mp4v')
return cv2.VideoWriter(output_path, fourcc, fps, (width, height))
except Exception as e:
logger.error(f"Failed to initialize video writer: {e}")
raise

def blur_faces(image, confidence_threshold=DEFAULT_CONFIDENCE_THRESHOLD,
blur_strength=DEFAULT_BLUR_STRENGTH):
"""
Detects and blurs faces in an image.

Args:
image: Input image (numpy array)
confidence_threshold: Minimum confidence for face detection (0-1)
blur_strength: Kernel size for Gaussian blur (must be odd)

Returns:
Image with blurred faces (numpy array)
"""
if image is None:
raise ValueError("Input image cannot be None")

if blur_strength % 2 == 0:
blur_strength += 1 # Ensure odd kernel size
logger.debug(f"Adjusted blur strength to {blur_strength} to make it odd")

(h, w) = image.shape[:2]

try:
blob = cv2.dnn.blobFromImage(
cv2.resize(image,INPUT_SIZE),
1.0,
INPUT_SIZE,
MEAN_VALUES
)

face_net.setInput(blob)
detections = face_net.forward()

for i in range(detections.shape[2]):
confidence = detections[0, 0, i, 2]

if confidence > confidence_threshold:
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")

# Ensure coordinates stay within image bounds
startX, startY = max(0, startX), max(0, startY)
endX, endY = min(w, endX), min(h, endY)
# Validate ROI dimensions
if endY > startY and endX > startX:
# Extract and blur face ROI
face_roi = image[startY:endY, startX:endX]
blurred_face = cv2.GaussianBlur(face_roi, (blur_strength, blur_strength), 0)
image[startY:endY, startX:endX] = blurred_face

except Exception as e:
logger.error(f"Error during face blurring: {e}")
raise

return image

def blur_faces_images(image_path):
"""Processes an image file and saves the blurred version."""
try:
if not os.path.exists(image_path):
raise FileNotFoundError(f"Image not found at {image_path}")

image = cv2.imread(image_path)
if image is None:
raise ValueError(f"Failed to load image from {image_path}")

blurred_image = blur_faces(image)

os.makedirs(OUTPUT_IMAGE_FOLDER, exist_ok=True)
filename, ext = os.path.splitext(os.path.basename(image_path))
output_path = os.path.join(OUTPUT_IMAGE_FOLDER, f"{filename}_blurred{ext}")

if not cv2.imwrite(output_path, blurred_image):
raise IOError(f"Failed to save image to {output_path}")

logger.info(f"Successfully saved blurred image to {output_path}")

except Exception as e:
logger.error(f"Error processing image: {e}")
raise

def process_video_stream(input_source=None, is_webcam=False):
"""
Processes either a video file or webcam stream with face blurring.

Args:
input_source: Path to video file (if not webcam)
is_webcam: Boolean flag for webcam processing
"""
try:
os.makedirs(OUTPUT_VIDEO_FOLDER, exist_ok=True)

if is_webcam:
video = cv2.VideoCapture(0)
if not video.isOpened():
raise ValueError("Unable to access the webcam.")
video.set(cv2.CAP_PROP_FRAME_WIDTH, WEBCAM_RESOLUTION[0])
video.set(cv2.CAP_PROP_FRAME_HEIGHT, WEBCAM_RESOLUTION[1])
output_path = os.path.join(OUTPUT_VIDEO_FOLDER, "webcam_blurred.mp4")
logger.info("Starting webcam processing...")
else:
if not os.path.exists(input_source):
raise FileNotFoundError(f"Video file not found at {input_source}")
video = cv2.VideoCapture(input_source)
if not video.isOpened():
raise ValueError(f"Unable to open video file: {input_source}")
name = os.path.basename(input_source)
output_path = os.path.join(OUTPUT_VIDEO_FOLDER, f"{os.path.splitext(name)[0]}_blurred.mp4")
logger.info(f"Processing video file: {input_source}")

out = save_video(video, output_path)
frame_count = 0
total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) if not is_webcam else -1

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

frame_count += 1
if not is_webcam and frame_count % 10 == 0:
logger.info(f"Processing frame {frame_count}/{total_frames}")

blurred_frame = blur_faces(frame)
cv2.imshow('Blurred Feed', blurred_frame)

if cv2.waitKey(1) & 0xFF == ord('q'):
logger.info("User requested early termination")
break

out.write(blurred_frame)

finally:
out.release()
video.release()
cv2.destroyAllWindows()
logger.info(f"Successfully saved video to {output_path}")

except Exception as e:
logger.error(f"Error processing video: {e}")
raise

def main():
"""Command line interface for the face blurring application."""
import argparse

parser = argparse.ArgumentParser(
description="Face blurring application that processes images, videos, or webcam streams"
)
parser.add_argument('--image', help='Path to input image')
parser.add_argument('--video', help='Path to input video')
parser.add_argument('--webcam', action='store_true', help='Use webcam')

args = parser.parse_args()

try:
if args.image:
blur_faces_images(args.image)
elif args.video:
process_video_stream(args.video, is_webcam=False)
elif args.webcam:
process_video_stream(is_webcam=True)
else:
logger.warning("No input source specified. Use --image, --video, or --webcam")

except Exception as e:
logger.error(f"Application error: {e}")
return 1

return 0

if __name__ == "__main__":
exit(main())
Binary file not shown.
Loading