当前位置:AIGC资讯 > AIGC > 正文

#Datawhale AI夏令营第4期#AIGC方向 文生图 Task2

Task2任务:对baseline的代码有一个更加细致的理解,然后学习如何借助AI来提升我们的自学习能力.

前沿知识:了解一下 AI生图技术 的能力&局限

AI生图技术,通常指的是使用人工智能(尤其是深度学习)来生成图像的技术。这类技术可以用于多种应用场景,比如图像增强、艺术创作、虚拟角色生成、产品可视化等。AI生成图片的能力非常广泛,可以生成各种类型的图片。

根据描述生成的一张图片:一个充满未来感的城市夜景,高楼林立,霓虹灯闪烁。

示例如下(图片由通义生成)

能力

图像合成与创造:

AI可以根据给定的描述或者条件生成全新的图像,例如根据文本描述生成对应的图像。

风格迁移:

技术能够将一种图像的艺术风格应用到另一种图像上,实现风格的转换。

图像修复与增强:

对于模糊、损坏或分辨率低的图像,AI可以帮助恢复细节,提高清晰度。

个性化定制:

用户可以通过调整参数来自定义生成的内容,如改变图像中的颜色、样式或场景布局。

高效生成:

一旦模型训练完成,可以快速生成大量的图像,这对于需要大量视觉素材的应用非常有用。

多模态生成:

结合文本、音频等多种输入形式生成图像,增加交互性和多样性。

局限性

数据偏见:

AI生图模型可能会放大训练数据中存在的偏见,导致生成的内容有失公正。

创造性限制:

尽管AI可以生成新的图像,但它缺乏人类的创造力和想象力,很难完全模仿人类艺术家的独特风格。

细节缺失:

在某些情况下,生成的图像可能在细节上不够精确或存在逻辑错误。

计算资源需求高:

高质量的图像生成通常需要大量的计算资源,这对小型团队或个人用户来说可能是个挑战。

伦理和隐私问题:

使用AI生成人脸或其他敏感信息可能导致侵犯隐私和伦理问题。

版权问题:

生成的图像如果与已有的作品过于相似,可能会引发版权争议。 AI翻车:
我们现在还可以经常在各类自媒体的文章中看到“AI翻车”的案例,那些往往也是需要解决的难点,某些“翻车”现象,也许在业界已有相关的解决方案。

目前大部分的模型,已经具备了去除 “AI味” 的能力,且可能存在容易误导他人的情况,这时候我们想辨别可能需要非常仔细地——

观察图片的细节。仔细检查人物的面部特征,尤其是眼睛和嘴巴

检查光线和阴影。分析图片中的光源是否一致,阴影的方向是否与光源相符,是否存在不自然的光线或阴影

分析像素。放大图片,寻找是否有模糊或像素化的部分。

注意背景。检查背景中是否有不协调的元素,比如物体边缘是否平滑,背景中是否有不自然的重复模式。

而这些细节上的AI特性,也许就是我们在某些特定场景下需要解决的挑战。

补充:Deepfake技术

Deepfake技术是一种利用深度学习技术来创建高度逼真且难以甄别的音视频内容的方法。这项技术最广为人知的应用之一是换脸,即将一个人的脸部替换成另一个人的脸部,同时保持声音、面部表情和身体动作的一致性。Deepfake技术的核心是生成式对抗网络(Generative Adversarial Networks, GANs),它通过两组相互竞争的人工智能模型来生成几乎可以以假乱真的内容。

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

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

主要功能模块:

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

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

智能体,通义的智能体应用市场,大家可以根据自己的需求找到很多有意思的小应用。

我们在学习中,遇到任务问题都可以向《通义千问》提问,AI时代,学习效率大大提升。通义千问就是我们日常学习工作的AI助手。

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

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

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)安装和卸载Python包、2)数据处理、3)使用CLIP模型进行图像-文本匹配、4)创建PyTorch数据集和数据加载器、5)使用Stable Diffusion生成图像,6)最终合并这些图像。

2.逐行解析代码

这段代码主要完成以下功能:

安装和卸载一些Python包;

从ModelScope加载一个名为lowres_anime的数据集,并保存图像到指定目录;

创建并处理一个用于数据清洗的JSONL文件;

