Before Alex merging too

This commit is contained in:
Dorian VELOSO 2025-01-14 11:58:19 +01:00
parent d9260e8365
commit 7b59711b16
37 changed files with 3288 additions and 131 deletions

View File

@ -2,7 +2,7 @@ import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
imagepath = "output_image.png"
imagepath = "ImagePNG/Dorian.png"
# Load Image
im = cv.imread(imagepath)

View File

Before

Width:  |  Height:  |  Size: 305 KiB

After

Width:  |  Height:  |  Size: 305 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -7,43 +7,49 @@ mp_face_detection = mp.solutions.face_detection
mp_face_mesh = mp.solutions.face_mesh
mp_drawing = mp.solutions.drawing_utils
filter_image_path = "ImagePNG\MArio.png"
filter_image_path = "ImagePNG\MoustacheMario.png"
filter_image = cv2.imread(filter_image_path, cv2.IMREAD_UNCHANGED)
def add_filter(image, filter_image, landmarks):
# Use of eyes as reference points
left_eye = landmarks[33]
right_eye = landmarks[263]
def add_filter(image, filter_image, landmarks, size_factor=1.4):
"""
Adds a filter to an image based on facial landmarks.
Adjusts the filter size using a `size_factor`.
"""
# Use eyes as reference points
left_eye = landmarks[33] # Left eye landmark
right_eye = landmarks[263] # Right eye landmark
# Distance between both eyes --> filter size
# Distance between eyes determines the filter size
eye_dist = np.linalg.norm(np.array(left_eye) - np.array(right_eye))
# Filter size
filter_width = int(eye_dist * 2) # Adjust the factor for desired size
# Calculate filter size using the size factor
filter_width = int(eye_dist * size_factor) # Adjust for desired size
filter_height = int(filter_width * filter_image.shape[0] / filter_image.shape[1])
resized_filter = cv2.resize(filter_image, (filter_width, filter_height))
# Filter position on the face
# Determine filter position above the eyes
center_x = int((left_eye[0] + right_eye[0]) / 2)
center_y = int((left_eye[1] + right_eye[1]) / 2)
x = int(center_x - filter_width / 2)
y = int(center_y - filter_height / 2)
# Extract the alpha channel (transparency) from the filter image
alpha_channel = resized_filter[:, :, 3] / 255.0 # Normalize alpha to range [0, 1]
filter_rgb = resized_filter[:, :, :3] # Extract the RGB channels
# Extract the alpha channel for blending
alpha_channel = resized_filter[:, :, 3] / 255.0 # Normalize alpha to [0, 1]
filter_rgb = resized_filter[:, :, :3]
# Overlay the filter onto the image, using the alpha channel as a mask
# Overlay the filter onto the image
for i in range(resized_filter.shape[0]):
for j in range(resized_filter.shape[1]):
if alpha_channel[i, j] > 0: # Check if the pixel is not fully transparent
# Blend the pixels: (1 - alpha) * original + alpha * filter
for c in range(3):
image[y + i, x + j, c] = (1 - alpha_channel[i, j]) * image[y + i, x + j, c] + alpha_channel[i, j] * filter_rgb[i, j, c]
if 0 <= y + i < image.shape[0] and 0 <= x + j < image.shape[1]: # Bounds check
alpha = alpha_channel[i, j]
if alpha > 0: # Only apply non-transparent pixels
image[y + i, x + j] = (
(1 - alpha) * image[y + i, x + j] + alpha * filter_rgb[i, j]
)
return image
input_image_path = "ImagePNG\Felipe.jpg"
input_image_path = "ImagePNG\Dorian.png"
input_image = cv2.imread(input_image_path)
# RGB for Mediapipe

View File

