Jonny001 commited on
Commit
c41fa1b
Β·
verified Β·
1 Parent(s): 58a3bfb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +34 -48
app.py CHANGED
@@ -63,31 +63,26 @@ custom_css = """
63
  --text-primary: #ffffff;
64
  --text-secondary: #a0a0c0;
65
  }
66
-
67
  body {
68
  background: var(--dark-bg) !important;
69
  color: var(--text-primary) !important;
70
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
71
  }
72
-
73
  .gr-block {
74
  background: var(--dark-panel) !important;
75
  border-radius: 12px !important;
76
  border: 1px solid rgba(0, 243, 255, 0.2) !important;
77
  box-shadow: 0 0 15px rgba(0, 243, 255, 0.1) !important;
78
  }
79
-
80
  .gr-box {
81
  border-color: rgba(0, 243, 255, 0.3) !important;
82
  color: var(--text-primary) !important;
83
  background: rgba(10, 10, 26, 0.7) !important;
84
  }
85
-
86
  h1, h2, h3, h4, label, .gr-label {
87
  color: var(--text-primary) !important;
88
  text-shadow: 0 0 5px rgba(0, 243, 255, 0.5);
89
  }
90
-
91
  .gr-button {
92
  background: linear-gradient(45deg, var(--neon-primary), var(--neon-secondary)) !important;
93
  color: black !important;
@@ -102,17 +97,14 @@ h1, h2, h3, h4, label, .gr-label {
102
  width: 100% !important;
103
  margin: 10px 0 !important;
104
  }
105
-
106
  .gr-button:not(:disabled):hover {
107
  transform: translateY(-2px);
108
  box-shadow: 0 0 15px var(--neon-primary), 0 0 30px rgba(0, 243, 255, 0.5) !important;
109
  }
110
-
111
  .gr-button:disabled {
112
  background: #4b5563 !important;
113
  box-shadow: none !important;
114
  }
115
-
116
  .status-indicator {
117
  display: inline-block;
118
  width: 12px;
@@ -123,7 +115,6 @@ h1, h2, h3, h4, label, .gr-label {
123
  box-shadow: 0 0 0 0 rgba(0, 255, 135, 0.7);
124
  animation: pulse 2s infinite;
125
  }
126
-
127
  @keyframes pulse {
128
  0% {
129
  box-shadow: 0 0 0 0 rgba(0, 255, 135, 0.7);
@@ -135,14 +126,12 @@ h1, h2, h3, h4, label, .gr-label {
135
  box-shadow: 0 0 0 0 rgba(0, 255, 135, 0);
136
  }
137
  }
138
-
139
  .status-text {
140
  color: var(--text-secondary);
141
  font-size: 0.9rem;
142
  display: flex;
143
  align-items: center;
144
  }
145
-
146
  .header {
147
  display: flex;
148
  justify-content: space-between;
@@ -154,7 +143,6 @@ h1, h2, h3, h4, label, .gr-label {
154
  border: 1px solid rgba(0, 243, 255, 0.3);
155
  box-shadow: 0 0 20px rgba(0, 243, 255, 0.2);
156
  }
157
-
158
  .title-section h1 {
159
  margin-bottom: 0.25rem;
160
  font-weight: 800;
@@ -163,39 +151,32 @@ h1, h2, h3, h4, label, .gr-label {
163
  -webkit-text-fill-color: transparent;
164
  text-shadow: 0 0 10px rgba(0, 243, 255, 0.5);
165
  }
166
-
167
  .title-section p {
168
  color: var(--text-secondary);
169
  margin: 0;
170
  }
171
-
172
  .instructions {
173
  background: linear-gradient(90deg, rgba(0,243,255,0.05) 0%, rgba(255,0,255,0.05) 100%) !important;
174
  padding: 1.5rem !important;
175
  margin-bottom: 2rem !important;
176
  border: 1px solid rgba(0, 243, 255, 0.2) !important;
177
  }
178
-
179
  .instructions h3 {
180
  margin-top: 0;
181
  margin-bottom: 0.75rem;
182
  color: var(--neon-primary) !important;
183
  }
184
-
185
  .instructions ul {
186
  margin-bottom: 0;
187
  padding-left: 1.5rem;
188
  }
189
-
190
  .instructions li {
191
  margin-bottom: 0.5rem;
192
  color: var(--text-secondary);
193
  }
194
-
195
  .instructions li:last-child {
196
  margin-bottom: 0;
197
  }
198
-
199
  .footer {
200
  text-align: center;
201
  margin-top: 2rem;
@@ -204,7 +185,6 @@ h1, h2, h3, h4, label, .gr-label {
204
  color: var(--text-secondary);
205
  font-size: 0.875rem;
206
  }
207
-
208
  .image-container {
209
  border: 2px solid rgba(0, 243, 255, 0.3);
210
  border-radius: 12px;
@@ -213,7 +193,6 @@ h1, h2, h3, h4, label, .gr-label {
213
  margin-bottom: 1.5rem;
214
  box-shadow: 0 0 15px rgba(0, 243, 255, 0.1);
215
  }
216
-
217
  .image-container .gr-label {
218
  background: rgba(0, 243, 255, 0.1);
219
  padding: 8px 12px;
@@ -221,7 +200,6 @@ h1, h2, h3, h4, label, .gr-label {
221
  margin-bottom: 10px;
222
  display: inline-block;
223
  }
224
-
225
  .control-panel {
226
  background: linear-gradient(90deg, rgba(0,243,255,0.08) 0%, rgba(255,0,255,0.08) 100%) !important;
227
  padding: 1.5rem !important;
@@ -229,7 +207,6 @@ h1, h2, h3, h4, label, .gr-label {
229
  border-radius: 12px !important;
230
  margin-bottom: 1.5rem !important;
231
  }
232
-
233
  .status-panel {
234
  background: var(--darker-panel) !important;
235
  padding: 1.5rem !important;
@@ -237,7 +214,6 @@ h1, h2, h3, h4, label, .gr-label {
237
  border-radius: 12px !important;
238
  box-shadow: 0 0 15px rgba(0, 255, 135, 0.1) !important;
239
  }
240
-
241
  .status-header {
242
  display: flex;
243
  align-items: center;
@@ -245,22 +221,18 @@ h1, h2, h3, h4, label, .gr-label {
245
  padding-bottom: 0.5rem;
246
  border-bottom: 1px solid rgba(0, 255, 135, 0.2);
247
  }
248
-
249
  .status-content {
250
  min-height: 100px;
251
  }
252
-
253
  .output-highlight {
254
  border: 2px solid var(--neon-accent) !important;
255
  box-shadow: 0 0 20px rgba(0, 255, 135, 0.3) !important;
256
  }
257
-
258
  .upload-text {
259
  color: var(--text-secondary);
260
  text-align: center;
261
  padding: 20px;
262
  }
263
-
264
  .progress-bar {
265
  height: 6px;
266
  background: rgba(0, 243, 255, 0.2);
@@ -268,7 +240,6 @@ h1, h2, h3, h4, label, .gr-label {
268
  margin: 10px 0;
269
  overflow: hidden;
270
  }
271
-
272
  .progress-fill {
273
  height: 100%;
274
  background: linear-gradient(90deg, var(--neon-primary), var(--neon-accent));
@@ -276,7 +247,6 @@ h1, h2, h3, h4, label, .gr-label {
276
  width: 0%;
277
  transition: width 0.3s ease;
278
  }
279
-
280
  .control-item {
281
  margin-bottom: 1rem;
282
  padding: 1rem;
@@ -284,11 +254,9 @@ h1, h2, h3, h4, label, .gr-label {
284
  border-radius: 8px;
285
  border: 1px solid rgba(0, 243, 255, 0.1);
286
  }
287
-
288
  .control-item:last-child {
289
  margin-bottom: 0;
290
  }
291
-
292
  .download-btn {
293
  background: linear-gradient(45deg, var(--neon-accent), #00cc70) !important;
294
  margin-top: 15px !important;
@@ -415,6 +383,13 @@ with gr.Blocks(
415
  visible=False,
416
  elem_classes="download-btn"
417
  )
 
 
 
 
 
 
 
418
 
419
  # Instructions at the bottom
420
  with gr.Row():
@@ -440,51 +415,62 @@ with gr.Blocks(
440
  </div>
441
  """)
