01_stable_diffusion_introduction_CN

news2024/11/25 7:15:48

stable_diffusion

配置

!pip install -Uq diffusers ftfy accelerate
# Installing transformers from source for now since we need the latest version for Depth2Img:
!pip install -Uq git+https://github.com/huggingface/transformers 
import torch
import requests
from PIL import Image
from io import BytesIO
from matplotlib import pyplot as plt

# We'll be exploring a number of pipelines today!
from diffusers import (
    StableDiffusionPipeline, 
    StableDiffusionImg2ImgPipeline,
    StableDiffusionInpaintPipeline, 
    StableDiffusionDepth2ImgPipeline
    )       

# We'll use a couple of demo images later in the notebook
def download_image(url):
    response = requests.get(url)
    return Image.open(BytesIO(response.content)).convert("RGB")

# Download images for inpainting example
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 = download_image(img_url).resize((512, 512))
mask_image = download_image(mask_url).resize((512, 512))
# Set device
device = (
    "mps"
    if torch.backends.mps.is_available()
    else "cuda"
    if torch.cuda.is_available()
    else "cpu"
)

从文本生成图像

我们先载入 Stable Diffusion 的管线,看看我们能做点什么。现有的 Stable Diffusion 模型有好多不同版本,截至本文书写时的最新版本是第2.1版。如果你想探究更旧的版本,只需要在 model_id 处修改即可(比如你可以试试将其改成 CompVis/stable-diffusion-v1-4 或从dreambooth concepts library选一个模型)。

# Load the pipeline
model_id = "stabilityai/stable-diffusion-2-1-base"
pipe = StableDiffusionPipeline.from_pretrained(model_id).to(device)
pipe.enable_attention_slicing()
unet\diffusion_pytorch_model.safetensors not found



Loading pipeline components...:   0%|          | 0/6 [00:00<?, ?it/s]

如果你的GPU内存不够用,这里有些办法也许可以减少内存使用:

  • 载入 FP16 精度的版本(但并不是所有的系统上都支持)。与此同时,在你对管线的某个特定部分实验时,你也需要把所有的张量换成 torch.float16 精度:

    pipe = StableDiffusionPipeline.from_pretrained(model_id, revision="fp16", torch_dtype=torch.float16).to(device)

  • 开启注意力机制切分(attention slicing)。这会牺牲一点点速度来减少GPU内存的使用:

pipe.enable_attention_slicing()

  • 降低要生成的图片的尺寸

当管线加载好了以后,我们可以用以下代码去使用文字提示生成图片:

# Set up a generator for reproducibility
generator = torch.Generator(device=device).manual_seed(42)

# Run the pipeline, showing some of the available arguments
pipe_output = pipe(
    prompt="What to generate Palette knife painting of an autumn cityscape",
    negative_prompt="Oversaturated, blurry, low quality", # What NOT to generate
    height=480, width=640,     # Specify the image size
    guidance_scale=8,          # How strongly to follow the prompt
    num_inference_steps=35,    # How many steps to take
    generator=generator        # Fixed random seed
)

# View the resulting image:
pipe_output.images[0]
  0%|          | 0/35 [00:00<?, ?it/s]

在这里插入图片描述

练习: 花点时间去用上面的代码块实验,使用你自己的文字提示,反复调整各项设置看看这些设置如何影响生成效果。使用不同的随机种子或者移除掉 generator 这个输入参数,看看能获取什么不同的效果。

主要的要调节参数介绍:

  • widthheight 指定了生成图片的尺寸。它们必须是可被 8 整除的数字,只有这样我们的可变分自编码器(VAE)才能正常工作(我们在将来的章节会了解到)。
  • 步数 num_inference_steps 也会影响生成的质量。默认设成 50 已经很好了,但有些时候你也可以用少到像 20 步这样,这对做实验就方便多了。
  • 使用 negative_prompt 来强调不希望生成的内容,一般会在无分类器引导(classifier-free guidance)的过程中用到,这可以是个非常有用的添加额外控制的方式。你可以留空这个地方不管,但很多用户觉得列出一些不想要的特性对更好的生成很有帮助。
  • guidance_scale 这个参数决定了无分类器引导(CFG)的影响强度有多大。增大这个值会使得生成的内容更接近文字提示;但这个值如果过大,可能会使得结果变得过饱和、不好看。

