# JoyAI-Image-Edit-Plus

[JoyAI-Image](https://github.com/jd-opensource/JoyAI-Image) es un modelo de base multimodal unificado para la comprensión de imágenes, la generación de imágenes a partir de texto y la edición de imágenes guiada por instrucciones. Combina un Modelo de Lenguaje Grande Multimodal (MLLM) de 8B con un Transformer de Difusión Multimodal (MMDiT) de 16B.

JoyAI-Image-Edit-Plus es un modelo de edición guiado por instrucciones para múltiples imágenes que acepta **múltiples imágenes de referencia** y una instrucción de texto para generar una nueva imagen que combine elementos de las referencias según la instrucción. Admite de 1 a 5 imágenes de referencia por muestra.

| Modelo | Descripción | Descargar |
|:-----:|:-----------:|:--------:|
| JoyAI-Image-Edit-Plus | Edición guiada por instrucciones de múltiples imágenes con composición de elementos a partir de varias referencias | [Hugging Face](https://huggingface.co/jdopensource/JoyAI-Image-Edit-Plus-Diffusers) |

```python
import torch
from PIL import Image
from diffusers import JoyImageEditPlusPipeline

pipeline = JoyImageEditPlusPipeline.from_pretrained(
    "jdopensource/JoyAI-Image-Edit-Plus-Diffusers", dtype=torch.bfloat16
)
pipeline.to("cuda")  # or "mps", "xpu", "cpu"

images = [
    Image.open("reference_0.png").convert("RGB"),
    Image.open("reference_1.png").convert("RGB"),
]

target_h, target_w = pipeline.image_processor.get_default_height_width(images[-1])

output = pipeline(
    images=images,
    prompt="Combine the person from the second image with the scene from the first image.",
    negative_prompt="low quality, blurry, deformed",
    height=target_h,
    width=target_w,
    num_inference_steps=30,
    guidance_scale=4.0,
    generator=torch.Generator("cuda").manual_seed(42),
).images[0]
output.save("joyimage_edit_plus_output.png")
```

## JoyImageEditPlusPipeline[[diffusers.JoyImageEditPlusPipeline]]

#### diffusers.JoyImageEditPlusPipeline[[diffusers.JoyImageEditPlusPipeline]]

```python
diffusers.JoyImageEditPlusPipeline(scheduler: FlowMatchEulerDiscreteScheduler, vae: AutoencoderKLWan, text_encoder: Qwen3VLForConditionalGeneration, tokenizer: Qwen2Tokenizer, transformer: JoyImageEditPlusTransformer3DModel, processor: Qwen3VLProcessor, text_token_max_length: int = 2048)
```

[Fuente](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit_plus.py#L129)

**Parámetros:**

scheduler ([FlowMatchEulerDiscreteScheduler](/docs/diffusers/main/es/api/schedulers/flow_match_euler_discrete#diffusers.FlowMatchEulerDiscreteScheduler)) : Un programador para usar en combinación con `transformer` para desruidar los latentes de imagen codificados.

vae ([AutoencoderKLWan](/docs/diffusers/main/es/api/models/autoencoder_kl_wan#diffusers.AutoencoderKLWan)) : Modelo de Autoencoder Variacional (VAE) para codificar y decodificar imágenes hacia y desde representaciones latentes.

text_encoder (`Qwen3VLForConditionalGeneration`) : Codificador de texto multimodal para la codificación de prompts con comprensión de imágenes en línea.

tokenizer (`Qwen2Tokenizer`) : Tokenizador para el procesamiento de texto.

transformer ([JoyImageEditPlusTransformer3DModel](/docs/diffusers/main/es/api/models/transformer_joyimage_edit_plus#diffusers.JoyImageEditPlusTransformer3DModel)) : Arquitectura de Transformer condicional (MMDiT) para desruidar los latentes de imagen codificados.

processor (`Qwen3VLProcessor`) : Procesador para entradas multimodales (texto + imágenes).

text_token_max_length (`int`, por defecto `2048`) : Longitud máxima de tokens para la codificación de texto.

Pipeline de difusión para edición guiada por instrucciones de múltiples imágenes usando JoyImage Edit Plus.

Admite múltiples imágenes de referencia con diferentes resoluciones. Cada imagen de referencia se codifica de forma independiente con VAE y se divide en parches, y luego se concatena con los parches de ruido objetivo para el desruido conjunto.

#### __call__[[diffusers.JoyImageEditPlusPipeline.__call__]]

```python
__call__(images: list[PIL.Image.Image] | list[list[PIL.Image.Image]] | None = None, prompt: str | list[str] = None, height: int | None = None, width: int | None = None, num_inference_steps: int = 30, timesteps: list[int] = None, sigmas: list[float] = None, guidance_scale: float = 4.0, negative_prompt: str | list[str] | None = None, generator: typing.Union[torch.Generator, list[torch.Generator], NoneType] = None, latents: typing.Optional[torch.Tensor] = None, prompt_embeds: typing.Optional[torch.Tensor] = None, prompt_embeds_mask: typing.Optional[torch.Tensor] = None, negative_prompt_embeds: typing.Optional[torch.Tensor] = None, negative_prompt_embeds_mask: typing.Optional[torch.Tensor] = None, output_type: str | None = 'pil', return_dict: bool = True, callback_on_step_end: typing.Union[typing.Callable[[int, int, dict], NoneType], diffusers.callbacks.PipelineCallback, diffusers.callbacks.MultiPipelineCallbacks, NoneType] = None, callback_on_step_end_tensor_inputs: list[str] = ['latents'], max_sequence_length: int = 4096)
```

[Fuente](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit_plus.py#L441)

**Parámetros:**

images (`list[Image.Image]` o `list[list[Image.Image]]`, *opcional*) : Imágenes de referencia para la edición. Cada imagen puede tener una resolución diferente. Si se proporciona una lista plana, se trata como una muestra con múltiples referencias.

prompt (`str` o `list[str]`, *opcional*) : El prompt o los prompts para guiar la generación de la imagen. Si no se define, se debe pasar `prompt_embeds` en su lugar.

height (`int`, *opcional*) : La altura en píxeles de la imagen generada. Si es `None`, se determina a partir de la última imagen de referencia.

width (`int`, *opcional*) : El ancho en píxeles de la imagen generada. Si es `None`, se determina a partir de la última imagen de referencia.

num_inference_steps (`int`, *opcional*, valor predeterminado `30`) : El número de pasos de desruido. Más pasos de desruido suelen conducir a una imagen de mayor calidad a costa de una inferencia más lenta.

timesteps (`list[int]`, *opcional*) : Pasos de tiempo personalizados para usar en el proceso de desruido. Si no se definen, se utiliza un espaciado uniforme.

sigmas (`list[float]`, *opcional*) : Sigmas personalizados para usar en el proceso de desruido.

guidance_scale (`float`, *opcional*, valor predeterminado `4.0`) : Escala de guía sin clasificador. Los valores más altos animan al modelo a generar imágenes más alineadas con el `prompt` a costa de una menor calidad de imagen.

negative_prompt (`str` o `list[str]`, *opcional*) : El prompt o los prompts que no deben guiar la generación de la imagen. Si no se define, se utiliza un prompt en blanco para la guía libre de clasificador.

generator (`torch.Generator` o `list[torch.Generator]`, *opcional*) : Uno o una lista de [generadores de torch](https://pytorch.org/docs/stable/generated/torch.Generator.html) para hacer la generación determinista.

latents (`torch.Tensor`, *opcional*) : Latentes ruidosos pregenerados para usarse como entradas para la generación de imágenes.

prompt_embeds (`torch.Tensor`, *opcional*) : Embeddings de texto pregenerados. Se pueden usar para ajustar fácilmente las entradas de texto.

prompt_embeds_mask (`torch.Tensor`, *opcional*) : Máscara de atención para las incrustaciones de texto pregeneradas.

negative_prompt_embeds (`torch.Tensor`, *opcional*) : Embeddings de texto negativo pregenerados.

negative_prompt_embeds_mask (`torch.Tensor`, *opcional*) : Máscara de atención para los embeddings de texto negativo pregenerados.

output_type (`str`, *opcional*, valor predeterminado `"pil"`) : El formato de salida de la imagen generada. Elija entre `"pil"` (`PIL.Image.Image`), `"np"` (`np.ndarray`), `"pt"` (`torch.Tensor`) o `"latent"` para la salida latente cruda.

return_dict (`bool`, *opcional*, valor predeterminado `True`) : Indica si se debe devolver un [JoyImageEditPlusPipelineOutput](/docs/diffusers/main/es/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput) en lugar de una tupla simple.

callback_on_step_end (`Callable`, *opcional*) : Una función que se llama al final de cada paso de desruido con los siguientes argumentos: el pipeline, el índice del paso, el timestep y un diccionario de entradas de tensor para el callback.

callback_on_step_end_tensor_inputs (`list[str]`, *opcional*, por defecto `["latents"]`) : La lista de entradas de tensor para la función `callback_on_step_end`.

max_sequence_length (`int`, *opcional*, valor predeterminado `4096`) : Longitud máxima de la secuencia para el codificador de texto.

**Devuelve:** [JoyImageEditPlusPipelineOutput](/docs/diffusers/main/es/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput) o `tuple`

Si `return_dict` es `True`, se devuelve [JoyImageEditPlusPipelineOutput](/docs/diffusers/main/es/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput); en caso contrario, se devuelve una `tuple` cuyo primer elemento es una lista de imágenes generadas.

Función invocada al llamar a la pipeline para la generación.

Ejemplos:
```python
>>> import torch
>>> from diffusers import JoyImageEditPlusPipeline
>>> from diffusers.utils import load_image

>>> model_id = "jdopensource/JoyAI-Image-Edit-Plus-Diffusers"
>>> pipe = JoyImageEditPlusPipeline.from_pretrained(model_id, torch_dtype=torch.bfloat16)
>>> pipe.to("cuda")

>>> images = [
...     load_image("dog.png"),
...     load_image("person.png"),
... ]
>>> output = pipe(
...     images=images,
...     prompt="Let the person lovingly play with the dog.",
...     height=1024,
...     width=1024,
...     num_inference_steps=30,
...     guidance_scale=4.0,
...     generator=torch.manual_seed(42),
... )
>>> output.images[0].save("output.png")
```

#### encode_prompt_multiple_images[[diffusers.JoyImageEditPlusPipeline.encode_prompt_multiple_images]]

```python
encode_prompt_multiple_images(prompt: str | list[str], device: typing.Optional[torch.device] = None, images: list[PIL.Image.Image] | None = None, max_sequence_length: int | None = None)
```

[Fuente](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit_plus.py#L229)

Codifica los prompts con tokens en línea mediante el procesador de Qwen3-VL.

#### prepare_latents[[diffusers.JoyImageEditPlusPipeline.prepare_latents]]

```python
prepare_latents(batch_size: int, num_channels_latents: int, height: int, width: int, dtype: dtype, device: device, generator: typing.Union[torch.Generator, list[torch.Generator], NoneType], reference_images: list[list[PIL.Image.Image]] | None = None, latents: typing.Optional[torch.Tensor] = None)
```

[Fuente](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit_plus.py#L274)

**Parámetros:**

latents : Ruido precalculado opcional para el slot objetivo. Forma `(B, C, 1, H', W')` donde `H'` y `W'` son las dimensiones del espacio latente. Cuando es `None`, se muestrea ruido aleatorio.

**Devuelve:** `padded_latents`

[B, max_patches, C, pt, ph, pw] target_mask: [B, max_patches] (True para los parches objetivo) shape_list: lista por muestra de tuplas (t, h, w) para cada componente

Prepara un tensor latente de 6D con relleno que incluye el ruido objetivo y los latentes de la imagen de referencia.

## JoyImageEditPlusPipelineOutput[[diffusers.JoyImageEditPlusPipelineOutput]]

#### diffusers.JoyImageEditPlusPipelineOutput[[diffusers.JoyImageEditPlusPipelineOutput]]

```python
diffusers.JoyImageEditPlusPipelineOutput(images: typing.Union[typing.List[PIL.Image.Image], numpy.ndarray])
```

[Fuente](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/joyimage/pipeline_output.py#L20)

Clase de salida para las tuberías de edición de múltiples imágenes de JoyImage Edit Plus.

