Diffusers documentation

الترميم

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.42.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

الترميم

يعمل Inpainting على استبدال أو تحرير مناطق محددة من الصورة. وهذا يجعله أداة مفيدة لاستعادة الصور، مثل إزالة العيوب والاضطرابات، أو حتى استبدال منطقة في الصورة بشيء جديد تمامًا. يعتمد Inpainting على قناع (mask) لتحديد المناطق التي يجب ملؤها في الصورة؛ حيث تُمثَّل المنطقة المراد إدخالها بالبكسلات البيضاء، وتُمثَّل المنطقة التي يجب الحفاظ عليها بالبكسلات السوداء. يتم ملء البكسلات البيضاء بناءً على الأمر النصي (prompt).

مع 🤗 Diffusers، إليك كيفية تنفيذ inpainting:

  1. حمّل نقطة تفتيش لإعادة الرسم باستخدام فئة AutoPipelineForInpainting. ستقوم هذه الفئة تلقائيًا باكتشاف فئة خط الأنابيب المناسبة للتحميل بناءً على نقطة التفتيش:
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint", dtype=torch.float16
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

ستلاحظ طوال الدليل أننا نستخدم enable_model_cpu_offload() و enable_xformers_memory_efficient_attention() لتوفير الذاكرة وزيادة سرعة الاستدلال. إذا كنت تستخدم PyTorch 2.0، فلا داعي لاستدعاء enable_xformers_memory_efficient_attention() على خط الأنابيب الخاص بك لأنه سيستخدم بالفعل scaled-dot product attention الأصلية في PyTorch 2.0.

  1. تحميل الصور الأساسية وأقنعة الصور:
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")
  1. أنشئ موجهًا (prompt) لإعادة رسم الصورة، وقم بتمريره إلى خط الأنابيب (pipeline) مع الصور الأساسية والقناع:
prompt = "a black cat with glowing eyes, cute, adorable, disney, pixar, highly detailed, 8k"
negative_prompt = "bad anatomy, deformed, ugly, disfigured"
image = pipeline(prompt=prompt, negative_prompt=negative_prompt, image=init_image, mask_image=mask_image).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
الصورة الأساسية
صورة القناع
صورة مولّدة

إنشاء صورة قناع

في جميع أنحاء هذا الدليل، يتم توفير صورة القناع في جميع أمثلة الأكواد لتسهيل الاستخدام. يمكنك إجراء إعادة رسم (Inpainting) على صورك الخاصة، لكنك ستحتاج إلى إنشاء صورة قناع لها. استخدم المساحة (Space) أدناه لإنشاء صورة قناع بسهولة.

ارفع صورة أساسية لتطبيق إعادة التلوين عليها، واستخدم أداة الرسم لتخطيط قناع. عند الانتهاء، انقر على Run لتوليد صورة القناع وتنزيلها.

تعتيم القناع

توفر طريقة blur() خياراً لكيفية دمج الصورة الأصلية بمنطقة إعادة الرسم. يُحدَّد مقدار الضبابية بواسطة المعامل blur_factor. يؤدي زيادة blur_factor إلى زيادة مقدار الضبابية المطبقة على حواف القناع، مما يُنعّم الانتقال بين الصورة الأصلية ومنطقة إعادة الرسم. أما قيمة منخفضة أو معدومة لـ blur_factor فتُحافظ على حواف القناع الأكثر حدة.

للاستخدام، أنشئ قناعًا ضبابيًا باستخدام معالج الصور.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image
from PIL import Image

pipeline = AutoPipelineForInpainting.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16).to('cuda')  # or "mps", "xpu", "cpu"

mask = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/seashore_mask.png")
blurred_mask = pipeline.mask_processor.blur(mask, blur_factor=33)
blurred_mask
قناع بدون ضباب
قناع مع تطبيق ضبابية

النماذج الشائعة