如果你想为文字提示找点灵感,你也可以从这里开始:Stable Diffusion Prompt Book

你可在下面看到增大guidance_scale 这个参数所带来的作用:

#@markdown comparing guidance scales:
cfg_scales = [1.1, 8, 12] #@param
prompt = "A collie with a pink hat" #@param
fig, axs = plt.subplots(1, len(cfg_scales), figsize=(16, 5))
for i, ax in enumerate(axs):
  im = pipe(prompt, height=480, width=480,
    guidance_scale=cfg_scales[i], num_inference_steps=35,
    generator=torch.Generator(device=device).manual_seed(42)).images[0]
  ax.imshow(im); ax.set_title(f'CFG Scale {cfg_scales[i]}');
  0%|          | 0/35 [00:00<?, ?it/s]



  0%|          | 0/35 [00:00<?, ?it/s]



  0%|          | 0/35 [00:00<?, ?it/s]

在这里插入图片描述

调一调上面的值,尝试不同的幅度和提示。当然了,如何解读这些参数是个很主观的事情,但对我来说,我觉得 8 到 12 这个值区间比其它情况产出的结果都好。

管线的组成部分

这里我们用的 StableDiffusionPipeline 比前面几个单元的 DDPMPipeline 要复杂一点。除了 UNet 和调度器之外,管线内还有很多其它的组成部分:

print(list(pipe.components.keys())) # List components
['vae', 'text_encoder', 'tokenizer', 'unet', 'scheduler', 'safety_checker', 'feature_extractor']

为了更好地理解管线如何工作,我们简要地一个一个看看各个组成部分,然后我们自己动手,把它们组合在一起,以此复现出整个管线功能。

可变分自编码器(VAE)

可变分自编码器(VAE)是一种模型,它可以将输入编码成一种被压缩过的表示形式,再把这个“隐式的”表示形式解码成某种接近输入的输出。当我们使用 Stable Diffusion 生成图片时,我们先在VAE的“隐空间”应用扩散过程生成隐编码,然后在结尾对它们解码来查看结果图片。

这里就是一个例子,使用VAE把输入图片编码成隐式的表示形式,再对它解码:

# Create some fake data (a random image, range (-1, 1))
images = torch.rand(1, 3, 512, 512).to(device) * 2 - 1 
print("Input images shape:", images.shape)

# Encode to latent space
with torch.no_grad():
  latents = 0.18215 * pipe.vae.encode(images).latent_dist.mean
print("Encoded latents shape:", latents.shape)

# Decode again
with torch.no_grad():
  decoded_images = pipe.vae.decode(latents / 0.18215).sample
print("Decoded images shape:", decoded_images.shape)
Input images shape: torch.Size([1, 3, 512, 512])
Encoded latents shape: torch.Size([1, 4, 64, 64])
Decoded images shape: torch.Size([1, 3, 512, 512])

如你所见,原本 512x512 尺寸的图片被压缩到 64x64的隐式表示形式(有四个通道)中。每一空间维度上都被压缩到了原有的八分之一,这也是为什么我们设定 widthheight 时需要它们是 8 的倍数。

使用这些信息量充裕的 4x64x64 隐编码可比使用 512px 大小的图片要高效多了,可以让我们的扩散模型更快,并使用更少的资源来训练和使用。VAE的解码过程并不是完美的,但即使损失了一点点质量,总的来说也足够好了。

注意:上面的代码例子包含了一个值为 0.18215 的缩放因子,以此来适配stable diffusion训练时的处理流程。

分词器(Tokenizer)和文本编码器(Text Encoder)

文本编码器的作用是将输入的字符串(文本提示)转化成数值表示形式,这样才能输入进 UNet 作为条件。文本首先要被管线中的分词器(tokenizer)转换成一系列的分词(token)。文本编码器有大约五万分词的词汇量 —— 任何不存在于这些词汇量中的词语都会被细分成多个更小的词语。这些分词然后就被送入文本编码器模型中 —— 文本编码器是一个transformer模型,最初被训练作为CLIP的文本编码器。这里我们希望这个经过了预训练的transformer模型学习到了足够好的文本表示能力,可以对我们这里的扩散任务一样有用。