442
 
443
- # Function to update status
444
- def update_status(status):
445
- return status
 
 
 
 
 
 
 
 
 
 
446
 
447
  # Enhanced submit function with status updates
448
  def process_swap(source_file, target_file, doFaceEnhancer, many_faces_option):
449
  if source_file is None or target_file is None:
450
- yield "❌ Please upload both source and target images", None, gr.update(visible=False)
451
  return
452
 
453
- yield "🟑 Processing: Analyzing faces and detecting features...", None, gr.update(visible=False)
454
  time.sleep(1)
455
 
456
- yield "🟑 Processing: Extracting facial landmarks and matching features...", None, gr.update(visible=False)
457
  time.sleep(1)
458
 
459
- yield "🟑 Processing: Swapping faces and applying transformations...", None, gr.update(visible=False)
460
  time.sleep(1)
461
 
462
  if doFaceEnhancer:
463
- yield "🟑 Processing: Enhancing face quality and refining details...", None, gr.update(visible=False)
464
  time.sleep(1)
465
 
466
  result = swap_face_image(source_file, target_file, doFaceEnhancer)
467
 
468
  if result is None:
469
- yield "❌ Error: Failed to process images. Please try again with different images.", None, gr.update(visible=False)
470
  else:
471
- yield "βœ… Processing complete! Result is ready for download.", result, gr.update(visible=True)
 
