VcRlAgent commited on
Commit
3c8b597
Β·
1 Parent(s): cc10554

Refactor to enable users to chose Avatar generation modes

Browse files
Files changed (4) hide show
  1. app copy.py +226 -0
  2. app.py +68 -27
  3. app.py.orig +0 -14
  4. requirement.txt.bk +0 -34
app copy.py ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ==========================================
2
+ # FaceForge AI – ZeroGPU Gradio Version
3
+ # Author: Vijay S. Chaudhari | 2025
4
+ # ==========================================
5
+
6
+ import gradio as gr
7
+ import spaces
8
+ import torch
9
+ import cv2
10
+ import numpy as np
11
+ from PIL import Image, ImageEnhance, ImageOps
12
+ from rembg import remove
13
+ from diffusers import StableDiffusionImg2ImgPipeline
14
+ import io
15
+
16
+
17
+ import torchvision
18
+ print("Printing Torch and TorchVision versions:")
19
+ print(torch.__version__)
20
+ print(torchvision.__version__)
21
+
22
+ # GPU libraries
23
+ from gfpgan import GFPGANer
24
+ from basicsr.archs.rrdbnet_arch import RRDBNet
25
+ from realesrgan import RealESRGANer
26
+
27
+ # ------------------------------------------
28
+ # Model Loading (Outside GPU decorator)
29
+ # ------------------------------------------
30
+
31
+ def load_models():
32
+ """Load models once at startup"""
33
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
34
+
35
+ # RealESRGAN upsampler
36
+ model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=2)
37
+ upsampler = RealESRGANer(
38
+ scale=2,
39
+ model_path='https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.1/RealESRGAN_x2plus.pth',
40
+ model=model,
41
+ tile=400,
42
+ tile_pad=10,
43
+ pre_pad=0,
44
+ half=True,
45
+ device=device
46
+ )
47
+
48
+ # GFPGAN enhancer
49
+ face_enhancer = GFPGANer(
50
+ model_path='https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth',
51
+ upscale=2,
52
+ arch='clean',
53
+ channel_multiplier=2,
54
+ bg_upsampler=upsampler,
55
+ device=device
56
+ )
57
+
58
+ # Stable Diffusion Img2Img pipeline (public model)
59
+ sd_pipe = StableDiffusionImg2ImgPipeline.from_pretrained(
60
+ "runwayml/stable-diffusion-v1-5",
61
+ torch_dtype=torch.float16
62
+ ).to(device)
63
+
64
+ # Optimize for ZeroGPU memory
65
+ sd_pipe.enable_attention_slicing()
66
+ sd_pipe.enable_model_cpu_offload()
67
+
68
+ return face_enhancer, sd_pipe
69
+
70
+ # Load models globally
71
+ face_enhancer, sd_pipe = load_models()
72
+
73
+ # ------------------------------------------
74
+ # GPU-Accelerated Functions
75
+ # ------------------------------------------
76
+
77
+ @spaces.GPU
78
+ def enhance_face(img: Image.Image) -> Image.Image:
79
+ """Enhance face using GFPGAN (GPU)"""
80
+ img_cv = cv2.cvtColor(np.array(img.convert('RGB')), cv2.COLOR_RGB2BGR)
81
+
82
+ with torch.no_grad():
83
+ _, _, restored_img = face_enhancer.enhance(
84
+ img_cv,
85
+ has_aligned=False,
86
+ only_center_face=False,
87
+ paste_back=True,
88
+ weight=0.5
89
+ )
90
+
91
+ restored_img = cv2.cvtColor(restored_img, cv2.COLOR_BGR2RGB)
92
+ return Image.fromarray(restored_img)
93
+
94
+ # ------------------------------------------
95
+ # Image Processing Functions
96
+ # ------------------------------------------
97
+
98
+ def enhance_image(img: Image.Image) -> Image.Image:
99
+ """Basic enhancement"""
100
+ img = ImageEnhance.Contrast(img).enhance(1.15)
101
+ img = ImageEnhance.Sharpness(img).enhance(1.1)
102
+ return img
103
+
104
+ @spaces.GPU
105
+ def create_headshot(img: Image.Image) -> Image.Image:
106
+ """Professional headshot with gradient background"""
107
+ # Enhance face
108
+ img_enhanced = enhance_face(img)
109
+
110
+ # Remove background
111
+ img_no_bg = remove(img_enhanced)
112
+
113
+ # Gradient background
114
+ bg = Image.new("RGB", img_no_bg.size, (200, 210, 230))
115
+ if img_no_bg.mode == 'RGBA':
116
+ bg.paste(img_no_bg, mask=img_no_bg.split()[3])
117
+
118
+ return enhance_image(bg)
119
+
120
+ @spaces.GPU
121
+ def create_passport(img: Image.Image) -> Image.Image:
122
+ """Passport photo with white background"""
123
+ # Enhance face
124
+ img_enhanced = enhance_face(img)
125
+
126
+ # Remove background
127
+ img_no_bg = remove(img_enhanced)
128
+
129
+ # White background (600x600)
130
+ bg = Image.new("RGB", (600, 600), (255, 255, 255))
131
+ img_no_bg.thumbnail((550, 550), Image.Resampling.LANCZOS)
132
+ offset = ((600 - img_no_bg.width) // 2, (600 - img_no_bg.height) // 2)
133
+
134
+ if img_no_bg.mode == 'RGBA':
135
+ bg.paste(img_no_bg, offset, mask=img_no_bg.split()[3])
136
+
137
+ return bg
138
+
139
+ @spaces.GPU
140
+ def create_avatar(img: Image.Image) -> Image.Image:
141
+ """Stylized AI avatar"""
142
+ # Enhance face
143
+ img_enhanced = enhance_face(img)
144
+
145
+ # Resize for SD (512x512)
146
+ img_resized = img_enhanced.convert("RGB").resize((512, 512))
147
+
148
+ # Stylize with SD prompt
149
+ #prompt = "highly detailed, digital portrait, professional lighting, cinematic style, artistic AI avatar"
150
+ #prompt = "stylized yet realistic portrait, balanced lighting, subtle gradient background, sharp focus on face"
151
+ #prompt = "studio portrait, even lighting, neutral background, realistic skin, confident pose"
152
+ prompt = "realistic professional headshot, soft studio lighting, neutral background, crisp details, natural skin tone"
153
+
154
+
155
+
156
+ with torch.autocast("cuda"):
157
+ result = sd_pipe(prompt=prompt, image=img_resized, strength=0.4, guidance_scale=5.0)
158
+
159
+ avatar = result.images[0]
160
+
161
+ return avatar
162
+
163
+ @spaces.GPU
164
+ def process_all(img: Image.Image):
165
+ """Process all three types at once"""
166
+ headshot = create_headshot(img)
167
+ passport = create_passport(img)
168
+ avatar = create_avatar(img)
169
+ return headshot, passport, avatar
170
+
171
+ # ------------------------------------------
172
+ # Gradio Interface
173
+ # ------------------------------------------
174
+
175
+ with gr.Blocks(theme=gr.themes.Soft(), title="FaceForge AI") as demo:
176
+ gr.Markdown(
177
+ """
178
+ # 🎨 FaceForge AI
179
+ ### GPU-Accelerated Professional Headshot & Avatar Generator
180
+ Upload your photo and generate professional headshots, passport photos, and AI avatars instantly!
181
+ """
182
+ )
183
+
184
+ with gr.Row():
185
+ with gr.Column():
186
+ input_image = gr.Image(type="pil", label="πŸ“· Upload Your Photo")
187
+ process_btn = gr.Button("✨ Generate All Images", variant="primary", size="lg")
188
+
189
+ with gr.Column():
190
+ gr.Markdown("### Results")
191
+
192
+ with gr.Row():
193
+ output_headshot = gr.Image(label="πŸ’Ό Professional Headshot", type="pil")
194
+ output_passport = gr.Image(label="πŸ›‚ Passport Photo", type="pil")
195
+ output_avatar = gr.Image(label="🎭 AI Avatar", type="pil")
196
+
197
+ # Process button
198
+ process_btn.click(
199
+ fn=process_all,
200
+ inputs=input_image,
201
+ outputs=[output_headshot, output_passport, output_avatar]
202
+ )
203
+
204
+ # Examples
205
+ gr.Examples(
206
+ examples=[], # Add example image paths if available
207
+ inputs=input_image
208
+ )
209
+
210
+ gr.Markdown(
211
+ """
212
+ ---
213
+ ### Features
214
+ - πŸ’Ό **Professional Headshots**: Perfect for LinkedIn and business profiles
215
+ - πŸ›‚ **Passport Photos**: Standard 600x600px with white background
216
+ - 🎭 **AI Avatars**: Stylized versions for social media
217
+ - ⚑ **GPU-Accelerated**: Fast processing with GFPGAN enhancement
218
+
219
+ Β© 2025 Vijay S. Chaudhari | Powered by ZeroGPU πŸš€
220
+ """
221
+ )
222
+
223
+ # Launch
224
+ if __name__ == "__main__":
225
+ demo.queue(max_size=20)
226
+ demo.launch()
app.py CHANGED
@@ -138,23 +138,21 @@ def create_passport(img: Image.Image) -> Image.Image:
138
 
139
  @spaces.GPU
140
  def create_avatar(img: Image.Image) -> Image.Image:
141
- """Stylized AI avatar"""
142
  # Enhance face
143
  img_enhanced = enhance_face(img)
144
 
145
  # Resize for SD (512x512)
146
  img_resized = img_enhanced.convert("RGB").resize((512, 512))
147
 
148
- # Stylize with SD prompt
149
  #prompt = "highly detailed, digital portrait, professional lighting, cinematic style, artistic AI avatar"
150
  #prompt = "stylized yet realistic portrait, balanced lighting, subtle gradient background, sharp focus on face"
151
  #prompt = "studio portrait, even lighting, neutral background, realistic skin, confident pose"
152
- prompt = "realistic professional headshot, soft studio lighting, neutral background, crisp details, natural skin tone"
153
-
154
-
155
 
156
  with torch.autocast("cuda"):
157
- result = sd_pipe(prompt=prompt, image=img_resized, strength=0.4, guidance_scale=5.0)
158
 
159
  avatar = result.images[0]
160
 
@@ -176,37 +174,80 @@ with gr.Blocks(theme=gr.themes.Soft(), title="FaceForge AI") as demo:
176
  gr.Markdown(
177
  """
178
  # 🎨 FaceForge AI
179
- ### GPU-Accelerated Professional Headshot & Avatar Generator
180
- Upload your photo and generate professional headshots, passport photos, and AI avatars instantly!
181
  """
182
  )
183
-
 
 
 
 
 
 
 
 
184
  with gr.Row():
185
- with gr.Column():
186
  input_image = gr.Image(type="pil", label="πŸ“· Upload Your Photo")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  process_btn = gr.Button("✨ Generate All Images", variant="primary", size="lg")
188
-
189
- with gr.Column():
190
  gr.Markdown("### Results")
191
-
192
- with gr.Row():
193
- output_headshot = gr.Image(label="πŸ’Ό Professional Headshot", type="pil")
194
- output_passport = gr.Image(label="πŸ›‚ Passport Photo", type="pil")
195
- output_avatar = gr.Image(label="🎭 AI Avatar", type="pil")
196
-
197
- # Process button
 
 
 
 
 
 
 
 
198
  process_btn.click(
199
- fn=process_all,
200
- inputs=input_image,
201
  outputs=[output_headshot, output_passport, output_avatar]
202
  )
203
 
204
- # Examples
205
- gr.Examples(
206
- examples=[], # Add example image paths if available
207
- inputs=input_image
208
- )
209
-
210
  gr.Markdown(
211
  """
212
  ---
 
138
 
139
  @spaces.GPU
140
  def create_avatar(img: Image.Image) -> Image.Image:
141
+ """Stylized AI avatar using Stable Diffusion Img2Img with user inputs"""
142
  # Enhance face
143
  img_enhanced = enhance_face(img)
144
 
145
  # Resize for SD (512x512)
146
  img_resized = img_enhanced.convert("RGB").resize((512, 512))
147
 
148
+ # Stylize with SD prompt. We are selecting these from UI now.
149
  #prompt = "highly detailed, digital portrait, professional lighting, cinematic style, artistic AI avatar"
150
  #prompt = "stylized yet realistic portrait, balanced lighting, subtle gradient background, sharp focus on face"
151
  #prompt = "studio portrait, even lighting, neutral background, realistic skin, confident pose"
152
+ #prompt = "realistic professional headshot, soft studio lighting, neutral background, crisp details, natural skin tone"
 
 
153
 
154
  with torch.autocast("cuda"):
155
+ result = sd_pipe(prompt=prompt, image=img_resized, strength=strength, guidance_scale=guidance_scale)
156
 
157
  avatar = result.images[0]
158
 
 
174
  gr.Markdown(
175
  """
176
  # 🎨 FaceForge AI
177
+ ### GPU-Accelerated Professional Headshot & Avatar Generator
178
+ Upload your photo and choose or customize how your AI avatar is generated.
179
  """
180
  )
181
+
182
+ # --- Define a mapping: Short Label -> Full Prompt Text ---
183
+ PROMPT_MAP = {
184
+ "🎬 Cinematic Portrait": "highly detailed, digital portrait, professional lighting, cinematic style, artistic AI avatar",
185
+ "🎨 Stylized Realism": "stylized yet realistic portrait, balanced lighting, subtle gradient background, sharp focus on face",
186
+ "🏒 Studio Professional": "studio portrait, even lighting, neutral background, realistic skin, confident pose",
187
+ "🀡 Natural Headshot": "realistic professional headshot, soft studio lighting, neutral background, crisp details, natural skin tone"
188
+ }
189
+
190
  with gr.Row():
191
+ with gr.Column(scale=1):
192
  input_image = gr.Image(type="pil", label="πŸ“· Upload Your Photo")
193
+
194
+ gr.Markdown("### βš™οΈ Avatar Generation Settings")
195
+
196
+ # Dropdown shows short labels only
197
+ preset_prompt = gr.Dropdown(
198
+ label="🎨 Choose Avatar Style Preset",
199
+ choices=list(PROMPT_MAP.keys()),
200
+ value="🀡 Natural Headshot"
201
+ )
202
+
203
+ # Optional custom prompt box for flexibility
204
+ custom_prompt = gr.Textbox(
205
+ label="✏️ Custom Prompt (optional)",
206
+ placeholder="Enter your own prompt or leave blank to use preset...",
207
+ lines=2
208
+ )
209
+
210
+ strength_slider = gr.Slider(
211
+ label="πŸŽ›οΈ Style Strength (0.0 = keep original, 1.0 = full restyle)",
212
+ minimum=0.1,
213
+ maximum=1.0,
214
+ value=0.45,
215
+ step=0.05
216
+ )
217
+
218
+ guidance_slider = gr.Slider(
219
+ label="🎯 Prompt Guidance Scale (higher = more prompt influence)",
220
+ minimum=1.0,
221
+ maximum=10.0,
222
+ value=5.5,
223
+ step=0.5
224
+ )
225
+
226
  process_btn = gr.Button("✨ Generate All Images", variant="primary", size="lg")
227
+
228
+ with gr.Column(scale=1):
229
  gr.Markdown("### Results")
230
+ output_headshot = gr.Image(label="πŸ’Ό Professional Headshot", type="pil")
231
+ output_passport = gr.Image(label="πŸ›‚ Passport Photo", type="pil")
232
+ output_avatar = gr.Image(label="🎭 AI Avatar", type="pil")
233
+
234
+ # --- Updated process function mapping with label β†’ full prompt translation ---
235
+ def process_all_with_params(img, preset_label, custom, strength, guidance):
236
+ # Map the selected label to its full prompt text
237
+ preset_prompt = PROMPT_MAP[preset_label]
238
+ # Use custom prompt if provided, otherwise fallback to preset
239
+ final_prompt = custom.strip() if custom and custom.strip() != "" else preset_prompt
240
+ headshot = create_headshot(img)
241
+ passport = create_passport(img)
242
+ avatar = create_avatar(img, final_prompt, strength, guidance)
243
+ return headshot, passport, avatar
244
+
245
  process_btn.click(
246
+ fn=process_all_with_params,
247
+ inputs=[input_image, preset_prompt, custom_prompt, strength_slider, guidance_slider],
248
  outputs=[output_headshot, output_passport, output_avatar]
249
  )
250
 
 
 
 
 
 
 
251
  gr.Markdown(
252
  """
253
  ---
app.py.orig DELETED
@@ -1,14 +0,0 @@
1
- import gradio as gr
2
- import spaces
3
- import torch
4
-
5
- zero = torch.Tensor([0]).cuda()
6
- print(zero.device) # <-- 'cpu' πŸ€”
7
-
8
- @spaces.GPU
9
- def greet(n):
10
- print(zero.device) # <-- 'cuda:0' πŸ€—
11
- return f"Hello {zero + n} Tensor"
12
-
13
- demo = gr.Interface(fn=greet, inputs=gr.Number(), outputs=gr.Text())
14
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirement.txt.bk DELETED
@@ -1,34 +0,0 @@
1
- # ---------- Core AI / Diffusion Stack ----------
2
- opencv-python-headless==4.9.0.80
3
- torch==2.2.1
4
- torchvision==0.17.1
5
- torchaudio==2.2.1
6
- diffusers==0.27.2
7
- transformers==4.39.0
8
- accelerate==0.28.0
9
- safetensors==0.4.2
10
-
11
- # ---------- Image Enhancement / Face Models ----------
12
- gfpgan==1.3.8
13
- realesrgan==0.3.0
14
- basicsr==1.4.2
15
- facexlib==0.3.0
16
-
17
- # ---------- Utility / Image Processing ----------
18
- opencv-python-headless==4.9.0.80
19
- rembg==2.0.57
20
- Pillow==10.2.0
21
- numpy==1.26.4
22
- torchvision==0.17.1
23
- torch==2.2.1
24
- torchaudio==2.2.1
25
-
26
- # ---------- Gradio / Hugging Face Runtime ----------
27
- gradio==4.39.0
28
- spaces==0.24.0
29
- huggingface-hub==0.24.0
30
-
31
- # ---------- Optional Stability / Safety ----------
32
- einops==0.7.0
33
- timm==0.9.12
34
-