prithivMLmods commited on
Commit
5b603ac
·
verified ·
1 Parent(s): ead1d74

Update app

Browse files
Files changed (1) hide show
  1. app.py +74 -89
app.py CHANGED
@@ -19,7 +19,7 @@ except ImportError:
19
  return func
20
  return decorator
21
 
22
- # --- Custom Theme Setup ---
23
  colors.steel_blue = colors.Color(
24
  name="steel_blue",
25
  c50="#EBF3F8",
@@ -92,9 +92,16 @@ steel_blue_theme = SteelBlueTheme()
92
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
93
 
94
  print("CUDA_VISIBLE_DEVICES=", os.environ.get("CUDA_VISIBLE_DEVICES"))
 
 
 
 
 
 
95
  print("Using device:", device)
96
 
97
  # --- Imports for Custom Pipeline ---
 
98
  from diffusers import FlowMatchEulerDiscreteScheduler
99
  from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
100
  from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
@@ -102,7 +109,7 @@ from qwenimage.qwen_fa3_processor import QwenDoubleStreamAttnProcessorFA3
102
 
103
  dtype = torch.bfloat16
104
 
105
- # Load Pipeline
106
  pipe = QwenImageEditPlusPipeline.from_pretrained(
107
  "Qwen/Qwen-Image-Edit-2509",
108
  transformer=QwenImageTransformer2DModel.from_pretrained(
@@ -114,35 +121,31 @@ pipe = QwenImageEditPlusPipeline.from_pretrained(
114
  torch_dtype=dtype
115
  ).to(device)
116
 
117
- # --- Load LoRAs ---
118
  print("Loading LoRA adapters...")
119
 
120
- # 1. Lightning (Required for fast 4-step inference)
121
- pipe.load_lora_weights("lightx2v/Qwen-Image-Lightning",
122
- weight_name="Qwen-Image-Lightning-4steps-V2.0-bf16.safetensors",
123
- adapter_name="lightning")
124
-
125
- # 2. Texture Edit
126
- pipe.load_lora_weights("tarn59/apply_texture_qwen_image_edit_2509",
127
- weight_name="apply_texture_v2_qwen_image_edit_2509.safetensors",
128
- adapter_name="texture")
129
 
130
- # 3. Fuse Objects
131
  pipe.load_lora_weights("dx8152/Qwen-Image-Edit-2509-Fusion",
132
  weight_name="溶图.safetensors",
133
- adapter_name="fusion")
134
 
135
- # 4. Face Swap
136
  pipe.load_lora_weights("Alissonerdx/BFS-Best-Face-Swap",
137
  weight_name="bfs_head_v3_qwen_image_edit_2509.safetensors",
138
- adapter_name="faceswap")
 
139
 
140
- # Attempt to set Flash Attention 3
141
  try:
142
  pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
143
  print("Flash Attention 3 Processor set successfully.")
144
  except Exception as e:
145
- print(f"Could not set FA3 processor: {e}. Using default attention.")
146
 
147
  MAX_SEED = np.iinfo(np.int32).max
148
 
@@ -161,6 +164,7 @@ def update_dimensions_on_upload(image):
161
  aspect_ratio = original_width / original_height
162
  new_width = int(new_height * aspect_ratio)
163
 
 
164
  new_width = (new_width // 16) * 16
165
  new_height = (new_height // 16) * 16
166
 
@@ -168,33 +172,32 @@ def update_dimensions_on_upload(image):
168
 
169
  @spaces.GPU(duration=60)
170
  def infer(
171
- image_input,
172
- image_reference,
173
  prompt,
174
- style_choice,
175
  seed,
176
  randomize_seed,
177
  guidance_scale,
178
  steps,
179
  progress=gr.Progress(track_tqdm=True)
180
  ):
181
- if image_input is None:
182
- raise gr.Error("Please upload the Main Input image.")
183
- if image_reference is None:
184
- raise gr.Error("Please upload the Reference/Texture image.")
185
- if not prompt:
186
- raise gr.Error("Please enter a prompt.")
187
-
188
- # Manage Adapters
189
- # We combine the specific style LoRA with the Lightning LoRA for speed
190
- if style_choice == "Texture Edit":
191
- pipe.set_adapters(["texture", "lightning"], adapter_weights=[1.0, 1.0])
192
- elif style_choice == "Fuse Objects":
193
- pipe.set_adapters(["fusion", "lightning"], adapter_weights=[1.0, 1.0])
194
- elif style_choice == "Face Swap":
195
- pipe.set_adapters(["faceswap", "lightning"], adapter_weights=[1.0, 1.0])
196
  else:
197
- pipe.set_adapters(["lightning"], adapter_weights=[1.0])
198
 
199
  if randomize_seed:
200
  seed = random.randint(0, MAX_SEED)
@@ -202,16 +205,11 @@ def infer(
202
  generator = torch.Generator(device=device).manual_seed(seed)
203
  negative_prompt = "worst quality, low quality, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry"
204
 
205
- # Prepare Images
206
- img1 = image_input.convert("RGB")
207
- img2 = image_reference.convert("RGB")
208
-
209
- # Resize logic based on the main input image
210
- width, height = update_dimensions_on_upload(img1)
211
 
212
- # Pass list of images [Content, Reference]
213
  result = pipe(
214
- image=[img1, img2],
215
  prompt=prompt,
216
  negative_prompt=negative_prompt,
217
  height=height,
@@ -224,29 +222,20 @@ def infer(
224
  return result, seed
225
 
226
  @spaces.GPU(duration=60)
227
- def infer_example(image_input, image_reference, prompt, style_choice):
228
- if image_input is None or image_reference is None:
229
  return None, 0
230
-
231
- guidance_scale = 1.0
232
- steps = 4 # Default fast steps
233
-
234
- result, seed = infer(
235
- image_input,
236
- image_reference,
237
- prompt,
238
- style_choice,
239
- 0, # seed
240
- True, # randomize
241
- guidance_scale,
242
- steps
243
- )
244
  return result, seed
245
 
 
246
  css="""
247
  #col-container {
248
  margin: 0 auto;
249
- max-width: 1100px;
250
  }
251
  #main-title h1 {font-size: 2.1em !important;}
252
  """
@@ -254,55 +243,51 @@ css="""
254
  with gr.Blocks(css=css, theme=steel_blue_theme) as demo:
255
  with gr.Column(elem_id="col-container"):
256
  gr.Markdown("# **Qwen-Image-Edit-2509-LoRAs-Fast-Fusion**", elem_id="main-title")
257
- gr.Markdown("Perform advanced dual-image editing: Texture Transfer, Object Fusion, and Face Swapping using [Qwen-Image-Edit](https://huggingface.co/Qwen/Qwen-Image-Edit-2509) LoRAs.")
258
 
259
  with gr.Row(equal_height=True):
260
- with gr.Column(scale=1):
261
- image_input = gr.Image(label="1. Main Content / Source", type="pil", height=250)
262
- image_reference = gr.Image(label="2. Reference / Texture / Face", type="pil", height=250)
263
 
264
- style_choice = gr.Dropdown(
265
- label="Choose Editing Style",
266
- choices=["Texture Edit", "Fuse Objects", "Face Swap"],
267
- value="Texture Edit",
268
- interactive=True
269
- )
270
-
271
  prompt = gr.Text(
272
- label="Prompt",
273
  show_label=True,
274
- placeholder="e.g., Apply wood texture to the bottle...",
275
  )
276
 
277
- run_button = gr.Button("Generate Fusion", variant="primary")
278
 
279
- with gr.Column(scale=1):
280
- output_image = gr.Image(label="Output Image", interactive=False, format="png", height=550)
281
 
282
- with gr.Accordion("Advanced Settings", open=False, visible=True):
 
 
 
 
 
 
283
  seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
284
  randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
285
- guidance_scale = gr.Slider(label="Guidance Scale", minimum=1.0, maximum=10.0, step=0.1, value=1.0)
286
- steps = gr.Slider(label="Inference Steps", minimum=1, maximum=50, step=1, value=4)
287
 
288
  gr.Examples(
289
  examples=[
290
- # Format: [Img1, Img2, Prompt, Style] - Assuming example files exist in 'examples/'
291
- # You will need to ensure these files exist or remove this block
292
- ["examples/coffee_mug.png", "examples/wood_texture.png", "Apply wood texture to the mug", "Texture Edit"],
293
- ["examples/bg_room.jpg", "examples/cat.png", "A cat sitting in the living room", "Fuse Objects"],
294
- ["examples/target_person.jpg", "examples/source_face.jpg", "Swap the face", "Face Swap"],
295
  ],
296
- inputs=[image_input, image_reference, prompt, style_choice],
297
  outputs=[output_image, seed],
298
  fn=infer_example,
299
  cache_examples=False,
300
- label="Examples (Ensure local files exist)"
301
  )
302
 
303
  run_button.click(
304
  fn=infer,
305
- inputs=[image_input, image_reference, prompt, style_choice, seed, randomize_seed, guidance_scale, steps],
306
  outputs=[output_image, seed]
307
  )
308
 
 
19
  return func
20
  return decorator
21
 
22
+ # --- Custom Theme Setup (Steel Blue) ---
23
  colors.steel_blue = colors.Color(
24
  name="steel_blue",
25
  c50="#EBF3F8",
 
92
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
93
 
94
  print("CUDA_VISIBLE_DEVICES=", os.environ.get("CUDA_VISIBLE_DEVICES"))
95
+ print("torch.__version__ =", torch.__version__)
96
+ print("cuda available:", torch.cuda.is_available())
97
+ if torch.cuda.is_available():
98
+ print("current device:", torch.cuda.current_device())
99
+ print("device name:", torch.cuda.get_device_name(torch.cuda.current_device()))
100
+
101
  print("Using device:", device)
102
 
103
  # --- Imports for Custom Pipeline ---
104
+ # Note: These require the local 'qwenimage' folder to be present
105
  from diffusers import FlowMatchEulerDiscreteScheduler
106
  from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
107
  from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
 
109
 
110
  dtype = torch.bfloat16
111
 
112
+ # Load Pipeline with Rapid-AIO Transformer (Fast Version)
113
  pipe = QwenImageEditPlusPipeline.from_pretrained(
114
  "Qwen/Qwen-Image-Edit-2509",
115
  transformer=QwenImageTransformer2DModel.from_pretrained(
 
121
  torch_dtype=dtype
122
  ).to(device)
123
 
124
+ # --- Load Fusion/Texture/Face-Swap LoRAs ---
125
  print("Loading LoRA adapters...")
126
 
127
+ # 1. Texture Edit
128
+ pipe.load_lora_weights("tarn59/apply_texture_qwen_image_edit_2509",
129
+ weight_name="apply_texture_v2_qwen_image_edit_2509.safetensors",
130
+ adapter_name="texture-edit")
 
 
 
 
 
131
 
132
+ # 2. Fuse Objects (Note: Filename contains non-ascii characters, handled as string)
133
  pipe.load_lora_weights("dx8152/Qwen-Image-Edit-2509-Fusion",
134
  weight_name="溶图.safetensors",
135
+ adapter_name="fuse-objects")
136
 
137
+ # 3. Face Swap
138
  pipe.load_lora_weights("Alissonerdx/BFS-Best-Face-Swap",
139
  weight_name="bfs_head_v3_qwen_image_edit_2509.safetensors",
140
+ adapter_name="face-swap")
141
+
142
 
143
+ # Attempt to set Flash Attention 3 (Requires H100 or compatible setup)
144
  try:
145
  pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
146
  print("Flash Attention 3 Processor set successfully.")
147
  except Exception as e:
148
+ print(f"Could not set FA3 processor (likely hardware mismatch): {e}. Using default attention.")
149
 
150
  MAX_SEED = np.iinfo(np.int32).max
151
 
 
164
  aspect_ratio = original_width / original_height
165
  new_width = int(new_height * aspect_ratio)
166
 
167
+ # Ensure dimensions are multiples of 16 (safer for transformers)
168
  new_width = (new_width // 16) * 16
169
  new_height = (new_height // 16) * 16
170
 
 
172
 
173
  @spaces.GPU(duration=60)
174
  def infer(
175
+ input_image,
 
176
  prompt,
177
+ lora_adapter,
178
  seed,
179
  randomize_seed,
180
  guidance_scale,
181
  steps,
182
  progress=gr.Progress(track_tqdm=True)
183
  ):
184
+ if input_image is None:
185
+ raise gr.Error("Please upload an image to edit.")
186
+
187
+ # Map Dropdown choices to internal Adapter names
188
+ adapters_map = {
189
+ "Texture Edit": "texture-edit",
190
+ "Fuse-Objects": "fuse-objects",
191
+ "Face-Swap": "face-swap",
192
+ }
193
+
194
+ active_adapter = adapters_map.get(lora_adapter)
195
+
196
+ # Reset adapters first, then activate selected
197
+ if active_adapter:
198
+ pipe.set_adapters([active_adapter], adapter_weights=[1.0])
199
  else:
200
+ pipe.set_adapters([], adapter_weights=[])
201
 
202
  if randomize_seed:
203
  seed = random.randint(0, MAX_SEED)
 
205
  generator = torch.Generator(device=device).manual_seed(seed)
206
  negative_prompt = "worst quality, low quality, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry"
207
 
208
+ original_image = input_image.convert("RGB")
209
+ width, height = update_dimensions_on_upload(original_image)
 
 
 
 
210
 
 
211
  result = pipe(
212
+ image=original_image,
213
  prompt=prompt,
214
  negative_prompt=negative_prompt,
215
  height=height,
 
222
  return result, seed
223
 
224
  @spaces.GPU(duration=60)
225
+ def infer_example(input_image, prompt, lora_adapter):
226
+ if input_image is None:
227
  return None, 0
228
+ input_pil = input_image.convert("RGB")
229
+ guidance_scale = 4.0 # Slightly higher default for better adherence
230
+ steps = 30
231
+ result, seed = infer(input_pil, prompt, lora_adapter, 0, True, guidance_scale, steps)
 
 
 
 
 
 
 
 
 
 
232
  return result, seed
233
 
234
+
235
  css="""
236
  #col-container {
237
  margin: 0 auto;
238
+ max-width: 960px;
239
  }
240
  #main-title h1 {font-size: 2.1em !important;}
241
  """
 
243
  with gr.Blocks(css=css, theme=steel_blue_theme) as demo:
244
  with gr.Column(elem_id="col-container"):
245
  gr.Markdown("# **Qwen-Image-Edit-2509-LoRAs-Fast-Fusion**", elem_id="main-title")
246
+ gr.Markdown("Perform advanced image manipulation including Texture editing, Object Fusion, and Face Swapping using specialized [LoRA](https://huggingface.co/models?other=base_model:adapter:Qwen/Qwen-Image-Edit-2509) adapters.")
247
 
248
  with gr.Row(equal_height=True):
249
+ with gr.Column():
250
+ input_image = gr.Gallery(label="Input Images", show_label=False, type="pil", interactive=True)
 
251
 
 
 
 
 
 
 
 
252
  prompt = gr.Text(
253
+ label="Edit Prompt",
254
  show_label=True,
255
+ placeholder="e.g., Change the material to wooden texture...",
256
  )
257
 
258
+ run_button = gr.Button("Edit Image", variant="primary")
259
 
260
+ with gr.Column():
261
+ output_image = gr.Image(label="Output Image", interactive=False, format="png", height=350)
262
 
263
+ with gr.Row():
264
+ lora_adapter = gr.Dropdown(
265
+ label="Choose Editing Style",
266
+ choices=["Texture Edit", "Fuse-Objects", "Face-Swap"],
267
+ value="Texture Edit"
268
+ )
269
+ with gr.Accordion("Advanced Settings", open=False, visible=False):
270
  seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
271
  randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
272
+ guidance_scale = gr.Slider(label="Guidance Scale", minimum=1.0, maximum=10.0, step=0.1, value=4.0)
273
+ steps = gr.Slider(label="Inference Steps", minimum=1, maximum=50, step=1, value=30)
274
 
275
  gr.Examples(
276
  examples=[
277
+ ["examples/texture_sample.jpg", "Change the material of the object to rusted metal texture.", "Texture Edit"],
278
+ ["examples/fusion_sample.jpg", "Fuse the product naturally into the background.", "Fuse-Objects"],
279
+ ["examples/face_sample.jpg", "Swap the face with a cyberpunk robot face.", "Face-Swap"],
 
 
280
  ],
281
+ inputs=[input_image, prompt, lora_adapter],
282
  outputs=[output_image, seed],
283
  fn=infer_example,
284
  cache_examples=False,
285
+ label="Examples (Ensure images exist in 'examples/' folder)"
286
  )
287
 
288
  run_button.click(
289
  fn=infer,
290
+ inputs=[input_image, prompt, lora_adapter, seed, randomize_seed, guidance_scale, steps],
291
  outputs=[output_image, seed]
292
  )
293