tonyassi commited on
Commit
ec156b8
Β·
verified Β·
1 Parent(s): 0a109c6

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +14 -209
app.py CHANGED
@@ -18,226 +18,31 @@ assert insightface.__version__ >= '0.7'
18
  app = FaceAnalysis(name='buffalo_l')
19
  app.prepare(ctx_id=0, det_size=(640, 640))
20
 
21
- # ensure model downloads fully
22
  swapper = insightface.model_zoo.get_model('inswapper_128.onnx', download=True, download_zip=True)
23
 
24
- # ---------- CTA / marketing config ----------
25
- BASE_UTM = "utm_source=hfspace_faceswap"
26
-
27
  # ---------- Swap logic ----------
28
  def swap_faces(src_img, dest_img):
29
- # Pre-run nudge
30
- gr.Warning(
31
- 'Skip the limits β€” HD, priority queue & no watermark at '
32
- '<a href="https://www.face-swap.co/?utm_source=hfspace_faceswap&utm_medium=warning" '
33
- 'target="_blank" rel="noopener">face-swap.co</a>'
34
- )
35
-
36
- if src_img is None or dest_img is None:
37
- raise gr.Error("Please upload both a source and a target image.")
38
-
39
  src_faces = app.get(src_img)
40
  dest_faces = app.get(dest_img)
41
 
42
  if len(src_faces) == 0 or len(dest_faces) == 0:
43
- raise gr.Error("No faces detected in one of the images. Try clearer, front-facing photos.")
44
 
45
  # Just swap first detected face from each image
46
  source_face = src_faces[0]
47
  dest_face = dest_faces[0]
48
  result = swapper.get(dest_img, dest_face, source_face, paste_back=True)
49
 
