0. 图片加噪过程¶
先看调度表,再看图片序列。原图权重下降表示图像信号变弱,噪声权重上升表示随机噪声变强。
In [3]:
# 真实图片扩散:按时间步逐渐加入噪声。
ddpm_photo = Image.fromarray(load_sample_image("flower.jpg")).resize((128, 128))
ddpm_image = np.asarray(ddpm_photo).astype("float32") / 255.0
sample = torch.tensor(ddpm_image).permute(2, 0, 1).unsqueeze(0) * 2 - 1
torch.manual_seed(12)
noise = torch.randn(sample.shape)
scheduler = DDPMScheduler(num_train_timesteps=1000)
timesteps = [0, 50, 150, 300, 500]
ddpm_images = []
diff_rows = []
for t in timesteps:
timestep = torch.tensor([t], dtype=torch.long)
noisy = scheduler.add_noise(sample, noise, timestep)
image = ((noisy[0].permute(1, 2, 0).numpy() + 1) / 2).clip(0, 1)
ddpm_images.append(image)
alpha_bar = float(scheduler.alphas_cumprod[t])
diff_rows.append({
"时间步": t,
"累计保留系数": alpha_bar,
"原图权重": np.sqrt(alpha_bar),
"噪声权重": np.sqrt(1 - alpha_bar),
"像素标准差": float(image.std()),
})
diff_1d_df = pd.DataFrame(diff_rows)
display(diff_1d_df.round(4))
| 时间步 | 累计保留系数 | 原图权重 | 噪声权重 | 像素标准差 | |
|---|---|---|---|---|---|
| 0 | 0 | 0.9999 | 0.9999 | 0.0100 | 0.2373 |
| 1 | 50 | 0.9700 | 0.9849 | 0.1733 | 0.2393 |
| 2 | 150 | 0.7859 | 0.8865 | 0.4627 | 0.2670 |
| 3 | 300 | 0.3940 | 0.6277 | 0.7785 | 0.3211 |
| 4 | 500 | 0.0778 | 0.2789 | 0.9603 | 0.3525 |
In [4]:
# 绘制真实图片在不同时间步下的前向扩散效果。
fig, axes = plt.subplots(2, 3, figsize=(9.0, 6.0))
for ax, image, timestep in zip(axes.ravel(), ddpm_images, timesteps):
ax.imshow(image)
ax.set_title(f"时间步 {timestep}", fontweight="bold")
ax.set_xticks([])
ax.set_yticks([])
for ax in axes.ravel()[len(ddpm_images):]:
ax.axis("off")
fig.suptitle("真实图片前向加噪", x=0.08, ha="left", fontsize=14, fontweight="bold", color="#0f172a")
plt.tight_layout()
plt.show()