@ -11,7 +11,7 @@ mp_face_mesh = mp.solutions.face_mesh
filter_image_path = "ImagePNG/MArio.png"
filter_image = cv2.imread(filter_image_path, cv2.IMREAD_UNCHANGED)
def add_filter(image, filter_image, bbox, scale_factor=1.2):
def add_filter_hat(image, filter_image, bbox, scale_factor=1.2):
"""
Add a filter image to a face image at a specified bounding box position,
scaling it dynamically based on the face size.
@ -42,7 +42,7 @@ def add_filter(image, filter_image, bbox, scale_factor=1.2):
return image
# Load input image
input_image_path = "ImagePNG/output.png"
input_image_path = "ImagePNG/Dorian.png"
input_image = cv2.imread(input_image_path)
# Convert to RGB for Mediapipe
@ -68,7 +68,7 @@ with mp_face_detection.FaceDetection(model_selection=1, min_detection_confidence
dynamic_scale_factor = 2.75 + face_height_ratio # Base size + adjustment
# Add filter to the image with dynamic scaling
input_image = add_filter(input_image, filter_image, (x_min, y_min, box_width, box_height), scale_factor=dynamic_scale_factor)
input_image = add_filter_hat(input_image, filter_image, (x_min, y_min, box_width, box_height), scale_factor=dynamic_scale_factor)
# Define output folder and save path
output_folder = "OutputImage"

View File

@ -0,0 +1,82 @@
import os
import cv2
import mediapipe as mp
import numpy as np
# Mediapipe setup
mp_face_detection = mp.solutions.face_detection
mp_face_mesh = mp.solutions.face_mesh
# Load the moustache filter
filter_image_path = "ImagePNG/MoustacheMario.png"
filter_image = cv2.imread(filter_image_path, cv2.IMREAD_UNCHANGED)
def add_filter_moustache(image, filter_image, nose_tip, scale_factor):
"""
Add a moustache filter to an image based on the nose tip position.
"""
nose_x, nose_y = nose_tip
# Scale the filter image dynamically based on the face width
filter_width = int(image.shape[1] * scale_factor * 0.1) # Scale relative to image width
filter_height = int(filter_width * filter_image.shape[0] / filter_image.shape[1])
resized_filter = cv2.resize(filter_image, (filter_width, filter_height))
# Adjust the position to place the moustache below the nose
x = int(nose_x - filter_width / 2)
y = int(nose_y + filter_height * 0.2)
# Extract alpha channel (transparency) from the filter
alpha_channel = resized_filter[:, :, 3] / 255.0 # Normalize to range [0, 1]
filter_rgb = resized_filter[:, :, :3]
# Overlay the filter on the image using alpha blending
for i in range(filter_height):
for j in range(filter_width):
if 0 <= y + i < image.shape[0] and 0 <= x + j < image.shape[1]:
alpha = alpha_channel[i, j]
if alpha > 0: # Apply only non-transparent pixels
image[y + i, x + j] = (
(1 - alpha) * image[y + i, x + j] + alpha * filter_rgb[i, j]
)
return image
# Load input image
input_image_path = "ImagePNG/Dorian.png"
input_image = cv2.imread(input_image_path)
# Convert to RGB for Mediapipe
rgb_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2RGB)
# Use Mediapipe Face Mesh for robust landmark detection
with mp_face_mesh.FaceMesh(static_image_mode=True, min_detection_confidence=0.5) as face_mesh:
results = face_mesh.process(rgb_image)
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
# Get the nose tip landmark (index 4 in Mediapipe Face Mesh)
nose_tip = face_landmarks.landmark[4]
nose_x = int(nose_tip.x * input_image.shape[1])
nose_y = int(nose_tip.y * input_image.shape[0])
# Dynamically calculate scale factor based on face size
face_width = abs(face_landmarks.landmark[454].x - face_landmarks.landmark[234].x) * input_image.shape[1]
dynamic_scale_factor = 1.5 + (face_width / input_image.shape[1]) # Base size + adjustment
# Add filter to the image
input_image = add_filter_moustache(input_image, filter_image, (nose_x, nose_y), scale_factor=dynamic_scale_factor)
# Define output folder and save path
output_folder = "OutputImage"
os.makedirs(output_folder, exist_ok=True) # Ensure the folder exists
filter_name = os.path.splitext(os.path.basename(filter_image_path))[0]
output_path = os.path.join(output_folder, f"{filter_name}_output_image_dynamic.jpg")
# Save the output image
cv2.imwrite(output_path, input_image)
# Display result
cv2.imshow("Image with Filter", input_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

View File

@ -1,87 +0,0 @@
import cv2
import mediapipe as mp
import numpy as np
mp_face_mesh = mp.solutions.face_mesh
# List of filters
filter_images = {
1: "C:\Users\doria\Documents\ECAM\Année 4\IT & Robotics Lab\GrpC_Identikit\ImageProcessing\ImagePNG\Chien1.png", # Replace with your filter image paths
2: "C:\Users\doria\Documents\ECAM\Année 4\IT & Robotics Lab\GrpC_Identikit\ImageProcessing\ImagePNG\MoustacheMario.png",
3: "C:\Users\doria\Documents\ECAM\Année 4\IT & Robotics Lab\GrpC_Identikit\ImageProcessing\ImagePNG\MArio.png"
}
def add_filter(image, filter_image, landmarks):
# Use eyes as reference points
left_eye = landmarks[33]
right_eye = landmarks[263]
# Distance between both eyes --> filter size
eye_dist = np.linalg.norm(np.array(left_eye) - np.array(right_eye))
# Adjust the factor for a smaller filter size
scaling_factor = 2.75
filter_width = int(eye_dist * scaling_factor)
filter_height = int(filter_width * filter_image.shape[0] / filter_image.shape[1])
resized_filter = cv2.resize(filter_image, (filter_width, filter_height))
# Filter position on the face
center_x = int((left_eye[0] + right_eye[0]) / 2)
center_y = int((left_eye[1] + right_eye[1]) / 2)
x = int(center_x - filter_width / 2)
y = int(center_y - filter_height / 2)
# Extract the alpha channel (transparency) from the filter image
alpha_channel = resized_filter[:, :, 3] / 255.0 # Normalize alpha to range [0, 1]
filter_rgb = resized_filter[:, :, :3] # Extract the RGB channels
# Overlay the filter onto the image, using the alpha channel as a mask
for i in range(resized_filter.shape[0]):
for j in range(resized_filter.shape[1]):
if alpha_channel[i, j] > 0: # Check if the pixel is not fully transparent
# Blend the pixels: (1 - alpha) * original + alpha * filter
for c in range(3):
image[y + i, x + j, c] = (1 - alpha_channel[i, j]) * image[y + i, x + j, c] + alpha_channel[i, j] * filter_rgb[i, j, c]
return image
def apply_filter_by_choice(choice, input_image_path):
# Validate the filter choice
if choice not in filter_images:
print(f"Filter {choice} does not exist. Please choose a valid filter number.")
return
# Load the input image and filter
input_image = cv2.imread(input_image_path)
filter_image_path = filter_images[choice]
filter_image = cv2.imread(filter_image_path, cv2.IMREAD_UNCHANGED)
# RGB for Mediapipe
rgb_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2RGB)
# FaceMesh init
with mp_face_mesh.FaceMesh(min_detection_confidence=0.5, min_tracking_confidence=0.5) as face_mesh:
# Face detection + key points
results = face_mesh.process(rgb_image)
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
# Key points
landmarks = [(lm.x * input_image.shape[1], lm.y * input_image.shape[0]) for lm in face_landmarks.landmark]
# Apply the filter
input_image = add_filter(input_image, filter_image, landmarks)
# Display result
cv2.imshow("Image with Filter", input_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Save the image
output_path = f"output_image_filter_{choice}.jpg"
cv2.imwrite(output_path, input_image)
print(f"Saved filtered image to {output_path}")
# Example usage:
filter_choice = int(input("Enter the filter number (1, 2, or 3): "))
apply_filter_by_choice(filter_choice, "Dorianvide.png")

View File

@ -0,0 +1,31 @@
import tkinter as tk
from tkinter import ttk
# Function to toggle the button state
def toggle_button():
if toggle_var.get():
toggle_button.config(text="Activated")
else:
toggle_button.config(text="Deactivated")
# Main window
root = tk.Tk()
root.title("Toggle Button with Dropdown Menu")
# Dropdown menu for options
options = ["Option 1", "Option 2", "Option 3"]
selected_option = tk.StringVar(root)
selected_option.set(options[0]) # default value
dropdown_menu = ttk.Combobox(root, textvariable=selected_option, values=options)
dropdown_menu.pack(pady=10)
# Variable to store the toggle state
toggle_var = tk.BooleanVar()
# Toggle button
toggle_button = tk.Button(root, text="Deactivated", command=toggle_button)
toggle_button.pack(pady=20)
# Start the GUI
root.mainloop()

View File

@ -4,10 +4,10 @@ from rembg import remove
from PIL import Image
# Store path of the image in the variable input_path
input_path = 'C:/Users/doria/Documents/ECAM/Année 4/IT & Robotics Lab/GrpC_Identikit/ImageProcessing/ImageJPG/Démon.png'
input_path = 'ImagePNG/map.png'
# Store path of the output image in the variable output_path
output_path = 'C:/Users/doria/Documents/ECAM/Année 4/IT & Robotics Lab/GrpC_Identikit/ImageProcessing/Code\Demon.png'
output_path = 'ImagePNG/map1.png'
# Processing the image
input = Image.open(input_path)

View File

@ -0,0 +1,238 @@
import cv2
import tkinter as tk
import mediapipe as mp
import numpy as np
import os
import math
# Load images with transparency
mario_hat_image_path = "ImagePNG/MArio.png"
sunglasses_image_path = "ImagePNG/Glasses.png"
moustache_image_path = "ImagePNG/MoustacheMario.png"
# Load images
mario_hat = cv2.imread(mario_hat_image_path, cv2.IMREAD_UNCHANGED)
sunglasses = cv2.imread(sunglasses_image_path, cv2.IMREAD_UNCHANGED)
moustache = cv2.imread(moustache_image_path, cv2.IMREAD_UNCHANGED)
# Check if images were loaded correctly
if mario_hat is None:
print("Error: Mario hat image not found.")
exit()
if sunglasses is None:
print("Error: Sunglasses image not found.")
exit()
if moustache is None:
print("Error: Moustache image not found.")
exit()
# Initialize MediaPipe FaceMesh
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(min_detection_confidence=0.5, min_tracking_confidence=0.5)
# Variables for toggling filters
mario_hat_active = False
sunglasses_active = False
moustache_active = False
show_angles = False
# Open webcam for capturing live feed
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Error: The webcam cannot be opened")
exit()
# Variable to hold the freeze frame
freeze_frame = None
def calculate_angles(landmarks):
left_eye = np.array(landmarks[33])
right_eye = np.array(landmarks[263])
nose_tip = np.array(landmarks[1])
chin = np.array(landmarks[152])
yaw = math.degrees(math.atan2(right_eye[1] - left_eye[1], right_eye[0] - left_eye[0]))
pitch = math.degrees(math.atan2(chin[1] - nose_tip[1], chin[0] - nose_tip[0]))
return yaw, pitch
def apply_mario_hat(frame, landmarks):
global mario_hat
if mario_hat_active and mario_hat is not None:
forehead = landmarks[10]
chin = landmarks[152]
left_side = landmarks[234]
right_side = landmarks[454]
face_width = int(np.linalg.norm(np.array(left_side) - np.array(right_side)))
hat_width = int(face_width * 4.0)
hat_height = int(hat_width * mario_hat.shape[0] / mario_hat.shape[1])
mario_hat_resized = cv2.resize(mario_hat, (hat_width, hat_height))
x = int(forehead[0] - hat_width / 2)
y = int(forehead[1] - hat_height * 0.7)
alpha_channel = mario_hat_resized[:, :, 3] / 255.0
hat_rgb = mario_hat_resized[:, :, :3]
for i in range(hat_height):
for j in range(hat_width):
if 0 <= y + i < frame.shape[0] and 0 <= x + j < frame.shape[1]:
alpha = alpha_channel[i, j]
if alpha > 0:
for c in range(3):
frame[y + i, x + j, c] = (1 - alpha) * frame[y + i, x + j, c] + alpha * hat_rgb[i, j, c]
return frame
def apply_sunglasses(frame, landmarks):
global sunglasses
if sunglasses_active and sunglasses is not None:
left_eye = landmarks[33]
right_eye = landmarks[263]
eye_dist = np.linalg.norm(np.array(left_eye) - np.array(right_eye))
scaling_factor = 1.75
sunglasses_width = int(eye_dist * scaling_factor)
sunglasses_height = int(sunglasses_width * sunglasses.shape[0] / sunglasses.shape[1])
sunglasses_resized = cv2.resize(sunglasses, (sunglasses_width, sunglasses_height))
center_x = int((left_eye[0] + right_eye[0]) / 2)
center_y = int((left_eye[1] + right_eye[1]) / 2)
x = int(center_x - sunglasses_resized.shape[1] / 2)
y = int(center_y - sunglasses_resized.shape[0] / 2)
alpha_channel = sunglasses_resized[:, :, 3] / 255.0
sunglasses_rgb = sunglasses_resized[:, :, :3]
for i in range(sunglasses_resized.shape[0]):
for j in range(sunglasses_resized.shape[1]):
if alpha_channel[i, j] > 0:
for c in range(3):
frame[y + i, x + j, c] = (1 - alpha_channel[i, j]) * frame[y + i, x + j, c] + alpha_channel[i, j] * sunglasses_rgb[i, j, c]
return frame
def apply_moustache(frame, landmarks):
global moustache
if moustache_active and moustache is not None:
nose_base = landmarks[1]
mouth_left = landmarks[61]
mouth_right = landmarks[291]
mouth_width = int(np.linalg.norm(np.array(mouth_left) - np.array(mouth_right)))
moustache_width = int(mouth_width * 1.5)
moustache_height = int(moustache_width * moustache.shape[0] / moustache.shape[1])
moustache_resized = cv2.resize(moustache, (moustache_width, moustache_height))
x = int(nose_base[0] - moustache_width / 2)
y = int(nose_base[1])
alpha_channel = moustache_resized[:, :, 3] / 255.0
moustache_rgb = moustache_resized[:, :, :3]
for i in range(moustache_height):
for j in range(moustache_width):
if 0 <= y + i < frame.shape[0] and 0 <= x + j < frame.shape[1]:
alpha = alpha_channel[i, j]
if alpha > 0:
for c in range(3):
frame[y + i, x + j, c] = (1 - alpha) * frame[y + i, x + j, c] + alpha * moustache_rgb[i, j, c]
return frame
def update_frame():
global mario_hat_active, sunglasses_active, show_angles, freeze_frame, moustache_active
ret, frame = cap.read()
if ret:
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = face_mesh.process(rgb_frame)
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
landmarks = [(lm.x * frame.shape[1], lm.y * frame.shape[0]) for lm in face_landmarks.landmark]
yaw, pitch = calculate_angles(landmarks)
if mario_hat_active:
frame = apply_mario_hat(frame, landmarks)
if sunglasses_active:
frame = apply_sunglasses(frame, landmarks)
if moustache_active:
frame = apply_moustache(frame, landmarks)
if show_angles:
cv2.putText(frame, f"Yaw: {yaw:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(frame, f"Pitch: {pitch:.2f}", (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow("Webcam Feed", frame)
freeze_frame = frame
root.after(10, update_frame)
def toggle_mario_hat():
global mario_hat_active
mario_hat_active = not mario_hat_active
status = "activated" if mario_hat_active else "deactivated"
print(f"Mario hat filter {status}")
def toggle_sunglasses():
global sunglasses_active
sunglasses_active = not sunglasses_active
status = "activated" if sunglasses_active else "deactivated"
print(f"Sunglasses filter {status}")
def toggle_moustache():
global moustache_active
moustache_active = not moustache_active
status = "activated" if moustache_active else "deactivated"
print(f"Moustache filter {status}")
def toggle_angles():
global show_angles
show_angles = not show_angles
status = "shown" if show_angles else "hidden"
print(f"Angles display {status}")
def show_freeze_frame():
if freeze_frame is not None:
cv2.imshow("Face Capture", freeze_frame)
def retake_image():
global freeze_frame
ret, frame = cap.read()
if ret:
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = face_mesh.process(rgb_frame)
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
landmarks = [(lm.x * frame.shape[1], lm.y * frame.shape[0]) for lm in face_landmarks.landmark]
frame = apply_mario_hat(frame, landmarks)
frame = apply_sunglasses(frame, landmarks)
frame = apply_moustache(frame, landmarks)
freeze_frame = frame.copy()
show_freeze_frame()
def save_image():
global freeze_frame
if freeze_frame is not None:
save_path = "E:/ECAM/2024-25/IT and Robotics Labs/captured_face.png"
cv2.imwrite(save_path, freeze_frame)
print(f"Image saved to {save_path}")
# Tkinter GUI setup
root = tk.Tk()
root.title("Face Capture Controls")
root.geometry("300x400")
root.configure(bg="#ffffff")
# Buttons on the control window with updated font and colors
mario_hat_button = tk.Button(root, text="Toggle Mario Hat Filter", font=("Arial", 12, "bold"), command=toggle_mario_hat, bg="#5A4D41", fg="white", padx=10, pady=5)
mario_hat_button.pack(pady=10)
sunglasses_button = tk.Button(root, text="Toggle Sunglasses Filter", font=("Arial", 12, "bold"), command=toggle_sunglasses, bg="#B8860B", fg="white", padx=10, pady=5)
sunglasses_button.pack(pady=10)
moustache_button = tk.Button(root, text="Toggle Moustache Filter", font=("Arial", 12, "bold"), command=toggle_moustache, bg="#8B8000", fg="white", padx=10, pady=5)
moustache_button.pack(pady=10)
retake_image_button = tk.Button(root, text="Retake Image", font=("Arial", 12, "bold"), command=retake_image, bg="#2E8B57", fg="white", padx=10, pady=5)
retake_image_button.pack(pady=10)
save_image_button = tk.Button(root, text="Save Captured Image", font=("Arial", 12, "bold"), command=save_image, bg="#6A5ACD", fg="white", padx=10, pady=5)
save_image_button.pack(pady=10)
freeze_frame_button = tk.Button(root, text="Show Freeze Frame", font=("Arial", 12, "bold"), command=show_freeze_frame, bg="#D2691E", fg="white", padx=10, pady=5)
freeze_frame_button.pack(pady=10)
# Graceful exit
def on_closing():
cap.release()
cv2.destroyAllWindows()
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_closing)
show_freeze_frame()
# Start Tkinter event loop and OpenCV frame updates
update_frame()
root.mainloop()

BIN
Project/Filters/Glasses.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
Project/Tmp/Dorian.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
Project/Tmp/Dorian_nobg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

2534
Project/dobot.py Normal file

File diff suppressed because it is too large Load Diff

267
Project/main.py Normal file
View File

@ -0,0 +1,267 @@
import cv2
import tkinter as tk
import mediapipe as mp
import numpy as np
import os
import math
from rembg import remove
from PIL import Image
#import dobot
import vector_draw
# Load images with transparency
mario_hat_image_path = "Filters/Mario hat.png"
sunglasses_image_path = "Filters/Glasses.png"
moustache_image_path = "Filters/MoustacheMario.png"
# Load images
mario_hat = cv2.imread(mario_hat_image_path, cv2.IMREAD_UNCHANGED)
sunglasses = cv2.imread(sunglasses_image_path, cv2.IMREAD_UNCHANGED)
moustache = cv2.imread(moustache_image_path, cv2.IMREAD_UNCHANGED)
# Check if images were loaded correctly
if mario_hat is None:
print("Error: Mario hat image not found.")
exit()
if sunglasses is None:
print("Error: Sunglasses image not found.")
exit()
if moustache is None:
print("Error: Moustache image not found.")
exit()
# Initialize MediaPipe FaceMesh
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(min_detection_confidence=0.5, min_tracking_confidence=0.5)
# Variables for toggling filters
mario_hat_active = False
sunglasses_active = False
moustache_active = False
show_angles = False
# Open webcam for capturing live feed
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Error: The webcam cannot be opened")
exit()
# Variable to hold the contour frame
contour_frame = None
resized_edges = None
def calculate_angles(landmarks):
left_eye = np.array(landmarks[33])
right_eye = np.array(landmarks[263])
nose_tip = np.array(landmarks[1])
chin = np.array(landmarks[152])
yaw = math.degrees(math.atan2(right_eye[1] - left_eye[1], right_eye[0] - left_eye[0]))
pitch = math.degrees(math.atan2(chin[1] - nose_tip[1], chin[0] - nose_tip[0]))
return yaw, pitch
def apply_mario_hat(frame, landmarks):
global mario_hat
if mario_hat_active and mario_hat is not None:
forehead = landmarks[10]
chin = landmarks[152]
left_side = landmarks[234]
right_side = landmarks[454]
face_width = int(np.linalg.norm(np.array(left_side) - np.array(right_side)))
hat_width = int(face_width * 4.0)
hat_height = int(hat_width * mario_hat.shape[0] / mario_hat.shape[1])
mario_hat_resized = cv2.resize(mario_hat, (hat_width, hat_height))
x = int(forehead[0] - hat_width / 2)
y = int(forehead[1] - hat_height * 0.7)
alpha_channel = mario_hat_resized[:, :, 3] / 255.0
hat_rgb = mario_hat_resized[:, :, :3]
for i in range(hat_height):
for j in range(hat_width):
if 0 <= y + i < frame.shape[0] and 0 <= x + j < frame.shape[1]:
alpha = alpha_channel[i, j]
if alpha > 0:
for c in range(3):
frame[y + i, x + j, c] = (1 - alpha) * frame[y + i, x + j, c] + alpha * hat_rgb[i, j, c]
return frame
def apply_sunglasses(frame, landmarks):
global sunglasses
if sunglasses_active and sunglasses is not None:
left_eye = landmarks[33]
right_eye = landmarks[263]
eye_dist = np.linalg.norm(np.array(left_eye) - np.array(right_eye))
scaling_factor = 1.75
sunglasses_width = int(eye_dist * scaling_factor)
sunglasses_height = int(sunglasses_width * sunglasses.shape[0] / sunglasses.shape[1])
sunglasses_resized = cv2.resize(sunglasses, (sunglasses_width, sunglasses_height))
center_x = int((left_eye[0] + right_eye[0]) / 2)
center_y = int((left_eye[1] + right_eye[1]) / 2)
x = int(center_x - sunglasses_resized.shape[1] / 2)
y = int(center_y - sunglasses_resized.shape[0] / 2)
alpha_channel = sunglasses_resized[:, :, 3] / 255.0
sunglasses_rgb = sunglasses_resized[:, :, :3]
for i in range(sunglasses_resized.shape[0]):
for j in range(sunglasses_resized.shape[1]):
if alpha_channel[i, j] > 0:
for c in range(3):
frame[y + i, x + j, c] = (1 - alpha_channel[i, j]) * frame[y + i, x + j, c] + alpha_channel[i, j] * sunglasses_rgb[i, j, c]
return frame
def apply_moustache(frame, landmarks):
global moustache
if moustache_active and moustache is not None:
nose_base = landmarks[1]
mouth_left = landmarks[61]
mouth_right = landmarks[291]
mouth_width = int(np.linalg.norm(np.array(mouth_left) - np.array(mouth_right)))
moustache_width = int(mouth_width * 1.5)
moustache_height = int(moustache_width * moustache.shape[0] / moustache.shape[1])
moustache_resized = cv2.resize(moustache, (moustache_width, moustache_height))
x = int(nose_base[0] - moustache_width / 2)
y = int(nose_base[1])
alpha_channel = moustache_resized[:, :, 3] / 255.0
moustache_rgb = moustache_resized[:, :, :3]
for i in range(moustache_height):
for j in range(moustache_width):
if 0 <= y + i < frame.shape[0] and 0 <= x + j < frame.shape[1]:
alpha = alpha_channel[i, j]
if alpha > 0:
for c in range(3):
frame[y + i, x + j, c] = (1 - alpha) * frame[y + i, x + j, c] + alpha * moustache_rgb[i, j, c]
return frame
def update_frame():
global mario_hat_active, sunglasses_active, show_angles, contour_frame, moustache_active
ret, frame = cap.read()
if ret:
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = face_mesh.process(rgb_frame)
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
landmarks = [(lm.x * frame.shape[1], lm.y * frame.shape[0]) for lm in face_landmarks.landmark]
yaw, pitch = calculate_angles(landmarks)
if mario_hat_active:
frame = apply_mario_hat(frame, landmarks)
if sunglasses_active:
frame = apply_sunglasses(frame, landmarks)
if moustache_active:
frame = apply_moustache(frame, landmarks)
if show_angles:
cv2.putText(frame, f"Yaw: {yaw:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(frame, f"Pitch: {pitch:.2f}", (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow("Webcam Feed", frame)
contour_frame = frame
root.after(100, update_frame)
def toggle_mario_hat():
global mario_hat_active
mario_hat_active = not mario_hat_active
status = "activated" if mario_hat_active else "deactivated"
print(f"Mario hat filter {status}")
def toggle_sunglasses():
global sunglasses_active
sunglasses_active = not sunglasses_active
status = "activated" if sunglasses_active else "deactivated"
print(f"Sunglasses filter {status}")
def toggle_moustache():
global moustache_active
moustache_active = not moustache_active
status = "activated" if moustache_active else "deactivated"
print(f"Moustache filter {status}")
def toggle_angles():
global show_angles
show_angles = not show_angles
status = "shown" if show_angles else "hidden"
print(f"Angles display {status}")
def show_contour_frame():
if contour_frame is not None:
# Display the result
cv2.imshow('Edges', resized_edges)
def save_image():
global contour_frame, resized_edges
if contour_frame is not None:
save_path = "Tmp/captured_face.png"
cv2.imwrite(save_path, contour_frame)
print(f"Image saved to {save_path}")
# Store path of the image in the variable input_path
input_path = 'Tmp/captured_face.png'
# Store path of the output image in the variable output_path
output_path = 'Tmp/captured_face_nobg.png'
# Processing the image
input = Image.open(input_path)
# Removing the background from the given Image
output = remove(input)
#Saving the image in the given path
output.save(output_path)
image = cv2.imread(output_path, cv2.IMREAD_GRAYSCALE)
mask = (image > 1) & (image < 254)
blurred_image = cv2.GaussianBlur(image, (11, 11), 0)
median_val = np.median(blurred_image[mask])
lower_threshold = int(max(0, 0.5 * median_val))
upper_threshold = int(min(255, 1.2 * median_val))
print(f"Automatic lower threshold: {lower_threshold}")
print(f"Automatic upper threshold: {upper_threshold}")
# Apply Canny edge detection using the calculated thresholds
edges = cv2.Canny(blurred_image, lower_threshold, upper_threshold)
# Resize the output image to a smaller size (e.g., 50% of the original size)
output_height, output_width = edges.shape[:2]
resized_edges = cv2.resize(edges, (output_width // 2, output_height // 2), interpolation=cv2.INTER_AREA)
# Save the resized result to a file
cv2.imwrite('Tmp/final_output_image.png', resized_edges)
def start_dobot():
vector_draw.vector_draw()
# Tkinter GUI setup
root = tk.Tk()
root.title("Control Tab")
root.geometry("300x370")
root.configure(bg="#004346")
# Buttons on the control window with updated font and colors
mario_hat_button = tk.Button(root, text="Add Mario Hat", font=("Arial", 12, "bold"), command=toggle_mario_hat, bg="#4C8577", fg="white", padx=10, pady=5, height=1, width=20)
mario_hat_button.pack(pady=10)
sunglasses_button = tk.Button(root, text="Add Glasses", font=("Arial", 12, "bold"), command=toggle_sunglasses, bg="#4C8577", fg="white", padx=10, pady=5, height=1, width=20)
sunglasses_button.pack(pady=10)
moustache_button = tk.Button(root, text="Add Mario Moustache", font=("Arial", 12, "bold"), command=toggle_moustache, bg="#4C8577", fg="white", padx=10, pady=5,height=1, width=20)
moustache_button.pack(pady=10)
save_image_button = tk.Button(root, text="Save/Retake Image", font=("Arial", 12, "bold"), command=save_image, bg="#49A078", fg="white", padx=10, pady=5,height=1, width=20)
save_image_button.pack(pady=10)
contour_frame_button = tk.Button(root, text="Show Contour Image", font=("Arial", 12, "bold"), command=show_contour_frame, bg="#216869", fg="white", padx=10, pady=5,height=1, width=20)
contour_frame_button.pack(pady=10)
#contour_frame_button = tk.Button(root, text="Start Dobot Drawing", font=("Arial", 12, "bold"), command=start_dobot, bg="#49A078", fg="white", padx=10, pady=5,height=1, width=20)
#contour_frame_button.pack(pady=10)
# Graceful exit
def on_closing():
cap.release()
cv2.destroyAllWindows()
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_closing)
show_contour_frame()
# Start Tkinter event loop and OpenCV frame updates
update_frame()
root.mainloop()

80
Project/vector_draw.py Normal file
View File

@ -0,0 +1,80 @@
import cv2
import numpy as np
import dobot
import time
def vector_draw():
# Drawing parameters
DRAW_SPEED = 1 # Drawing speed for
DRAW_DEPTH = -30.5 # Initial height (null)
INIT_POSITION = [-100, 150]
# --------------------------------------------------------------------------
# IMAGE TREATMENT
# --------------------------------------------------------------------------
# Load the image in grayscale
image = cv2.imread("Tmp/captured_face.png", cv2.IMREAD_GRAYSCALE)
# Create a mask to exclude background pixels (assuming background is near white or black)
# For example, exclude pixels that are close to white (255) and black (0)
mask = (image > 1) & (image < 254) # Keep only pixels that are not close to white or black
# Apply Gaussian Blur to reduce noise
blurred_image = cv2.GaussianBlur(image, (11, 11), 0)
# Calculate the median of only the foreground pixels
median_val = np.median(blurred_image[mask])
# Automatically calculate thresholds based on the median pixel intensity
lower_threshold = int(max(0, 0.5 * median_val))
upper_threshold = int(min(255, 1.2 * median_val))
print(f"Automatic lower threshold: {lower_threshold}")
print(f"Automatic upper threshold: {upper_threshold}")
# Apply Canny edge detection using the calculated thresholds
edges = cv2.Canny(blurred_image, lower_threshold, upper_threshold)
# Find Contours
contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# Initialize an array to store all points
all_points = []
# Define Dobot workspace dimensions (e.g., in mm)
robot_workspace = (200, 200*2/3) # Replace with your Dobot's range in mm
# Scale function to map image coordinates to Dobot's workspace
def scale_coordinates(point, img_dim, robot_dim):
img_x, img_y = point
img_width, img_height = img_dim
robot_x_range, robot_y_range = robot_dim
# Map x and y with scaling
robot_x = (img_x / img_width) * robot_x_range
robot_y = (img_y / img_height) * robot_y_range
return robot_x, robot_y
# Collect points for Dobot
for cnt in contours:
# Scale and store points
for point in cnt:
x, y = point[0]
x, y = scale_coordinates((x, y), (image.shape[1], image.shape[0]), robot_workspace)
all_points.append((x, y))
all_points.append((-1,-1))
robot_x_old = 0
robot_y_old = 0
for i, (robot_x, robot_y) in enumerate(all_points):
if robot_x == -1 or robot_y == -1:
# Lift the pen at the end of each contour
dobot.setCPCmd(1, robot_x_old + INIT_POSITION[0], robot_y_old + INIT_POSITION[1], DRAW_DEPTH+15, DRAW_SPEED, 1)
else:
if robot_x_old == -1 or robot_y_old == -1:
dobot.setCPCmd(1, robot_x + INIT_POSITION[0], robot_y + INIT_POSITION[1], DRAW_DEPTH+15, DRAW_SPEED, 1)
dobot.setCPCmd(1, robot_x + INIT_POSITION[0], robot_y + INIT_POSITION[1], DRAW_DEPTH, DRAW_SPEED, 1)
time.sleep(0.1)
robot_x_old = robot_x
robot_y_old = robot_y
vector_draw()

View File

@ -7,39 +7,45 @@ mp_face_detection = mp.solutions.face_detection
mp_face_mesh = mp.solutions.face_mesh
mp_drawing = mp.solutions.drawing_utils
filter_image_path = "ImagePNG\MArio.png"
filter_image_path = "ImagePNG\MoustacheMario.png"
filter_image = cv2.imread(filter_image_path, cv2.IMREAD_UNCHANGED)
def add_filter(image, filter_image, landmarks):
# Use of eyes as reference points
left_eye = landmarks[33]
right_eye = landmarks[263]
def add_filter(image, filter_image, landmarks, size_factor=1.4):
"""
Adds a filter to an image based on facial landmarks.
Adjusts the filter size using a `size_factor`.
"""
# Use eyes as reference points
left_eye = landmarks[33] # Left eye landmark
right_eye = landmarks[263] # Right eye landmark
# Distance between both eyes --> filter size
# Distance between eyes determines the filter size
eye_dist = np.linalg.norm(np.array(left_eye) - np.array(right_eye))
# Filter size
filter_width = int(eye_dist * 2) # Adjust the factor for desired size
# Calculate filter size using the size factor
filter_width = int(eye_dist * size_factor) # Adjust for desired size
filter_height = int(filter_width * filter_image.shape[0] / filter_image.shape[1])
resized_filter = cv2.resize(filter_image, (filter_width, filter_height))
# Filter position on the face
# Determine filter position above the eyes
center_x = int((left_eye[0] + right_eye[0]) / 2)
center_y = int((left_eye[1] + right_eye[1]) / 2)
x = int(center_x - filter_width / 2)
y = int(center_y - filter_height / 2)
# Extract the alpha channel (transparency) from the filter image
alpha_channel = resized_filter[:, :, 3] / 255.0 # Normalize alpha to range [0, 1]
filter_rgb = resized_filter[:, :, :3] # Extract the RGB channels
# Extract the alpha channel for blending
alpha_channel = resized_filter[:, :, 3] / 255.0 # Normalize alpha to [0, 1]
filter_rgb = resized_filter[:, :, :3]
# Overlay the filter onto the image, using the alpha channel as a mask
# Overlay the filter onto the image
for i in range(resized_filter.shape[0]):
for j in range(resized_filter.shape[1]):
if alpha_channel[i, j] > 0: # Check if the pixel is not fully transparent
# Blend the pixels: (1 - alpha) * original + alpha * filter
for c in range(3):
image[y + i, x + j, c] = (1 - alpha_channel[i, j]) * image[y + i, x + j, c] + alpha_channel[i, j] * filter_rgb[i, j, c]
if 0 <= y + i < image.shape[0] and 0 <= x + j < image.shape[1]: # Bounds check
alpha = alpha_channel[i, j]
if alpha > 0: # Only apply non-transparent pixels
image[y + i, x + j] = (
(1 - alpha) * image[y + i, x + j] + alpha * filter_rgb[i, j]
)
return image

View File

@ -11,7 +11,7 @@ mp_face_mesh = mp.solutions.face_mesh
filter_image_path = "ImagePNG/MArio.png"
filter_image = cv2.imread(filter_image_path, cv2.IMREAD_UNCHANGED)
def add_filter(image, filter_image, bbox, scale_factor=1.2):
def add_filter_hat(image, filter_image, bbox, scale_factor=1.2):
"""
Add a filter image to a face image at a specified bounding box position,
scaling it dynamically based on the face size.
@ -68,7 +68,7 @@ with mp_face_detection.FaceDetection(model_selection=1, min_detection_confidence
dynamic_scale_factor = 2.75 + face_height_ratio # Base size + adjustment
# Add filter to the image with dynamic scaling
input_image = add_filter(input_image, filter_image, (x_min, y_min, box_width, box_height), scale_factor=dynamic_scale_factor)
input_image = add_filter_hat(input_image, filter_image, (x_min, y_min, box_width, box_height), scale_factor=dynamic_scale_factor)
# Define output folder and save path
output_folder = "OutputImage"

0
remove_bg.py Normal file
View File