我们这里通过对一个文字提示进行编码,验证一下这个过程。首先,我们手动进行分词,并将它输入到文本编码器中,再使用管线的 _encode_prompt 方法,观察一下完成的过程,这包括补全或截断分词串的长度,使得分词串的长度等于最大长度 77 :

# Tokenizing and encoding an example prompt manualy:

# Tokenize
input_ids = pipe.tokenizer(["A painting of a flooble"])['input_ids']
print("Input ID -> decoded token")
for input_id in input_ids[0]:
  print(f"{input_id} -> {pipe.tokenizer.decode(input_id)}")

# Feed through CLIP text encoder
input_ids = torch.tensor(input_ids).to(device)
with torch.no_grad():
  text_embeddings = pipe.text_encoder(input_ids)['last_hidden_state']
print("Text embeddings shape:", text_embeddings.shape)
Input ID -> decoded token
49406 -> <|startoftext|>
320 -> a
3086 -> painting
539 -> of
320 -> a
4062 -> floo
1059 -> ble
49407 -> <|endoftext|>
Text embeddings shape: torch.Size([1, 8, 1024])
# Get the final text embeddings using the pipeline's _encode_prompt function:
text_embeddings = pipe._encode_prompt("A painting of a flooble", device, 1, False, '')
text_embeddings.shape
F:\software\Anaconda\envs\test\lib\site-packages\diffusers\pipelines\stable_diffusion\pipeline_stable_diffusion.py:237: FutureWarning: `_encode_prompt()` is deprecated and it will be removed in a future version. Use `encode_prompt()` instead. Also, be aware that the output format changed from a concatenated tensor to a tuple.
  deprecate("_encode_prompt()", "1.0.0", deprecation_message, standard_warn=False)



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

Cell In[6], line 2
      1 # Get the final text embeddings using the pipeline's _encode_prompt function:
----> 2 text_embeddings = pipe._encode_prompt("A painting of a flooble", device, 1, False, '')
      3 text_embeddings.shape


File F:\software\Anaconda\envs\test\lib\site-packages\diffusers\pipelines\stable_diffusion\pipeline_stable_diffusion.py:251, in StableDiffusionPipeline._encode_prompt(self, prompt, device, num_images_per_prompt, do_classifier_free_guidance, negative_prompt, prompt_embeds, negative_prompt_embeds, lora_scale)
    239 prompt_embeds_tuple = self.encode_prompt(
    240     prompt=prompt,
    241     device=device,
   (...)
    247     lora_scale=lora_scale,
    248 )
    250 # concatenate for backwards comp
--> 251 prompt_embeds = torch.cat([prompt_embeds_tuple[1], prompt_embeds_tuple[0]])
    253 return prompt_embeds


TypeError: expected Tensor as element 0 in argument 0, but got NoneType

这些文本嵌入(text embedding),也即文本编码器中最后一个transformer模块的“隐状态(hidden state)”,将会被送入 UNet 中作为 forward 函数的一个额外输入,下面部分我们会详细看到。

UNet

UNet 模型接收一个带噪的输入,并预测噪声,和我们之前单元中看到的 UNet 一样。但与以往例子不同的是,这里的输入并不是图片了,而是图片的隐式表示形式(latent representation)。此外,除了把用于暗示带噪程度的timestep输入进 UNet 作为条件外,这里模型也把文字提示(prompt)的文本嵌入(text embeddings)作为了额外输入。这里我们假数据试着让它预测一下:

# Dummy inputs:
timestep = pipe.scheduler.timesteps[0]
latents = torch.randn(1, 4, 64, 64).to(device)
text_embeddings = torch.randn(1, 77, 1024).to(device)

# Model prediction:
with torch.no_grad():
  unet_output = pipe.unet(latents, timestep, text_embeddings).sample
print('UNet output shape:', unet_output.shape) # Same shape as the input latents

调度器(Scheduler)

调度器保存了如何加噪的计划安排,管理着如何基于模型的预测更新带噪样本。默认的调度器是 PNDMScheduler 调度器,但你也可以用其它的(比如 LMSDiscreteScheduler 调度器),只要它们用相同的配置初始化。