472
 
473
  # Connect the button with enhanced function
474
  submit.click(
475
  fn=process_swap,
476
  inputs=[source_image, target_image, face_enhancer, many_faces],
477
- outputs=[info_text, output_image, download_btn]
478
  )
479
 
480
- # Download button functionality
481
- def download_result():
482
- return "πŸ’Ύ Download initiated! Check your downloads folder."
483
 
484
  download_btn.click(
485
- fn=download_result,
486
  inputs=None,
487
- outputs=info_text
488
  )
489
 
490
  if __name__ == "__main__":
 
63
  --text-primary: #ffffff;
64
  --text-secondary: #a0a0c0;
65
  }
 
66
  body {
67
  background: var(--dark-bg) !important;
68
  color: var(--text-primary) !important;
69
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
70
  }
 
71
  .gr-block {
72
  background: var(--dark-panel) !important;
73
  border-radius: 12px !important;
74
  border: 1px solid rgba(0, 243, 255, 0.2) !important;
75
  box-shadow: 0 0 15px rgba(0, 243, 255, 0.1) !important;
76
  }
 
77
  .gr-box {
78
  border-color: rgba(0, 243, 255, 0.3) !important;
79
  color: var(--text-primary) !important;
80
  background: rgba(10, 10, 26, 0.7) !important;
81
  }
 
82
  h1, h2, h3, h4, label, .gr-label {
83
  color: var(--text-primary) !important;
84
  text-shadow: 0 0 5px rgba(0, 243, 255, 0.5);
85
  }
 
86
  .gr-button {
87
  background: linear-gradient(45deg, var(--neon-primary), var(--neon-secondary)) !important;
88
  color: black !important;
 
97
  width: 100% !important;
98
  margin: 10px 0 !important;
99
  }
 
100
  .gr-button:not(:disabled):hover {
101
  transform: translateY(-2px);
102
  box-shadow: 0 0 15px var(--neon-primary), 0 0 30px rgba(0, 243, 255, 0.5) !important;
103
  }
 
