Spaces:
Build error
Build error
Add application file
Browse files
app.py
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import os
|
3 |
+
import cv2
|
4 |
+
import torch
|
5 |
+
from PIL import Image
|
6 |
+
from insightface.app import FaceAnalysis
|
7 |
+
from ip_adapter.ip_adapter_faceid import IPAdapterFaceID
|
8 |
+
from transformers import CLIPFeatureExtractor
|
9 |
+
from diffusers import StableDiffusionPipeline, EulerDiscreteScheduler, AutoencoderKL
|
10 |
+
from diffusers.pipelines.stable_diffusion import StableDiffusionSafetyChecker
|
11 |
+
import dlib
|
12 |
+
import imutils
|
13 |
+
from imutils import face_utils
|
14 |
+
import numpy as np
|
15 |
+
from skimage import transform as tf
|
16 |
+
|
17 |
+
base_model_path = "SG161222/Realistic_Vision_V6.0_B1_noVAE"
|
18 |
+
base_cache = "model-cache"
|
19 |
+
vae_model_path = "stabilityai/sd-vae-ft-mse"
|
20 |
+
ip_cache = "./ip-cache"
|
21 |
+
device = "cuda"
|
22 |
+
|
23 |
+
# Setup function to load models and other dependencies
|
24 |
+
def setup():
|
25 |
+
"""Load the model into memory to make running multiple predictions efficient"""
|
26 |
+
# Get ip-adapter-faceid model
|
27 |
+
if not os.path.exists("ip-cache/ip-adapter-faceid_sd15.bin"):
|
28 |
+
os.makedirs(ip_cache, exist_ok=True)
|
29 |
+
os.system(f"wget -O ip-cache/ip-adapter-faceid_sd15.bin https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sd15.bin")
|
30 |
+
|
31 |
+
# Download shape_predictor_68_face_landmarks.dat if it doesn't exist
|
32 |
+
if not os.path.exists("faceid/shape_predictor_68_face_landmarks.dat"):
|
33 |
+
os.makedirs("faceid", exist_ok=True)
|
34 |
+
os.system("wget -O faceid/shape_predictor_68_face_landmarks.dat https://github.com/italojs/facial-landmarks-recognition/raw/master/shape_predictor_68_face_landmarks.dat")
|
35 |
+
|
36 |
+
# Face embedding
|
37 |
+
app = FaceAnalysis(name="buffalo_l", providers=['CUDAExecutionProvider', 'CPUExecutionProvider'])
|
38 |
+
app.prepare(ctx_id=0, det_size=(640, 640))
|
39 |
+
|
40 |
+
# SD
|
41 |
+
noise_scheduler = EulerDiscreteScheduler(
|
42 |
+
num_train_timesteps=1000,
|
43 |
+
beta_start=0.00085,
|
44 |
+
beta_end=0.012
|
45 |
+
)
|
46 |
+
vae = AutoencoderKL.from_pretrained(
|
47 |
+
vae_model_path
|
48 |
+
).to(dtype=torch.float16)
|
49 |
+
pipe = StableDiffusionPipeline.from_pretrained(
|
50 |
+
base_model_path,
|
51 |
+
torch_dtype=torch.float16,
|
52 |
+
scheduler=noise_scheduler,
|
53 |
+
vae=vae,
|
54 |
+
feature_extractor=CLIPFeatureExtractor.from_pretrained("openai/clip-vit-base-patch32"),
|
55 |
+
safety_checker=StableDiffusionSafetyChecker.from_pretrained("CompVis/stable-diffusion-safety-checker"),
|
56 |
+
cache_dir=base_cache,
|
57 |
+
)
|
58 |
+
pipe = pipe.to(device)
|
59 |
+
|
60 |
+
# IP adapter
|
61 |
+
ip_model = IPAdapterFaceID(
|
62 |
+
pipe,
|
63 |
+
"ip-cache/ip-adapter-faceid_sd15.bin",
|
64 |
+
device
|
65 |
+
)
|
66 |
+
|
67 |
+
return app, ip_model
|
68 |
+
|
69 |
+
app, ip_model = setup()
|
70 |
+
|
71 |
+
def get_face_landmarks(image_path):
|
72 |
+
detector = dlib.get_frontal_face_detector()
|
73 |
+
predictor = dlib.shape_predictor('faceid/shape_predictor_68_face_landmarks.dat')
|
74 |
+
image = cv2.imread(image_path)
|
75 |
+
image = imutils.resize(image, width=512)
|
76 |
+
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
77 |
+
rects = detector(gray, 1)
|
78 |
+
for (i, rect) in enumerate(rects):
|
79 |
+
shape = predictor(gray, rect)
|
80 |
+
shape = face_utils.shape_to_np(shape)
|
81 |
+
return shape, image
|
82 |
+
|
83 |
+
def morph_faces(image1_path, image2_path, alpha=0.5):
|
84 |
+
landmarks1, image1 = get_face_landmarks(image1_path)
|
85 |
+
landmarks2, image2 = get_face_landmarks(image2_path)
|
86 |
+
average_landmarks = (landmarks1 + landmarks2) / 2
|
87 |
+
tform1 = tf.estimate_transform('similarity', landmarks1, average_landmarks)
|
88 |
+
tform2 = tf.estimate_transform('similarity', landmarks2, average_landmarks)
|
89 |
+
morphed_image1 = tf.warp(image1, inverse_map=tform1.inverse, output_shape=(512, 512))
|
90 |
+
morphed_image2 = tf.warp(image2, inverse_map=tform2.inverse, output_shape=(512, 512))
|
91 |
+
morphed_image = (1 - alpha) * morphed_image1 + alpha * morphed_image2
|
92 |
+
morphed_image = (morphed_image * 255).astype(np.uint8) # Convert to [0, 255] range
|
93 |
+
output_path = "tmp.png"
|
94 |
+
cv2.imwrite(output_path, morphed_image)
|
95 |
+
return output_path
|
96 |
+
|
97 |
+
def generate_image(face_image_1, face_image_2, prompt, negative_prompt, width, height, num_inference_steps, seed):
|
98 |
+
if seed is None:
|
99 |
+
seed = int.from_bytes(os.urandom(4), "big")
|
100 |
+
|
101 |
+
baby_image_path = morph_faces(face_image_1.name, face_image_2.name)
|
102 |
+
|
103 |
+
def generate_images(faceid_embeds, num_outputs=1):
|
104 |
+
images = ip_model.generate(
|
105 |
+
prompt=prompt,
|
106 |
+
negative_prompt=negative_prompt,
|
107 |
+
faceid_embeds=faceid_embeds,
|
108 |
+
num_samples=num_outputs,
|
109 |
+
width=width,
|
110 |
+
height=height,
|
111 |
+
num_inference_steps=num_inference_steps,
|
112 |
+
seed=seed
|
113 |
+
)
|
114 |
+
return images
|
115 |
+
|
116 |
+
faceid_embeds = app.get(cv2.imread(baby_image_path))[0].normed_embedding
|
117 |
+
faceid_embeds = torch.from_numpy(faceid_embeds).unsqueeze(0)
|
118 |
+
|
119 |
+
generated_images = generate_images(faceid_embeds)
|
120 |
+
return generated_images[0]
|
121 |
+
|
122 |
+
# Gradio Interface
|
123 |
+
gr_interface = gr.Interface(
|
124 |
+
fn=generate_image,
|
125 |
+
inputs=[
|
126 |
+
gr.Image(type="file", label="First Face Image"),
|
127 |
+
gr.Image(type="file", label="Second Face Image"),
|
128 |
+
gr.Textbox(value="portrait of a 6 y.o. boy, male child, 8k, HD, happy, in living room, perfect eyes, cute", label="Prompt"),
|
129 |
+
gr.Textbox(value="(mascara, makeup: 1.4), (breasts, boobs, naked, nude: 1.4), (beard, old, mustache, wrinkles: 1.4), (deformed iris, deformed pupils, semi-realistic, cgi, 3d, render, sketch, cartoon, drawing, anime, mutated hands and fingers:1.4), (deformed, distorted, disfigured:1.3), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, disconnected limbs, mutation, mutated, ugly, disgusting, amputation", label="Negative Prompt"),
|
130 |
+
gr.Slider(256, 1024, value=768, step=64, label="Width"),
|
131 |
+
gr.Slider(256, 1024, value=768, step=64, label="Height"),
|
132 |
+
gr.Slider(1, 200, value=30, step=1, label="Number of Inference Steps"),
|
133 |
+
gr.Number(value=None, label="Random Seed")
|
134 |
+
],
|
135 |
+
outputs=gr.Image(label="Generated Image"),
|
136 |
+
title="Face Morphing and Image Generation with Stable Diffusion"
|
137 |
+
)
|
138 |
+
|
139 |
+
gr_interface.launch()
|