Spaces:
Running on Zero
Running on Zero
Professional Noob commited on
Update qwenimage/pipeline_qwenimage_edit_plus.py
Browse files
qwenimage/pipeline_qwenimage_edit_plus.py
CHANGED
|
@@ -44,7 +44,7 @@ EXAMPLE_DOC_STRING = """
|
|
| 44 |
Examples:
|
| 45 |
```py
|
| 46 |
>>> import torch
|
| 47 |
-
>>> from PIL import Image
|
| 48 |
>>> from diffusers import QwenImageEditPlusPipeline
|
| 49 |
>>> from diffusers.utils import load_image
|
| 50 |
|
|
@@ -67,23 +67,25 @@ CONDITION_IMAGE_SIZE = 384 * 384
|
|
| 67 |
VAE_IMAGE_SIZE = 1024 * 1024
|
| 68 |
|
| 69 |
|
|
|
|
| 70 |
def pad_to_aspect(img: Image.Image, target_w: int, target_h: int) -> Image.Image:
|
| 71 |
-
"""Pad (letterbox) to target aspect ratio without warping
|
| 72 |
return ImageOps.pad(
|
| 73 |
-
img,
|
| 74 |
(int(target_w), int(target_h)),
|
| 75 |
method=Image.Resampling.LANCZOS,
|
| 76 |
color=(0, 0, 0),
|
| 77 |
centering=(0.5, 0.5),
|
| 78 |
)
|
| 79 |
|
|
|
|
| 80 |
def choose_condition_area(canvas_area: int, base_area: int = CONDITION_IMAGE_SIZE) -> int:
|
| 81 |
"""Choose a conditioning target area derived from canvas area with sensible bounds."""
|
| 82 |
-
# Scale conditioning area roughly with canvas, anchored at 384^2 when canvas is ~1MP.
|
| 83 |
scaled = int(canvas_area * (base_area / (1024 * 1024)))
|
| 84 |
return int(min(base_area, max(256 * 256, scaled)))
|
| 85 |
|
| 86 |
|
|
|
|
| 87 |
# Copied from diffusers.pipelines.qwenimage.pipeline_qwenimage.calculate_shift
|
| 88 |
def calculate_shift(
|
| 89 |
image_seq_len,
|
|
@@ -685,42 +687,40 @@ class QwenImageEditPlusPipeline(DiffusionPipeline, QwenImageLoraLoaderMixin):
|
|
| 685 |
|
| 686 |
device = self._execution_device
|
| 687 |
# 3. Preprocess image
|
|
|
|
| 688 |
if image is not None and not (isinstance(image, torch.Tensor) and image.size(1) == self.latent_channels):
|
| 689 |
if not isinstance(image, list):
|
| 690 |
image = [image]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 691 |
condition_image_sizes = []
|
| 692 |
condition_images = []
|
| 693 |
vae_image_sizes = []
|
| 694 |
vae_images = []
|
| 695 |
|
| 696 |
-
#
|
| 697 |
-
# Default: all images. This can be overridden (e.g. extras conditioning-only).
|
| 698 |
if vae_image_indices is None:
|
| 699 |
vae_image_indices = list(range(len(image)))
|
| 700 |
vae_set = set(int(i) for i in vae_image_indices)
|
| 701 |
|
| 702 |
-
# Conditioning resolution: derived from canvas unless explicitly provided.
|
| 703 |
-
canvas_area = int(width) * int(height)
|
| 704 |
-
cond_area = int(condition_area) if condition_area is not None else choose_condition_area(canvas_area)
|
| 705 |
-
cond_w, cond_h = calculate_dimensions(cond_area, float(width) / float(height))
|
| 706 |
-
|
| 707 |
for idx, img in enumerate(image):
|
| 708 |
-
#
|
| 709 |
-
if isinstance(img, Image.Image)
|
| 710 |
-
pil = img.convert("RGB")
|
| 711 |
-
else:
|
| 712 |
-
pil = img
|
| 713 |
|
|
|
|
| 714 |
if pad_to_canvas and isinstance(pil, Image.Image):
|
| 715 |
pil = pad_to_aspect(pil, int(width), int(height))
|
| 716 |
|
| 717 |
-
# Conditioning (VL) path: always include
|
| 718 |
condition_image_sizes.append((cond_w, cond_h))
|
| 719 |
condition_images.append(self.image_processor.resize(pil, cond_h, cond_w))
|
| 720 |
|
| 721 |
-
# VAE
|
| 722 |
if idx in vae_set:
|
| 723 |
-
# IMPORTANT: VAE preprocessing uses the *canvas* size to avoid drift/zoom.
|
| 724 |
vae_image_sizes.append((int(width), int(height)))
|
| 725 |
vae_images.append(self.image_processor.preprocess(pil, int(height), int(width)).unsqueeze(2))
|
| 726 |
|
|
|
|
| 44 |
Examples:
|
| 45 |
```py
|
| 46 |
>>> import torch
|
| 47 |
+
>>> from PIL import Image
|
| 48 |
>>> from diffusers import QwenImageEditPlusPipeline
|
| 49 |
>>> from diffusers.utils import load_image
|
| 50 |
|
|
|
|
| 67 |
VAE_IMAGE_SIZE = 1024 * 1024
|
| 68 |
|
| 69 |
|
| 70 |
+
|
| 71 |
def pad_to_aspect(img: Image.Image, target_w: int, target_h: int) -> Image.Image:
|
| 72 |
+
"""Pad (letterbox) to target aspect ratio without warping."""
|
| 73 |
return ImageOps.pad(
|
| 74 |
+
img.convert("RGB"),
|
| 75 |
(int(target_w), int(target_h)),
|
| 76 |
method=Image.Resampling.LANCZOS,
|
| 77 |
color=(0, 0, 0),
|
| 78 |
centering=(0.5, 0.5),
|
| 79 |
)
|
| 80 |
|
| 81 |
+
|
| 82 |
def choose_condition_area(canvas_area: int, base_area: int = CONDITION_IMAGE_SIZE) -> int:
|
| 83 |
"""Choose a conditioning target area derived from canvas area with sensible bounds."""
|
|
|
|
| 84 |
scaled = int(canvas_area * (base_area / (1024 * 1024)))
|
| 85 |
return int(min(base_area, max(256 * 256, scaled)))
|
| 86 |
|
| 87 |
|
| 88 |
+
|
| 89 |
# Copied from diffusers.pipelines.qwenimage.pipeline_qwenimage.calculate_shift
|
| 90 |
def calculate_shift(
|
| 91 |
image_seq_len,
|
|
|
|
| 687 |
|
| 688 |
device = self._execution_device
|
| 689 |
# 3. Preprocess image
|
| 690 |
+
|
| 691 |
if image is not None and not (isinstance(image, torch.Tensor) and image.size(1) == self.latent_channels):
|
| 692 |
if not isinstance(image, list):
|
| 693 |
image = [image]
|
| 694 |
+
|
| 695 |
+
# Conditioning resolution derived from canvas area (or overridden)
|
| 696 |
+
canvas_area = int(width) * int(height)
|
| 697 |
+
cond_area = int(condition_area) if condition_area is not None else choose_condition_area(canvas_area)
|
| 698 |
+
cond_w, cond_h = calculate_dimensions(cond_area, float(width) / float(height))
|
| 699 |
+
|
| 700 |
condition_image_sizes = []
|
| 701 |
condition_images = []
|
| 702 |
vae_image_sizes = []
|
| 703 |
vae_images = []
|
| 704 |
|
| 705 |
+
# Which images participate in the VAE latent stream (default: all)
|
|
|
|
| 706 |
if vae_image_indices is None:
|
| 707 |
vae_image_indices = list(range(len(image)))
|
| 708 |
vae_set = set(int(i) for i in vae_image_indices)
|
| 709 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 710 |
for idx, img in enumerate(image):
|
| 711 |
+
# Ensure PIL RGB for padding/resize stability
|
| 712 |
+
pil = img.convert("RGB") if isinstance(img, Image.Image) else img
|
|
|
|
|
|
|
|
|
|
| 713 |
|
| 714 |
+
# Strong recommendation: pad to canvas aspect to avoid warping
|
| 715 |
if pad_to_canvas and isinstance(pil, Image.Image):
|
| 716 |
pil = pad_to_aspect(pil, int(width), int(height))
|
| 717 |
|
| 718 |
+
# Conditioning (VL) path: always include, using a canvas-derived size
|
| 719 |
condition_image_sizes.append((cond_w, cond_h))
|
| 720 |
condition_images.append(self.image_processor.resize(pil, cond_h, cond_w))
|
| 721 |
|
| 722 |
+
# VAE path: include only selected indices, and use the *canvas* size
|
| 723 |
if idx in vae_set:
|
|
|
|
| 724 |
vae_image_sizes.append((int(width), int(height)))
|
| 725 |
vae_images.append(self.image_processor.preprocess(pil, int(height), int(width)).unsqueeze(2))
|
| 726 |
|