Stable Diffusion Inpainting وStable Diffusion XL (SDXL) Inpainting وKandinsky 2.2 Inpainting من بين أكثر النماذج شيوعًا في إعادة التلوين (Inpainting). عادةً ما تنتج SDXL صورًا بدقة أعلى من Stable Diffusion v1.5، كما أن Kandinsky 2.2 قادر أيضًا على توليد صور عالية الجودة.

Stable Diffusion Inpainting

يعتبر Stable Diffusion Inpainting نموذج انتشار كامن (latent diffusion model) تم ضبطه بدقة على صور بأبعاد 512x512 في مهمة inpainting. وهو نقطة انطلاق جيدة لأنه سريع نسبيًا ويولّد صورًا بجودة عالية. لاستخدام هذا النموذج في inpainting، ستحتاج إلى تمرير موجه (prompt) وصورة أساسية (base) وصورة قناع (mask) إلى خط الأنابيب (pipeline):

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)

Stable Diffusion XL (SDXL) لإعادة رسم الصور

SDXL هو إصدار أكبر وأكثر قوة من Stable Diffusion v1.5. يمكن لهذا النموذج اتباع عملية نموذج من مرحلتين (على الرغم من إمكانية استخدام كل نموذج على حدة)؛ حيث يولّد النموذج الأساسي صورة، ثم يأخذ نموذج التحسين تلك الصورة ويعزز تفاصيلها وجودتها بشكل أكبر. اطّلع على دليل SDXL للحصول على دليل أكثر شمولاً حول كيفية استخدام SDXL وتكوين معامِلاته.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "diffusers/stable-diffusion-xl-1.0-inpainting-0.1", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)

Kandinsky 2.2 Inpainting

تشبه عائلة نماذج Kandinsky نموذج SDXL لأنها تستخدم نموذجين أيضًا؛ حيث يقوم نموذج المسبق للصورة (image prior model) بإنشاء تمثيلات (embeddings) للصورة، بينما يولّد نموذج الانتشار (diffusion model) الصور من هذه التمثيلات. يمكنك تحميل نموذج المسبق للصورة ونموذج الانتشار بشكل منفصل، لكن أسهل طريقة لاستخدام Kandinsky 2.2 هي تحميله في فئة AutoPipelineForInpainting التي تستخدم KandinskyV22InpaintCombinedPipeline في الخلفية.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint", dtype=torch.float16
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
الصورة الأساسية
Stable Diffusion Inpainting
Stable Diffusion XL Inpainting
Kandinsky 2.2 Inpainting

نقاط التفتيش غير المحددة لإعادة التلوين

حتى الآن، استخدم هذا الدليل نقاط تحقق مخصصة لإعادة التلوين مثل stable-diffusion-v1-5/stable-diffusion-inpainting. لكن يمكنك أيضاً استخدام نقاط تحقق عادية مثل stable-diffusion-v1-5/stable-diffusion-v1-5. لنقارن نتائج نقطتي التحقق هاتين.

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

stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpainting
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, image], rows=1, cols=2)
stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpainting

ومع ذلك، في المهام الأساسية أكثر مثل مسح كائن من صورة (مثل الصخور في الطريق على سبيل المثال)، فإن نقطة التفتيش العادية تعطي نتائج جيدة إلى حد كبير. لا يوجد فرق ملحوظ بين نقطة التفتيش العادية ونقطة التفتيش الخاصة بإصلاح الصور.

stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpaint
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/road-mask.png")

image = pipeline(prompt="road", image=init_image, mask_image=mask_image).images[0]
make_image_grid([init_image, image], rows=1, cols=2)
stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpainting

المفاضلة عند استخدام نقطة تحقق غير مخصصة لإعادة التلوين هي أن جودة الصورة الإجمالية قد تكون أدنى، لكنها تميل بشكل عام إلى الحفاظ على منطقة القناع (وهو السبب الذي يجعلك ترى حدود القناع). تم تدريب نقاط التحقق المخصصة لإعادة التلوين عمداً لتوليد صور معاد تلوينها بجودة أعلى، ويشمل ذلك إنشاء انتقال أكثر طبيعية بين المناطق المقنعة وغير المقنعة. ونتيجة لذلك، من المرجح أن تقوم هذه النقاط بتغيير منطقتك غير المقنعة.

