DALL-E与文本生成图像技术

🎙️ 语音朗读 当前: 晓晓 (温柔女声)

DALL-E与文本生成图像技术

2022年是AIGC(AI生成内容)爆发的一年,文本生成图像技术从实验室走向大众。本文将深入解析DALL-E系列模型的技术原理与演进路线。

1. 从DALL-E到DALL-E 2

DALL-E 1:自回归生成

DALL-E 1采用自回归方式,将图像生成视为序列生成问题:

1
文本 → BPE编码 → Transformer → 自回归生成图像token → VQ-VAE解码 → 图像

核心思路是将图像离散化为token序列,然后像语言模型一样逐个生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class DALLE_VQVAE(nn.Module):
"""VQ-VAE将图像编码为离散token"""
def __init__(self, num_embeddings=8192, embed_dim=256):
super().__init__()
self.encoder = nn.Sequential(
nn.Conv2d(3, 64, 4, 2, 1),
ResBlock(64),
nn.Conv2d(64, 256, 4, 2, 1),
ResBlock(256),
nn.Conv2d(256, embed_dim, 1)
)
self.codebook = nn.Embedding(num_embeddings, embed_dim)
self.decoder = nn.Sequential(
nn.Conv2d(embed_dim, 256, 1),
ResBlock(256),
nn.ConvTranspose2d(256, 64, 4, 2, 1),
ResBlock(64),
nn.ConvTranspose2d(64, 3, 4, 2, 1)
)

def encode(self, x):
z = self.encoder(x)
# 量化:找最近的codebook向量
distances = (z.unsqueeze(2) - self.codebook.weight.unsqueeze(0).unsqueeze(0))
indices = distances.norm(dim=-1).argmin(dim=-1)
return indices

def decode(self, indices):
z_q = self.codebook(indices)
return self.decoder(z_q.permute(0, 3, 1, 2))

DALL-E 2:先验+解码器

DALL-E 2(也称为unCLIP)采用两阶段架构:

1
2
3
4
5
文本 → CLIP文本编码器 → 文本embedding

先验网络(Prior) → 图像embedding

解码器(Decoder) → 生成图像

2. DALL-E 2核心组件

2.1 先验网络(Prior)

先验网络将CLIP文本embedding映射到CLIP图像embedding:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class DiffusionPrior(nn.Module):
"""
使用扩散模型作为先验网络
从文本embedding生成图像embedding
"""
def __init__(self, clip_model, embed_dim=512):
super().__init__()
self.clip = clip_model
self.transformer = nn.Transformer(
d_model=embed_dim * 2,
nhead=8,
num_encoder_layers=6,
num_decoder_layers=6
)
self.embed_dim = embed_dim

def forward(self, text_embedding, t, noise=None):
"""
扩散过程:在图像embedding上添加噪声
然后用Transformer预测去噪
"""
# 时间步编码
t_emb = self.time_embed(t)

# 拼接文本embedding和噪声图像embedding
x = torch.cat([text_embedding, noise], dim=-1)

# Transformer预测噪声
predicted_noise = self.transformer(x, t_emb)
return predicted_noise

@torch.no_grad()
def sample(self, text_embedding, num_steps=50):
"""DDIM采样生成图像embedding"""
# 从纯噪声开始
x = torch.randn(1, self.embed_dim)

for t in reversed(range(num_steps)):
# 预测噪声
noise_pred = self.forward(text_embedding, t, x)

# DDIM更新
alpha = 1 - (t / num_steps)
x = (x - (1 - alpha).sqrt() * noise_pred) / alpha.sqrt()

return x # 生成的图像embedding

2.2 解码器(Decoder)

解码器从CLIP图像embedding生成高分辨率图像,使用级联扩散模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class CascadedDecoder(nn.Module):
"""
级联扩散解码器
64×64 → 256×256 → 1024×1024
"""
def __init__(self):
super().__init__()
# 低分辨率解码器
self.base_decoder = UNet(
input_channels=3 + 512, # 噪声图像 + CLIP embedding
output_channels=3,
channels=[128, 256, 512, 512],
attention_resolutions=[16, 8]
)

# 超分辨率解码器
self.sr_64_256 = UNet(
input_channels=3 + 512,
output_channels=3,
channels=[128, 256, 512, 512, 512],
attention_resolutions=[32, 16, 8]
)

self.sr_256_1024 = UNet(
input_channels=3 + 512,
output_channels=3,
channels=[128, 256, 512, 512, 512, 512],
attention_resolutions=[64, 32, 16]
)

def decode(self, clip_image_embedding, num_steps=50):
"""从CLIP图像embedding生成高分辨率图像"""
# 第一阶段:生成64×64图像
img_64 = self.diffusion_sample(
self.base_decoder,
clip_image_embedding,
shape=(1, 3, 64, 64),
steps=num_steps
)

# 第二阶段:上采样到256×256
img_256 = self.diffusion_sample(
self.sr_64_256,
clip_image_embedding,
condition=img_64,
shape=(1, 3, 256, 256),
steps=num_steps
)

# 第三阶段:上采样到1024×1024
img_1024 = self.diffusion_sample(
self.sr_256_1024,
clip_image_embedding,
condition=img_256,
shape=(1, 3, 1024, 1024),
steps=num_steps
)

return img_1024

3. DALL-E API使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import openai

def generate_image(prompt, size="1024x1024", n=1):
"""使用DALL-E API生成图像"""
response = openai.Image.create(
prompt=prompt,
n=n,
size=size,
response_format="url"
)

image_urls = [item["url"] for item in response["data"]]
return image_urls

# 创意生成示例
prompts = [
"一只穿着宇航服的猫在月球上行走,赛博朋克风格",
"中国水墨画风格的未来城市",
"梵高风格的纽约天际线",
]

for prompt in prompts:
urls = generate_image(prompt)
print(f"Prompt: {prompt}")
print(f"Generated: {urls[0]}")

图像编辑功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def edit_image(image_path, mask_path, prompt):
"""使用DALL-E进行图像编辑"""
with open(image_path, "rb") as img, open(mask_path, "rb") as mask:
response = openai.Image.create_edit(
image=img,
mask=mask,
prompt=prompt,
n=1,
size="1024x1024"
)
return response["data"][0]["url"]

# 示例:将照片中的猫替换为狗
new_url = edit_image(
"cat_photo.png",
"cat_mask.png", # 白色区域为需要编辑的部分
"一只金毛犬坐在沙发上"
)

4. 文本生成图像技术对比

模型 方法 分辨率 质量 速度
DALL-E 自回归 256×256
DALL-E 2 扩散 1024×1024
Stable Diffusion 潜扩散 512×512
Imagen 扩散 1024×1024 很高
Midjourney 扩散 1024×1024 很高

5. AIGC的伦理考量

文本生成图像技术的普及带来了重要的伦理问题:

  • 版权问题:AI生成的图像版权归谁?
  • 深度伪造:生成虚假图像的滥用风险
  • 偏见放大:训练数据中的偏见被模型继承
  • 艺术家权益:AI对创意行业的冲击

总结

DALL-E系列展示了文本到图像生成的巨大潜力。从自回归到扩散模型的技术演进,使得生成质量不断提升。随着AIGC技术的成熟,我们正在进入一个创意民主化的新时代——每个人都可以用自然语言来创造视觉内容。

© 2019-2026 ovo$^{mc^2}$ All Rights Reserved. | 站点总访问 28969 次 | 访客 19045
Theme by hiero