| | import cv2 |
| | import os |
| | import gradio as gr |
| | import numpy as np |
| | from moviepy.editor import * |
| | import logging |
| | os.makedirs('logs',exist_ok=True) |
| | logging.basicConfig(filename='./logs/error.log', level=logging.ERROR) |
| | class FaceSwapper: |
| | def __init__(self): |
| | self.logger = logging.getLogger() |
| | self.face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') |
| |
|
| | def swap_faces(self, image1, image2, alpha): |
| | try: |
| | |
| | img1 = cv2.imread(image1.name) |
| | img2 = cv2.imread(image2.name) |
| | |
| | |
| | faces = self.face_cascade.detectMultiScale(img1) |
| | faces1 = self.face_cascade.detectMultiScale(img2) |
| | |
| | if len(faces) > 0: |
| | for (x, y, w, h) in faces: |
| | |
| | cropped_face = img1[y:y+h, x:x+w] |
| | |
| | |
| | desired_width = faces1[0][0] + faces1[0][2] |
| | desired_height = faces1[0][1] + faces1[0][3] |
| | |
| | |
| | resized_cropped_face = cv2.resize(cropped_face, (desired_width, desired_height)) |
| | |
| | |
| | blended_face = cv2.addWeighted(resized_cropped_face, alpha, img2[y:y+h, x:x+w], 1-alpha, 0) |
| | |
| | |
| | x_position = x |
| | y_position = y |
| | img1[y_position:y_position+desired_height, x_position:x_position+desired_width] = blended_face |
| | |
| | return img1 |
| | else: |
| | return None |
| | |
| | except Exception as e: |
| | logger.error(f"An error occurred during face swapping: {e}") |
| | return None |
| |
|
| | def generate_morph(self, image1, image2, num_frames, alpha): |
| | try: |
| | |
| | img1 = cv2.imread(image1.name) |
| | img2 = cv2.imread(image2.name) |
| | |
| | |
| | faces = self.face_cascade.detectMultiScale(img1) |
| | faces1 = self.face_cascade.detectMultiScale(img2) |
| | |
| | if len(faces) > 0: |
| | frames = [] |
| | for i in range(num_frames): |
| | alpha_i = alpha + (1-alpha) * i / (num_frames-1) |
| | img = self.swap_faces(image1, image2, alpha_i) |
| | frames.append(img) |
| | |
| | |
| | fps = 30 |
| | height, width, _ = frames[0].shape |
| | fourcc = cv2.VideoWriter_fourcc(*'mp4v') |
| | video = cv2.VideoWriter('output.mp4', fourcc, fps, (width, height)) |
| | |
| | for frame in frames: |
| | video.write(frame) |
| | |
| | video.release() |
| | return 'output.mp4' |
| | else: |
| | return None |
| | |
| | except Exception as e: |
| | logger.error(f"An error occurred during morphing: {e}") |
| | return None |
| | |
| | iface = gr.Interface( |
| | fn=lambda image1, image2, alpha, num_frames: FaceSwapper().generate_morph(image1, image2, num_frames, alpha), |
| | inputs=[ |
| | gr.inputs.Image(type="filepath", label="Image 1", max_size=1024*1024), |
| | gr.inputs.Image(type="filepath", label="Image 2", max_size=1024*1024), |
| | "slider", |
| | "number" |
| | ], |
| | outputs="video", |
| | title="Face Swapper", |
| | description="Swap faces between two images and generate a morph video", |
| | debug=True, |
| | catch_exceptions=True, |
| | ) |
| |
|
| | iface.launch() |