50
- out_img = Image.fromarray(np.uint8(result)).convert("RGB")
51
-
52
- # Post-success promo
53
- gr.Info(
54
- '✨ Like this preview?<br>'
55
- '<strong>Get HD face swaps</strong> (higher resolution, priority queue & no watermark) β€” '
56
- '<a href="https://www.face-swap.co/?utm_source=hfspace_faceswap&utm_medium=info" '
57
- 'target="_blank" rel="noopener">Upgrade on face-swap.co</a>',
58
- duration=8
59
- )
60
-
61
- return out_img
62
-
63
- def open_side():
64
- return gr.Sidebar(open=True)
65
-
66
- # ---------- Custom CSS (same vibe as video app) ----------
67
- CUSTOM_CSS = """
68
- .sticky-cta {
69
- position: sticky; top: 0; z-index: 1000;
70
- background: #a5b4fc;
71
- color: #0f172a;
72
- padding: 10px 14px;
73
- text-align: center;
74
- border-bottom: 1px solid #333;
75
- display: block;
76
- text-decoration: none;
77
- cursor: pointer;
78
- }
79
- .sticky-cta:hover { filter: brightness(0.97); }
80
- .sticky-cta .pill { background:#4f46e5; color:#fff; padding:4px 10px; border-radius:999px; margin-left:10px; }
81
- .sticky-cta .cta-link { font-weight:600; text-decoration: underline; }
82
-
83
- /* centered, single-label API CTA */
84
- .api-cta-wrap { text-align:center; margin-top:10px; }
85
- .api-cta-hero {
86
- display:inline-flex; align-items:center; gap:10px;
87
- padding:10px 14px; border-radius:14px;
88
- background: linear-gradient(90deg,#0ea5e9 0%, #a8a9de 100%);
89
- color:#fff; font-weight:800; letter-spacing:0.1px;
90
- box-shadow: 0 6px 22px rgba(99,102,241,0.35);
91
- border: 1px solid rgba(255,255,255,0.22);
92
- text-decoration:none;
93
- }
94
- .api-cta-hero:hover { filter:brightness(1.05); transform: translateY(-1px); transition: all .15s ease; }
95
-
96
- .api-cta-hero .new {
97
- background:#fff; color:#0ea5e9; font-weight:900;
98
- padding:2px 8px; border-radius:999px; font-size:12px; line-height:1;
99
- }
100
- .api-cta-hero .txt { font-weight:800; }
101
- .api-cta-hero .chev { opacity:.95; }
102
- @media (max-width: 520px){
103
- .api-cta-hero { padding:9px 12px; gap:8px; font-size:14px; }
104
- .api-cta-hero .new { display:none; }
105
- }
106
-
107
- /* floating bottom promo */
108
- .bottom-promo {
109
- position: fixed; left: 50%; transform: translateX(-50%);
110
- bottom: 16px; z-index: 1001; background:#0b0b0b; color:#fff;
111
- border: 1px solid #2a2a2a; border-radius: 12px; padding: 10px 14px;
112
- box-shadow: 0 8px 24px rgba(0,0,0,0.3);
113
- }
114
- .bottom-promo a { color:#4ea1ff; text-decoration:none; font-weight:600; }
115
-
116
- /* big CTA button */
117
- .upgrade-btn { width: 100%; font-size: 16px; padding: 10px 14px; }
118
-
119
- /* hero markdown centering + larger heading */
120
- #hero-md {
121
- text-align: center;
122
- }
123
- #hero-md h3,
124
- #hero-md .prose h3 {
125
- font-size: 2.1rem;
126
- line-height: 1.2;
127
- font-weight: 800;
128
- margin-bottom: 0.25rem;
129
- }
130
- #hero-md p,
131
- #hero-md .prose p {
132
- font-size: 1.05rem;
133
- }
134
- """
135
-
136
- # ---------- UI (Blocks) ----------
137
- with gr.Blocks(title="Image Face Swap", theme=gr.themes.Soft(), css=CUSTOM_CSS) as demo:
138
- # Sticky banner
139
- gr.HTML(
140
- '<a class="sticky-cta" '
141
- 'href="https://www.face-swap.co/?utm_source=hfspace_faceswap&utm_medium=banner" '
142
- 'target="_blank" rel="noopener" aria-label="Upgrade to Pro on face-swap.co">'
143
- '⚑ <strong>Upgrade to HD</strong> β€” priority queue & higher resolution swaps!'
144
- '<span class="pill">GPU</span>'
145
- '</a>'
146
- )
147
-
148
- # Hero / intro
149
- gr.Markdown(
150
- f"""
151
- ### Image Face Swap (Preview)
152
- [face-swap.co](https://www.face-swap.co/?utm_source=hfspace_faceswap&utm_medium=subtitle)
153
-
154
- **Free preview** runs on CPU and may be limited in resolution to keep it fast.
155
- Want full-quality **HD AI face swap** with GPU speed? **[Go Pro β†—](https://www.face-swap.co/?utm_source=hfspace_faceswap&utm_medium=go_pro)**
156
-
157
- {wellcomingMessage}
158
- """,
159
- elem_id="hero-md"
160
- )
161
-
162
- # API CTA
163
- gr.HTML(
164
- """
165
- <div class="api-cta-wrap">
166
- <a class="api-cta-hero"
167
- href="https://www.face-swap.co/api?utm_source=hfspace_faceswap&utm_medium=hero_api_new"
168
- target="_blank" rel="noopener" aria-label="Face Swap API">
169
- <span class="new">NEW</span>
170
- <span class="txt">Face Swap API</span>
171
- <span class="chev">β†—</span>
172
- </a>
173
- </div>
174
- """
175
- )
176
-
177
- with gr.Row():
178
- with gr.Column(scale=5):
179
- src_img = gr.Image(type="numpy", label="Source Image (face to copy)")
180
- dest_img = gr.Image(type="numpy", label="Target Image (face to replace)")
181
-
182
- go = gr.Button("Swap Face", variant="primary")
183
- pro = gr.Button("⚑ Upgrade to HD on face-swap.co", elem_classes=["upgrade-btn"])
184
-
185
- with gr.Column(scale=5):
186
- out_img = gr.Image(label="Result")
187
-
188
- # Examples
189
- gr.Examples(
190
- examples=[["./Images/kim.jpg", "./Images/marilyn.jpg"]],
191
- inputs=[src_img, dest_img],
192
- outputs=[out_img],
193
- fn=swap_faces,
194
- cache_examples=True,
195
- run_on_click=True,
196
- label="Try an example"
197
- )
198
-
199
- # Sidebar CTA
200
- with gr.Sidebar(open=False) as side:
201
- gr.Markdown(
202
- "### Upgrade to HD 1920x1080\n"
203
- "- Higher resolution face swaps\n"
204
- "- Priority queue\n"
205
- "- API access & automation\n"
206
- "- No watermark"
207
- )
208
- pro_pro = gr.Button("Open Pro Checkout", variant="primary")
209
- pro_api = gr.Button("API Access", variant="primary")
210
-
211
- # Floating bottom promo
212
- gr.HTML(
213
- '<div class="bottom-promo">'
214
- 'Want HD & faster processing? '
215
- '<a href="https://www.face-swap.co/?utm_source=hfspace_faceswap&utm_medium=upgrade" '
216
- 'target="_blank" rel="noopener">Upgrade</a>'
217
- '</div>'
218
- )
219
-
220
- # Open sidebar on click
221
- go.click(fn=open_side, inputs=None, outputs=side, queue=False)
222
-
223
- # Main action
224
- go.click(fn=swap_faces, inputs=[src_img, dest_img], outputs=out_img)
225
-
226
- # JS-only Pro buttons
227
- pro.click(
228
- fn=None, inputs=None, outputs=None,
229
- js="()=>window.open('https://www.face-swap.co/?utm_source=hfspace_faceswap&utm_medium=upgrade_to_hd','_blank')"
230
- )
231
- pro_pro.click(
232
- fn=None, inputs=None, outputs=None,
233
- js="()=>window.open('https://www.face-swap.co/?utm_source=hfspace_faceswap&utm_medium=sidebar_pro','_blank')"
234
- )
235
- pro_api.click(
236
- fn=None, inputs=None, outputs=None,
237
- js="()=>window.open('https://www.face-swap.co/api?utm_source=hfspace_faceswap&utm_medium=sidebar_api','_blank')"
238
- )
239
-
240
- demo.queue()
241
-
242
- if __name__ == "__main__":
243
- demo.launch()
 