إذا كان الحفاظ على المنطقة غير المقنّعة مهماً لمهمتك، يمكنك استخدام طريقة VaeImageProcessor.apply_overlay() لإجبار المنطقة غير المقنّعة من الصورة على البقاء كما هي، على حساب بعض الانتقالات الأقل طبيعية بين المنطقتين المقنّعة وغير المقنّعة.

import PIL
import numpy as np
import torch

from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

device = "cuda"  # or "mps", "xpu", "cpu"
pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting",
    dtype=torch.float16,
    variant="fp16"
)
pipeline = pipeline.to(device)

img_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo.png"
mask_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo_mask.png"

init_image = load_image(img_url).resize((512, 512))
mask_image = load_image(mask_url).resize((512, 512))

prompt = "Face of a yellow cat, high resolution, sitting on a park bench"
repainted_image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image).images[0]
repainted_image.save("repainted_image.png")

unmasked_unchanged_image = pipeline.image_processor.apply_overlay(mask_image, init_image, repainted_image)
unmasked_unchanged_image.save("force_unmasked_unchanged.png")
make_image_grid([init_image, mask_image, repainted_image, unmasked_unchanged_image], rows=2, cols=2)

إعداد معلمات خط الأنابيب

تعتمد ميزات الصورة - مثل الجودة و«الإبداع» - على معاملات خط الأنابيب. ومن المهم معرفة ما تفعله هذه المعاملات للحصول على النتائج التي تريدها. دعونا نلقي نظرة على أهم المعاملات ونرى كيف يؤثر تغييرها على المخرجات.

القوة

strength هو مقياد لمدى إضافة الضوضاء إلى الصورة الأساسية، مما يؤثر على مدى تشابه الصورة الناتجة مع الصورة الأساسية.

  • 📈 تعني قيمة strength العالية إضافة المزيد من الضوضاء إلى الصورة، مما يطيل عملية إزالة الضوضاء، لكنك ستحصل على صور بجودة أعلى وتختلف بشكل أكبر عن الصورة الأساسية
  • 📉 تعني قيمة strength المنخفضة إضافة ضوضاء أقل إلى الصورة، مما يجعل عملية إزالة الضوضاء أسرع، لكن جودة الصورة قد لا تكون بنفس الجودة العالية، وتتشابه الصورة المولّدة مع الصورة الأساسية بشكل أكبر
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, strength=0.6).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
strength = 0.6
strength = 0.8
strength = 1.0

مقياس التوجيه

يؤثر guidance_scale على مدى توافق النص الوصفي مع الصورة المولّدة.

  • 📈 تعني قيمة عالية لـ guidance_scale أن النص الموجه والصورة المولّدة متطابقتان بشكل وثيق، لذا فإن المخرجات تمثل تفسيرًا أكثر صرامةً للنص الموجه
  • 📉 قيمة منخفضة لـ guidance_scale تعني أن المطالبة والصورة المولّدة متطابقتان بشكل أقل إحكامًا، لذا قد تكون المخرجات أكثر تنوعًا عن المطالبة

يمكنك استخدام strength وguidance_scale معًا للحصول على تحكم أكبر في مدى تعبيرية النموذج. على سبيل المثال، يؤدي الجمع بين قيم عالية لـstrength وguidance_scale إلى منح النموذج أقصى قدر من الحرية الإبداعية.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, guidance_scale=2.5).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
guidance_scale = 2.5
guidance_scale = 7.5
guidance_scale = 12.5

الموجّه السلبي

تفترض الموجهة السلبية الدور المعاكس للموجهة؛ فهي توجه النموذج بعيدًا عن توليد عناصر معينة في الصورة. وهذا مفيد لتحسين جودة الصورة بسرعة ومنع النموذج من توليد أشياء لا ترغب في ظهورها.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
negative_prompt = "bad architecture, unstable, poor details, blurry"
image = pipeline(prompt=prompt, negative_prompt=negative_prompt, image=init_image, mask_image=mask_image).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
negative_prompt = "bad architecture, unstable, poor details, blurry"

