Datawhale X 魔搭 AI夏令营 第四期 AIGC方向 task02 精读代码,实战进阶

前情提要

Datawhale X 魔搭 AI夏令营 第四期 AIGC方向 task01 从零入门AI生图原理&实践-CSDN博客

        在task01中,我们了解了利用大模型进行文生图的基本原理,并利用主办方提供的baseline跑出了一组图片。但我们对这一过程尚没有足够深入的理解,因此,在这一部分的任务中,我们将利用通义千问辅助我们分析baseline的源代码,探索文生图过程中的运行机理。

1 关于通义千问

        通义千问是由阿里云开发的人工智能助手,能够在多个领域为用户提供高效的信息支持和辅助。在接下来的学习过程中,通义千问将帮助我们分析源代码。

        有什么不会的,问问通义千问吧:通义官网

2 精读baseline

        首先看看baseline代码的框架结构:

图1 baseline的框架结构(图源datawhale教程)

        从框架图可以清晰地看出baseline从环境配置到生成图像的处理过程,下面利用通义千问分析源代码是如何执行这一过程的。

2.1 分析baseline执行过程

将下面的代码和对通义千问生成内容的要求丢给它,然后等待返回分析结果。

你是一个优秀的python开发工程师,现在我们需要你帮我们分析这个代码的主体框架,你需要把代码按照工作流分成几部分,用中文回答我的问题。

!pip install simple-aesthetics-predictor

!pip install -v -e data-juicer

!pip uninstall pytorch-lightning -y
!pip install peft lightning pandas torchvision

!pip install -e DiffSynth-Studio

from modelscope.msdatasets import MsDataset

ds = MsDataset.load(
    'AI-ModelScope/lowres_anime',
    subset_name='default',
    split='train',
    cache_dir="/mnt/workspace/kolors/data"
)

import json, os
from data_juicer.utils.mm_utils import SpecialTokens
from tqdm import tqdm


