# JoyAI-Image-Edit-Plus

[JoyAI-Image](https://github.com/jd-opensource/JoyAI-Image) é um modelo de fundação multimodal unificado para compreensão de imagens, geração de imagens a partir de texto e edição de imagens guiada por instruções. Ele combina um Modelo de Linguagem Grande Multimodal (MLLM) de 8B com um Transformer de Difusão Multimodal (MMDiT) de 16B.

JoyAI-Image-Edit-Plus é um modelo de edição guiado por instruções para múltiplas imagens que aceita **várias imagens de referência** e uma instrução de texto para gerar uma nova imagem que combina elementos das referências de acordo com a instrução. Ele suporta de 1 a 5 imagens de referência por amostra.

| Model | Descrição | Download |
|:-----:|:-----------:|:--------:|
| JoyAI-Image-Edit-Plus | Edição guiada por instruções com múltiplas imagens e composição de elementos a partir de múltiplas referências | [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)
```

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

**Parâmetros:**

scheduler ([FlowMatchEulerDiscreteScheduler](/docs/diffusers/v0.43.0/pt/api/schedulers/flow_match_euler_discrete#diffusers.FlowMatchEulerDiscreteScheduler)) : Um scheduler a ser usado em combinação com `transformer` para desruidar os latentes da imagem codificada.

vae ([AutoencoderKLWan](/docs/diffusers/v0.43.0/pt/api/models/autoencoder_kl_wan#diffusers.AutoencoderKLWan)) : Modelo de Variational Auto-Encoder (VAE) para codificar e decodificar imagens para e a partir de representações latentes.

text_encoder (`Qwen3VLForConditionalGeneration`) : Codificador de texto multimodal para codificação de prompts com compreensão de imagens embutidas.

tokenizer (`Qwen2Tokenizer`) : Tokenizador para processamento de texto.

transformer ([JoyImageEditPlusTransformer3DModel](/docs/diffusers/v0.43.0/pt/api/models/transformer_joyimage_edit_plus#diffusers.JoyImageEditPlusTransformer3DModel)) : Arquitetura de Transformer condicional (MMDiT) para desruidar os latentes da imagem codificada.

processor (`Qwen3VLProcessor`) : Processador para entradas multimodais (texto + imagens).

text_token_max_length (`int`, padrão `2048`) : Comprimento máximo de tokens para a codificação de texto.

Pipeline de difusão para edição guiada por instruções de múltiplas imagens usando JoyImage Edit Plus.

Suporta múltiplas imagens de referência com diferentes resoluções. Cada imagem de referência é codificada independentemente pelo VAE e convertida em patches, depois concatenada com os patches de ruído do alvo para a remoção de ruído conjunta.

#### __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)
```

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

**Parâmetros:**

images (`list[Image.Image]` ou `list[list[Image.Image]]`, *opcional*) : Imagens de referência para edição. Cada imagem pode ter uma resolução diferente. Se uma lista plana for fornecida, ela é tratada como uma única amostra com múltiplas referências.

prompt (`str` ou `list[str]`, *opcional*) : O prompt ou os prompts para orientar a geração da imagem. Se não definido, é necessário passar `prompt_embeds` em vez disso.

height (`int`, *opcional*) : A altura em pixels da imagem gerada. Se `None`, determinada a partir da última imagem de referência.

width (`int`, *opcional*) : A largura em pixels da imagem gerada. Se `None`, determinada a partir da última imagem de referência.

num_inference_steps (`int`, *opcional*, padrão `30`) : O número de etapas de desruidamento. Mais etapas de desruidamento geralmente resultam em uma imagem de maior qualidade, em detrimento de uma inferência mais lenta.

timesteps (`list[int]`, *opcional*) : Passos de tempo personalizados para usar no processo de desruido. Se não definido, é usado espaçamento igual.

sigmas (`list[float]`, *opcional*) : Sigmas personalizados para usar no processo de desruidamento.

guidance_scale (`float`, *opcional*, padrão `4.0`) : Escala de orientação sem classificador. Valores mais altos incentivam o modelo a gerar imagens mais alinhadas com o `prompt` em detrimento de uma menor qualidade de imagem.

negative_prompt (`str` ou `list[str]`, *opcional*) : O prompt ou os prompts que não devem orientar a geração da imagem. Se não definido, um prompt em branco é usado para a orientação sem classificador.

generator (`torch.Generator` ou `list[torch.Generator]`, *opcional*) : Um ou uma lista de [geradores do torch](https://pytorch.org/docs/stable/generated/torch.Generator.html) para tornar a geração determinística.

latents (`torch.Tensor`, *opcional*) : Latentes ruidosos pré-gerados para serem usados como entradas para a geração de imagens.

prompt_embeds (`torch.Tensor`, *opcional*) : Incorporações de texto pré-geradas. Pode ser usado para ajustar facilmente as entradas de texto.

prompt_embeds_mask (`torch.Tensor`, *opcional*) : Máscara de atenção para embeddings de texto pré-gerados.

negative_prompt_embeds (`torch.Tensor`, *opcional*) : Embeddings de texto negativo pré-gerados.

negative_prompt_embeds_mask (`torch.Tensor`, *opcional*) : Máscara de atenção para embeddings de texto negativo pré-gerados.

output_type (`str`, *opcional*, padrão `"pil"`) : O formato de saída da imagem gerada. Escolha entre `"pil"` (`PIL.Image.Image`), `"np"` (`np.ndarray`), `"pt"` (`torch.Tensor`) ou `"latent"` para saída latente bruta.

return_dict (`bool`, *opcional*, padrão `True`) : Se deve ou não retornar um [JoyImageEditPlusPipelineOutput](/docs/diffusers/v0.43.0/pt/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput) em vez de uma tupla simples.

callback_on_step_end (`Callable`, *opcional*) : Uma função chamada no final de cada etapa de desruidamento com os argumentos: o pipeline, o índice da etapa, o timestep e um dicionário de entradas de tensor do callback.

callback_on_step_end_tensor_inputs (`list[str]`, *opcional*, padrão `["latents"]`) : A lista de entradas de tensor para a função `callback_on_step_end`.

max_sequence_length (`int`, *opcional*, padrão `4096`) : Comprimento máximo da sequência para o codificador de texto.

**Retorna:** [JoyImageEditPlusPipelineOutput](/docs/diffusers/v0.43.0/pt/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput) ou `tuple`

Se `return_dict` for `True`, [JoyImageEditPlusPipelineOutput](/docs/diffusers/v0.43.0/pt/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput) é retornado; caso contrário, uma `tuple` é retornada, onde o primeiro elemento é uma lista de imagens geradas.

Função invocada ao chamar o pipeline para geração.

Exemplos:
```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)
```

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

Codifique prompts com tokens inline por meio do processador 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)
```

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

**Parâmetros:**

latents : Ruído pré-computado opcional para o slot de destino. Formato `(B, C, 1, H', W')`, onde `H'` e `W'` são as dimensões do espaço latente. Quando `None`, um ruído aleatório é amostrado.

**Retorna:** `padded_latents`

[B, max_patches, C, pt, ph, pw] target_mask: [B, max_patches] (True para patches de destino) shape_list: lista por amostra de tuplas (t, h, w) para cada componente

Prepare um tensor latente 6D com preenchimento (padding) contendo o ruído alvo + os latentes da imagem de referência.

## JoyImageEditPlusPipelineOutput[[diffusers.JoyImageEditPlusPipelineOutput]]

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

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

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

Classe de saída para pipelines de edição de múltiplas imagens do JoyImage Edit Plus.