Padding mask crop

تتمثل إحدى الطرق لزيادة جودة الصور المُعاد توليدها (Inpainting) في استخدام معامل padding_mask_crop. عند تفعيل هذا الخيار، يتم اقتطاع المنطقة المقنّعة مع بعض الحشو الذي يحدده المستخدم، كما يتم اقتطاع نفس المنطقة من الصورة الأصلية. يتم رفع دقة كل من الصورة والقناع إلى دقة أعلى لعملية إعادة التوليد، ثم تُدمج فوق الصورة الأصلية. هذه طريقة سريعة وسهلة لتحسين جودة الصورة دون الحاجة إلى استخدام خط أنابيب منفصل مثل StableDiffusionUpscalePipeline.

أضف معامل padding_mask_crop إلى استدعاء خط الأنابيب واضبطه على قيمة الحشو المطلوبة.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image
from PIL import Image

generator = torch.Generator(device='cuda').manual_seed(0)  # or "mps", "xpu", "cpu"
pipeline = AutoPipelineForInpainting.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16).to('cuda')

base = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/seashore.png")
mask = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/seashore_mask.png")

image = pipeline("boat", image=base, mask_image=mask, strength=0.75, generator=generator, padding_mask_crop=32).images[0]
image
صورة inpaint الافتراضية
استكمال الصورة مع تفعيل padding_mask_crop

خطوط أنابيب التلوين المتسلسل

يمكن ربط AutoPipelineForInpainting بخطوط أنابيب 🤗 Diffusers الأخرى لتحرير مخرجاتها. وهذا مفيد غالبًا لتحسين جودة المخرجات من خطوط أنابيب الانتشار الأخرى لديك، وإذا كنت تستخدم خطوط أنابيب متعددة، فقد يكون ربطها معًا أكثر كفاءة في استخدام الذاكرة للحفاظ على المخرجات في الفضاء الكامن وإعادة استخدام مكوّنات خط الأنابيب نفسه.

من النص إلى الصورة إلى إعادة التلوين

يسمح لكِ بسلسلة خط أنابيب من النص إلى الصورة مع خط أنابيب إعادة الرسم (Inpainting) بإعادة رسم الصورة المولّدة، دون الحاجة إلى توفير صورة أساسية في البداية. وهذا يجعل من السهل تعديل مخرجات النص إلى الصورة المفضلة لديك دون الحاجة إلى توليد صورة جديدة بالكامل.

ابدأ بخط أنابيب النص إلى الصورة لإنشاء قلعة:

import torch
from diffusers import AutoPipelineForText2Image, AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16, variant="fp16", use_safetensors=True
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

text2image = pipeline("concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k").images[0]

تحميل صورة القناع الخاصة بالمخرجات من الأعلى:

mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_text-chain-mask.png")

ودعونا نملأ المنطقة المقنّعة بمشهد لشلال:

pipeline = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint", dtype=torch.float16
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

prompt = "digital painting of a fantasy waterfall, cloudy"
image = pipeline(prompt=prompt, image=text2image, mask_image=mask_image).images[0]
make_image_grid([text2image, mask_image, image], rows=1, cols=3)
النص إلى صورة
inpaint

التوليد من صورة إلى صورة

يمكنك أيضًا ربط خط أنابيب إعادة الرسم (inpainting) قبل خط أنابيب آخر مثل تحويل الصورة إلى صورة أو مُعظِّم (upscaler) لتحسين الجودة.

ابدأ بتعبئة صورة:

import torch
from diffusers import AutoPipelineForInpainting, AutoPipelineForImage2Image
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image_inpainting = pipeline(prompt=prompt, image=init_image, mask_image=mask_image).images[0]

# resize image to 1024x1024 for SDXL
image_inpainting = image_inpainting.resize((1024, 1024))