我们可以画出图像来观察随着timestep添加噪声的计划安排,看看不同时间的噪声水平(基于 α ˉ \bar{\alpha} αˉ这个参数)是什么样的:

plt.plot(pipe.scheduler.alphas_cumprod, label=r'$\bar{\alpha}$')
plt.xlabel('Timestep (high noise to low noise ->)');
plt.title('Noise schedule');plt.legend();

在这里插入图片描述

pip install scipy
Looking in indexes: http://mirrors.aliyun.com/pypi/simple/
Collecting scipy
  Downloading http://mirrors.aliyun.com/pypi/packages/32/8e/7f403535ddf826348c9b8417791e28712019962f7e90ff845896d6325d09/scipy-1.10.1-cp38-cp38-win_amd64.whl (42.2 MB)
Requirement already satisfied: numpy<1.27.0,>=1.19.5 in f:\software\anaconda\envs\test\lib\site-packages (from scipy) (1.23.0)
Installing collected packages: scipy
Successfully installed scipy-1.10.1
Note: you may need to restart the kernel to use updated packages.

如果你想尝试不同的调度器,你可以像下面代码中一样换一个新的:

from diffusers import LMSDiscreteScheduler

# Replace the scheduler
pipe.scheduler = LMSDiscreteScheduler.from_config(pipe.scheduler.config)

# Print the config
print('Scheduler config:', pipe.scheduler)

# Generate an image with this new scheduler
pipe(prompt="Palette knife painting of an winter cityscape", height=480, width=480,
     generator=torch.Generator(device=device).manual_seed(42)).images[0]
Scheduler config: LMSDiscreteScheduler {
  "_class_name": "LMSDiscreteScheduler",
  "_diffusers_version": "0.21.4",
  "beta_end": 0.012,
  "beta_schedule": "scaled_linear",
  "beta_start": 0.00085,
  "clip_sample": false,
  "num_train_timesteps": 1000,
  "prediction_type": "epsilon",
  "set_alpha_to_one": false,
  "skip_prk_steps": true,
  "steps_offset": 1,
  "timestep_spacing": "linspace",
  "trained_betas": null,
  "use_karras_sigmas": false
}




  0%|          | 0/50 [00:00<?, ?it/s]

在这里插入图片描述

在这里你可以了解更多使用不同调度器的信息。

DIY一个采样循环

现在我们已经一个个看过这些组成部分了,我们可以把它们拼装到一起,来复现一下整个管线的功能:

guidance_scale = 8 #@param
num_inference_steps=30 #@param
prompt = "Beautiful picture of a wave breaking" #@param
negative_prompt = "zoomed in, blurry, oversaturated, warped" #@param

# Encode the prompt
text_embeddings = pipe._encode_prompt(prompt, device, 1, True, negative_prompt)

# Create our random starting point
latents = torch.randn((1, 4, 64, 64), device=device, generator=generator)
latents *= pipe.scheduler.init_noise_sigma

# Prepare the scheduler
pipe.scheduler.set_timesteps(num_inference_steps, device=device)

# Loop through the sampling timesteps
for i, t in enumerate(pipe.scheduler.timesteps):

  # expand the latents if we are doing classifier free guidance
  latent_model_input = torch.cat([latents] * 2)

  # Apply any scaling required by the scheduler
  latent_model_input = pipe.scheduler.scale_model_input(latent_model_input, t)

  # predict the noise residual with the unet
  with torch.no_grad():
    noise_pred = pipe.unet(latent_model_input, t, encoder_hidden_states=text_embeddings).sample

  # perform guidance
  noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
  noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)

  # compute the previous noisy sample x_t -> x_t-1
  latents = pipe.scheduler.step(noise_pred, t, latents).prev_sample

# Decode the resulting latents into an image
with torch.no_grad():
  image = pipe.decode_latents(latents.detach())

# View
pipe.numpy_to_pil(image)[0]
F:\software\Anaconda\envs\test\lib\site-packages\diffusers\pipelines\stable_diffusion\pipeline_stable_diffusion.py:430: FutureWarning: The decode_latents method is deprecated and will be removed in 1.0.0. Please use VaeImageProcessor.postprocess(...) instead
  deprecate("decode_latents", "1.0.0", deprecation_message, standard_warn=False)