os.makedirs("./data/lora_dataset/train", exist_ok=True)
os.makedirs("./data/data-juicer/input", exist_ok=True)
with open("./data/data-juicer/input/metadata.jsonl", "w") as f:
    for data_id, data in enumerate(tqdm(ds)):
        image = data["image"].convert("RGB")
        image.save(f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg")
        metadata = {"text": "二次元", "image": [f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg"]}
        f.write(json.dumps(metadata))
        f.write("\n")

data_juicer_config = """
# global parameters
project_name: 'data-process'
dataset_path: './data/data-juicer/input/metadata.jsonl'  # path to your dataset directory or file
np: 4  # number of subprocess to process your dataset

text_keys: 'text'
image_key: 'image'
image_special_token: '<__dj__image>'

export_path: './data/data-juicer/output/result.jsonl'

# process schedule
# a list of several process operators with their arguments
process:
    - image_shape_filter:
        min_width: 1024
        min_height: 1024
        any_or_all: any
    - image_aspect_ratio_filter:
        min_ratio: 0.5
        max_ratio: 2.0
        any_or_all: any
"""
with open("data/data-juicer/data_juicer_config.yaml", "w") as file:
    file.write(data_juicer_config.strip())

!dj-process --config data/data-juicer/data_juicer_config.yaml

import pandas as pd
import os, json
from PIL import Image
from tqdm import tqdm


texts, file_names = [], []
os.makedirs("./data/data-juicer/output/images", exist_ok=True)
with open("./data/data-juicer/output/result.jsonl", "r") as f:
    for line in tqdm(f):
        metadata = json.loads(line)
        texts.append(metadata["text"])
        file_names.append(metadata["image"][0])

df = pd.DataFrame({"text": texts, "file_name": file_names})
df.to_csv("./data/data-juicer/output/result.csv", index=False)

df

from transformers import CLIPProcessor, CLIPModel
import torch

model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

images = [Image.open(img_path) for img_path in df["file_name"]]
inputs = processor(text=df["text"].tolist(), images=images, return_tensors="pt", padding=True)

outputs = model(**inputs)
logits_per_image = outputs.logits_per_image  # this is the image-text similarity score
probs = logits_per_image.softmax(dim=1)  # we can take the softmax to get the probabilities

probs

from torch.utils.data import Dataset, DataLoader

class CustomDataset(Dataset):
    def __init__(self, df, processor):
        self.texts = df["text"].tolist()
        self.images = [Image.open(img_path) for img_path in df["file_name"]]
        self.processor = processor

    def __len__(self):
        return len(self.texts)

    def __getitem__(self, idx):
        inputs = self.processor(text=self.texts[idx], images=self.images[idx], return_tensors="pt", padding=True)
        return inputs

dataset = CustomDataset(df, processor)
dataloader = DataLoader(dataset, batch_size=8)

for batch in dataloader:
    outputs = model(**batch)
    logits_per_image = outputs.logits_per_image
    probs = logits_per_image.softmax(dim=1)
    print(probs)

import torch
from diffusers import StableDiffusionPipeline

torch.manual_seed(1)
pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v-1-4", torch_dtype=torch.float16)
pipe = pipe.to("cuda")

prompt = "二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒"
negative_prompt = "丑陋、变形、嘈杂、模糊、低对比度"
guidance_scale = 4
num_inference_steps = 50

image = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    guidance_scale=guidance_scale,
    num_inference_steps=num_inference_steps,
    height=1024,
    width=1024,
).images[0]

image.save("example_image.png")
image

from PIL import Image

torch.manual_seed(1)
image = pipe(
    prompt="二次元,日系动漫,演唱会的观众席,人山人海,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,舞台上衣着华丽的歌星们在唱歌",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("1.jpg")

torch.manual_seed(1)
image = pipe(
    prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,露出憧憬的神情",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,色情擦边",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("2.jpg")

torch.manual_seed(2)
image = pipe(
    prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,露出憧憬的神情",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,色情擦边",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("3.jpg")

torch.manual_seed(5)
image = pipe(
    prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙,对着流星许愿,闭着眼睛,十指交叉,侧面",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,扭曲的手指,多余的手指",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("4.jpg")

torch.manual_seed(0)
image = pipe(
    prompt="二次元,一个紫色中等长度头发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("5.jpg")

torch.manual_seed(1)
image = pipe(
    prompt="二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("6.jpg")

torch.manual_seed(7)
image = pipe(
    prompt="二次元,紫色长发少女,穿着黑色连衣裙,试衣间,心情忐忑",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("7.jpg")

torch.manual_seed(0)
image = pipe(
    prompt="二次元,紫色长发少女,穿着黑色礼服,连衣裙,在台上唱歌",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("8.jpg")

import numpy as np
from PIL import Image


images = [np.array(Image.open(f"{i}.jpg")) for i in range(1, 9)]
image = np.concatenate([
    np.concatenate(images[0:2], axis=1),
    np.concatenate(images[2:4], axis=1),
    np.concatenate(images[4:6], axis=1),
    np.concatenate(images[6:8], axis=1),
], axis=0)
image = Image.fromarray(image).resize((1024, 2048))
image

通义千问向我们回复了如下内容:

这段代码可以分为几个主要的工作流程部分来分析:

1. 安装和卸载依赖包
这部分使用 `!pip` 命令安装和卸载Python环境中的依赖包。这些命令包括:
- 安装 `simple-aesthetics-predictor`, `data-juicer`, `peft`, `lightning`, `pandas`, `torchvision` 和 `DiffSynth-Studio`。
- 卸载并重新安装 `pytorch-lightning`。

2. 加载数据集
这部分加载了一个名为 `lowres_anime` 的数据集,并将数据保存到指定的目录中。

3. 数据预处理与转换
这部分对原始数据进行预处理,包括创建必要的文件夹,将图像数据和对应的文本描述转换为JSON格式,并存储到文件中。

 4. 配置和运行 DataJuicer
这部分创建了一个 YAML 文件来配置 DataJuicer 的参数,并使用这些参数过滤和处理图像数据。

5. 数据后处理
这部分读取经过 DataJuicer 处理的数据,并将其转换为Pandas DataFrame,以便进一步处理。

6. 计算图像和文本相似性
这部分使用CLIP模型计算处理后的图像与其对应文本之间的相似性。

7. 创建自定义数据集类
这部分定义了一个自定义的 PyTorch `Dataset` 类,用于加载处理后的数据,并创建一个 DataLoader 对象以批量处理数据。

8. 使用 StableDiffusionPipeline 生成图像
这部分使用 `StableDiffusionPipeline` 根据不同的提示(prompt)生成一系列图像,并保存到本地。

9. 图像拼接
最后一部分将生成的多个图像拼接成一个大的图像,并调整其大小。

整个过程从加载原始数据开始,通过一系列的数据处理步骤,最终使用深度学习模型生成新的图像内容。每一步都是为了准备数据、处理数据或利用模型生成结果。

2.2 逐行分析

在代码前加上如下指示,让通义千问再次分析:

你是一个优秀的python开发工程师,现在我们需要你帮我们逐行分析这个代码,用中文回答我的问题。

通义千问回答了如下内容:

# 安装 simple-aesthetics-predictor 包
!pip install simple-aesthetics-predictor

# 以可编辑模式安装 data-juicer 包,并启用详细输出
!pip install -v -e data-juicer

# 卸载 pytorch-lightning 包
!pip uninstall pytorch-lightning -y
# 安装 peft, lightning, pandas 和 torchvision 包
!pip install peft lightning pandas torchvision

# 以可编辑模式安装 DiffSynth-Studio 包
!pip install -e DiffSynth-Studio

# 导入 ModelScope 的 MsDataset 类,用于加载数据集
from modelscope.msdatasets import MsDataset

# 加载 ModelScope 中名为 lowres_anime 的数据集
ds = MsDataset.load(
    'AI-ModelScope/lowres_anime',
    subset_name='default',  # 子集名称
    split='train',  # 数据集分割,这里选择训练集
    cache_dir="/mnt/workspace/kolors/data"  # 缓存目录
)

# 导入 json, os 模块
import json, os
# 导入 SpecialTokens 类,可能是用于处理特殊标记的工具
from data_juicer.utils.mm_utils import SpecialTokens
# 导入 tqdm 模块,用于显示进度条
from tqdm import tqdm

# 创建存储训练图像的目录
os.makedirs("./data/lora_dataset/train", exist_ok=True)
# 创建存储 DataJuicer 输入文件的目录
os.makedirs("./data/data-juicer/input", exist_ok=True)
# 打开 metadata.jsonl 文件用于写入
with open("./data/data-juicer/input/metadata.jsonl", "w") as f:
    # 遍历数据集,并为每条数据创建元数据
    for data_id, data in enumerate(tqdm(ds)):
        # 将图像转换为 RGB 模式并保存
        image = data["image"].convert("RGB")
        image.save(f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg")
        # 创建包含文本和图像路径的元数据
        metadata = {"text": "二次元", "image": [f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg"]}
        # 写入元数据到文件
        f.write(json.dumps(metadata))
        f.write("\n")

# 定义 DataJuicer 的配置字符串
data_juicer_config = """
# 全局参数
project_name: 'data-process'
dataset_path: './data/data-juicer/input/metadata.jsonl'  # 数据集文件路径
np: 4  # 处理数据集时使用的子进程数量

text_keys: 'text'
image_key: 'image'
image_special_token: '<__dj__image>'

export_path: './data/data-juicer/output/result.jsonl'

# 处理流程
# 一系列处理操作及其参数
process:
    - image_shape_filter:
        min_width: 1024  # 最小宽度
        min_height: 1024  # 最小高度
        any_or_all: any  # 至少满足一个条件即可
    - image_aspect_ratio_filter:
        min_ratio: 0.5  # 最小宽高比
        max_ratio: 2.0  # 最大宽高比
        any_or_all: any  # 至少满足一个条件即可
"""

# 将 DataJuicer 配置写入文件
with open("data/data-juicer/data_juicer_config.yaml", "w") as file:
    file.write(data_juicer_config.strip())

# 使用 DataJuicer 对数据集进行处理
!dj-process --config data/data-juicer/data_juicer_config.yaml

# 导入 pandas, os, json 模块
import pandas as pd
import os, json
# 导入 Image 模块,用于处理图像
from PIL import Image
# 导入 tqdm 模块,用于显示进度条
from tqdm import tqdm

# 创建存储处理后图像的目录
os.makedirs("./data/data-juicer/output/images", exist_ok=True)
# 打开处理后的结果文件
with open("./data/data-juicer/output/result.jsonl", "r") as f:
    # 初始化两个列表用于存储文本和图像文件名
    texts, file_names = [], []
    # 遍历文件中的每一行
    for line in tqdm(f):
        # 解析 JSON 格式的元数据
        metadata = json.loads(line)
        # 将文本添加到列表
        texts.append(metadata["text"])
        # 将图像文件名添加到列表
        file_names.append(metadata["image"][0])

# 创建 DataFrame 并保存为 CSV 文件
df = pd.DataFrame({"text": texts, "file_name": file_names})
df.to_csv("./data/data-juicer/output/result.csv", index=False)

# 显示 DataFrame
df

# 导入 CLIPModel 和 CLIPProcessor
from transformers import CLIPProcessor, CLIPModel
# 导入 PyTorch
import torch

# 加载预训练的 CLIP 模型
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
# 加载预训练的 CLIP 处理器
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

# 从 DataFrame 中读取图像文件,并进行处理
images = [Image.open(img_path) for img_path in df["file_name"]]
inputs = processor(text=df["text"].tolist(), images=images, return_tensors="pt", padding=True)

# 通过模型获取输出
outputs = model(**inputs)
# 获取图像与文本的相似度分数
logits_per_image = outputs.logits_per_image
# 计算概率分布
probs = logits_per_image.softmax(dim=1)

# 显示概率分布
probs

# 导入 PyTorch 的 Dataset 和 DataLoader 类
from torch.utils.data import Dataset, DataLoader

# 定义自定义数据集类
class CustomDataset(Dataset):
    def __init__(self, df, processor):
        # 初始化文本、图像和处理器
        self.texts = df["text"].tolist()
        self.images = [Image.open(img_path) for img_path in df["file_name"]]
        self.processor = processor

    # 返回数据集的长度
    def __len__(self):
        return len(self.texts)

    # 获取指定索引的数据项
    def __getitem__(self, idx):
        # 使用处理器对文本和图像进行处理
        inputs = self.processor(text=self.texts[idx], images=self.images[idx], return_tensors="pt", padding=True)
        return inputs

# 创建自定义数据集实例
dataset = CustomDataset(df, processor)
# 创建 DataLoader 实例
dataloader = DataLoader(dataset, batch_size=8)

# 遍历数据加载器中的批次
for batch in dataloader:
    # 通过模型获取输出
    outputs = model(**batch)
    # 获取图像与文本的相似度分数
    logits_per_image = outputs.logits_per_image
    # 计算概率分布
    probs = logits_per_image.softmax(dim=1)
    # 输出概率分布
    print(probs)

# 导入 PyTorch
import torch
# 导入 StableDiffusionPipeline
from diffusers import StableDiffusionPipeline

# 设置随机种子以确保生成结果的一致性
torch.manual_seed(1)
# 加载预训练的 StableDiffusionPipeline 模型
pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v-1-4", torch_dtype=torch.float16)
# 将模型移动到 GPU 上
pipe = pipe.to("cuda")

# 定义生成图像的提示
prompt = "二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒"
# 定义负面提示
negative_prompt = "丑陋、变形、嘈杂、模糊、低对比度"
# 设置引导尺度
guidance_scale = 4
# 设置推理步数
num_inference_steps = 50

# 生成图像
image = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    guidance_scale=guidance_scale,
    num_inference_steps=num_inference_steps,
    height=1024,
    width=1024,
).images[0]

# 保存生成的图像
image.save("example_image.png")
# 显示生成的图像
image

# 导入 Image 模块,用于处理图像
from PIL import Image

# 设置随机种子以确保生成结果的一致性
torch.manual_seed(1)
# 使用不同的提示生成图像
image = pipe(
    prompt="二次元,日系动漫,演唱会的观众席,人山人海,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,舞台上衣着华丽的歌星们在唱歌",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,  # 注意这里使用了 cfg_scale 而不是 guidance_scale
    num_inference_steps=50, height=1024, width=1024,
)
# 保存生成的图像
image.save("1.jpg")

# 设置随机种子以确保生成结果的一致性
torch.manual_seed(1)
# 使用不同的提示生成图像
image = pipe(
    prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,露出憧憬的神情",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,色情擦边",
    cfg_scale=4,  # 注意这里使用了 cfg_scale 而不是 guidance_scale
    num_inference_steps=50, height=1024, width=1024,
)
# 保存生成的图像
image.save("2.jpg")

# 设置随机种子以确保生成结果的一致性
torch.manual_seed(2)
# 使用不同的提示生成图像
image = pipe(
    prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,露出憧憬的神情",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,色情擦边",
    cfg_scale=4,  # 注意这里使用了 cfg_scale 而不是 guidance_scale
    num_inference_steps=50, height=1024, width=1024,
)
# 保存生成的图像
image.save("3.jpg")

# 设置随机种子以确保生成结果的一致性
torch.manual_seed(5)
# 使用不同的提示生成图像
image = pipe(
    prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙,对着流星许愿,闭着眼睛,十指交叉,侧面",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,扭曲的手指,多余的手指",
    cfg_scale=4,  # 注意这里使用了 cfg_scale 而不是 guidance_scale
    num_inference_steps=50, height=1024, width=1024,
)
# 保存生成的图像
image.save("4.jpg")

# 设置随机种子以确保生成结果的一致性
torch.manual_seed(0)
# 使用不同的提示生成图像
image = pipe(
    prompt="二次元,一个紫色中等长度头发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,  # 注意这里使用了 cfg_scale 而不是 guidance_scale
    num_inference_steps=50, height=1024, width=1024,
)
# 保存生成的图像
image.save("5.jpg")

# 设置随机种子以确保生成结果的一致性
torch.manual_seed(1)
# 使用不同的提示生成图像
image = pipe(
    prompt="二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,  # 注意这里使用了 cfg_scale 而不是 guidance_scale
    num_inference_steps=50, height=1024, width=1024,
)
# 保存生成的图像
image.save("6.jpg")

# 设置随机种子以确保生成结果的一致性
torch.manual_seed(7)
# 使用不同的提示生成图像
image = pipe(
    prompt="二次元,紫色长发少女,穿着黑色连衣裙,试衣间,心情忐忑",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,  # 注意这里使用了 cfg_scale 而不是 guidance_scale
    num_inference_steps=50, height=1024, width=1024,
)
# 保存生成的图像
image.save("7.jpg")

# 设置随机种子以确保生成结果的一致性
torch.manual_seed(0)
# 使用不同的提示生成图像
image = pipe(
    prompt="二次元,紫色长发少女,穿着黑色礼服,连衣裙,在台上唱歌",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,  # 注意这里使用了 cfg_scale 而不是 guidance_scale
    num_inference_steps=50, height=1024, width=1024,
)
# 保存生成的图像
image.save("8.jpg")

# 导入 numpy 和 Image 模块
import numpy as np
from PIL import Image

# 读取已生成的图像,并组合成一个新的图像
images = [np.array(Image.open(f"{i}.jpg")) for i in range(1, 9)]
image = np.concatenate([
    np.concatenate(images[0:2], axis=1),
    np.concatenate(images[2:4], axis=1),
    np.concatenate(images[4:6], axis=1),
    np.concatenate(images[6:8], axis=1),
], axis=0)
# 将组合后的图像转换为 PIL.Image 对象并调整大小
image = Image.fromarray(image).resize((1024, 2048))
# 显示组合后的图像
image

        回答很长,但是为每行代码都做了注释,我们可以在阅读代码的过程中利用注释快速地了解各部分代码的作用。

        另外,通义千问具有连续问答功能,因此我们可以继续提问对代码不了解的地方,让通义提供解答。

3 实战演练一一基于话剧的连环画制作

        在了解了baseline的运行原理后,我们再利用baseline的代码生成一组8幅情节连续的图片。

3.1 准备提示词

        这次我们让通义千问写提示词。给出我们的要求,让通义根据要求给出8幅图片的提示词。

我们的要求:

你是一个文生图专家,我们现在要做一个实战项目,就是要编排一个文生图话剧
话剧由8张场景图片生成,你需要输出每张图片的生图提示词

具体的场景:
1、男主在篮球馆看球星打球
2、男主想要成为一位球星
3、男主在篮球场努力练习
4、男主和其他人打篮球赛
5、男主进入了球队,穿上了属于自己的球衣
6、男主从通道走进篮球馆
7、男主在比赛中表现出色
8、男主赢得了比赛

例子:写实,一个短发黄种人男孩,坐在球场观众席,看着下面的比赛、背影,白色T恤

通义的回答:

当然可以。我们将把所有提到红色球衣的地方改为黄色球衣。下面是更新后的提示词:

场景 1: 男主在篮球馆看球星打球
提示词: 写实,一个短发黄种人男孩,坐在球场观众席,看着下面的比赛、背影,白色T恤
场景 2: 男主想要成为一位球星
提示词: 写实,一个短发黄种人男孩站在篮球场上,目光坚定地望着前方,手里拿着篮球,身穿蓝色训练服,背景是空旷的篮球场
场景 3: 男主在篮球场努力练习
提示词: 写实,一个短发黄种人男孩在篮球场上独自练习投篮,汗水湿透了他的蓝色训练服,背景是黄昏下的篮球场
场景 4: 男主和其他人打篮球赛
提示词: 写实,一个短发黄种人男孩和其他球员正在进行激烈的篮球比赛,他正在运球突破对方防守,身穿黄色球衣,背景是热闹的篮球场
场景 5: 男主进入了球队,穿上了属于自己的球衣
提示词: 写实,一个短发黄种人男孩站在更衣室内,身穿黄色球衣,背后印有他的名字和号码,脸上洋溢着自豪的笑容
场景 6: 男主从通道走进篮球馆
提示词: 写实,一个短发黄种人男孩从球员通道走出,身穿黄色球衣,背景是灯火辉煌的篮球馆入口
场景 7: 男主在比赛中表现出色
提示词: 写实,一个短发黄种人男孩在比赛中扣篮,身穿黄色球衣,背景是欢呼的人群和篮球架
场景 8: 男主赢得了比赛
提示词: 写实,一个短发黄种人男孩手持奖杯庆祝胜利,身穿黄色球衣,周围是队友和教练,背景是庆祝的球迷

3.2 运行baseline  

        用这些提示词替换baseline中图像生成部分的提示词,再运行一次baseline得到想要的结果

        (悄悄在这里放一首See You Again

3.3 展示结果

图2 根据提示生成的8幅连续图像

3.4 美学打分

task01中报名的赛事要求美学打分需要超过6,我们利用下面的代码进行美学分数评估:

import torch, os
from PIL import Image
from transformers import CLIPProcessor
from aesthetics_predictor import AestheticsPredictorV2Linear
from modelscope import snapshot_download
 
 
model_id = snapshot_download('AI-ModelScope/aesthetics-predictor-v2-sac-logos-ava1-l14-linearMSE', cache_dir="models/")
predictor = AestheticsPredictorV2Linear.from_pretrained(model_id)
processor = CLIPProcessor.from_pretrained(model_id)
device = "cuda"
predictor = predictor.to(device)
 
 
def get_aesthetics_score(image):
    inputs = processor(images=image, return_tensors="pt")
    inputs = {k: v.to(device) for k, v in inputs.items()}
    with torch.no_grad():
        outputs = predictor(**inputs)
    prediction = outputs.logits
    return prediction.tolist()[0][0]
 
 
def evaluate(folder):
    scores = []
    for file_name in os.listdir(folder):
        if os.path.isfile(os.path.join(folder, file_name)):
            image = Image.open(os.path.join(folder, file_name))
            scores.append(get_aesthetics_score(image))
    if len(scores) == 0:
        return 0
    else:
        return sum(scores) / len(scores)
 
 
score = evaluate("./images")
print(score)

        对刚刚生成的图片的美学打分如下:

图3 美学打分的结果

        PS:要记得运行后记得关闭实例避免算力时长浪费

4 试试scepter studio

        SCEPTER是基于开源基模型和自研微调编辑算法构建的生成定制和编辑工具箱,提供围绕生成、微调、编辑、数据处理等一系列的工具和插件。魔搭提供了在线的体验功能:

Scepter万能图片编辑生成工作台icon-default.png?t=N7T8https://www.modelscope.cn/studios/iic/scepter_studio        SCEPTER是一个专注于生成式训练、微调和推理的开源代码库,涵盖了一系列下游任务,包括图像生成、转换和编辑等。SCEPTER整合了社区驱动的流行实现以及阿里巴巴集团通义实验室的专有方法,为AIGC领域的研究人员和从业者提供了全面的工具包。这个灵活的库旨在促进创新并加速生成模型领域迅速发展的进程。(翻译自项目Github页面)

        项目的Github地址如下,可以利用教程在本地进行部署。SCEPTERSCEPTER is an open-source framework used for training, fine-tuning, and inference with generative models. - modelscope/sceptericon-default.png?t=N7T8https://github.com/modelscope/scepter

         本轮的工作到这里就告一段落。AI生图在近几年随着人工智能(尤其是大模型)的发展在速度和质量上均获得了长足的进步,从StableDIffusion刚刚面世时生成图像的粗糙甚至产生恐怖谷效应到如今的以假乱真,AI生图的上限仍在不断刷新我们的认知。想要了解更多内容,可以访问魔搭社区挑选感兴趣的工具进行体验,持续探索AI生图前沿技术。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值