-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
128 lines (103 loc) · 3.99 KB
/
main.py
File metadata and controls
128 lines (103 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import cv2
import os
import requests
import time
import replicate
from PIL import Image
# Configurations
IMAGE_DIR = './photos' # Directory containing carousel images
CAROUSEL_INTERVAL = 5 # Seconds between switching images
MARGIN_RATIO = 0.2 # How much space aroudn the face to capture
FACE_SWAP_MODEL = "xiankgx/face-swap:cff87316e31787df12002c9e20a78a017a36cb31fde9862d8dedd15ab29b7288" #face swap model on replicate
def load_images_from_directory(directory):
"""Load images from a given directory."""
images = []
for filename in os.listdir(directory):
if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
img_path = os.path.join(directory, filename)
images.append(cv2.imread(img_path))
return images
def initialize_webcam():
"""Initialize webcam capture."""
cap = cv2.VideoCapture(0)
if not cap.isOpened():
raise RuntimeError("Failed to initialize webcam")
return cap
def detect_face(frame):
"""Detects a face in a given frame using OpenCV's Haar cascade."""
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
if len(faces) > 0:
(x, y, w, h) = faces[0]
# Calculate the margin to add around the face
margin_x = int(w * MARGIN_RATIO)
margin_y = int(h * MARGIN_RATIO)
# Adjust the rectangle to include the margin, ensuring it stays within the frame boundaries
x_start = max(0, x - margin_x)
y_start = max(0, y - margin_y)
x_end = min(frame.shape[1], x + w + margin_x)
y_end = min(frame.shape[0], y + h + margin_y)
# Crop the frame with the margin
return frame[y_start:y_end, x_start:x_end]
return None
def save_temp_image(image, filename):
"""Saves a temporary image to disk."""
img = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
img.save(filename)
return filename
def face_swap(base_image, face_image):
"""Calls the Replicate API to perform face-swapping."""
base_image_path = save_temp_image(base_image, 'base_image.jpg')
face_image_path = save_temp_image(face_image, 'face_image.jpg')
input_data = {
"local_source": open(face_image_path, "rb"),
"local_target": open(base_image_path, "rb")
}
response = replicate.run(
FACE_SWAP_MODEL,
input=input_data
)
if response and "image" in response:
image_url = response["image"].url
swapped_image_path = 'swapped_image.png'
image_response = requests.get(image_url)
if image_response.status_code == 200:
with open(swapped_image_path, 'wb') as f:
f.write(image_response.content)
# Load the saved image using OpenCV
swapped_image = cv2.imread(swapped_image_path)
return swapped_image
print("Face swap failed.")
return base_image # Return the base image if face swap fails
def display_image(base_image, face_image):
"""Displays either the base image or a face-swapped version."""
if face_image is not None:
base_image = face_swap(base_image, face_image)
cv2.imshow('Carousel', base_image)
cv2.waitKey(1) # Small delay for image rendering
def main():
images = load_images_from_directory(IMAGE_DIR)
if not images:
print("No images found in the directory.")
return
cap = initialize_webcam()
i = 0
n = len(images)
try:
while True:
ret, frame = cap.read()
if not ret:
print("Failed to capture frame from webcam.")
break
face = detect_face(frame)
display_image(images[i % n], face)
i += 1
time.sleep(CAROUSEL_INTERVAL)
except KeyboardInterrupt:
print("Exiting program.")
finally:
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()