在这里插入图片描述

其它的一些管线

Img2Img

直到现在,我们生成的图片还都是完全从随机的隐变量来开始生成的,而且也都使用了完整的扩散模型采样循环。但其实我们不必从头开始。Img2Img 这个管线首先将一张已有的图片进行编码,编码成一系列的隐变量,然后在这些隐变量上随机加噪声,以这些作为起始点。噪声加多大量、去噪需要的步数决定了这个 img2img 过程的“强度”。只加一点点噪声(强度低)只会带来微小改变,而加入最大量的噪声并跑完完整的去噪过程又会生成出几乎完全不像原始图片的结果,即使可能在整体结构上还多少有点相似。

这个管线无需什么特殊模型,只要模型的 ID 和我们的文字到图像模型一样就行,没有新的需要下载的文件。

# Loading an Img2Img pipeline
model_id = "stabilityai/stable-diffusion-2-1-base"
img2img_pipe = StableDiffusionImg2ImgPipeline.from_pretrained(model_id).to(device)
unet\diffusion_pytorch_model.safetensors not found



Loading pipeline components...:   0%|          | 0/6 [00:00<?, ?it/s]

在本节的“配置”部分,我们加载了一个名为 init_image 的图片来用于这里的演示,当然你也可以用你自己的图片替换它。这里是使用该管线的代码:

# Apply Img2Img
result_image = img2img_pipe(
    prompt="An oil painting of a man on a bench",
    image = init_image, # The starting image
    strength = 0.6, # 0 for no change, 1.0 for max strength
).images[0]

# View the result
fig, axs = plt.subplots(1, 2, figsize=(12, 5))
axs[0].imshow(init_image);axs[0].set_title('Input Image')
axs[1].imshow(result_image);axs[1].set_title('Result');
---------------------------------------------------------------------------

RuntimeError                              Traceback (most recent call last)


