Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 7.3k
[Modular] Qwen#12220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
[Modular] Qwen #12220
Changes from all commits
3bd289ffa1a9cd44e058cff06e9549e683ff72763c57a1bc65fbc817100122c84dbf170a9f7f94483400a56280630faada2d5d876b89cc408dce330d16b7b9dd8d0f62c0572978f00387bf9730cd3a6a65ecbbffef66598eed3ae0a95651a4efac2c1668c775b408faa7414e6675ae146bf38c80e9c496f97e24a70841199c5830eFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -523,6 +523,7 @@ def resize( | ||
| size=(height, width), | ||
| ) | ||
| image = self.pt_to_numpy(image) | ||
| return image | ||
| def binarize(self, image: PIL.Image.Image) -> PIL.Image.Image: | ||
| @@ -838,6 +839,137 @@ def apply_overlay( | ||
| return image | ||
| class InpaintProcessor(ConfigMixin): | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really nice! (not for this PR, we could attempt to have an example of the processor for an inpaint pipeline) | ||
| """ | ||
| Image processor for inpainting image and mask. | ||
| """ | ||
| config_name = CONFIG_NAME | ||
| @register_to_config | ||
| def __init__( | ||
| self, | ||
| do_resize: bool = True, | ||
| vae_scale_factor: int = 8, | ||
| vae_latent_channels: int = 4, | ||
| resample: str = "lanczos", | ||
| reducing_gap: int = None, | ||
| do_normalize: bool = True, | ||
| do_binarize: bool = False, | ||
| do_convert_grayscale: bool = False, | ||
| mask_do_normalize: bool = False, | ||
| mask_do_binarize: bool = True, | ||
| mask_do_convert_grayscale: bool = True, | ||
| ): | ||
| super().__init__() | ||
| self._image_processor = VaeImageProcessor( | ||
| do_resize=do_resize, | ||
| vae_scale_factor=vae_scale_factor, | ||
| vae_latent_channels=vae_latent_channels, | ||
| resample=resample, | ||
| reducing_gap=reducing_gap, | ||
| do_normalize=do_normalize, | ||
| do_binarize=do_binarize, | ||
| do_convert_grayscale=do_convert_grayscale, | ||
| ) | ||
| self._mask_processor = VaeImageProcessor( | ||
| do_resize=do_resize, | ||
| vae_scale_factor=vae_scale_factor, | ||
| vae_latent_channels=vae_latent_channels, | ||
| resample=resample, | ||
| reducing_gap=reducing_gap, | ||
| do_normalize=mask_do_normalize, | ||
| do_binarize=mask_do_binarize, | ||
| do_convert_grayscale=mask_do_convert_grayscale, | ||
| ) | ||
| def preprocess( | ||
| self, | ||
| image: PIL.Image.Image, | ||
| mask: PIL.Image.Image = None, | ||
| height: int = None, | ||
| width: int = None, | ||
| padding_mask_crop: Optional[int] = None, | ||
| ) -> Tuple[torch.Tensor, torch.Tensor]: | ||
| """ | ||
| Preprocess the image and mask. | ||
| """ | ||
| if mask is None and padding_mask_crop is not None: | ||
| raise ValueError("mask must be provided if padding_mask_crop is provided") | ||
| # if mask is None, same behavior as regular image processor | ||
| if mask is None: | ||
| return self._image_processor.preprocess(image, height=height, width=width) | ||
| if padding_mask_crop is not None: | ||
| crops_coords = self._image_processor.get_crop_region(mask, width, height, pad=padding_mask_crop) | ||
| resize_mode = "fill" | ||
| else: | ||
| crops_coords = None | ||
| resize_mode = "default" | ||
| processed_image = self._image_processor.preprocess( | ||
| image, | ||
| height=height, | ||
| width=width, | ||
| crops_coords=crops_coords, | ||
| resize_mode=resize_mode, | ||
| ) | ||
| processed_mask = self._mask_processor.preprocess( | ||
| mask, | ||
| height=height, | ||
| width=width, | ||
| resize_mode=resize_mode, | ||
| crops_coords=crops_coords, | ||
| ) | ||
| if crops_coords is not None: | ||
| postprocessing_kwargs = { | ||
| "crops_coords": crops_coords, | ||
| "original_image": image, | ||
| "original_mask": mask, | ||
| } | ||
| else: | ||
| postprocessing_kwargs = { | ||
| "crops_coords": None, | ||
| "original_image": None, | ||
| "original_mask": None, | ||
| } | ||
| return processed_image, processed_mask, postprocessing_kwargs | ||
| def postprocess( | ||
| self, | ||
| image: torch.Tensor, | ||
| output_type: str = "pil", | ||
| original_image: Optional[PIL.Image.Image] = None, | ||
| original_mask: Optional[PIL.Image.Image] = None, | ||
| crops_coords: Optional[Tuple[int, int, int, int]] = None, | ||
| ) -> Tuple[PIL.Image.Image, PIL.Image.Image]: | ||
| """ | ||
| Postprocess the image, optionally apply mask overlay | ||
| """ | ||
| image = self._image_processor.postprocess( | ||
| image, | ||
| output_type=output_type, | ||
| ) | ||
| # optionally apply the mask overlay | ||
| if crops_coords is not None and (original_image is None or original_mask is None): | ||
| raise ValueError("original_image and original_mask must be provided if crops_coords is provided") | ||
| elif crops_coords is not None and output_type != "pil": | ||
| raise ValueError("output_type must be 'pil' if crops_coords is provided") | ||
| elif crops_coords is not None: | ||
| image = [ | ||
| self._image_processor.apply_overlay(original_mask, original_image, i, crops_coords) for i in image | ||
| ] | ||
| return image | ||
| class VaeImageProcessorLDM3D(VaeImageProcessor): | ||
| """ | ||
| Image processor for VAE LDM3D. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -56,6 +56,8 @@ | ||
| ("stable-diffusion-xl", "StableDiffusionXLModularPipeline"), | ||
| ("wan", "WanModularPipeline"), | ||
| ("flux", "FluxModularPipeline"), | ||
| ("qwenimage", "QwenImageModularPipeline"), | ||
| ("qwenimage-edit", "QwenImageEditModularPipeline"), | ||
| ] | ||
| ) | ||
| @@ -64,6 +66,8 @@ | ||
| ("StableDiffusionXLModularPipeline", "StableDiffusionXLAutoBlocks"), | ||
| ("WanModularPipeline", "WanAutoBlocks"), | ||
| ("FluxModularPipeline", "FluxAutoBlocks"), | ||
| ("QwenImageModularPipeline", "QwenImageAutoBlocks"), | ||
| ("QwenImageEditModularPipeline", "QwenImageEditAutoBlocks"), | ||
| ] | ||
| ) | ||
| @@ -133,8 +137,8 @@ def __getattr__(self, name): | ||
| Allow attribute access to intermediate values. If an attribute is not found in the object, look for it in the | ||
| intermediates dict. | ||
| """ | ||
| if name in self.intermediates: | ||
| return self.intermediates[name] | ||
| if name in self.values: | ||
| return self.values[name] | ||
| raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'") | ||
| def __repr__(self): | ||
| @@ -548,8 +552,11 @@ class AutoPipelineBlocks(ModularPipelineBlocks): | ||
| def __init__(self): | ||
| sub_blocks = InsertableDict() | ||
| for block_name, block_cls in zip(self.block_names, self.block_classes): | ||
| sub_blocks[block_name] = block_cls() | ||
| for block_name, block in zip(self.block_names, self.block_classes): | ||
yiyixuxu marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if inspect.isclass(block): | ||
| sub_blocks[block_name] = block() | ||
| else: | ||
| sub_blocks[block_name] = block | ||
| self.sub_blocks = sub_blocks | ||
| if not (len(self.block_classes) == len(self.block_names) == len(self.block_trigger_inputs)): | ||
| raise ValueError( | ||
| @@ -830,7 +837,9 @@ def expected_configs(self): | ||
| return expected_configs | ||
| @classmethod | ||
| def from_blocks_dict(cls, blocks_dict: Dict[str, Any]) -> "SequentialPipelineBlocks": | ||
| def from_blocks_dict( | ||
| cls, blocks_dict: Dict[str, Any], description: Optional[str] = None | ||
| ) -> "SequentialPipelineBlocks": | ||
| """Creates a SequentialPipelineBlocks instance from a dictionary of blocks. | ||
| Args: | ||
| @@ -852,12 +861,19 @@ def from_blocks_dict(cls, blocks_dict: Dict[str, Any]) -> "SequentialPipelineBlo | ||
| instance.block_classes = [block.__class__ for block in sub_blocks.values()] | ||
| instance.block_names = list(sub_blocks.keys()) | ||
| instance.sub_blocks = sub_blocks | ||
| if description is not None: | ||
| instance.description = description | ||
| return instance | ||
| def __init__(self): | ||
| sub_blocks = InsertableDict() | ||
| for block_name, block_cls in zip(self.block_names, self.block_classes): | ||
| sub_blocks[block_name] = block_cls() | ||
| for block_name, block in zip(self.block_names, self.block_classes): | ||
| if inspect.isclass(block): | ||
| sub_blocks[block_name] = block() | ||
| else: | ||
| sub_blocks[block_name] = block | ||
| self.sub_blocks = sub_blocks | ||
| def _get_inputs(self): | ||
| @@ -1280,8 +1296,11 @@ def outputs(self) -> List[str]: | ||
| def __init__(self): | ||
| sub_blocks = InsertableDict() | ||
| for block_name, block_cls in zip(self.block_names, self.block_classes): | ||
| sub_blocks[block_name] = block_cls() | ||
| for block_name, block in zip(self.block_names, self.block_classes): | ||
| if inspect.isclass(block): | ||
| sub_blocks[block_name] = block() | ||
| else: | ||
| sub_blocks[block_name] = block | ||
| self.sub_blocks = sub_blocks | ||
| @classmethod | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my understanding. This one is for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for guiders/hooks