# JoyAI-Image-Edit-Plus

[JoyAI-Image](https://github.com/jd-opensource/JoyAI-Image)는 이미지 이해, 텍스트-이미지 생성, 지시 기반 이미지 편집을 위한 통합 멀티모달 파운데이션 모델입니다. 8B 멀티모달 대규모 언어 모델(MLLM)과 16B 멀티모달 디퓨전 트랜스포머(MMDiT)를 결합합니다.

JoyAI-Image-Edit-Plus는 **여러 참조 이미지**와 텍스트 지시를 받아 지시에 따라 참조 이미지의 요소를 결합한 새로운 이미지를 생성하는 다중 이미지 지시 기반 편집 모델입니다. 샘플당 1~5개의 참조 이미지를 지원합니다.

| 모델 | 설명 | 다운로드 |
|:-----:|:-----------:|:--------:|
| JoyAI-Image-Edit-Plus | 여러 참조 이미지에서 요소를 구성하여 다중 이미지 지시 기반 편집 | [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)
```

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

**매개변수:**

scheduler ([FlowMatchEulerDiscreteScheduler](/docs/diffusers/main/ko/api/schedulers/flow_match_euler_discrete#diffusers.FlowMatchEulerDiscreteScheduler)) : `transformer`와 함께 사용하여 인코딩된 이미지 라텐트를 디노이즈하는 데 사용되는 스케줄러입니다.

vae ([AutoencoderKLWan](/docs/diffusers/main/ko/api/models/autoencoder_kl_wan#diffusers.AutoencoderKLWan)) : 이미지를 잠재 표현으로 인코딩하고 잠재 표현에서 이미지로 디코딩하는 Variational Auto-Encoder (VAE) 모델입니다.

text_encoder (`Qwen3VLForConditionalGeneration`) : 인라인 이미지 이해를 위한 프롬프트 인코딩에 사용되는 멀티모달 텍스트 인코더.

tokenizer (`Qwen2Tokenizer`) : 텍스트 처리를 위한 토크나이저.

transformer ([JoyImageEditPlusTransformer3DModel](/docs/diffusers/main/ko/api/models/transformer_joyimage_edit_plus#diffusers.JoyImageEditPlusTransformer3DModel)) : 인코딩된 이미지 레이턴트를 디노이즈하기 위한 조건부 Transformer (MMDiT) 아키텍처입니다.

processor (`Qwen3VLProcessor`) : 멀티모달 입력(텍스트 + 이미지)을 위한 프로세서

text_token_max_length (`int`, 기본값 `2048`) : 텍스트 인코딩을 위한 최대 토큰 길이입니다.

JoyImage Edit Plus를 사용하여 다중 이미지 지시 기반 편집을 위한 Diffusion 파이프라인.

다양한 해상도를 가진 여러 참조 이미지를 지원합니다. 각 참조 이미지는 독립적으로 VAE 인코딩 및 패치화되며, 이후 목표 노이즈 패치와 연결되어 공동 디노이징에 사용됩니다.

#### __호출__[[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 = None, sigmas: list = 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 = ['latents'], max_sequence_length: int = 4096)
```

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

**매개변수:**

images (`list[Image.Image]` 또는 `list[list[Image.Image]]`, *선택 사항*) : 편집을 위한 참조 이미지입니다. 각 이미지는 서로 다른 해상도를 가질 수 있습니다. 평탄한 리스트가 제공되면 여러 참조를 가진 하나의 샘플로 처리됩니다.

prompt (`str` 또는 `list[str]`, *선택 사항*) : 이미지 생성을 안내할 프롬프트입니다. 정의되지 않은 경우 `prompt_embeds`를 대신 전달해야 합니다.

height (`int`, *선택 사항*) : 생성된 이미지의 픽셀 단위 높이. `None`인 경우 마지막 참조 이미지에서 결정됩니다.

width (`int`, *선택 사항*) : 생성된 이미지의 픽셀 단위 너비입니다. `None`인 경우 마지막 참조 이미지에서 결정됩니다.

num_inference_steps (`int`, *선택 사항*, 기본값 `30`) : 디노이징 단계 수입니다. 디노이징 단계가 많을수록 일반적으로 추론 속도가 느려지는 대신 더 높은 품질의 이미지를 생성합니다.

timesteps (`list[int]`, *선택 사항*) : 노이즈 제거 과정에 사용할 커스텀 타임스텝입니다. 정의되지 않은 경우, 균등 간격이 사용됩니다.

sigmas (`list[float]`, *선택 사항*) : 노이즈 제거 과정에 사용할 커스텀 시그마.

guidance_scale (`float`, *선택 사항*, 기본값 `4.0`) : Classifier-free guidance scale. 값이 높을수록 모델은 이미지 품질이 낮아지는 대신 `prompt`와 더 일치하는 이미지를 생성하도록 유도됩니다.

negative_prompt (`str` 또는 `list[str]`, *선택 사항*) : 이미지 생성을 안내하지 않을 프롬프트입니다. 정의되지 않으면 classifier-free guidance에 빈 프롬프트가 사용됩니다.

generator (`torch.Generator` 또는 `list[torch.Generator]`, *선택 사항*) : 생성을 결정적으로 만들기 위한 [torch generator](https://pytorch.org/docs/stable/generated/torch.Generator.html) 하나 또는 목록.

latents (`torch.Tensor`, *선택 사항*) : 이미지 생성의 입력으로 사용할 사전 생성된 노이즈된 잠재 변수(latents).

prompt_embeds (`torch.Tensor`, *선택 사항*) : 미리 생성된 텍스트 임베딩. 텍스트 입력을 쉽게 조정하는 데 사용할 수 있습니다.

prompt_embeds_mask (`torch.Tensor`, *선택 사항*) : 사전 생성된 텍스트 임베딩에 사용할 어텐션 마스크입니다.

negative_prompt_embeds (`torch.Tensor`, *선택 사항*) : 미리 생성된 부정 텍스트 임베딩.

negative_prompt_embeds_mask (`torch.Tensor`, *선택 사항*) : 사전 생성된 부정 텍스트 임베딩에 사용할 어텐션 마스크입니다.

output_type (`str`, *선택 사항*, 기본값 `"pil"`) : 생성된 이미지의 출력 형식입니다. `"pil"` (`PIL.Image.Image`), `"np"` (`np.ndarray`), `"pt"` (`torch.Tensor`), 또는 원시 latent 출력을 위한 `"latent"` 중 하나를 선택합니다.

return_dict (`bool`, *선택 사항*, 기본값 `True`) : 일반 튜플 대신 [JoyImageEditPlusPipelineOutput](/docs/diffusers/main/ko/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput)을 반환할지 여부.

callback_on_step_end (`Callable`, *선택 사항*) : 각 디노이징 단계의 끝에서 호출되는 함수입니다. 인수는 다음과 같습니다: 파이프라인, 단계 인덱스, 타임스텝, 콜백 텐서 입력의 딕셔너리.

callback_on_step_end_tensor_inputs (`list[str]`, *선택 사항*, 기본값 `["latents"]`) : `callback_on_step_end` 함수의 텐서 입력 목록.

max_sequence_length (`int`, *선택 사항*, 기본값 `4096`) : 텍스트 인코더의 최대 시퀀스 길이입니다.

**반환값:** [JoyImageEditPlusPipelineOutput](/docs/diffusers/main/ko/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput) 또는 `tuple`

`return_dict`가 `True`인 경우 [JoyImageEditPlusPipelineOutput](/docs/diffusers/main/ko/api/pipelines/joyimage_edit_plus#diffusers.JoyImageEditPlusPipelineOutput)가 반환되고, 그렇지 않으면 첫 번째 요소가 생성된 이미지의 목록인 `tuple`이 반환됩니다.

생성을 위해 파이프라인을 호출할 때 호출되는 함수.

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

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

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

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

**매개변수:**

latents : 대상 슬롯에 사용할 선택적 사전 계산된 노이즈. `(B, C, 1, H', W')` 모양이며, 여기서 `H'`와 `W'`는 잠재 공간의 차원입니다. `None`인 경우 무작위 노이즈가 샘플링됩니다.

**반환값:** `padded_latents`

[B, max_patches, C, pt, ph, pw] target_mask: [B, max_patches] (True for target patches) shape_list: per-sample list of (t, h, w) tuples for each component

6D 패딩된 latent 텐서를 준비합니다. 대상 노이즈와 참조 이미지 latent를 포함합니다.

## JoyImageEditPlusPipelineOutput[[diffusers.JoyImageEditPlusPipelineOutput]]

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

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

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

JoyImage Edit Plus 다중 이미지 편집 파이프라인의 출력 클래스입니다.