104
  .gr-button:disabled {
105
  background: #4b5563 !important;
106
  box-shadow: none !important;
107
  }
 
108
  .status-indicator {
109
  display: inline-block;
110
  width: 12px;
 
115
  box-shadow: 0 0 0 0 rgba(0, 255, 135, 0.7);
116
  animation: pulse 2s infinite;
117
  }
 
118
  @keyframes pulse {
119
  0% {
120
  box-shadow: 0 0 0 0 rgba(0, 255, 135, 0.7);
 
126
  box-shadow: 0 0 0 0 rgba(0, 255, 135, 0);
127
  }
128
  }
 
129
  .status-text {
130
  color: var(--text-secondary);
131
  font-size: 0.9rem;
132
  display: flex;
133
  align-items: center;
134
  }
 
135
  .header {
136
  display: flex;
137
  justify-content: space-between;
 
143
  border: 1px solid rgba(0, 243, 255, 0.3);
144
  box-shadow: 0 0 20px rgba(0, 243, 255, 0.2);
145
  }
 
146
  .title-section h1 {
147
  margin-bottom: 0.25rem;
148
  font-weight: 800;
 
151
  -webkit-text-fill-color: transparent;
152
  text-shadow: 0 0 10px rgba(0, 243, 255, 0.5);
153
  }
 
154
  .title-section p {
155
  color: var(--text-secondary);
156
  margin: 0;
157
  }
 
158
  .instructions {
159
  background: linear-gradient(90deg, rgba(0,243,255,0.05) 0%, rgba(255,0,255,0.05) 100%) !important;
160
  padding: 1.5rem !important;
161
  margin-bottom: 2rem !important;
162
  border: 1px solid rgba(0, 243, 255, 0.2) !important;
163
  }
 
164
  .instructions h3 {
165
  margin-top: 0;
166
  margin-bottom: 0.75rem;
167
  color: var(--neon-primary) !important;
168
  }
 
169
  .instructions ul {
170
  margin-bottom: 0;
171
  padding-left: 1.5rem;
172
  }
 
173
  .instructions li {
174
  margin-bottom: 0.5rem;
175
  color: var(--text-secondary);
176
  }
 
177
  .instructions li:last-child {
178
  margin-bottom: 0;
179
  }
 
180
  .footer {
181
  text-align: center;
182
  margin-top: 2rem;
 
185
  color: var(--text-secondary);
186
  font-size: 0.875rem;
187
  }
 
188
  .image-container {
189
  border: 2px solid rgba(0, 243, 255, 0.3);
190
  border-radius: 12px;
 
193
  margin-bottom: 1.5rem;
194
  box-shadow: 0 0 15px rgba(0, 243, 255, 0.1);
195
  }
 
196
  .image-container .gr-label {
197
  background: rgba(0, 243, 255, 0.1);
198
  padding: 8px 12px;
 
200
  margin-bottom: 10px;
201
  display: inline-block;
202
  }
 
203
  .control-panel {
204
  background: linear-gradient(90deg, rgba(0,243,255,0.08) 0%, rgba(255,0,255,0.08) 100%) !important;
205
  padding: 1.5rem !important;
 
207
  border-radius: 12px !important;
208
  margin-bottom: 1.5rem !important;
209
  }
 
210
  .status-panel {
211
  background: var(--darker-panel) !important;
212
  padding: 1.5rem !important;
 
214
  border-radius: 12px !important;
215
  box-shadow: 0 0 15px rgba(0, 255, 135, 0.1) !important;
216
  }
 
217
  .status-header {
218
  display: flex;
219
  align-items: center;
 
221
  padding-bottom: 0.5rem;
222
  border-bottom: 1px solid rgba(0, 255, 135, 0.2);
223
  }
 
224
  .status-content {
225
  min-height: 100px;
226
  }
 
227
  .output-highlight {
228
  border: 2px solid var(--neon-accent) !important;
229
  box-shadow: 0 0 20px rgba(0, 255, 135, 0.3) !important;
230
  }
 
