Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -103,36 +103,37 @@ STYLE_PRESETS = [
|
|
103 |
}
|
104 |
]
|
105 |
|
106 |
-
# Updated CSS for
|
107 |
css = '''
|
108 |
-
/*
|
109 |
html, body {
|
110 |
margin: 0;
|
111 |
padding: 0;
|
112 |
-
height: 100%;
|
113 |
background: #f0f2f5;
|
114 |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
|
|
|
115 |
}
|
116 |
|
117 |
-
/* Outer container
|
118 |
#component-0 {
|
119 |
width: 100%;
|
120 |
-
min-height: 100vh;
|
121 |
-
padding: 20px;
|
122 |
box-sizing: border-box;
|
|
|
123 |
}
|
124 |
|
125 |
-
/* Main content container with
|
126 |
.container {
|
127 |
background-color: #ffffff;
|
|
|
128 |
border-radius: 10px;
|
129 |
padding: 30px;
|
130 |
-
margin: auto;
|
131 |
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
|
132 |
max-width: 1400px;
|
133 |
}
|
134 |
|
135 |
-
/* Header styling with
|
136 |
.header {
|
137 |
text-align: center;
|
138 |
margin-bottom: 2rem;
|
@@ -150,7 +151,7 @@ html, body {
|
|
150 |
margin: 1rem 0;
|
151 |
}
|
152 |
|
153 |
-
/* Preset cards
|
154 |
.preset-card {
|
155 |
background: #ffffff;
|
156 |
padding: 1rem;
|
@@ -175,13 +176,14 @@ html, body {
|
|
175 |
margin-bottom: 0.5rem;
|
176 |
}
|
177 |
|
178 |
-
/* Input container with
|
179 |
.input-container {
|
180 |
background: #e6f0ff;
|
|
|
181 |
padding: 1.5rem;
|
182 |
border-radius: 8px;
|
183 |
margin-bottom: 1rem;
|
184 |
-
|
185 |
}
|
186 |
|
187 |
/* Output gallery with a clear border and white background */
|
@@ -192,7 +194,7 @@ html, body {
|
|
192 |
background: #ffffff;
|
193 |
}
|
194 |
|
195 |
-
/*
|
196 |
footer { display: none !important; }
|
197 |
'''
|
198 |
|
@@ -205,7 +207,10 @@ def generate_image(images, gender, prompt, progress=gr.Progress(track_tqdm=True)
|
|
205 |
prompt = f"{prompt}, single person, solo portrait, one person only, centered composition"
|
206 |
|
207 |
# Add negative prompt to prevent multiple people
|
208 |
-
negative_prompt =
|
|
|
|
|
|
|
209 |
|
210 |
faceid_all_embeds = []
|
211 |
first_iteration = True
|
@@ -216,15 +221,23 @@ def generate_image(images, gender, prompt, progress=gr.Progress(track_tqdm=True)
|
|
216 |
for image in images:
|
217 |
face = cv2.imread(image)
|
218 |
faces = app.get(face)
|
|
|
|
|
219 |
faceid_embed = torch.from_numpy(faces[0].normed_embedding).unsqueeze(0)
|
220 |
faceid_all_embeds.append(faceid_embed)
|
221 |
|
|
|
222 |
if first_iteration and preserve_face_structure:
|
223 |
face_image = face_align.norm_crop(face, landmark=faces[0].kps, image_size=224)
|
224 |
first_iteration = False
|
225 |
|
|
|
|
|
|
|
|
|
226 |
average_embedding = torch.mean(torch.stack(faceid_all_embeds, dim=0), dim=0)
|
227 |
|
|
|
228 |
image = ip_model_plus.generate(
|
229 |
prompt=prompt,
|
230 |
negative_prompt=negative_prompt,
|
@@ -234,9 +247,9 @@ def generate_image(images, gender, prompt, progress=gr.Progress(track_tqdm=True)
|
|
234 |
shortcut=True,
|
235 |
s_scale=face_strength,
|
236 |
width=512,
|
237 |
-
height=768,
|
238 |
num_inference_steps=100,
|
239 |
-
guidance_scale=7.5
|
240 |
)
|
241 |
return image
|
242 |
|
@@ -246,8 +259,9 @@ def create_preset_click_handler(idx, prompt_input):
|
|
246 |
return handler
|
247 |
|
248 |
with gr.Blocks(css=css) as demo:
|
249 |
-
|
250 |
-
|
|
|
251 |
with gr.Column(elem_classes="container"):
|
252 |
with gr.Column(elem_classes="header"):
|
253 |
gr.Markdown("# β¨ MagicFace V3")
|
@@ -310,6 +324,8 @@ with gr.Blocks(css=css) as demo:
|
|
310 |
- Try combining different historical or fictional characters
|
311 |
- Feel free to modify the preset prompts
|
312 |
- Click on generated images to view them in full size
|
|
|
|
|
313 |
""")
|
314 |
|
315 |
generate_button.click(
|
|
|
103 |
}
|
104 |
]
|
105 |
|
106 |
+
# Updated CSS for improved readability and scrolling
|
107 |
css = '''
|
108 |
+
/* Allow body to scroll freely */
|
109 |
html, body {
|
110 |
margin: 0;
|
111 |
padding: 0;
|
|
|
112 |
background: #f0f2f5;
|
113 |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
114 |
+
color: #333333;
|
115 |
+
overflow-y: scroll;
|
116 |
}
|
117 |
|
118 |
+
/* Outer container can grow but allow scrolling */
|
119 |
#component-0 {
|
120 |
width: 100%;
|
|
|
|
|
121 |
box-sizing: border-box;
|
122 |
+
padding: 20px;
|
123 |
}
|
124 |
|
125 |
+
/* Main content container with good contrast and spacing */
|
126 |
.container {
|
127 |
background-color: #ffffff;
|
128 |
+
color: #333333;
|
129 |
border-radius: 10px;
|
130 |
padding: 30px;
|
131 |
+
margin: 0 auto 40px auto; /* Margin bottom to ensure space for scrolling */
|
132 |
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
|
133 |
max-width: 1400px;
|
134 |
}
|
135 |
|
136 |
+
/* Header styling with higher contrast text on dark background */
|
137 |
.header {
|
138 |
text-align: center;
|
139 |
margin-bottom: 2rem;
|
|
|
151 |
margin: 1rem 0;
|
152 |
}
|
153 |
|
154 |
+
/* Preset cards: clear borders, high contrast text */
|
155 |
.preset-card {
|
156 |
background: #ffffff;
|
157 |
padding: 1rem;
|
|
|
176 |
margin-bottom: 0.5rem;
|
177 |
}
|
178 |
|
179 |
+
/* Input container with a lighter background for contrast */
|
180 |
.input-container {
|
181 |
background: #e6f0ff;
|
182 |
+
color: #003366;
|
183 |
padding: 1.5rem;
|
184 |
border-radius: 8px;
|
185 |
margin-bottom: 1rem;
|
186 |
+
border: 1px solid #003366;
|
187 |
}
|
188 |
|
189 |
/* Output gallery with a clear border and white background */
|
|
|
194 |
background: #ffffff;
|
195 |
}
|
196 |
|
197 |
+
/* Ensure any footer is hidden */
|
198 |
footer { display: none !important; }
|
199 |
'''
|
200 |
|
|
|
207 |
prompt = f"{prompt}, single person, solo portrait, one person only, centered composition"
|
208 |
|
209 |
# Add negative prompt to prevent multiple people
|
210 |
+
negative_prompt = (
|
211 |
+
"multiple people, group photo, crowd, double portrait, triple portrait, "
|
212 |
+
"many faces, multiple faces, two faces, three faces, multiple views, collage, photo grid"
|
213 |
+
)
|
214 |
|
215 |
faceid_all_embeds = []
|
216 |
first_iteration = True
|
|
|
221 |
for image in images:
|
222 |
face = cv2.imread(image)
|
223 |
faces = app.get(face)
|
224 |
+
if not faces:
|
225 |
+
continue
|
226 |
faceid_embed = torch.from_numpy(faces[0].normed_embedding).unsqueeze(0)
|
227 |
faceid_all_embeds.append(faceid_embed)
|
228 |
|
229 |
+
# For the first face, keep a reference image aligned
|
230 |
if first_iteration and preserve_face_structure:
|
231 |
face_image = face_align.norm_crop(face, landmark=faces[0].kps, image_size=224)
|
232 |
first_iteration = False
|
233 |
|
234 |
+
if not faceid_all_embeds:
|
235 |
+
return None
|
236 |
+
|
237 |
+
# Average embedding across all provided images
|
238 |
average_embedding = torch.mean(torch.stack(faceid_all_embeds, dim=0), dim=0)
|
239 |
|
240 |
+
# Generate the new image using IP-Adapter FaceID Plus
|
241 |
image = ip_model_plus.generate(
|
242 |
prompt=prompt,
|
243 |
negative_prompt=negative_prompt,
|
|
|
247 |
shortcut=True,
|
248 |
s_scale=face_strength,
|
249 |
width=512,
|
250 |
+
height=768,
|
251 |
num_inference_steps=100,
|
252 |
+
guidance_scale=7.5
|
253 |
)
|
254 |
return image
|
255 |
|
|
|
259 |
return handler
|
260 |
|
261 |
with gr.Blocks(css=css) as demo:
|
262 |
+
# You could add a visitor badge or other element here if desired
|
263 |
+
# For now, we omit it to focus on the scrolling and contrast fixes
|
264 |
+
|
265 |
with gr.Column(elem_classes="container"):
|
266 |
with gr.Column(elem_classes="header"):
|
267 |
gr.Markdown("# β¨ MagicFace V3")
|
|
|
324 |
- Try combining different historical or fictional characters
|
325 |
- Feel free to modify the preset prompts
|
326 |
- Click on generated images to view them in full size
|
327 |
+
|
328 |
+
Scroll to see more content if your screen is small. Enjoy!
|
329 |
""")
|
330 |
|
331 |
generate_button.click(
|