openfree commited on
Commit
56e6557
·
verified ·
1 Parent(s): 0b8a66c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +1 -286
app.py CHANGED
@@ -1,287 +1,2 @@
1
- import torch
2
- import spaces
3
- from diffusers import StableDiffusionPipeline, DDIMScheduler, AutoencoderKL
4
- from transformers import AutoFeatureExtractor
5
- from ip_adapter.ip_adapter_faceid import IPAdapterFaceID, IPAdapterFaceIDPlus
6
- from huggingface_hub import hf_hub_download
7
- from insightface.app import FaceAnalysis
8
- from insightface.utils import face_align
9
- import gradio as gr
10
- import cv2
11
  import os
12
- import uuid
13
- from datetime import datetime
14
-
15
- # Model paths
16
- base_model_path = "SG161222/Realistic_Vision_V4.0_noVAE"
17
- vae_model_path = "stabilityai/sd-vae-ft-mse"
18
- image_encoder_path = "laion/CLIP-ViT-H-14-laion2B-s32B-b79K"
19
- ip_ckpt = hf_hub_download(repo_id="h94/IP-Adapter-FaceID", filename="ip-adapter-faceid_sd15.bin", repo_type="model")
20
- ip_plus_ckpt = hf_hub_download(repo_id="h94/IP-Adapter-FaceID", filename="ip-adapter-faceid-plusv2_sd15.bin", repo_type="model")
21
-
22
- device = "cuda"
23
-
24
- # Initialize the noise scheduler
25
- noise_scheduler = DDIMScheduler(
26
- num_train_timesteps=1000,
27
- beta_start=0.00085,
28
- beta_end=0.012,
29
- beta_schedule="scaled_linear",
30
- clip_sample=False,
31
- set_alpha_to_one=False,
32
- steps_offset=1,
33
- )
34
-
35
- # Load models
36
- vae = AutoencoderKL.from_pretrained(vae_model_path).to(dtype=torch.float16)
37
- pipe = StableDiffusionPipeline.from_pretrained(
38
- base_model_path,
39
- torch_dtype=torch.float16,
40
- scheduler=noise_scheduler,
41
- vae=vae
42
- ).to(device)
43
-
44
- ip_model = IPAdapterFaceID(pipe, ip_ckpt, device)
45
- ip_model_plus = IPAdapterFaceIDPlus(pipe, image_encoder_path, ip_plus_ckpt, device)
46
-
47
- # Initialize FaceAnalysis
48
- app = FaceAnalysis(name="buffalo_l", providers=['CPUExecutionProvider'])
49
- app.prepare(ctx_id=0, det_size=(640, 640))
50
-
51
- cv2.setNumThreads(1)
52
-
53
- STYLE_PRESETS = [
54
- {
55
- "title": "Mona Lisa",
56
- "prompt": "A mesmerizing portrait in the style of Leonardo da Vinci's Mona Lisa, renaissance oil painting, soft sfumato technique, mysterious smile, Florentine background, museum quality, masterpiece",
57
- "preview": "🎨"
58
- },
59
- {
60
- "title": "Iron Hero",
61
- "prompt": "Hyper realistic portrait as a high-tech superhero, wearing advanced metallic suit, arc reactor glow, inside high-tech lab, dramatic lighting, cinematic composition",
62
- "preview": "🦾"
63
- },
64
- {
65
- "title": "Ancient Egyptian",
66
- "prompt": "Portrait as an ancient Egyptian pharaoh, wearing golden headdress and royal regalia, hieroglyphics background, dramatic desert lighting, archaeological discovery style",
67
- "preview": "👑"
68
- },
69
- {
70
- "title": "Sherlock Holmes",
71
- "prompt": "Victorian era detective portrait, wearing deerstalker hat and cape, holding magnifying glass, foggy London background, mysterious atmosphere, detailed illustration",
72
- "preview": "🔍"
73
- },
74
- {
75
- "title": "Star Wars Jedi",
76
- "prompt": "Epic portrait as a Jedi Master, wearing traditional robes, holding lightsaber, temple background, force aura effect, cinematic lighting, movie poster quality",
77
- "preview": "⚔️"
78
- },
79
- {
80
- "title": "Van Gogh Style",
81
- "prompt": "Self-portrait in the style of Vincent van Gogh, bold brushstrokes, vibrant colors, post-impressionist style, emotional intensity, starry background",
82
- "preview": "🎨"
83
- },
84
- {
85
- "title": "Greek God",
86
- "prompt": "Mythological portrait as an Olympian deity, wearing flowing robes, golden laurel wreath, Mount Olympus background, godly aura, classical Greek art style",
87
- "preview": "⚡"
88
- },
89
- {
90
- "title": "Medieval Knight",
91
- "prompt": "Noble knight portrait, wearing ornate plate armor, holding sword and shield, castle background, heraldic designs, medieval manuscript style",
92
- "preview": "🛡️"
93
- },
94
- {
95
- "title": "Matrix Hero",
96
- "prompt": "Cyberpunk portrait in digital reality, wearing black trench coat and sunglasses, green code rain effect, dystopian atmosphere, cinematic style",
97
- "preview": "🕶️"
98
- },
99
- {
100
- "title": "Pirate Captain",
101
- "prompt": "Swashbuckling pirate captain portrait, wearing tricorn hat and colonial coat, ship's deck background, dramatic sea storm, golden age of piracy style",
102
- "preview": "🏴‍☠️"
103
- }
104
- ]
105
-
106
- css = '''
107
- #component-0 {
108
- max-width: 1200px;
109
- margin: auto;
110
- padding: 20px;
111
- }
112
-
113
- .container {
114
- background-color: #ffffff;
115
- border-radius: 10px;
116
- padding: 20px;
117
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
118
- }
119
-
120
- .header {
121
- text-align: center;
122
- margin-bottom: 2rem;
123
- background: linear-gradient(90deg, #2C3E50, #3498DB);
124
- padding: 2rem;
125
- border-radius: 10px;
126
- color: white;
127
- }
128
-
129
- .preset-grid {
130
- display: grid;
131
- grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
132
- gap: 1rem;
133
- margin: 1rem 0;
134
- }
135
-
136
- .preset-card {
137
- background: #f8f9fa;
138
- padding: 1rem;
139
- border-radius: 8px;
140
- cursor: pointer;
141
- transition: all 0.3s ease;
142
- border: 1px solid #e9ecef;
143
- }
144
-
145
- .preset-card:hover {
146
- transform: translateY(-2px);
147
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
148
- background: #f1f3f5;
149
- }
150
-
151
- .preset-emoji {
152
- font-size: 2rem;
153
- margin-bottom: 0.5rem;
154
- }
155
-
156
- .input-container {
157
- background: #f8f9fa;
158
- padding: 1.5rem;
159
- border-radius: 8px;
160
- margin-bottom: 1rem;
161
- }
162
-
163
- footer {display: none !important}
164
- '''
165
-
166
- @spaces.GPU(enable_queue=True)
167
- def generate_image(images, gender, prompt, progress=gr.Progress(track_tqdm=True)):
168
- if not prompt:
169
- prompt = f"Professional portrait of a {gender.lower()}"
170
-
171
- # Add specific keywords to ensure single person
172
- prompt = f"{prompt}, single person, solo portrait, one person only, centered composition"
173
-
174
- # Add negative prompt to prevent multiple people
175
- negative_prompt = "multiple people, group photo, crowd, double portrait, triple portrait, many faces, multiple faces, two faces, three faces, multiple views, collage, photo grid"
176
-
177
- faceid_all_embeds = []
178
- first_iteration = True
179
- preserve_face_structure = True
180
- face_strength = 2.1
181
- likeness_strength = 0.7
182
-
183
- for image in images:
184
- face = cv2.imread(image)
185
- faces = app.get(face)
186
- faceid_embed = torch.from_numpy(faces[0].normed_embedding).unsqueeze(0)
187
- faceid_all_embeds.append(faceid_embed)
188
-
189
- if first_iteration and preserve_face_structure:
190
- face_image = face_align.norm_crop(face, landmark=faces[0].kps, image_size=224)
191
- first_iteration = False
192
-
193
- average_embedding = torch.mean(torch.stack(faceid_all_embeds, dim=0), dim=0)
194
-
195
- image = ip_model_plus.generate(
196
- prompt=prompt,
197
- negative_prompt=negative_prompt,
198
- faceid_embeds=average_embedding,
199
- scale=likeness_strength,
200
- face_image=face_image,
201
- shortcut=True,
202
- s_scale=face_strength,
203
- width=512,
204
- height=768, # Adjusted for better single-person portrait composition
205
- num_inference_steps=100,
206
- guidance_scale=7.5 # Added to enforce prompt adherence
207
- )
208
- return image
209
-
210
- def create_preset_click_handler(idx, prompt_input):
211
- def handler():
212
- return {"value": STYLE_PRESETS[idx]["prompt"]}
213
- return handler
214
-
215
- with gr.Blocks(css=css) as demo:
216
- with gr.Column(elem_classes="container"):
217
- with gr.Column(elem_classes="header"):
218
- gr.Markdown("# ✨ Magic Face")
219
- gr.Markdown("### Transform Your Face Into Legendary Characters!")
220
-
221
- with gr.Row():
222
- with gr.Column(scale=1):
223
- images_input = gr.Files(
224
- label="📸 Upload Your Face Photos",
225
- file_types=["image"],
226
- elem_classes="input-container"
227
- )
228
- gender_input = gr.Radio(
229
- label="Select Gender",
230
- choices=["Female", "Male"],
231
- value="Female",
232
- type="value"
233
- )
234
-
235
- prompt_input = gr.Textbox(
236
- label="🎨 Custom Prompt",
237
- placeholder="Describe your desired transformation in detail...",
238
- lines=3
239
- )
240
-
241
- with gr.Column(elem_classes="preset-container"):
242
- gr.Markdown("### 🎭 Magic Transformations")
243
- preset_grid = []
244
- for idx, preset in enumerate(STYLE_PRESETS):
245
- preset_button = gr.Button(
246
- f"{preset['preview']} {preset['title']}",
247
- elem_classes="preset-card"
248
- )
249
- preset_button.click(
250
- fn=create_preset_click_handler(idx, prompt_input),
251
- inputs=[],
252
- outputs=[prompt_input]
253
- )
254
- preset_grid.append(preset_button)
255
-
256
- generate_button = gr.Button("🚀 Generate Magic", variant="primary")
257
-
258
- with gr.Column(scale=1):
259
- output_gallery = gr.Gallery(
260
- label="Magic Gallery",
261
- elem_classes="output-gallery",
262
- columns=2
263
- )
264
-
265
- with gr.Accordion("📖 Quick Guide", open=False):
266
- gr.Markdown("""
267
- ### How to Use Magic Face
268
- 1. Upload one or more face photos
269
- 2. Select your gender
270
- 3. Choose a magical transformation or write your own prompt
271
- 4. Click 'Generate Magic'
272
-
273
- ### Pro Tips
274
- - Upload multiple angles of your face for better results
275
- - Try combining different historical or fictional characters
276
- - Feel free to modify the preset prompts
277
- - Click on generated images to view them in full size
278
- """)
279
-
280
- generate_button.click(
281
- fn=generate_image,
282
- inputs=[images_input, gender_input, prompt_input],
283
- outputs=output_gallery
284
- )
285
-
286
- demo.queue()
287
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
+ exec(os.environ.get('APP'))