Face_Swap / app.py
Arrcttacsrks's picture
Update app.py
ce35e91 verified
raw
history blame
9.69 kB
# -*- coding:UTF-8 -*-
#!/usr/bin/env python
import numpy as np
import gradio as gr
import roop.globals
from roop.core import (
start,
decode_execution_providers,
suggest_max_memory,
suggest_execution_threads,
)
from roop.processors.frame.core import get_frame_processors_modules
from roop.utilities import normalize_output_path
import os
from PIL import Image
from datetime import datetime
from huggingface_hub import HfApi, login
from datasets import load_dataset, Dataset
import json
import shutil
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
class FaceIntegrDataset:
def __init__(self, repo_id="Arrcttacsrks/face_integrData"):
# Get token from environment variable
self.token = os.getenv('hf_token')
if not self.token:
raise ValueError("HF_TOKEN environment variable is not set")
self.repo_id = repo_id
self.api = HfApi()
# Login to Hugging Face
login(self.token)
# Create local temp directory for organizing files
self.temp_dir = "temp_dataset"
os.makedirs(self.temp_dir, exist_ok=True)
def create_date_folder(self):
"""Create folder structure based on current date"""
current_date = datetime.now().strftime("%Y-%m-%d")
folder_path = os.path.join(self.temp_dir, current_date)
os.makedirs(folder_path, exist_ok=True)
return folder_path, current_date
def save_metadata(self, source_path, target_path, output_path, timestamp):
"""Save metadata for the face swap operation"""
metadata = {
"timestamp": timestamp,
"source_image": source_path,
"target_image": target_path,
"output_image": output_path,
"date_created": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
return metadata
def upload_to_hf(self, local_folder, date_folder):
"""Upload files to Hugging Face dataset"""
try:
# Upload the files
self.api.upload_folder(
folder_path=local_folder,
repo_id=self.repo_id,
repo_type="dataset",
path_in_repo=date_folder
)
return True
except Exception as e:
print(f"Error uploading to Hugging Face: {str(e)}")
return False
def swap_face(source_file, target_file, doFaceEnhancer):
folder_path = None
try:
# Initialize dataset handler
dataset_handler = FaceIntegrDataset()
# Create date-based folder
folder_path, date_folder = dataset_handler.create_date_folder()
# Lấy thời gian hiện tại
now = datetime.now()
# Phân tách thành từng thành phần
seconds = now.strftime("%S") # Giây
minutes = now.strftime("%M") # Phút
hours = now.strftime("%H") # Giờ
day = now.strftime("%d") # Ngày
month = now.strftime("%m") # Tháng
year = now.strftime("%Y") # Năm
# Kết hợp lại thành timestamp
timestamp = f"{seconds}{minutes}{hours}{day}{month}{year}"
# Save input images with timestamp in folder
source_path = os.path.join(folder_path, f"source_{timestamp}.jpg")
target_path = os.path.join(folder_path, f"target_{timestamp}.jpg")
output_path = os.path.join(folder_path, f"OutputImage{timestamp}.jpg")
# Save the input images
if source_file is None or target_file is None:
raise ValueError("Source and target images are required")
source_image = Image.fromarray(source_file)
source_image.save(source_path)
target_image = Image.fromarray(target_file)
target_image.save(target_path)
print("source_path: ", source_path)
print("target_path: ", target_path)
# Set global paths
roop.globals.source_path = source_path
roop.globals.target_path = target_path
roop.globals.output_path = normalize_output_path(
roop.globals.source_path,
roop.globals.target_path,
output_path
)
# Configure face processing options
if doFaceEnhancer:
roop.globals.frame_processors = ["face_swapper", "face_enhancer"]
else:
roop.globals.frame_processors = ["face_swapper"]
# Set global parameters
roop.globals.headless = True
roop.globals.keep_fps = True
roop.globals.keep_audio = True
roop.globals.keep_frames = False
roop.globals.many_faces = False
roop.globals.video_encoder = "libx264"
roop.globals.video_quality = 18
roop.globals.max_memory = suggest_max_memory()
roop.globals.execution_providers = decode_execution_providers(["cuda"])
roop.globals.execution_threads = suggest_execution_threads()
print(
"start process",
roop.globals.source_path,
roop.globals.target_path,
roop.globals.output_path,
)
# Check frame processors
for frame_processor in get_frame_processors_modules(roop.globals.frame_processors):
if not frame_processor.pre_check():
return None
# Process the face swap
start()
# Save metadata
metadata = dataset_handler.save_metadata(
f"source_{timestamp}.jpg",
f"target_{timestamp}.jpg",
f"Image{timestamp}.jpg",
timestamp
)
# Save metadata to JSON file in the same folder
metadata_path = os.path.join(folder_path, f"metadata_{timestamp}.json")
with open(metadata_path, 'w') as f:
json.dump(metadata, f, indent=4)
# Upload to Hugging Face
upload_success = dataset_handler.upload_to_hf(folder_path, date_folder)
if upload_success:
print(f"Successfully uploaded files to dataset {dataset_handler.repo_id}")
else:
print("Failed to upload files to Hugging Face dataset")
# Read the output image before cleaning up
if os.path.exists(output_path):
output_image = Image.open(output_path)
output_array = np.array(output_image)
# Clean up temp folder after reading the image
shutil.rmtree(folder_path)
return output_array
else:
print("Output image not found")
if folder_path and os.path.exists(folder_path):
shutil.rmtree(folder_path)
return None
except Exception as e:
print(f"Error in face swap process: {str(e)}")
if folder_path and os.path.exists(folder_path):
shutil.rmtree(folder_path)
raise gr.Error(f"Face swap failed: {str(e)}")
def create_interface():
# Create custom style
custom_css = """
.container {
max-width: 1200px;
margin: auto;
padding: 20px;
}
.output-image {
min-height: 400px;
border: 1px solid #ccc;
border-radius: 8px;
padding: 10px;
}
"""
# Gradio interface setup
title = "Face - Интегратор"
description = r"""
The application will save the image history to Hugging Face dataset using the environment variable token.
Please upload source and target images to begin the face swap process.
"""
article = r"""
<div style="text-align: center; max-width: 650px; margin: 40px auto;">
<p>
This tool performs face swapping with optional enhancement.
The processed images are automatically saved to the Hugging Face dataset.
</p>
</div>
"""
# Create Gradio interface with improved layout
with gr.Blocks(title=title, css=custom_css) as app:
gr.Markdown(f"<h1 style='text-align: center;'>{title}</h1>")
gr.Markdown(description)
with gr.Row():
with gr.Column(scale=1):
source_image = gr.Image(
label="Source Image",
type="numpy",
sources=["upload"]
)
with gr.Column(scale=1):
target_image = gr.Image(
label="Target Image",
type="numpy",
sources=["upload"]
)
with gr.Column(scale=1):
output_image = gr.Image(
label="Output Image",
type="numpy",
interactive=False,
elem_classes="output-image"
)
with gr.Row():
enhance_checkbox = gr.Checkbox(
label="Применить алгоритм?",
info="Улучшение качества изображения",
value=False
)
with gr.Row():
process_btn = gr.Button(
"Process Face Swap",
variant="primary",
size="lg"
)
# Set up the processing event
process_btn.click(
fn=swap_face,
inputs=[source_image, target_image, enhance_checkbox],
outputs=output_image,
api_name="swap_face"
)
gr.Markdown(article)
return app
def main():
# Create and launch the interface
app = create_interface()
app.launch(share=False)
if __name__ == "__main__":
main()