18
  app = FaceAnalysis(name='buffalo_l')
19
  app.prepare(ctx_id=0, det_size=(640, 640))
20
 
21
+ # ensure model downloads fully; safer with download=True and zip=True like your working version
22
  swapper = insightface.model_zoo.get_model('inswapper_128.onnx', download=True, download_zip=True)
23
 
 
 
 
24
  # ---------- Swap logic ----------
25
  def swap_faces(src_img, dest_img):
 
 
 
 
 
 
 
 
 
 
26
  src_faces = app.get(src_img)
27
  dest_faces = app.get(dest_img)
28
 
29
  if len(src_faces) == 0 or len(dest_faces) == 0:
30
+ raise gr.Error("No faces detected in one of the images.")
31
 
32
  # Just swap first detected face from each image
33
  source_face = src_faces[0]
34
  dest_face = dest_faces[0]
35
  result = swapper.get(dest_img, dest_face, source_face, paste_back=True)
36
 
37
+ return Image.fromarray(np.uint8(result)).convert("RGB")
38
+
39
+ # ---------- Interface ----------
40
+ gr.Interface(
41
+ fn=swap_faces,
42
+ inputs=[gr.Image(), gr.Image()],
43
+ outputs=gr.Image(),
44
+ description=wellcomingMessage,
45
+ examples=[
46
+ ['./Images/kim.jpg', './Images/marilyn.jpg'],
47
+ ],
48
+ ).launch()