# JoyAI-Image-Edit-Plus

[JoyAI-Image](https://github.com/jd-opensource/JoyAI-Image) adalah model dasar multimodal terpadu untuk pemahaman gambar, pembuatan gambar dari teks, dan pengeditan gambar yang dipandu instruksi. Model ini menggabungkan Multimodal Large Language Model (MLLM) 8B dengan Multimodal Diffusion Transformer (MMDiT) 16B.

JoyAI-Image-Edit-Plus adalah model pengeditan yang dipandu instruksi untuk multi-gambar, yang menerima **beberapa gambar referensi** dan instruksi teks untuk menghasilkan gambar baru yang menggabungkan elemen dari gambar referensi sesuai dengan instruksi. Model ini mendukung 1–5 gambar referensi per sampel.

| Model | Deskripsi | Unduh |
|:-----:|:-----------:|:--------:|
| JoyAI-Image-Edit-Plus | Pengeditan berbasis instruksi multi-gambar dengan komposisi elemen dari beberapa referensi | [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)
```

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

**Parameter:**

scheduler ([FlowMatchEulerDiscreteScheduler](/docs/diffusers/v0.43.0/id/api/schedulers/flow_match_euler_discrete#diffusers.FlowMatchEulerDiscreteScheduler)) : Penjadwal yang digunakan bersama `transformer` untuk menghilangkan noise pada latens gambar yang telah dikodekan.

vae ([AutoencoderKLWan](/docs/diffusers/v0.43.0/id/api/models/autoencoder_kl_wan#diffusers.AutoencoderKLWan)) : Model Variational Auto-Encoder (VAE) untuk mengodekan dan mendekodekan gambar ke dan dari representasi laten.

text_encoder (`Qwen3VLForConditionalGeneration`) : Encoder teks multimodal untuk enkoding prompt dengan pemahaman gambar inline.

tokenizer (`Qwen2Tokenizer`) : Tokenizer untuk pemrosesan teks.

transformer ([JoyImageEditPlusTransformer3DModel](/docs/diffusers/v0.43.0/id/api/models/transformer_joyimage_edit_plus#diffusers.JoyImageEditPlusTransformer3DModel)) : Arsitektur Conditional Transformer (MMDiT) untuk menghilangkan noise pada latens gambar yang telah dikodekan.

processor (`Qwen3VLProcessor`) : Pemroses untuk input multimodal (teks + gambar).

text_token_max_length (`int`, defaultnya `2048`) : Panjang token maksimum untuk pengkodean teks.

Pipeline difusi untuk pengeditan berbasis instruksi multi-gambar menggunakan JoyImage Edit Plus.

Mendukung beberapa gambar referensi dengan resolusi yang berbeda. Setiap gambar referensi di-VAE-encode dan di-patchify secara independen, kemudian digabungkan dengan patch noise target untuk denoising bersama.

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

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

**Parameter:**

images (`list[Image.Image]` atau `list[list[Image.Image]]`, *opsional*) : Gambar referensi untuk pengeditan. Setiap gambar dapat memiliki resolusi yang berbeda. Jika daftar datar diberikan, daftar tersebut dianggap sebagai satu sampel dengan beberapa referensi.

prompt (`str` atau `list[str]`, *opsional*) : Prompt atau prompt-prompt untuk mengarahkan generasi gambar. Jika tidak didefinisikan, Anda harus meneruskan `prompt_embeds` sebagai gantinya.

height (`int`, *opsional*) : Tinggi gambar yang dihasilkan dalam piksel. Jika `None`, ditentukan dari gambar referensi terakhir.

width (`int`, *opsional*) : Lebar gambar yang dihasilkan dalam piksel. Jika `None`, ditentukan dari gambar referensi terakhir.

num_inference_steps (`int`, *opsional*, defaultnya `30`) : Jumlah langkah denoising. Semakin banyak langkah denoising, biasanya menghasilkan gambar dengan kualitas lebih tinggi, namun dengan biaya inferensi yang lebih lambat.

timesteps (`list[int]`, *opsional*) : Timesteps kustom untuk digunakan dalam proses denoising. Jika tidak didefinisikan, spasi yang sama digunakan.

sigmas (`list[float]`, *opsional*) : Sigma kustom untuk digunakan dalam proses denoising.

guidance_scale (`float`, *opsional*, default `4.0`) : Skala panduan tanpa klasifikasi. Nilai yang lebih tinggi mendorong model untuk menghasilkan gambar yang lebih selaras dengan `prompt` dengan mengorbankan kualitas gambar yang lebih rendah.

negative_prompt (`str` atau `list[str]`, *opsional*) : Prompt atau prompt-prompt yang tidak akan memandu generasi gambar. Jika tidak didefinisikan, prompt kosong digunakan untuk classifier-free guidance.

generator (`torch.Generator` atau `list[torch.Generator]`, *opsional*) : Satu atau daftar [generator torch](https://pytorch.org/docs/stable/generated/torch.Generator.html) untuk membuat proses generasi menjadi deterministik.

latents (`torch.Tensor`, *opsional*) : Laten berisik yang telah dibuat sebelumnya untuk digunakan sebagai input untuk generasi gambar.

prompt_embeds (`torch.Tensor`, *opsional*) : Embedding teks yang sudah dibuat sebelumnya. Dapat digunakan untuk dengan mudah menyesuaikan input teks.

prompt_embeds_mask (`torch.Tensor`, *opsional*) : Attention mask untuk embedding teks yang telah dibuat sebelumnya.

negative_prompt_embeds (`torch.Tensor`, *opsional*) : Embedding teks negatif yang telah dibuat sebelumnya.

negative_prompt_embeds_mask (`torch.Tensor`, *opsional*) : Attention mask untuk embedding teks negatif yang telah dibuat sebelumnya.

output_type (`str`, *opsional*, defaultnya `"pil"`) : Format output dari gambar yang dihasilkan. Pilih antara `"pil"` (`PIL.Image.Image`), `"np"` (`np.ndarray`), `"pt"` (`torch.Tensor`), atau `"latent"` untuk output laten mentah.

return_dict (`bool`, *opsional*, defaultnya `True`) : Apakah akan mengembalikan [JoyImageEditPlusPipelineOutput](/docs/diffusers/v0.43.0/id/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput) alih-alih tuple biasa.

callback_on_step_end (`Callable`, *opsional*) : Fungsi yang dipanggil di akhir setiap langkah denoising dengan argumen: pipeline, indeks langkah, timestep, dan dict dari input tensor callback.

callback_on_step_end_tensor_inputs (`list[str]`, *opsional*, defaultnya `["latents"]`) : Daftar input tensor untuk fungsi `callback_on_step_end`.

max_sequence_length (`int`, *opsional*, defaultnya `4096`) : Panjang maksimum urutan untuk pengkode teks.

**Mengembalikan:** [JoyImageEditPlusPipelineOutput](/docs/diffusers/v0.43.0/id/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput) atau `tuple`

Jika `return_dict` adalah `True`, [JoyImageEditPlusPipelineOutput](/docs/diffusers/v0.43.0/id/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput) dikembalikan, selain itu sebuah `tuple` dikembalikan di mana elemen pertama adalah daftar gambar yang dihasilkan.

Fungsi yang dipanggil saat memanggil pipeline untuk generasi.

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

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

Encode prompt dengan token inline melalui prosesor 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)
```

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

**Parameter:**

latents : Noise yang sudah dihitung sebelumnya secara opsional untuk slot target. Bentuknya `(B, C, 1, H', W')` di mana `H'` dan `W'` adalah dimensi ruang laten. Ketika `None`, noise acak akan diambil.

**Mengembalikan:** `padded_latents`

[B, max_patches, C, pt, ph, pw] target_mask: [B, max_patches] (True untuk patch target) shape_list: daftar per sampel dari tuple (t, h, w) untuk setiap komponen

Siapkan tensor laten bantalan 6D dengan target noise + laten gambar referensi.

## JoyImageEditPlusPipelineOutput[[diffusers.JoyImageEditPlusPipelineOutput]]

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

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

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

Kelas output untuk pipeline pengeditan multi-gambar JoyImage Edit Plus.

