-
-
Notifications
You must be signed in to change notification settings - Fork 349
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
base: main
Are you sure you want to change the base?
Changes from 2 commits
2807975
06edf46
9a30978
e452ff2
8266a36
4a5ee0c
ea141c4
a9e69cf
4eaf971
2ede0b3
a82cbce
882022f
6554608
b7e283b
319f580
b11fbf6
a92b016
dea5923
3fc57af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,164 @@ | ||||||||||||||||||||||
import os | ||||||||||||||||||||||
import cv2 | ||||||||||||||||||||||
import numpy as np | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Load DNN model once to avoid reloading it for each frame | ||||||||||||||||||||||
def load_face_detection_model(): | ||||||||||||||||||||||
"""Loads the pre-trained face detection model.""" | ||||||||||||||||||||||
prototxt_path = "./protocol/deploy.prototxt.txt" | ||||||||||||||||||||||
model_path = "./model/res10_300x300_ssd_iter_140000_fp16.caffemodel" | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hard-coded file paths should be made configurable or use relative paths that work from different execution contexts. Consider using os.path.join() for cross-platform compatibility.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
return cv2.dnn.readNetFromCaffe(prototxt_path, model_path) | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Global variable to store the model (avoids reloading it multiple times) | ||||||||||||||||||||||
face_net = load_face_detection_model() | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
|
||||||||||||||||||||||
#save video function | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment should follow proper Python comment formatting with a space after the hash and proper capitalization: '# Save video function'.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
def save_video(video, output_path): | ||||||||||||||||||||||
|
||||||||||||||||||||||
ChrisEssomba marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||
# Get video properties | ||||||||||||||||||||||
fps = video.get(cv2.CAP_PROP_FPS) | ||||||||||||||||||||||
frame_width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) | ||||||||||||||||||||||
frame_height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) | ||||||||||||||||||||||
res = (frame_width, frame_height) | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Define the video writer | ||||||||||||||||||||||
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # MP4 codec | ||||||||||||||||||||||
out = cv2.VideoWriter(output_path, fourcc, fps, res) | ||||||||||||||||||||||
return out | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra space before 'out' should be removed for consistent formatting.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
|
||||||||||||||||||||||
def blur_faces(image, confidence_threshold=0.5, blur_strength=61): | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The magic number 61 for blur_strength should be defined as a named constant to improve code maintainability and make it easier to adjust.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
""" | ||||||||||||||||||||||
Detects and blurs faces in an image. | ||||||||||||||||||||||
|
||||||||||||||||||||||
Parameters: | ||||||||||||||||||||||
image (numpy.ndarray): Input image. | ||||||||||||||||||||||
confidence_threshold (float): Minimum confidence for face detection. | ||||||||||||||||||||||
blur_strength (int): Kernel size for Gaussian blur (must be odd). | ||||||||||||||||||||||
|
||||||||||||||||||||||
Returns: | ||||||||||||||||||||||
numpy.ndarray: Image with blurred faces. | ||||||||||||||||||||||
""" | ||||||||||||||||||||||
(h, w) = image.shape[:2] | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Prepare the image for the deep learning model | ||||||||||||||||||||||
blob = cv2.dnn.blobFromImage( | ||||||||||||||||||||||
cv2.resize(image, (300, 300)), | ||||||||||||||||||||||
1.0, | ||||||||||||||||||||||
(300, 300), | ||||||||||||||||||||||
(104.0, 177.0, 123.0) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The magic numbers (300, 300) and (104.0, 177.0, 123.0) should be defined as named constants to improve code readability and maintainability.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Perform detection | ||||||||||||||||||||||
face_net.setInput(blob) | ||||||||||||||||||||||
detections = face_net.forward() | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Process detections | ||||||||||||||||||||||
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) | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Extract and blur face ROI | ||||||||||||||||||||||
face_roi = image[startY:endY, startX:endX] | ||||||||||||||||||||||
blurred_face = cv2.GaussianBlur(face_roi, (blur_strength, blur_strength), 0) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code doesn't validate that blur_strength is odd, which is required for cv2.GaussianBlur. If an even number is passed, OpenCV will raise an error. Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
image[startY:endY, startX:endX] = blurred_face | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no validation that the face ROI has non-zero dimensions. If startY >= endY or startX >= endX, this will create an empty array that could cause issues with GaussianBlur.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
|
||||||||||||||||||||||
return image | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
def blur_faces_images(image_path): | ||||||||||||||||||||||
""" | ||||||||||||||||||||||
Load an image, blurs detected faces in each frame, and saves the output. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The docstring incorrectly mentions 'each frame' when this function processes a single image, not video frames. It should read 'Load an image, blur detected faces, and save the output.'
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
|
||||||||||||||||||||||
Parameters: | ||||||||||||||||||||||
image_path (str): Path to the input image. | ||||||||||||||||||||||
""" | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Load and process the image | ||||||||||||||||||||||
image = cv2.imread(image_path) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function doesn't check if cv2.imread successfully loaded the image. If the file doesn't exist or is corrupted, image will be None, causing a crash in blur_faces().
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
blurred_image = blur_faces(image) | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Create output folder | ||||||||||||||||||||||
name = os.path.basename(image_path) | ||||||||||||||||||||||
output_folder = "./output_images/" | ||||||||||||||||||||||
os.makedirs(output_folder, exist_ok=True) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hard-coded output paths should be configurable. Consider making output directories configurable through parameters or constants to improve maintainability.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
|
||||||||||||||||||||||
# Save the processed image in the right folder | ||||||||||||||||||||||
output_path = os.path.join(output_folder, name) | ||||||||||||||||||||||
cv2.imwrite(output_path, blurred_image) | ||||||||||||||||||||||
|
||||||||||||||||||||||
def blur_faces_videos(video_path): | ||||||||||||||||||||||
""" | ||||||||||||||||||||||
Processes a video, blurs detected faces in each frame, and saves the output. | ||||||||||||||||||||||
|
||||||||||||||||||||||
Parameters: | ||||||||||||||||||||||
video_path (str): Path to the input video. | ||||||||||||||||||||||
""" | ||||||||||||||||||||||
|
||||||||||||||||||||||
name = os.path.basename(video_path) | ||||||||||||||||||||||
output_folder = "./output_videos/" | ||||||||||||||||||||||
os.makedirs(output_folder, exist_ok=True) | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Ensure the output file has a valid extension | ||||||||||||||||||||||
output_path = os.path.join(output_folder, os.path.splitext(name)[0] + "_blurred.mp4") | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hard-coded output paths should be configurable. Consider making output directories configurable through parameters or constants to improve maintainability.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
|
||||||||||||||||||||||
video, output_path, out= save_video(video_path) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The save_video function only takes 2 parameters (video and output_path) but this line expects it to return 3 values. The function call should be 'video = cv2.VideoCapture(video_path)' and 'out = save_video(video, output_path)' on separate lines.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
|
||||||||||||||||||||||
while True: | ||||||||||||||||||||||
ret, frame = video.read() | ||||||||||||||||||||||
if not ret: | ||||||||||||||||||||||
break | ||||||||||||||||||||||
|
||||||||||||||||||||||
blurred_frame = blur_faces(frame) # Apply face blurring | ||||||||||||||||||||||
cv2.imshow('Blurred Video', blurred_frame) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if cv2.waitKey(1) & 0xFF == ord('q'): | ||||||||||||||||||||||
break | ||||||||||||||||||||||
|
||||||||||||||||||||||
out.write(blurred_frame) # Save the processed frame | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Release resources | ||||||||||||||||||||||
out.release() | ||||||||||||||||||||||
video.release() | ||||||||||||||||||||||
cv2.destroyAllWindows() | ||||||||||||||||||||||
print(f"Video saved at: {output_path}") | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
def blur_face_webcam(): | ||||||||||||||||||||||
""" | ||||||||||||||||||||||
Captures video from the webcam, applies face blurring in real-time, | ||||||||||||||||||||||
and allows stopping the recording by pressing 'q'. | ||||||||||||||||||||||
""" | ||||||||||||||||||||||
|
||||||||||||||||||||||
video = cv2.VideoCapture(0) # Open webcam | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function doesn't check if the webcam was successfully opened. If no camera is available, this could cause issues in the processing loop.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
output_folder = "./output_videos/" | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hard-coded output paths should be configurable. Consider making output directories configurable through parameters or constants to improve maintainability.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
os.makedirs(output_folder, exist_ok=True) | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Ensure the output file has a valid extension | ||||||||||||||||||||||
output_path = os.path.join(output_folder, ("webcam_blurred.mp4")) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unnecessary parentheses around the string literal. This should be simplified to: os.path.join(output_folder, "webcam_blurred.mp4")
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
|
||||||||||||||||||||||
out= save_video(video, output_path) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing space around assignment operator. Should be 'out = save_video(video, output_path)'.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||
while True: | ||||||||||||||||||||||
ret, frame = video.read() | ||||||||||||||||||||||
if not ret: | ||||||||||||||||||||||
break | ||||||||||||||||||||||
|
||||||||||||||||||||||
blurred_frame = blur_faces(frame) | ||||||||||||||||||||||
cv2.imshow('Blurred Webcam Feed', blurred_frame) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if cv2.waitKey(1) & 0xFF == ord('q'): | ||||||||||||||||||||||
break | ||||||||||||||||||||||
out.write(blurred_frame) # Save the processed frame | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Release resources | ||||||||||||||||||||||
out.release() | ||||||||||||||||||||||
video.release() | ||||||||||||||||||||||
cv2.destroyAllWindows() | ||||||||||||||||||||||
print(f"Video saved at: {output_path}") | ||||||||||||||||||||||
|
Uh oh!
There was an error while loading. Please reload this page.