Datawhale X 魔搭 AI夏令营 Task2:精读代码,实战进阶

Part1:磨刀准备一一认识通义千问

  1. 通义千问的自我介绍

首先,我们来看下它的自我介绍。通义千问是具有信息查询、语言理解、文本创作等多能力的AI助手。我们可以看到,编程与技术支持能力是它的强项之一。(P1:通义千问自我介绍)

接下来我们把场景聚焦到编程与技术支持这个方向,让他详细介绍下自己可以如何帮助大家编程。(P2:编程能力介绍)。

  1. 抱走你的AI学习助教

作为一个AI助手,通义千问就是你专属的、可随时触达的、24小时随时待命的贴心助教,可以帮助你解决很多学习中遇到的问题。

所以当你遇到学习问题的时候,问问千问吧。在这里请接收一下通义千问的邀请函!

  1. 使用操作指南

官方链接:https://tongyi.aliyun.com/qianwen/

step1 注册账号

step2 通义主要功能模块

主要功能模块:

  1. 对话,支持文字输入,文件上传等模式,我们本次课程主要使用当前模块;

  2. 效率,各种学习办公小工具;

  3. 智能体,通义的智能体应用市场,大家可以根据自己的需求找到很多

Part2:精读baseline——从零入门AI生图

在task1的任务中, 我们拿到baseline文件后, 根据教程指示顺畅通关, 似乎没有什么问题。但是可能有些同学看到这个baseline的代码会一脸懵,就很想知道某一个模块、某一行究竟是干啥的,下面我们就借助前面讲到的通义千问来精读这个代码。

首先我们来直观感知下这个文生图代码的框架结构:

!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. 分析代码的主体架构

  1. 输入的Prompt

 

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

  1. 返回的结果

这段代码主要分为以下几个部分:

  1. 安装和卸载依赖包

  • 使用 !pip 命令来安装或卸载 Python 包。包括:

    • simple-aesthetics-predictor, data-juicer, peft, lightning, pandas, torchvision, 和 DiffSynth-Studio 的安装。

    • 卸载 pytorch-lightning(使用 -y 自动确认卸载)。

  1. 加载数据集

  • 使用 ModelScope 的 MsDataset 类加载名为 AI-ModelScope/lowres_anime 的数据集,并指定子集名称为 default 和分割为 train,缓存目录设置为 /mnt/workspace/kolors/data

  1. 数据预处理

  • 将数据集中的图像转换为 RGB 模式,并保存到指定目录。

  • 创建包含图像路径和文本描述的元数据文件 metadata.jsonl

  • 编写并保存 data_juicer_config.yaml 配置文件,用于后续的数据过滤和处理。

  1. 使用 Data-Juicer 进行数据处理

  • 使用 dj-process 命令根据配置文件对数据进行过滤和处理,生成 result.jsonl 文件。

  1. 数据整理与训练

  • 读取 result.jsonl 文件中的数据,并将其转换为 Pandas DataFrame,然后保存为 CSV 文件,并且将图片保存到./data/lora_dataset_processed/train文件夹下。

  • 下载模型download_models(["Kolors", "SDXL-vae-fp16-fix"])

  • 在前面模型的基础上,执行Lora微调训练

  • 加载微调后的模型

  1. 图像生成

  • 设置正向提示词,反向提示词,执行次数,图片尺寸

  • 设置随机种子,控制图片是否可以重复生成,并将图像保存为 .jpg 文件。

  1. 合并图像

  • 最后,将生成的多个图像合并成一个大图像,并调整大小。

整个流程涵盖了从数据加载、预处理、特征提取、模型预测到图像生成等多个方面。每一部分都有其特定的功能,共同构成了一个完整的二次元图像处理和生成的工作流。

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

  1. 数据准备

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

    具体的场景图片
    1、女主走在林间小道上
    2、天色渐渐昏暗
    3、突然,下起了大雨
    4、雾气蒙蒙,视线开始模糊
    5、过了一会,雨过天晴,发现进来到了一座大山前
    6、女主开始爬山
    7、走到了山顶,俯瞰山下是壮观的美景
    8、忽然,女主从床上醒来发现刚刚的都是一场梦

    生图提示词要求
    1、风格为二次元
    2、根据场景确定是使用全身还是上半身
    3、人物描述
    4、场景描述
    5、做啥事情

    例子:
    二次元,一个红色长发少女,在小路上,行走,林间,昏暗

  3. 通义的回答:

  4. 了解了您的具体要求后,我将为这八个场景分别编写生图提示词。以下是根据您的指示制定的提示词列表:

  5. 女主走在林间小道上

    • 二次元风格,全身,一个红发少女,身穿轻盈的古风长裙,在幽静的林间小道上行走,四周是葱郁的树木与绽放的野花,阳光透过树叶洒下斑驳的光影。
  6. 天色渐渐昏暗

    • 二次元风格,上半身特写,红发少女站在林间,天色转暗,夕阳的余晖映照在她的脸上,周围环境逐渐变得昏暗,眼神透露出一丝不安。
  7. 突然,下起了大雨

    • 二次元风格,全身,红发少女手持一把油纸伞,站在倾盆大雨中,水珠沿着伞沿滴落,她的表情显得有些惊讶,四周是被雨水打湿的树木和草地。
  8. 雾气蒙蒙,视线开始模糊

    • 二次元风格,全身,红发少女在雾气弥漫的小道上缓缓前行,视线透过轻纱般的雾气望向远方,身后是若隐若现的树木,她的表情略显迷茫。
  9. 过了一会,雨过天晴,发现进来到了一座大山前

    • 二次元风格,全身,红发少女站在山脚下,身后是渐渐散去的云雾,阳光洒落在她身上,前方是巍峨的大山,她的眼神中充满了好奇和期待。
  10. 女主开始爬山

    • 二次元风格,全身,红发少女身着便于行动的装束,正奋力攀爬陡峭的山路,背景是层层叠叠的山峦,她的表情坚定而努力。
  11. 走到了山顶,俯瞰山下是壮观的美景

    • 二次元风格,上半身特写,红发少女立于山巅之上,眺望着脚下延绵不绝的山脉与云海,微风吹拂着她的衣袂,她的表情充满欣喜和感慨。
  12. 忽然,女主从床上醒来发现刚刚的都是一场梦

    • 二次元风格,上半身特写,红发少女躺在床上,刚从梦中惊醒,眼神中带着疑惑与迷茫,屋内的布置简洁而古朴,窗外透进柔和的晨光。

设置好关键词以后,再去修改prompt就可以得到新的图了

从中可以发现,通过设置合适的关键词可以一定程度上的保证图像之间的连贯性,确保了每一张图片的人物不会产生太大的变化。

通过本次任务,我学会了如何运用AI给出合适的提示词以此来获得更好的作品。

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值