“Datawhale x魔搭 AI夏令营”-AIGC方向-Day2从零入门AI生图原理&实践

学习内容提要

从通过代码实现AI文生图逐渐进阶,教程偏重图像工作流、微调、图像优化等思路,最后会简单介绍AIGC应用方向、数字人技术(选学)

Task02:精读代码,实战进阶

具体Datawhale教程学习内容见链接:https://linklearner.com/activity/14/10/32

AIGC相关知识框图

解读baseline代码

文生图代码的框架结构:

使用通义输入问题:

通义返回答案:

好的,让我们逐行分析这段代码。

1. 环境准备与依赖安装

!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
  • 第一行安装了simple-aesthetics-predictor包。
  • 第二行安装了data-juicer包,并且是以开发模式安装,即编辑源码后无需重新安装即可生效。
  • 第三行卸载了pytorch-lightning包。
  • 第四行安装了一系列包,包括peft(可能是指PEFT,即Prompt-Encoder Fine-Tuning)、lightningpytorch-lightning的新版本或另一个库)、pandastorchvision
  • 第五行同样以开发模式安装了DiffSynth-Studio包。

2. 加载数据集

from modelscope.msdatasets import MsDataset

ds = MsDataset.load(
    'AI-ModelScope/lowres_anime',
    subset_name='default',
    split='train',
    cache_dir="/mnt/workspace/kolors/data"
)
  • 导入MsDataset类,这是来自ModelScope的模块,用于加载数据集。
  • 使用MsDataset.load方法加载名为lowres_anime的数据集,指定子集名称为default,只加载训练集,并将缓存目录设置为/mnt/workspace/kolors/data

3. 数据集预处理

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")
  • 导入了jsonos模块,以及SpecialTokens类和tqdm进度条库。
  • 创建两个目录:./data/lora_dataset/train./data/data-juicer/input,如果它们已经存在则不会报错。
  • 遍历数据集中的每个元素,将图像转换为RGB格式,并保存到指定的目录中,同时将每张图像的路径和对应的标签("二次元")写入metadata.jsonl文件。

4. 配置文件定义与数据清洗

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
  • 定义了一个字符串变量data_juicer_config,其中包含了data-juicer工具所需的配置信息,包括项目名、数据集路径、要保留的图像尺寸要求(最小宽度和高度均为1024像素),以及图像的宽高比范围。
  • 将配置信息写入到data_juicer_config.yaml文件中。
  • 运行dj-process命令,使用上述配置文件对数据集进行清洗。

5. 清洗后数据集处理

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
  • 导入了pandasosjsonPIL.Image以及tqdm
  • 创建一个目录./data/data-juicer/output/images
  • 读取清洗后生成的result.jsonl文件中的每一行,并从中提取文本描述和图像路径,存储到列表textsfile_names中。
  • 使用pandas创建DataFrame并将数据保存为CSV文件result.csv

6. 特征提取

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
  • 导入CLIPProcessorCLIPModel类,以及torch库。
  • 加载预训练的CLIP模型和处理器。
  • 从DataFrame中读取图像文件,并使用处理器对图像和文本进行预处理。
  • 使用CLIP模型计算图像与文本之间的相似度分数,并将其转化为概率分布。

7. 定制数据集与加载器

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)
  • 定义了一个CustomDataset类,继承自torch.utils.data.Dataset
  • 实现了__init____len____getitem__方法,用于初始化数据集、返回数据集大小和获取数据集中的单个样本。
  • 使用CustomDataset实例化一个数据集,并创建一个DataLoader对象来迭代数据集,批量大小为8。
  • 遍历DataLoader,使用CLIP模型计算每个批次的图像与文本之间的相似度分数,并打印出概率分布。

8. 图像生成

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")

# 下面是一系列使用不同提示和参数生成图像的代码
  • 导入torchStableDiffusionPipeline
  • 设置随机种子以保证结果的一致性。
  • 加载预训练的StableDiffusionPipeline模型,并将其移动到GPU上。
  • 使用不同的提示和参数生成多幅图像,并将它们保存到本地文件系统中。

9. 图像展示

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
  • 导入numpyPIL.Image
  • 读取之前生成的8幅图像,并将它们拼接成一幅大图。
  • 调整大图的大小为1024x2048像素,并展示最终的图像。

这段代码实现了一个完整的流程,从数据集加载、预处理、清洗、特征提取、数据集封装、使用深度学习模型生成特定主题图像,到最后展示生成的结果。

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

通义千问上输入

你是一个文生图专家,我们现在要做一个实战项目,就是要编排一个文生图话剧
话剧由8张场景图片生成,你需要输出每张图片的生图提示词
具体的场景图片
1、女主正在上课
2、开始睡着了
3、进入梦乡,梦到自己站在路旁
4、王子骑马而来
5、两人相谈甚欢
6、一起坐在马背上
7、下课了,梦醒了
8、又回到了学习生活中
生图提示词要求
1、风格为古风
2、根据场景确定是使用全身还是上半身
3、人物描述
4、场景描述
5、做啥事情
例子:
古风,水墨画,一个黑色长发少女,坐在教室里,盯着黑板,深思,上半身,红色长裙
好的,这里为您展示前四张场景的示例图像:

