# Outpainting

يمتدّ التوسيع الخارجي (Outpainting) بالصورة خارج حدودها الأصلية، مما يتيح لك إضافة عناصر بصرية أو استبدالها أو تعديلها في الصورة مع الحفاظ على الصورة الأصلية. وكما هو الحال مع [التعبئة الداخلية (Inpainting)](../using-diffusers/inpaint)، فإنك تريد ملء المنطقة البيضاء (في هذه الحالة، المنطقة خارج الصورة الأصلية) بعناصر بصرية جديدة مع الإبقاء على الصورة الأصلية (الممثلة بقناع من البكسلات السوداء). هناك طريقتان رئيسيتان للتوسيع الخارجي، مثل استخدام [ControlNet](https://hf.co/blog/OzzyGT/outpainting-controlnet) أو استخدام [Differential Diffusion](https://hf.co/blog/OzzyGT/outpainting-differential-diffusion).

ستُظهر لك هذه الدليل كيفية تنفيذ outpainting باستخدام نموذج inpainting وControlNet ومقدّر ZoeDepth.

قبل أن تبدأ، تأكد من تثبيت مكتبة [controlnet_aux](https://github.com/huggingface/controlnet_aux) حتى تتمكن من استخدام مُقدِّر ZoeDepth.

```py
!pip install -q controlnet_aux
```

## تجهيز الصورة

ابدأ باختيار صورة لإضافة خلفية لها، ثم احذف الخلفية باستخدام مساحة مثل [BRIA-RMBG-1.4](https://hf.co/spaces/briaai/BRIA-RMBG-1.4).

<iframe src="https://briaai-bria-rmbg-1-4.hf.space" frameborder="0" width="850" height="450"
>

على سبيل المثال، احذف الخلفية من هذه الصورة التي تظهر فيها زوج من الأحذية.

  
    
    الصورة الأصلية
  
  
    
    تمت إزالة الخلفية
  

تعمل نماذج [Stable Diffusion XL (SDXL)](../api/pipelines/stable_diffusion/stable_diffusion_xl) بشكل أفضل مع الصور ذات الأبعاد 1024x1024، لكن يمكنك تغيير حجم الصورة إلى أي أبعاد طالما أن جهازك يمتلك ذاكرة كافية لدعم ذلك. كما يجب استبدال الخلفية الشفافة في الصورة بخلفية بيضاء. أنشئ دالة (مثل تلك أدناه) تقوم بتغيير حجم الصورة ولصقها على خلفية بيضاء.

```py
import random

import requests
import torch
from controlnet_aux import ZoeDetector
from PIL import Image, ImageOps

from diffusers import (
    AutoencoderKL,
    ControlNetModel,
    StableDiffusionXLControlNetPipeline,
    StableDiffusionXLInpaintPipeline,
)

def scale_and_paste(original_image):
    aspect_ratio = original_image.width / original_image.height

    if original_image.width > original_image.height:
        new_width = 1024
        new_height = round(new_width / aspect_ratio)
    else:
        new_height = 1024
        new_width = round(new_height * aspect_ratio)

    resized_original = original_image.resize((new_width, new_height), Image.LANCZOS)
    white_background = Image.new("RGBA", (1024, 1024), "white")
    x = (1024 - new_width) // 2
    y = (1024 - new_height) // 2
    white_background.paste(resized_original, (x, y), resized_original)

    return resized_original, white_background

original_image = Image.open(
    requests.get(
        "https://huggingface.co/datasets/stevhliu/testing-images/resolve/main/no-background-jordan.png",
        stream=True,
    ).raw
).convert("RGBA")
resized_img, white_bg_image = scale_and_paste(original_image)
```

لتجنب إضافة تفاصيل إضافية غير مرغوب فيها، استخدم مُقدِّر ZoeDepth لتوفير إرشادات إضافية أثناء التوليد ولضمان بقاء الأحذية متسقة مع الصورة الأصلية.

```py
zoe = ZoeDetector.from_pretrained("lllyasviel/Annotators")
image_zoe = zoe(white_bg_image, detect_resolution=512, image_resolution=1024)
image_zoe
```

    

## Outpaint

بمجرد أن يصبح صورتك جاهزة، يمكنك توليد المحتوى في المنطقة البيضاء المحيطة بالحذاء باستخدام [controlnet-inpaint-dreamer-sdxl](https://hf.co/destitech/controlnet-inpaint-dreamer-sdxl)، وهو SDXL ControlNet مُدرَّب على inpainting.

حمّل ControlNet الخاص بتعبئة الصور (inpainting) ونموذج ZoeDepth ووحدة VAE، ثم مرّرها إلى [StableDiffusionXLControlNetPipeline](/docs/diffusers/main/ar/api/pipelines/controlnet_sdxl#diffusers.StableDiffusionXLControlNetPipeline). بعد ذلك يمكنك إنشاء دالة اختيارية `generate_image` (للتسهيل) لتوسيع صورة أولية.

```py
controlnets = [
    ControlNetModel.from_pretrained(
        "destitech/controlnet-inpaint-dreamer-sdxl", dtype=torch.float16, variant="fp16"
    ),
    ControlNetModel.from_pretrained(
        "diffusers/controlnet-zoe-depth-sdxl-1.0", dtype=torch.float16
    ),
]
vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", dtype=torch.float16).to("cuda")  # or "mps", "xpu", "cpu"
pipeline = StableDiffusionXLControlNetPipeline.from_pretrained(
    "SG161222/RealVisXL_V4.0", dtype=torch.float16, variant="fp16", controlnet=controlnets, vae=vae
).to("cuda")

def generate_image(prompt, negative_prompt, inpaint_image, zoe_image, seed: int = None):
    if seed is None:
        seed = random.randint(0, 2**32 - 1)

    generator = torch.Generator(device="cpu").manual_seed(seed)

    image = pipeline(
        prompt,
        negative_prompt=negative_prompt,
        image=[inpaint_image, zoe_image],
        guidance_scale=6.5,
        num_inference_steps=25,
        generator=generator,
        controlnet_conditioning_scale=[0.5, 0.8],
        control_guidance_end=[0.9, 0.6],
    ).images[0]

    return image

prompt = "nike air jordans on a basketball court"
negative_prompt = ""

temp_image = generate_image(prompt, negative_prompt, white_bg_image, image_zoe, 908097)
```

الصق الصورة الأصلية فوق الصورة المُوسَّعة الأولية. ستقوم بتحسين الخلفية المُوسَّعة في خطوة لاحقة.

```py
x = (1024 - resized_img.width) // 2
y = (1024 - resized_img.height) // 2
temp_image.paste(resized_img, (x, y), resized_img)
temp_image
```

    

> [!TIP]
> الآن هو وقت مناسب لتحرير بعض الذاكرة إذا كنت تعاني من نقصها!
>
> ```py
> pipeline=None
> torch.cuda.empty_cache()
> ```

الآن وبعد أن حصلت على صورة مبدئية مُوسَّعة، حمّل [StableDiffusionXLInpaintPipeline](/docs/diffusers/main/ar/api/pipelines/stable_diffusion/stable_diffusion_xl#diffusers.StableDiffusionXLInpaintPipeline) باستخدام نموذج [RealVisXL](https://hf.co/SG161222/RealVisXL_V4.0) لتوليد الصورة النهائية الموسَّعة بجودة أفضل.

```py
pipeline = StableDiffusionXLInpaintPipeline.from_pretrained(
    "OzzyGT/RealVisXL_V4.0_inpainting",
    dtype=torch.float16,
    variant="fp16",
    vae=vae,
).to("cuda")  # or "mps", "xpu", "cpu"
```

جهّز قناعًا للصورة النهائية بعد التوسيع. لإنشاء انتقال أكثر طبيعية بين الصورة الأصلية والخلفية الموسّعة، قم بتنعيم القناع لمساعدته على الاندماج بشكل أفضل.

```py
mask = Image.new("L", temp_image.size)
mask.paste(resized_img.split()[3], (x, y))
mask = ImageOps.invert(mask)
final_mask = mask.point(lambda p: p > 128 and 255)
mask_blurred = pipeline.mask_processor.blur(final_mask, blur_factor=20)
mask_blurred
```

    

أنشئ موجهًا (prompt) أفضل ومرره إلى دالة `generate_outpaint` لتوليد الصورة النهائية المُوسَّعة. مرة أخرى، الصق الصورة الأصلية فوق الخلفية النهائية المُوسَّعة.

```py
def generate_outpaint(prompt, negative_prompt, image, mask, seed: int = None):
    if seed is None:
        seed = random.randint(0, 2**32 - 1)

    generator = torch.Generator(device="cpu").manual_seed(seed)

    image = pipeline(
        prompt,
        negative_prompt=negative_prompt,
        image=image,
        mask_image=mask,
        guidance_scale=10.0,
        strength=0.8,
        num_inference_steps=30,
        generator=generator,
    ).images[0]

    return image

prompt = "high quality photo of nike air jordans on a basketball court, highly detailed"
negative_prompt = ""

final_image = generate_outpaint(prompt, negative_prompt, temp_image, mask_blurred, 7688778)
x = (1024 - resized_img.width) // 2
y = (1024 - resized_img.height) // 2
final_image.paste(resized_img, (x, y), resized_img)
final_image
```

    