الآن لنمرّر الصورة إلى خط أنابيب إعادة رسم (inpainting) آخر مع نموذج SDXL المُحسّن (refiner) لتعزيز تفاصيل الصورة وجودتها:

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stabilityai/stable-diffusion-xl-refiner-1.0", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

image = pipeline(prompt=prompt, image=image_inpainting, mask_image=mask_image, output_type="latent").images[0]

من المهم تحديد output_type="latent" في خط الأنابيب للحفاظ على جميع المخرجات في الفضاء الكامن (latent space) لتجنب خطوة فك الترميز ثم الترميز غير الضرورية. يعمل هذا فقط إذا كانت خطوط الأنابيب المتسلسلة تستخدم نفس نموذج VAE. على سبيل المثال، في قسم Text-to-image-to-inpaint، يستخدم Kandinsky 2.2 فئة VAE مختلفة عن نموذج Stable Diffusion، لذا لن يعمل. ولكن إذا استخدمت Stable Diffusion v1.5 لكلا خطي الأنابيب، فيمكنك إبقاء كل شيء في الفضاء الكامن لأنهما كلاهما يستخدم AutoencoderKL.

أخيرًا، يمكنك تمرير هذه الصورة إلى خط أنابيب من صورة إلى صورة لإضافة اللمسات الأخيرة إليها. من الكفاءة استخدام طريقة from_pipe() لإعادة استخدام مكونات خط الأنابيب الموجودة، وتجنب تحميل جميع مكونات خط الأنابيب في الذاكرة مرة أخرى دون داعٍ.

pipeline = AutoPipelineForImage2Image.from_pipe(pipeline)
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

image = pipeline(prompt=prompt, image=image).images[0]
make_image_grid([init_image, mask_image, image_inpainting, image], rows=2, cols=2)
الصورة الأولية
inpaint
صورة إلى صورة

في الواقع، مهمة تحويل الصورة إلى صورة ومهمة إعادة بناء الصورة (Inpainting) متشابهتان جداً. يقوم تحويل الصورة إلى صورة بإنشاء صورة جديدة تشبه الصورة الموجودة التي تم تقديمها. بينما تقوم إعادة بناء الصورة (Inpainting) بالشيء نفسه، لكنها تحوّل فقط منطقة الصورة المحددة بواسطة القناع (Mask) وتبقى بقية الصورة دون تغيير. يمكنك التفكير في إعادة بناء الصورة (Inpainting) كأداة أكثر دقة لإجراء تغييرات محددة، بينما يتمتع تحويل الصورة إلى صورة بنطاق أوسع لإجراء تغييرات أكثر شمولاً.

التحكم في توليد الصور

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

وزن الأوامر

توفر أوزان المُوجِّه (Prompt weighting) طريقة قابلة للقياس لتوسيع تمثيل المفاهيم في المُوجِّه. يمكنك استخدامه لزيادة أو تقليل حجم متجه التضمين النصي (text embedding vector) لكل مفهوم في المُوجِّه، مما يحدد بدوره مقدار كل مفهوم الذي سيتم توليده. تقدم مكتبة Compel صياغة بديهية لتوسيع أوزان المُوجِّه وتوليد التضمينات. تعلّم كيفية إنشاء التضمينات في دليل أوزان المُوجِّه.

بمجرد توليد التضمينات، مررها إلى معامل prompt_embeds (وnegative_prompt_embeds إذا كنت تستخدم موجهًا سلبيًا) في AutoPipelineForInpainting. تستبدل التضمينات معامل prompt:

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16,
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

image = pipeline(prompt_embeds=prompt_embeds, # generated from Compel
    negative_prompt_embeds=negative_prompt_embeds, # generated from Compel
    image=init_image,
    mask_image=mask_image
).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)

ControlNet

تُستخدم نماذج ControlNet مع نماذج الانتشار الأخرى مثل Stable Diffusion، وتوفر طريقة أكثر مرونة ودقة للتحكم في كيفية توليد الصورة. تقبل وحدة ControlNet مدخل صورة إضافية كشرط توجيهي، يوجّه نموذج الانتشار للحفاظ على الخصائص الموجودة فيها.

