# JoyAI-Image-Edit

[JoyAI-Image](https://github.com/jd-opensource/JoyAI-Image) هو نموذج أساسي متعدد الوسائط موحّد لفهم الصور، وتوليد الصور من النص، وتحرير الصور وفق التعليمات. يجمع بين نموذج لغة كبير متعدد الوسائط (MLLM) بحجم 8B، ومحوّل انتشار متعدد الوسائط (MMDiT) بحجم 16B. مبدأ محوري في JoyAI-Image هو التعاون الدائري المغلق بين الفهم والتوليد والتحرير.

يدعم JoyAI-Image-Edit تحرير الصور بشكل عام بالإضافة إلى قدرات التحرير المكاني التي تشمل تحريك الكائنات، وتدوير الكائنات، والتحكم في الكاميرا.

| النموذج | الوصف | تنزيل |
|:-----:|:-----------:|:--------:|
| JoyAI-Image-Edit | تحرير الصور الموجَّه بالتعليمات مع التلاعب المكاني الدقيق والقابل للتحكم | [Hugging Face](https://huggingface.co/jdopensource/JoyAI-Image-Edit-Diffusers) |

```python
import torch
from diffusers import JoyImageEditPipeline
from diffusers.utils import load_image

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

image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg")
prompt = "Add wings to the astronaut."

output = pipeline(
    image=image,
    prompt=prompt,
    num_inference_steps=40,
    guidance_scale=4.0,
    generator=torch.Generator("cuda").manual_seed(0),
).images[0]
output.save("joyimage_edit_output.png")
```

## التحرير المكاني

يدعم JoyAI-Image ثلاثة أنماط لأوامر التحرير المكاني: **نقل الكائن**، و**تدوير الكائن**، و**التحكم في الكاميرا**. للحصول على أفضل النتائج، اتبع قوالب الأوامر أدناه بأقرب ما يمكن. لمزيد من المعلومات، راجع [SpatialEdit](https://github.com/EasonXiao-888/SpatialEdit).

### حركة الكائن

نقل كائن مستهدف إلى منطقة محددة محاطة بمربع أحمر في الصورة المدخلة.

```text
Move the <object> into the red box and finally remove the red box.
```

### دوران الكائن

تدوير كائن إلى عرض قياسي محدد. القيم المدعومة لـ`<view>`: `front`، `right`، `left`، `rear`، `front right`، `front left`، `rear right`، `rear left`.

```text
Rotate the <object> to show the <view> side view.
```

### التحكم في الكاميرا

غيّر زاوية الكاميرا مع إبقاء المشهد ثلاثي الأبعاد دون تغيير.

```text
Move the camera.
- Camera rotation: Yaw {y_rotation}°, Pitch {p_rotation}°.
- Camera zoom: in/out/unchanged.
- Keep the 3D scene static; only change the viewpoint.
```

## JoyImageEditPipeline[[diffusers.JoyImageEditPipeline]]

#### diffusers.JoyImageEditPipeline[[diffusers.JoyImageEditPipeline]]

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

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit.py#L100)

خط أنابيب الانتشار لتحرير الصور باستخدام بنية JoyImage.

يقوم خط المعالجة بتشفير شروط النص والصورة عبر مشفّر نصوص Qwen3-VL، وإزالة الضوضاء من الكمونيات باستخدام محوّل ثلاثي الأبعاد، وفك ترميز النتيجة باستخدام WAN VAE.

ترتيب تفريغ النموذج: text_encoder -> transformer -> vae.

#### __call__[[diffusers.JoyImageEditPipeline.__call__]]

```python
__call__(image: typing.Union[PIL.Image.Image, numpy.ndarray, torch.Tensor, list[PIL.Image.Image], list[numpy.ndarray], list[torch.Tensor], NoneType] = None, prompt: str | list[str] = None, height: int | None = None, width: int | None = None, num_inference_steps: int = 40, timesteps: typing.List[int] = None, sigmas: typing.List[float] = None, guidance_scale: float = 4.0, negative_prompt: typing.Union[str, typing.List[str], NoneType] = None, num_images_per_prompt: typing.Optional[int] = 1, generator: typing.Union[torch.Generator, typing.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: typing.Optional[str] = 'pil', return_dict: bool = True, callback_on_step_end: typing.Union[typing.Callable[[int, int, typing.Dict], NoneType], diffusers.callbacks.PipelineCallback, diffusers.callbacks.MultiPipelineCallbacks, NoneType] = None, callback_on_step_end_tensor_inputs: typing.List[str] = ['latents'], max_sequence_length: int = 4096, enable_denormalization: bool = True)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit.py#L600)

**المعاملات:**

prompt (*str* أو *List[str]*) : الأمر أو الأوامر الموجِّهة للتوليد.

height (*int*) : ارتفاع المخرجات المولّدة بالبكسل.

width (*int*) : عرض المخرجات المولّدة بالبكسل.

image (*PipelineImageInput*، *اختياري*) : صورة مرجعية تُستخدم للشروط. عند تقديمها، يعمل خط الأنابيب في وضع تحرير الصور مع `num_items=2`.

num_inference_steps (*int*، *optional*، القيمة الافتراضية 40) : عدد خطوات إزالة الضوضاء. تحسّن الخطوات الإضافية الجودة بشكل عام على حساب بطء الاستدلال.

timesteps (*List[int]*، *اختياري*) : خطوات زمنية مخصصة لعملية إزالة الضوضاء. عند تقديمها، يُستنتج `num_inference_steps` من طول القائمة.

sigmas (*List[float]*, *optional*) : Custom sigmas for the denoising process. Mutually exclusive with `timesteps`.

guidance_scale (*float*، *optional*، القيمة الافتراضية 4.0) : مقياس التوجيه الحر من التصنيف.

negative_prompt (*str* أو *List[str]*، *اختياري*) : موجه(ات) سلبية(ة) تُستخدم لكبح المحتوى غير المرغوب فيه.

num_images_per_prompt (*int*، *اختياري*، القيمة الافتراضية 1) : عدد العينات المولّدة لكل موجه.

generator (*torch.Generator* أو *List[torch.Generator]*، *اختياري*) : مولّدات عشوائية (RNG) للعينة الحتمية.

latents (*torch.Tensor*، *اختياري*) : كامنات ضجيج مُولّدة مسبقًا للفتحة المستهدفة. تُسحب من توزيع غاوسي عند عدم تقديمها. يمكن استخدامها لبذر التوليد من متجه ضجيج ابتدائي محدد.

prompt_embeds (*torch.Tensor*، *اختياري*) : تضمينات موجهات محسوبة مسبقًا. عند توفيرها يمكن إهمال `prompt`.

prompt_embeds_mask (*torch.Tensor*، *اختياري*) : قناع الانتباه لـ `prompt_embeds`.

negative_prompt_embeds (*torch.Tensor*، *اختياري*) : تمثيلات مدمجة (embeddings) مُسبقة الحساب للموجّهات السلبية.

negative_prompt_embeds_mask (*torch.Tensor*، *اختياري*) : قناع الانتباه (Attention mask) الخاص بـ `negative_prompt_embeds`.

output_type (*str*، *اختياري*، القيمة الافتراضية `"pil"`) : صيغة الإخراج. مرّر `"latent"` لإرجاع القيم الكامنة الخام.

return_dict (*bool*، *اختياري*، القيمة الافتراضية *True*) : ما إذا كان يجب إرجاع [JoyImageEditPipelineOutput](/docs/diffusers/v0.43.0/ar/api/pipelines/joyimage_edit#diffusers.JoyImageEditPipelineOutput) أو مجرد tensor.

callback_on_step_end (*Callable*، *PipelineCallback*، *MultiPipelineCallbacks*، *اختياري*) : استدعاء يُستدعى في نهاية كل خطوة إزالة ضوضاء، وتوقيعه `(self, step: int, timestep: int, callback_kwargs: Dict)`.

callback_on_step_end_tensor_inputs (*List[str]*، *اختياري*، القيمة الافتراضية `["latents"]`) : مفاتيح المصفوفات (Tensor) المضمنة في `callback_kwargs` لـ `callback_on_step_end`.

max_sequence_length (*int*، *optional*، القيمة الافتراضية 4096) : الحد الأقصى لطول التسلسل لتشفير الاستعلام.

enable_denormalization (*bool*، *اختياري*، القيمة الافتراضية *True*) : إزالة تطبيع الكمّيات الكامنة قبل فك ترميز VAE.

**يعيد:** [*~pipelines.joyimage.JoyImageEditPipelineOutput*] أو *torch.Tensor*

إذا كان `return_dict` هو `True`، تُرجع كائن مخرجات خط الأنابيب الذي يحتوي على الصورة أو الصور المولّدة. وإلا تُرجع متجه الصورة مباشرة.

إنشاء صورة معدّلة مشروطة بصورة مرجعية وموجّه نصي.

أمثلة:
```python
>>> import torch
>>> from diffusers import JoyImageEditPipeline
>>> from diffusers.utils import load_image

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

>>> image = load_image("https://huggingface.co/datasets/diffusers/docs-images/resolve/main/astronaut.jpg")
>>> output = pipe(
...     image=image,  # pass an image for editing; omit for text-to-image generation
...     prompt="Add wings to the astronaut.",
...     num_inference_steps=40,
...     guidance_scale=4.0,
...     generator=torch.manual_seed(0),
... )
>>> output.images[0].save("joyimage_edit.png")
```

#### check_inputs[[diffusers.JoyImageEditPipeline.check_inputs]]

```python
check_inputs(prompt, height, width, negative_prompt = None, prompt_embeds = None, negative_prompt_embeds = None, prompt_embeds_mask = None, negative_prompt_embeds_mask = None, callback_on_step_end_tensor_inputs = None)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit.py#L409)

**يرفع:** ``ValueError``

- ``ValueError`` -- عند أي مجموعة غير صالحة من الحُجج.

تحقق من مدخلات خط الأنابيب قبل المرور الأمامي.

#### denormalize_latents[[diffusers.JoyImageEditPipeline.denormalize_latents]]

```python
denormalize_latents(latent: Tensor)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit.py#L476)

**المعاملات:**

latent : متجه كامن مُطبَّع.

**يعيد:**

الموتر الكامن (Latent tensor) على المقياس المتوقع بواسطة `vae.decode`.

عكس `normalize_latents` لاستعادة مقياس الكمون الأصلي.

#### encode_prompt[[diffusers.JoyImageEditPipeline.encode_prompt]]

```python
encode_prompt(prompt: typing.Union[str, typing.List[str]], device: typing.Optional[torch.device] = None, num_images_per_prompt: int = 1, prompt_embeds: typing.Optional[torch.Tensor] = None, prompt_embeds_mask: typing.Optional[torch.Tensor] = None, max_sequence_length: int = 1024, template_type: str = 'image')
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit.py#L364)

**المعاملات:**

prompt : سلسلة نصية للطلب أو قائمة من سلاسل الطلب.

device : جهاز الهدف.

num_images_per_prompt : عدد المخرجات التي سيتم توليدها لكل موجه.

prompt_embeds : تضمينات موجهات محسوبة مسبقًا.

prompt_embeds_mask : قناع الانتباه للتضمينات المحسوبة مسبقًا.

max_sequence_length : الحد الأقصى لطول تسلسل الإخراج.

template_type : مفتاح قالب الاستعلام (`"image"` أو `"multiple_images"`).

**يعيد:**

مجموعة (Tuple) من (prompt_embeds, prompt_embeds_mask).

ترميز موجه نصي إلى تمثيلات (مسار النص فقط).

تتجاوز `prompt_embeds` المحسوبة مسبقًا الترميز بالكامل.

#### encode_prompt_multiple_images[[diffusers.JoyImageEditPipeline.encode_prompt_multiple_images]]

```python
encode_prompt_multiple_images(prompt: typing.Union[str, typing.List[str]], device: typing.Optional[torch.device] = None, num_images_per_prompt: int = 1, images: typing.Optional[torch.Tensor] = None, prompt_embeds: typing.Optional[torch.Tensor] = None, prompt_embeds_mask: typing.Optional[torch.Tensor] = None, template_type: typing.Optional[str] = 'multiple_images', max_sequence_length: typing.Optional[int] = None)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit.py#L286)

**المعاملات:**

prompt : سلسلة أو سلاسل تعليمات، قد تحتوي اختيارياً على رموز `&amp;lt;image>\n`.

device : جهاز الهدف.

num_images_per_prompt : عدد المخرجات التي سيتم توليدها لكل موجه.

images : تينسورات البكسلات المقابلة لرموز الصور المضمنة.

prompt_embeds : تضمينات موجهات محسوبة مسبقًا.

prompt_embeds_mask : قناع الانتباه للتضمينات المحسوبة مسبقًا.

template_type : يجب أن يكون `"multiple_images"`.

max_sequence_length : إذا تم ضبطه، يُقصّ المخرَج إلى هذه الطول (مع الإبقاء على آخر `max_sequence_length` رموز).

**يعيد:**

مجموعة (Tuple) من (prompt_embeds, prompt_embeds_mask).

ترميز الموجهات التي تحتوي على رموز صور مضمنة عبر معالج Qwen.

تُستبدل رموز `&amp;lt;image>\n` في كل سلسلة موجهات برموز Qwen الخاصة بالرؤية قبل تمريرها إلى المُشفِّر متعدد الوسائط.

#### normalize_latents[[diffusers.JoyImageEditPipeline.normalize_latents]]

```python
normalize_latents(latent: Tensor)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit.py#L447)

**المعاملات:**

latent : متجه كامن خام من `vae.encode`.

**يعيد:**

موتر كامن مُطبَّع.

قم بتطبيع الكمونيات باستخدام إحصاءات لكل قناة من إعدادات VAE.

Uses (latent - mean) / std عندما يعرض VAE `latents_mean` و`latents_std`؛ وإلا يتم الرجوع إلى التوسيع باستخدام `scaling_factor`.

#### prepare_latents[[diffusers.JoyImageEditPipeline.prepare_latents]]

```python
prepare_latents(batch_size: int, num_channels_latents: int, height: int, width: int, video_length: int, dtype: dtype, device: device, generator: typing.Union[torch.Generator, typing.List[torch.Generator], NoneType], latents: typing.Optional[torch.Tensor] = None, image: typing.Optional[typing.List[PIL.Image.Image]] = None, enable_denormalization: bool = True)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/joyimage/pipeline_joyimage_edit.py#L502)

**المعاملات:**

batch_size : عدد العينات في الدفعة.

num_channels_latents : بُعد القناة الكامنة من إعدادات التحويلي.

height : الارتفاع المكاني بالبكسلات.

width : العرض المكاني بالبكسلات.

video_length : عدد الإطارات (1 للاستدلال على الصور).

dtype : نوع البيانات النقطي العائم (Floating-point dtype) للموتر الخفي (latent tensor).

device : جهاز الهدف.

generator : مولّدات الأرقام العشوائية (RNG) للعينة القابلة للتكرار.

latents : ضوضاء أولية اختيارية يوفّرها المستخدم للفتحة المستهدفة. عند تعيين `None` يتم أخذ عينة من ضوضاء عشوائية.

image : قائمة اختيارية لصور مرجعية بصيغة PIL يتم ترميزها بواسطة VAE كفتحات شرطية.

enable_denormalization : ما إذا كان سيتم تطبيع الكامنات المرجعية المُرمّزة.

**يعيد:**

مجموعة من `(latents, image_latents)` حيث يكون شكل `latents` هو `(B, 1, C, T, H', W')` وشكل `image_latents` هو `(B, N_ref, C, T, H', W')` أو `None` عندما لا تُعطى صور مرجعية.

**يرفع:** `ValueError`

- `ValueError` -- إذا كان `generator` قائمة يختلف طولها عن `batch_size`.

جهّز متجه الكامنة الضوضائي الأولي لحلقة إزالة الضوضاء.

## JoyImageEditPipelineOutput[[diffusers.JoyImageEditPipelineOutput]]

#### diffusers.JoyImageEditPipelineOutput[[diffusers.JoyImageEditPipelineOutput]]

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

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/joyimage/pipeline_output.py#L11)

فئة الإخراج لخطوط أنابيب توليد JoyImageEdit.