231
  .upload-text {
232
  color: var(--text-secondary);
233
  text-align: center;
234
  padding: 20px;
235
  }
 
236
  .progress-bar {
237
  height: 6px;
238
  background: rgba(0, 243, 255, 0.2);
 
240
  margin: 10px 0;
241
  overflow: hidden;
242
  }
 
243
  .progress-fill {
244
  height: 100%;
245
  background: linear-gradient(90deg, var(--neon-primary), var(--neon-accent));
 
247
  width: 0%;
248
  transition: width 0.3s ease;
249
  }
 
250
  .control-item {
251
  margin-bottom: 1rem;
252
  padding: 1rem;
 
254
  border-radius: 8px;
255
  border: 1px solid rgba(0, 243, 255, 0.1);
256
  }
 
257
  .control-item:last-child {
258
  margin-bottom: 0;
259
  }
 
260
  .download-btn {
261
  background: linear-gradient(45deg, var(--neon-accent), #00cc70) !important;
262
  margin-top: 15px !important;
 
383
  visible=False,
384
  elem_classes="download-btn"
385
  )
386
+
387
+ # Add a file component for downloading
388
+ download_file = gr.File(
389
+ label="Download Result",
390
+ visible=False,
391
+ interactive=False
392
+ )
393
 
394
  # Instructions at the bottom
395
  with gr.Row():
 
415
  </div>
416
  """)
417
 
418
+ # Function to save the output image and return file path
419
+ def save_output_image(img):
420
+ if img is None:
421
+ return None, gr.update(visible=False)
422
+
423
+ # Convert PIL Image to numpy array
424
+ img_array = np.array(img)
425
+
426
+ # Save the image to a temporary file
427
+ output_path = "swapped_result.jpg"
428
+ Image.fromarray(img_array).save(output_path)
429
+
430
+ return output_path, gr.update(visible=True, value=output_path)
431
 
432
  # Enhanced submit function with status updates
433
  def process_swap(source_file, target_file, doFaceEnhancer, many_faces_option):
434
  if source_file is None or target_file is None:
435
+ yield "❌ Please upload both source and target images", None, gr.update(visible=False), None, gr.update(visible=False)
436
  return
437
 
438
+ yield "🟑 Processing: Analyzing faces and detecting features...", None, gr.update(visible=False), None, gr.update(visible=False)
439
  time.sleep(1)
440
 
441
+ yield "🟑 Processing: Extracting facial landmarks and matching features...", None, gr.update(visible=False), None, gr.update(visible=False)
442
  time.sleep(1)
443
 
444
+ yield "🟑 Processing: Swapping faces and applying transformations...", None, gr.update(visible=False), None, gr.update(visible=False)
445
  time.sleep(1)
446
 
447
  if doFaceEnhancer:
448
+ yield "🟑 Processing: Enhancing face quality and refining details...", None, gr.update(visible=False), None, gr.update(visible=False)
449
  time.sleep(1)
450
 
451
  result = swap_face_image(source_file, target_file, doFaceEnhancer)
452
 
453
  if result is None:
454
+ yield "❌ Error: Failed to process images. Please try again with different images.", None, gr.update(visible=False), None, gr.update(visible=False)
455
  else:
456
+ file_path, file_update = save_output_image(result)
457
+ yield "βœ… Processing complete! Result is ready for download.", result, gr.update(visible=True), file_path, file_update
458
 
459
  # Connect the button with enhanced function
460
  submit.click(
461
  fn=process_swap,
462
  inputs=[source_image, target_image, face_enhancer, many_faces],
463
+ outputs=[info_text, output_image, download_btn, download_file]
464
  )
465
 
466
+ # Download button functionality - show the file download component
467
+ def show_download():
468
+ return gr.update(visible=True)
469
 
470
  download_btn.click(
471
+ fn=show_download,
472
  inputs=None,
473
+ outputs=download_file
474
  )
475
 
476
  if __name__ == "__main__":