RuntimeError: CUDA out of memory. Tried to allocate 128.00 MiB (GPU 0; 4.00 GiB total capacity; 9.90 GiB already allocated; 0 bytes free; 10.01 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation.  See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF

练习: 用这个管线做实验,试试你自己的图片,或者试试不同的强度和文字提示。你可以使用很多和文字到图片管线相同的输入参数。所以尽可能试试不同的图片尺寸、生成步数吧。

In-Painting

如果我们想在一张图中保留一部分不变而在其它部分生成新东西,那该怎么办呢?这种技术叫 inpainting 。虽然我们可以通过前面演示中的同一个模型(用 StableDiffusionInpaintPipelineLegacy 管线)来实现,但我们这里可以用一个自定义的微调版 Stable Diffusion 模型来得到更好的效果。这里的 Stable Diffusion 模型接收一个掩模(mask)作为额外条件性输入。这个掩模图片需要和输入图片尺寸一致,白色区域表示要被替换的部分,黑色区域表示要保留的部分。以下代码就展示了我们如何载入这个管线并如何应用到前面载入的示例图片和掩模上:

# Load the inpainting pipeline (requires a suitable inpainting model)
pipe = StableDiffusionInpaintPipeline.from_pretrained("runwayml/stable-diffusion-inpainting")
pipe = pipe.to(device)
Downloading (…)ain/model_index.json:   0%|          | 0.00/548 [00:00<?, ?B/s]


F:\software\Anaconda\envs\test\lib\site-packages\huggingface_hub\file_download.py:137: UserWarning: `huggingface_hub` cache-system uses symlinks by default to efficiently store duplicated files but your machine does not support them in C:\Users\11637\.cache\huggingface\hub. Caching files will still work but in a degraded version that might require more space on your disk. This warning can be disabled by setting the `HF_HUB_DISABLE_SYMLINKS_WARNING` environment variable. For more details, see https://huggingface.co/docs/huggingface_hub/how-to-cache#limitations.
To support symlinks on Windows, you either need to activate Developer Mode or to run Python as an administrator. In order to see activate developer mode, see this article: https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development
  warnings.warn(message)
unet\diffusion_pytorch_model.safetensors not found



Fetching 16 files:   0%|          | 0/16 [00:00<?, ?it/s]



Downloading pytorch_model.bin:   0%|          | 0.00/1.22G [00:00<?, ?B/s]



Downloading (…)_checker/config.json:   0%|          | 0.00/4.78k [00:00<?, ?B/s]



Downloading pytorch_model.bin:   0%|          | 0.00/492M [00:00<?, ?B/s]



Downloading (…)tokenizer/merges.txt:   0%|          | 0.00/525k [00:00<?, ?B/s]



Downloading (…)cial_tokens_map.json:   0%|          | 0.00/472 [00:00<?, ?B/s]



Downloading (…)cheduler_config.json:   0%|          | 0.00/313 [00:00<?, ?B/s]



Downloading (…)okenizer_config.json:   0%|          | 0.00/806 [00:00<?, ?B/s]



Downloading (…)tokenizer/vocab.json:   0%|          | 0.00/1.06M [00:00<?, ?B/s]



Downloading (…)rocessor_config.json:   0%|          | 0.00/342 [00:00<?, ?B/s]



Downloading (…)49d/unet/config.json:   0%|          | 0.00/748 [00:00<?, ?B/s]



Downloading (…)_encoder/config.json:   0%|          | 0.00/617 [00:00<?, ?B/s]



Downloading (…)b49d/vae/config.json:   0%|          | 0.00/552 [00:00<?, ?B/s]



Downloading (…)on_pytorch_model.bin:   0%|          | 0.00/335M [00:00<?, ?B/s]

ProxyError: (MaxRetryError("HTTPSConnectionPool(host='huggingface.co', port=443): Max retries exceeded with url: /runwayml/stable-diffusion-inpainting/resolve/51388a731f57604945fddd703ecb5c50e8e7b49d/config.json (Caused by ProxyError('Cannot connect to proxy.', timeout('_ssl.c:1114: The handshake operation timed out')))"), '(Request ID: fb3b77aa-4c46-4dd6-9245-5a2f602160e4)')
# Inpaint with a prompt for what we want the result to look like
prompt = "A small robot, high resolution, sitting on a park bench"
image = pipe(prompt=prompt, image=init_image, mask_image=mask_image).images[0]

# View the result
fig, axs = plt.subplots(1, 3, figsize=(16, 5))
axs[0].imshow(init_image);axs[0].set_title('Input Image')
axs[1].imshow(mask_image);axs[1].set_title('Mask')
axs[2].imshow(image);axs[2].set_title('Result');

当和其它可以自动生成掩模的模型结合起来的时候,这个模型将会相当强大。比如这个示例space就用了一个名为 CLIPSeg 的模型,它可以根据文字描述自动地用掩模去掉一个物体。

题外话:管理你的模型缓存

探索不同的管线和模型可能会占满你的硬盘空间。你可用这个指令看看你都下载了哪些模型到你的硬盘上:

!ls ~/.cache/huggingface/diffusers/ # List the contents of the cache directory
models--CompVis--stable-diffusion-v1-4
models--ddpm-bedroom-256
models--google--ddpm-bedroom-256
models--google--ddpm-celebahq-256
models--runwayml--stable-diffusion-inpainting
models--stabilityai--stable-diffusion-2-1-base

看看缓存相关文档来了解如何高效地查看和管理缓存。

Depth2Image

在这里插入图片描述

Input image, depth image and generated examples (image source: StabilityAI)

Img2Img 已经很厉害了,但有时我们还想用原始图片的组成成分但使用完全不同的颜色或纹理来生成新图片。通过调节 Img2Img 的“强度”来保留图片整体结构但却不保留原有颜色将会很困难。

所以这里就需要另一个微调的模型了!这个模型需要输入额外的深度信息作为生成条件。相关管线使用了一个深度预测模型来预测出一个深度图,然后这个深度图会被输入微调过的 UNet 中用以生成图片。我们这里希望生成的图片能够保留原始图片的深度信息和总体结构,同时又在相关部分填入全新的内容。

# Load the Depth2Img pipeline (requires a suitable model)
pipe = StableDiffusionDepth2ImgPipeline.from_pretrained("stabilityai/stable-diffusion-2-depth")
pipe = pipe.to(device)
# Inpaint with a prompt for what we want the result to look like
prompt = "An oil painting of a man on a bench"
image = pipe(prompt=prompt, image=init_image).images[0]

# View the result
fig, axs = plt.subplots(1, 2, figsize=(16, 5))
axs[0].imshow(init_image);axs[0].set_title('Input Image')
axs[1].imshow(image);axs[1].set_title('Result');
  0%|          | 0/40 [00:00<?, ?it/s]

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1169674.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目实战:删除特定水果库存记录

1、在index.js中添加删除点击事件 1.1、common.js function $(key){if(key){if(key.startsWith("#")){key key.substring(1)return document.getElementById(key)}else{let nodeList document.getElementsByName(key)return Array.from(nodeList)}} } window.onloa…

c语言从入门到实战——VS2022实用调试技巧

VS实用调试技巧 前言1. 什么是bug2. 什么是调试&#xff08;debug&#xff09;3. Debug和Release4. VS调试快捷键4.1 环境准备4.2 调试快捷键 5. 监视和内存观察5.1 监视5.2 内存 6. 调试举例17. 调试举例28. 编程常见错误归类8.1 编译型错误8.2 链接型错误8.3 运行时错误 前言…

UI自动化测试:会消失的弹窗(Toast)如何定位?

前言 看到标题可能有的小伙伴们懵了&#xff0c;什么是Toast&#xff0c;其实Toast大家都见过&#xff0c;就是一般在我们页面中停留大概2~3秒的时间后自动消失的弹框&#xff0c;那么既然要做自动化&#xff0c;可能Toast也需要大家进行测试&#xff0c;那么小编今天就来介绍…

如何使用CSS命名规范提高您的编码效率

CSS命名约定可以提高团队成员在项目中的协作能力&#xff0c;通过允许开发人员简化工作流程&#xff0c;增强项目的可维护性和可扩展性。在本文中&#xff0c;我们将深入探讨CSS命名约定的世界&#xff0c;展示实际示例以及它们为您的开发过程带来的好处。 在前端开发中&#x…

[极客大挑战 2019]Http 1

题目环境&#xff1a; 看起来挺花里胡哨的 F12查看源代码寻找隐藏文件 这是啥子呀&#xff0c;果然防不胜防 点击隐藏文件Secret.php 它不是来自这个地址的请求 报头&#xff1a;https://Sycsecret.buuoj.cn 需要抓包&#xff0c;在抓包前了解部分数据包参数 GET:到 Host:来自 …

Flutter vs 前端 杂谈:SliverAppBar、手动实现Appbar、前端Html+JS怎么实现滚动变化型Appbar - 比较

Flutter vs 前端 杂谈 SliverAppBar的弹性背景的显隐效果使用HtmlJS怎么实现 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550…

MySQL数据库中不同数据类型字段关联后结果居然有这么大差异?

点击上方蓝字关注我 在数据库的世界里&#xff0c;数据的连接操作是至关重要的。但在处理关联表的字段的数据类型不同时&#xff0c;得到的结果经常会出乎预料。 1. 案例 1.1 数据库中先创建表及数据 -- 创建tb1 CREATE TABLE tb1 (id BIGINT NOT NULL PRIMARY KEY, NAME VARC…

掌握Maven和SpringBoot的灵活性:定制化lib目录和依赖范围

前言 在开发基于Maven和SpringBoot的项目时&#xff0c;我们经常会使用第三方库来满足需求。然而&#xff0c;有时候我们需要更灵活地控制这些库的依赖范围和加载方式。本文将介绍如何使用Maven和SpringBoot实现定制化的lib目录和依赖范围。经过如下定制化后&#xff0c;打包执…

【C语言】备战校赛Day3

日期:11.3 星期五 L1-007 念数字 题目描述 输入一个整数&#xff0c;输出每个数字对应的拼音。当整数为负数时&#xff0c;先输出fu字。十个数字对应的拼音如下&#xff1a; 0: ling 1: yi 2: er 3: san 4: si 5: wu 6: liu 7: qi 8: ba 9: jiu 输入描述 输入在一行中给出一个…

Spring Data Redis + RabbitMQ - 基于 string + hash 实现缓存,计数(高内聚)

目录 一、Spring Data Redis 1.1、缓存功能(分析) 1.2、案例实现 一、Spring Data Redis 1.1、缓存功能(分析) hash 类型存储缓存相比于 string 类型就有更多的更合适的使用场景. 例如,我有以下这样一个 UserInfo 信息 假设这样一个场景就是:万一只想获取其中某一个…

MySQL第三讲·SQL boy的CRUD操作

你好&#xff0c;我是安然无虞。 文章目录 增删查改&#xff1a;如何操作表中的数据&#xff1f;添加数据插入数据记录插入查询结果 删除数据修改数据查询数据select&#xff5c;where&#xff5c;group by&#xff5c;havingfromorder bylimit 增删查改&#xff1a;如何操作表…

C++标准模板(STL)- 类型支持 (类型属性,is_literal_type,is_polymorphic,is_empty)

类型特性 类型特性定义一个编译时基于模板的结构&#xff0c;以查询或修改类型的属性。 试图特化定义于 <type_traits> 头文件的模板导致未定义行为&#xff0c;除了 std::common_type 可依照其所描述特化。 定义于<type_traits>头文件的模板可以用不完整类型实例…

uniapp小程序刮刮乐抽奖

使用canvas画布画出刮刮乐要被刮的图片&#xff0c;使用移动清除画布。 当前代码封装为刮刮乐的组件&#xff1b; vue代码&#xff1a; <template><view class"page" v-if"merchantInfo.cdn_static"><image class"bg" :src&q…

强化学习的动态规划二

一、典型示例 考虑如下所示的44网格。 图1 非终端状态为S {1, 2, . . . , 14}。在每个状态下有四种可能的行为&#xff0c;A {up, down, right, left}&#xff0c;这些行为除了会将代理从网格上移走外&#xff0c;其他都会确定性地引起相应的状态转换。因此&#xff0c;例如&…

VMware产品收集日志方法汇总

概述 vCenter日志是一个用于存储与vSphere环境相关的各种活动、事件和警告的日志系统。通过收集并分析vCenter日志&#xff0c;管理员可以获得有关其虚拟化环境的重要洞察和故障排除信息。 vCenter日志由多个组件组成&#xff0c;包括vCenter Server、ESXi主机和其他vSphere组…

软件测试面试题:Web 端测试和 App 端测试有何不同

Web 端测试和 App 端测试是针对不同平台的上的应用进行测试&#xff0c;Web应用和App端的应用实现方式不同&#xff0c;测试时的侧重点也不一样。 今天这篇文章就来介绍下两者的不同之处以及测试时的侧重点。 Web 端应用和 App 端应用的区别 平台兼容性 Web 端应用可以在任何…

C#开源的一个能利用Windows通知栏背单词的软件 - ToastFish

前言 今天给大家推荐一个C#开源且免费的能利用Windows通知栏背单词的软件&#xff0c;可以让你在上班、上课等恶劣环境下安全隐蔽地背单词&#xff08;利用摸鱼时间背单词的软件&#xff09;&#xff1a;ToastFish。 操作系统要求 目前该软件只支持Windows10及以上系统&…

【C语言】C语言⻘蛙跳台阶问题--递归问题

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 本期专栏&#x1f525;&#xff1a;本期将分享一些猜数字小游戏怎么一步一步实现的 &#x1f308;作者寄语 &#x1f308;&#xff1a; 小菜鸟的力量不在于它的体型&#xff0c;而在于它内心…

Fourier分析导论——第3章——Fourier级数的收敛性(E.M. Stein R. Shakarchi)

第 3 章 Fourier级数的收敛性(Convergence of Fourier Series) The sine and cosine series, by which one can represent an arbitrary function in a given interval, enjoy among other remarkable properties that of being convergent. This property did not escape…

nodejs+vue网上商城系统系统-毕业设计

网上商城系统的架构设计通常分为三层&#xff1a;客户端层、应用层和数据层。 客户端层&#xff1a;客户端层是用户与系统交互的界面&#xff0c;包括Web页面、移动App等。用户可以通过客户端层进行商品浏览、下单、支付等操作。应用层&#xff1a;应用层是业务逻辑处理的中心&…