使用data-juicer工具过滤和处理数据集;

将处理后的数据集转换为CSV格式;

根据数据集通过DiffSynth做Lora微调;

加载Lora微调后的模型;

设置提示词,用微调后的模型生成图片。

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

我们假定一个剧本,具体的场景图片

1、女主正在上课

2、开始睡着了

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

4、王子骑马而来

5、两人相谈甚欢

6、一起坐在马背上

7、下课了,梦醒了

8、又回到了学习生活中

然后我们在通义千问的辅助下,生成提示词:

 我们再修改润色一下,最终得到的提示词如下:

图片编号

场景描述

正向提示词

反向提示词

图片1

女主正在上课

古风,水墨画,一个黑色长发少女,坐在教室里,盯着黑板,深思,上半身,红色长裙

丑陋,变形,嘈杂,模糊,低对比度

图片2

开始睡着了

古风,水墨画,一个黑色长发少女,坐在教室里,趴在桌子上睡着了,上半身,红色长裙

丑陋,变形,嘈杂,模糊,低对比度

图片3

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

古风,水墨画,一个黑色长发少女,站在路边,上半身,红色长裙

丑陋,变形,嘈杂,模糊,低对比度

图片4

王子骑马而来

古风,水墨画,一个英俊少年,骑着白马,上半身,白色衬衫

丑陋,变形,嘈杂,模糊,低对比度

图片5

两人相谈甚欢

古风,水墨画,一个英俊少年,白色衬衫,一个黑色长发少女,红色长裙,两个人一起聊天,开心,上半身

丑陋,变形,嘈杂,模糊,低对比度

图片6

一起坐在马背上

古风,水墨画,一个英俊少年,白色衬衫,一个黑色长发少女,红色长裙,两个人一起骑着马,全身

丑陋,变形,嘈杂,模糊,低对比度

图片7

下课了,梦醒了

古风,水墨画,一个黑色长发少女,坐在教室里,下课铃声响了,同学们开始走动,从睡梦中醒来,深思,上半身,红色长裙

丑陋,变形,嘈杂,模糊,低对比度

图片8

又回到了学习生活中

古风,水墨画,一个黑色长发少女,坐在教室里,盯着黑板,认真上课,上半身,红色长裙

丑陋,变形,嘈杂,模糊,低对比度

接下来我们运行baseline代码:

torch.manual_seed(0)
image = pipe(
    prompt="古风,水墨画,一个黑色长发少女,坐在教室里,盯着黑板,深思,上半身,红色长裙",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("1.jpg")

 效果展示如下:

小伙伴们,喜欢的话,点赞收藏关注吧。 

总结

文章概述:
本文探讨了如何通过深入理解baseline代码和借助AI技术来提升自学习能力,并详细介绍了AI生图技术的能力与局限。文章首先介绍了AI生图技术的多种应用场景及其能力,包括图像合成与创造、风格迁移、图像修复与增强、个性化定制等,以及技术存在的局限性,如数据偏见、创造性限制、计算资源需求高等。文章还提到了AI图像识别中可能遇到的“AI翻车”现象及其解决方案。
接下来,文章引出了通义千问这一具有多能力的AI助手,并介绍了其在编程与技术支持方面的优势。通过通义千问,可以辅助理解复杂的代码,提升学习效率。
在精读baseline部分,文章详细解释了一段用于AI生图的代码,包括其主题架构和各部分的功能。通过逐行解析代码,展示了数据准备、使用CLIP模型进行图像-文本匹配、创建PyTorch数据集和数据加载器、以及使用Stable Diffusion模型生成图像的全过程,并最终将这些图像进行合并。
最后,文章进行了一次基于话剧的连环画制作实战演练。通过通义千问辅助生成提示词,并运用之前介绍的Stable Diffusion模型生成了符合剧本场景的图片。每个场景都配置了详细的正向和反向提示词,确保生成图像的准确性和美观性。
总结:
本文通过对AI生图技术的深入了解和baseline代码的细致分析,展示了如何在自学习过程中借助AI技术提升效率和创造力。同时,也揭示了AI技术的局限性和可能遇到的问题,提出了相应的解决方案。文章最后通过一次实战演练,演示了如何将理论知识应用于实践,生成高质量的图像作品。

更新时间 2024-08-26