输出

好的,基于您的要求,我将为您设计每一张场景图片的生图提示词。我们将确保每张图片都符合古风的要求,并且包含人物描述、场景描述以及他们在做什么。接下来是针对每个场景的具体提示词:

1. 女主正在上课

  • 提示词:古风,工笔画,一个黑色长发少女,身穿绿色长裙,坐在古色古香的学堂内,正凝视着前方的先生,认真听讲,上半身特写。

2. 开始睡着了

  • 提示词:古风,淡墨渲染,一个黑色长发少女,身穿绿色长裙,坐在古色古香的学堂内,头轻轻垂下,陷入梦乡,上半身特写。

3. 进入梦乡,梦到自己站在路旁

  • 提示词:古风,轻柔水彩,一个黑色长发少女,身穿绿色长裙,站在青石铺就的小路上,四周是朦胧的云雾,似乎正期待着什么,全身。

4. 王子骑马而来

  • 提示词:古风,细腻线条,一个黑色长发少女,身穿绿色长裙,站在小路旁,远处一位英俊少年骑着白马缓缓而来,全身。

5. 两人相谈甚欢

  • 提示词:古风,细腻笔触,一个黑色长发少女,身穿绿色长裙,与一位英俊少年并肩而立,两人正在交谈,表情愉快,全身。

6. 一起坐在马背上

  • 提示词:古风,流畅线条,一个黑色长发少女,身穿绿色长裙,与英俊少年同坐于白马之上,两人并肩而行,背景是翠绿的山林,全身。

7. 下课了,梦醒了

  • 提示词:古风,淡雅色彩,一个黑色长发少女,身穿绿色长裙,坐在学堂内,突然睁开眼睛,从梦中醒来,上半身特写。

8. 又回到了学习生活中

  • 提示词:古风,细致勾勒,一个黑色长发少女,身穿绿色长裙,坐在学堂内,正低头专注地看书,周围是其他认真学习的同学,上半身特写。

为了更好地帮助您理解这些场景,我可以为您生成这些场景的示例图像。请确认是否需要生成这些图像。
好的,这里为您展示前四张场景的示例图像:

场景 1: 女主正在上课

女主正在上课

场景 2: 开始睡着了

开始睡着了

场景 3: 进入梦乡,梦到自己站在路旁

进入梦乡,梦到自己站在路旁

场景 4: 王子骑马而来

王子骑马而来

场景 5: 两人相谈甚欢

场景 6: 一起坐在马背上

场景 7: 下课了,梦醒了

场景 8: 又回到了学习生活中

问题

发现一个问题:没有识别到关键词“红色长裙”,所以我重新强调了一下“穿着红色长裙”。于是得到如下回答:

当然可以,我将把“红色长裙”这一细节加入到提示词中。以下是更新后的提示词:
场景 1: 女主正在上课
古风,淡雅色彩
一个黑色长发少女,穿着红色长裙
坐在教室里,上半身特写
背景是木质桌椅和纸窗,墙上挂着毛笔字
少女正认真听讲,手里拿着毛笔
场景 2: 开始睡着了
古风,柔和色调
黑色长发少女,穿着红色长裙
侧脸特写,半闭的眼睛,嘴角微微上扬
背景是一本书和一支掉落的毛笔
少女趴在桌上,渐渐入眠
场景 3: 进入梦乡,梦到自己站在路旁
古风,梦幻色彩
全身像,黑色长发少女,穿着红色长裙
站在一条古道旁,四周是朦胧的山林
背景是雾气缭绕的小径和远处的山峦
少女眺望着远方,表情略带疑惑
场景 4: 王子骑马而来
古风,明亮色彩
全身像,黑色长发少女,穿着红色长裙
一位英俊少年骑着白马缓缓靠近
背景是开阔的草原和远处的宫殿轮廓
少年向少女伸出手,眼神温柔
场景 5: 两人相谈甚欢
古风,温馨色调
半身像,黑色长发少女与英俊少年相对而坐,少女穿着红色长裙
背景是树荫下的石桌石凳
两人脸上带着微笑,正在进行愉快的对话
场景 6: 一起坐在马背上
古风,动感色彩
全身像,黑色长发少女与英俊少年并肩坐在马背上,少女穿着红色长裙
背景是快速后退的风景
少女双手环抱着少年腰间,两人笑容满面
场景 7: 下课了,梦醒了
古风,现实色彩
半身像,黑色长发少女,穿着红色长裙
背景是教室内部,同学们陆续离开
少女从梦中醒来,眼神迷茫,随后露出微笑
场景 8: 又回到了学习生活中
古风,自然色彩
半身像,黑色长发少女,穿着红色长裙
背景是书架和古籍
少女手捧书本,专注阅读
现在我们可以根据这些提示词来生成图像。您希望现在就开始生成这些图像吗?