على سبيل المثال، لنشترط صورة باستخدام ControlNet مُدرَّب مسبقًا على صور inpaint:

import torch
import numpy as np
from diffusers import ControlNetModel, StableDiffusionControlNetInpaintPipeline
from diffusers.utils import load_image, make_image_grid

# load ControlNet
controlnet = ControlNetModel.from_pretrained("lllyasviel/control_v11p_sd15_inpaint", dtype=torch.float16, variant="fp16")

# pass ControlNet to the pipeline
pipeline = StableDiffusionControlNetInpaintPipeline.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", controlnet=controlnet, dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

# prepare control image
def make_inpaint_condition(init_image, mask_image):
    init_image = np.array(init_image.convert("RGB")).astype(np.float32) / 255.0
    mask_image = np.array(mask_image.convert("L")).astype(np.float32) / 255.0

    assert init_image.shape[0:1] == mask_image.shape[0:1], "image and image_mask must have the same image size"
    init_image[mask_image > 0.5] = -1.0  # set as masked pixel
    init_image = np.expand_dims(init_image, 0).transpose(0, 3, 1, 2)
    init_image = torch.from_numpy(init_image)
    return init_image

control_image = make_inpaint_condition(init_image, mask_image)

الآن قم بتوليد صورة من الصور الأساسية والقناع والتحكم. ستلاحظ أن خصائص الصورة الأساسية محفوظة بقوة في الصورة المولّدة.

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, control_image=control_image).images[0]
make_image_grid([init_image, mask_image, PIL.Image.fromarray(np.uint8(control_image[0][0])).convert('RGB'), image], rows=2, cols=2)

يمكنك الذهاب خطوة أبعد وربط ذلك بخط أنابيب من صورة إلى صورة لتطبيق أسلوب جديد:

from diffusers import AutoPipelineForImage2Image

pipeline = AutoPipelineForImage2Image.from_pretrained(
    "nitrosocke/elden-ring-diffusion", dtype=torch.float16,
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

prompt = "elden ring style castle" # include the token "elden ring style" in the prompt
negative_prompt = "bad architecture, deformed, disfigured, poor details"

image_elden_ring = pipeline(prompt, negative_prompt=negative_prompt, image=image).images[0]
make_image_grid([init_image, mask_image, image, image_elden_ring], rows=2, cols=2)
الصورة الأولية
Controlnet inpaint
صورة إلى صورة

تحسين

قد يكون تشغيل نماذج الانتشار صعبًا وبطيئًا إذا كانت مواردك محدودة، لكن الأمر لا يجب أن يكون كذلك مع بعض حيل التحسين. أحد أكبر التحسينات (والأسهل) التي يمكنك تفعيلها هو الانتقال إلى الانتباه الموفّر للذاكرة. إذا كنت تستخدم PyTorch 2.0، فإن الانتباه المتدرّج بناتج النقطة مفعّل تلقائيًا ولا تحتاج إلى القيام بأي شيء آخر. أما للمستخدمين الذين لا يستخدمون PyTorch 2.0، فيمكنك تثبيت واستخدام تنفيذ xFormers للانتباه الموفّر للذاكرة. كلا الخيارين يقللان من استخدام الذاكرة ويسرّعان الاستدلال.

يمكنك أيضًا نقل النموذج إلى وحدة المعالجة المركزية (CPU) لتوفير المزيد من الذاكرة:

+ pipeline.enable_xformers_memory_efficient_attention()
+ pipeline.enable_model_cpu_offload()

لتسريع كود الاستدلال الخاص بك بشكل أكبر، استخدم torch_compile. يجب عليك تغليف torch.compile حول المكوّن الأكثر كثافة في خط الأنابيب، وهو عادةً UNet:

pipeline.unet = torch.compile(pipeline.unet, mode="reduce-overhead", fullgraph=True)

تعرّف على المزيد في دليلَي تقليل استهلاك الذاكرة وتسريع الاستدلال.

Update on GitHub