你还别说,这生成的场景,我感觉写的文笔还挺好的,感觉都可以让它写小说了……
后面调整之后的图片如下:

好的,我已经生成了前四个场景的图像。接下来是剩余场景的图像生成。

这里是已经生成的图像:

  1. 女主正在上课

  2. 开始睡着了

  3. 进入梦乡,梦到自己站在路旁

  4. 王子骑马而来

  5. 两人相谈甚欢

  6. 一起坐在马背上

  7. 下课了,梦醒了

  8. 又回到了学习生活中


然后我发现他没有改成古风,就提醒他。结果发现它并不能理解这个图片不是古风。比如男生是短发的……就不符合古风要求。

baseline 修改重跑

按照教程里面这个场景设置了

结果

1、女主正在上课


2、开始睡着了

3、进入梦乡,梦到自己站在路旁

4、王子骑马而来

5、两人相谈甚欢

6、一起坐在马背上

7、下课了,梦醒了

8、又回到学习中


这才符合我们对于古风的定位嘛

其他尝试

试着复现《蛤蟆先生去看心理医生》的大章标题。

你是一个文生图专家,我们现在要做一个实战项目,就是要编排一个文生图话剧
话剧由8张场景图片生成,你需要输出每张图片的生图提示词
具体的场景图片
1、蛤蟆先生最近感觉整个人都不太好了
2、挚友田鼠先生前来相助
3、蛤蟆先生去看心理医生,心理医生是一头鹿
4、两人相谈甚欢
5、两人一起吃午餐
6、蛤蟆先生最后变得开心
7、蛤蟆先生向鹿先生告别
8、蛤蟆先生又回到了绅士的生活,身边有很多朋友
生图提示词要求
1、风格为童话
2、根据场景确定是使用全身还是上半身
3、人物描述
4、场景描述
5、做啥事情

得到回答:

好的,让我们为这个童话风格的话剧编写生成图像的提示词。每一张图都将包含风格、人物和场景描述,以及正在进行的动作。
好的,我们将添加“可爱风”和“卡通风”到原有的提示词中,以确保生成的图像更加温馨可爱。下面是更新后的提示词列表:

  1. 蛤蟆先生最近感觉整个人都不太好了

    • 卡通风, 可爱风, 童话风格, 全身, 蛤蟆先生忧郁的表情, 床上躺着, 阴暗的房间, 愁眉不展
  2. 挚友田鼠先生前来相助

    • 卡通风, 可爱风, 童话风格, 上半身, 田鼠先生关切的眼神, 蛤蟆先生略显沮丧, 客厅沙发, 田鼠先生安慰蛤蟆先生
  3. 蛤蟆先生去看心理医生,心理医生是一头鹿

    • 卡通风, 可爱风, 童话风格, 上半身, 蛤蟆先生坐在椅子上, 心理医生鹿先生坐对面, 医生办公室, 鹿先生倾听蛤蟆先生
  4. 两人相谈甚欢

    • 卡通风, 可爱风, 童话风格, 上半身, 蛤蟆先生微笑, 鹿先生点头, 咖啡桌旁, 对话进行中
  5. 两人一起吃午餐

    • 卡通风, 可爱风, 童话风格, 全身, 蛤蟆先生与鹿先生, 餐桌前, 餐馆内, 正在享用美食
  6. 蛤蟆先生最后变得开心

    • 卡通风, 可爱风, 童话风格, 上半身, 蛤蟆先生笑得很灿烂, 公园长椅, 阳光明媚, 感到轻松愉快
  7. 蛤蟆先生向鹿先生告别

    • 卡通风, 可爱风, 童话风格, 全身, 蛤蟆先生挥手告别, 鹿先生微笑点头, 诊所门口, 送别场景
  8. 蛤蟆先生又回到了绅士的生活,身边有很多朋友

    • 卡通风, 可爱风, 童话风格, 全身, 蛤蟆先生穿着整洁, 与众多动物朋友聚会, 宽敞的客厅, 欢乐的气氛

再用baseline跑一下

emm怎么说呢,SAN值狂掉啊。还发现一个问题,训练出来的模型对于修改场景中一部分的细节prompt提示词并不变化,所以猜测他的场景比较简单。

再来看看通义生成的部分图片,确实还是很抽象的。

“童话风格, 蛤蟆先生, 全身, 沉闷的卧室, 感到沮丧”。

“童话风格, 蛤蟆先生, 田鼠先生, 上半身, 蛤蟆的家, 安慰蛤蟆”。

“童话风格, 蛤蟆先生, 鹿心理医生, 上半身, 心理咨询室, 咨询治疗”。

posted on 2024-08-14 23:31  琢磨亿下  阅读(37)  评论(0编辑  收藏  举报

导航