DataWhale X 魔搭AI夏令营 task02笔记

准备工具

通义千问 通义tongyi.ai_你的全能AI助手

通义千问是一个语言大模型,使用简单,提问的字数上限较高

使用通义来分析baseline的代码

step1 代码准备

!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

 step2 对整段代码进行提问

以下是返回的结果:

这段代码主要完成了以下几个任务:

  1. 安装和卸载依赖库

    • 安装 simple-aesthetics-predictordata-juicerpeftlightningpandastorchvision 和 DiffSynth-Studio 库。
    • 卸载 pytorch-lightning 并重新安装 lightning
  2. 加载数据集

    • 使用 ModelScope 加载名为 AI-ModelScope/lowres_anime 的数据集,并将数据集保存到指定的缓存目录 /mnt/workspace/kolors/data
  3. 数据预处理

    • 将数据集中的图像转换为 RGB 格式并保存到文件系统。
    • 创建 JSONL 文件来记录每张图片对应的元数据(包括文本描述和图片路径)。
  4. 使用 Data-Juicer 进行数据过滤

    • 配置 Data-Juicer 的 YAML 文件,定义了数据集的处理流程,包括过滤掉不符合尺寸要求或长宽比异常的图片。
    • 调用 Data-Juicer 对数据进行处理,输出处理后的结果到 JSONL 文件。
  5. 整理处理后的数据

    • 读取 Data-Juicer 输出的 JSONL 文件,并创建 CSV 文件,其中包含文本描述和图片路径。
    • 使用 CLIP 模型计算文本和图片之间的相似度。
  6. 创建 PyTorch 数据集和数据加载器

    • 基于 DataFrame 创建了一个自定义的数据集类 CustomDataset
    • 使用 DataLoader 从自定义的数据集中加载批次数据。
  7. 生成图片

    • 使用 StableDiffusionPipeline 生成基于不同提示(prompt)的二次元风格图片。
    • 通过不同的种子(seed)和提示语句生成多张图片,并保存这些图片。
  8. 合并图片

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

总结起来,整个代码可以分为以下几个部分:

  1. 环境准备 - 安装必要的库和配置环境。
  2. 数据加载与处理 - 加载原始数据集,并对其进行预处理和过滤。
  3. 特征提取与相似度计算 - 利用 CLIP 模型提取特征并计算文本与图片之间的相似度。
  4. 数据集构建 - 构建 PyTorch 数据集以供后续模型训练使用。
  5. 图像生成 - 使用 Stable Diffusion 模型根据给定的提示生成新的图像。
  6. 图像整合 - 合并生成的多张图像为一张大图像。

以上的回答较为笼统,所以需要更加精细的提问

step3 按照在terminal里的分段给的代码分段进行提问

!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

这段代码是使用python自带的包管理工具pip安装simple-aesthetics-predictordata-juicerpeftlightningpandastorchvision 和 DiffSynth-Studio 库,并卸载 pytorch-lightning 并重新安装 lightning

Simple-Aesthetics-Predictor是一个用于预测图像美学质量的模型。它可以评估一张图片的艺术美感程度,并给出相应的评分。这通常基于深度学习技术实现,可以用于自动化图片筛选或评价任务。

Data-Juicer是一个高质量文本数据清洗工具,用于处理和清洗大规模文本数据集,以提高数据的质量和一致性。它可以帮助去除重复项、校正拼写错误等,是进行自然语言处理(NLP)任务前的重要预处理步骤。

PEFT (Prompt-Enhanced Fine-Tuning)是一种用于微调大型语言模型的技术,它通过添加额外的参数层来适应下游任务,而不需要修改模型本身的权重。这种方法可以在保持原有模型大小的同时有效地适应新的任务。

Lightning (PyTorch Lightning)是一个用于简化 PyTorch 模型训练和研究过程的库。它提供了一种更简洁的方式来进行深度学习实验,使得用户能够专注于模型的设计和调整,而不是复杂的训练循环和设置。

Pandas是一个强大的数据分析库,提供了高性能、易用的数据结构和数据分析工具。它非常适合处理表格数据,并且广泛应用于数据清洗、转换、分析等领域。

TorchVision是 PyTorch 的一个子项目,专注于计算机视觉任务。它包含了许多常用的预训练模型、数据集以及图像变换工具,可以大大简化计算机视觉应用的开发过程。

from modelscope.msdatasets import MsDataset

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

第一行代码是从 ModelScope 库的 msdatasets 模块中导入了 MsDataset 类。ModelScope 是阿里云推出的一个模型开放平台,提供了大量的预训练模型和数据集。

接下来的代码

'AI-ModelScope/lowres_anime': 这里指定了要加载的数据集名称。在 ModelScope 中,数据集通常按照 组织名/数据集名 的格式命名。

subset_name='default': 指定了数据集的子集名称。这里使用 'default' 表示加载默认子集,如果数据集有多个子集,则可以通过这个参数选择不同的子集。

split='train': 指定了要加载的数据集分割部分。通常数据集会被分为训练集 ('train')、验证集 ('validation') 和测试集 ('test') 等。这里加载的是训练集部分。

cache_dir="/mnt/workspace/kolors/data": 指定了数据集缓存的位置。加载的数据集会缓存到这个目录下,以便后续快速访问。这里的数据集将会被缓存到 /mnt/workspace/kolors/data 目录中。

ds 是一个 MsDataset 实例,它包含了加载的数据集。你可以使用这个实例来访问数据集中的数据。

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

前三行导入需要的模块

  • json: 用于处理 JSON 格式的文件。
  • os: 提供了一组用于与操作系统交互的功能。
  • SpecialTokens: 这个类可能来自 data-juicer 库,但在这个上下文中似乎没有直接使用。
  • tqdm: 一个进度条库,用于显示循环进度。

接下来的两行创建两个目录:./data/lora_dataset/train 和 ./data/data-juicer/inputexist_ok=True 表示如果目录已经存在,则不会引发异常。

剩下的代码

打开一个名为 metadata.jsonl 的文件,用于写入元数据信息。

使用 tqdm 包装 ds 数据集,显示一个进度条,跟踪数据处理进度。

对于 ds 中的每一个数据点 data

  • 从数据点中获取图像,并将其转换为 RGB 格式。
  • 将图像保存到 /mnt/workspace/kolors/data/lora_dataset/train/ 目录下,文件名为 {data_id}.jpg
  • 创建一个字典 metadata,其中包含一个键 "text",其值为字符串 "二次元",以及一个键 "image",其值是一个列表,列表中包含保存的图像路径。
  • 将 metadata 字典序列化为 JSON 格式,并写入到文件中。
  • 每个元数据条目后面添加换行符 \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

""""""中的内容是定义配置内容

  • project_name: 定义项目名称。
  • dataset_path: 指定要处理的数据集文件的路径。
  • np: 指定用于数据处理的子进程数。
  • text_keys: 指定元数据中包含文本信息的键。
  • image_key: 指定元数据中包含图像路径的键。
  • image_special_token: 如果数据集中包含图像,可以用这个特殊标记替换图像路径。
  • export_path: 指定处理后的数据输出文件的路径。
  • process: 定义了一系列的数据处理操作。例如,这里定义了过滤图像尺寸和长宽比的操作。

打开文件并将配置内容写入到 data/data-juicer/data_juicer_config.yaml 文件中。

使用 dj-process 命令行工具运行数据处理,这里通过 ! 前缀在 Jupyter Notebook 或类似的环境中运行系统命令。

--config: 指定要使用的配置文件路径。

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


texts, file_names = [], []
os.makedirs("./data/lora_dataset_processed/train", exist_ok=True)
with open("./data/data-juicer/output/result.jsonl", "r") as file:
    for data_id, data in enumerate(tqdm(file.readlines())):
        data = json.loads(data)
        text = data["text"]
        texts.append(text)
        image = Image.open(data["image"][0])
        image_path = f"./data/lora_dataset_processed/train/{data_id}.jpg"
        image.save(image_path)
        file_names.append(f"{data_id}.jpg")
data_frame = pd.DataFrame()
data_frame["file_name"] = file_names
data_frame["text"] = texts
data_frame.to_csv("./data/lora_dataset_processed/train/metadata.csv", index=False, encoding="utf-8-sig")
data_frame

截止到os.makedirs,在前面的代码块已经有了注释,这里不再赘述

剩余代码

打开处理后的数据集文件 ./data/data-juicer/output/result.jsonl

使用 tqdm 包装 file.readlines() 来显示一个进度条,跟踪数据处理进度。

对于文件中的每一行数据:

  • 将每一行数据解析为 JSON 对象。
  • 从 JSON 对象中提取文本描述,并将其添加到 texts 列表中。
  • 从 JSON 对象中提取图像路径,使用 PIL.Image 打开图像。
  • 将图像保存到 ./data/lora_dataset_processed/train/ 目录下,文件名为 {data_id}.jpg
  • 将图像文件名添加到 file_names 列表中。
  • 创建一个空的 pandas DataFrame。

将 file_names 和 texts 列表作为列添加到 DataFrame 中。

将 DataFrame 保存到 CSV 文件 ./data/lora_dataset_processed/train/metadata.csv 中。index=False 表示不保存索引列,encoding="utf-8-sig" 设置编码格式。

最后一行 data_frame 将 DataFrame 输出到控制台,用于检查 DataFrame 的内容。

from diffsynth import download_models

download_models(["Kolors", "SDXL-vae-fp16-fix"])

下载 diffsynth 库中 Kolors 和 SDXL-vae-fp16-fix 模型。

!python DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py -h

运行 train_kolors_lora.py 脚本,并通过 -h 参数请求帮助信息

import os

cmd = """
python DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py \
  --pretrained_unet_path models/kolors/Kolors/unet/diffusion_pytorch_model.safetensors \
  --pretrained_text_encoder_path models/kolors/Kolors/text_encoder \
  --pretrained_fp16_vae_path models/sdxl-vae-fp16-fix/diffusion_pytorch_model.safetensors \
  --lora_rank 16 \
  --lora_alpha 4.0 \
  --dataset_path data/lora_dataset_processed \
  --output_path ./models \
  --max_epochs 1 \
  --center_crop \
  --use_gradient_checkpointing \
  --precision "16-mixed"
""".strip()

os.system(cmd)

定义一个多行字符串 cmd,它包含了要执行的shell命令。由于字符串跨越多行,所以在每行结尾使用了 \ 符号来进行转义,表示下一行是当前行的延续。最后 .strip() 方法用于移除字符串两端的空白字符。

  • python DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py: 运行名为 train_kolors_lora.py 的Python脚本。
  • --pretrained_unet_path models/kolors/Kolors/unet/diffusion_pytorch_model.safetensors: 指定预训练的 U-Net 模型路径。
  • --pretrained_text_encoder_path models/kolors/Kolors/text_encoder: 指定预训练的文本编码器路径。
  • --pretrained_fp16_vae_path models/sdxl-vae-fp16-fix/diffusion_pytorch_model.safetensors: 指定预训练的 VAE (变分自动编码器) 路径。
  • --lora_rank 16: 设置 LoRA 的秩(rank)为 16。
  • --lora_alpha 4.0: 设置 LoRA 的 alpha 参数为 4.0。
  • --dataset_path data/lora_dataset_processed: 指定数据集的路径。
  • --output_path ./models: 指定输出模型的保存路径。
  • --max_epochs 1: 设置最大训练周期数为 1。
  • --center_crop: 启用中心裁剪。
  • --use_gradient_checkpointing: 启用梯度检查点(gradient checkpointing),以节省内存。
  • --precision "16-mixed": 设置混合精度训练为 FP16。

使用 os.system() 函数执行 cmd 字符串中的命令。这会启动一个新的子进程来执行命令,并等待命令完成。

from diffsynth import ModelManager, SDXLImagePipeline
from peft import LoraConfig, inject_adapter_in_model
import torch

"""
定义一个load_lora函数,该函数接收一个模型 model,LoRA 的秩 lora_rank,LoRA 的 alpha 参数 lora_alpha,以及 LoRA 模型的路径 lora_path。
创建一个 LoraConfig 实例,配置 LoRA 的参数。
使用 inject_adapter_in_model 函数将 LoRA 适配器注入到模型中。
加载 LoRA 模型的状态字典,并将其加载到模型中。
返回注入了 LoRA 适配器的模型。
"""

def load_lora(model, lora_rank, lora_alpha, lora_path):
    lora_config = LoraConfig(
        r=lora_rank,
        lora_alpha=lora_alpha,
        init_lora_weights="gaussian",
        target_modules=["to_q", "to_k", "to_v", "to_out"],
    )
    model = inject_adapter_in_model(lora_config, model)
    state_dict = torch.load(lora_path, map_location="cpu")
    model.load_state_dict(state_dict, strict=False)
    return model


# Load models
"""
使用 ModelManager 加载模型,指定使用半精度浮点数 torch.float16,设备为 GPU (cuda)。
指定要加载的模型文件路径列表,包括文本编码器、U-Net 和 VAE 模型。
从 model_manager 创建一个 SDXLImagePipeline 实例。
"""
model_manager = ModelManager(torch_dtype=torch.float16, device="cuda",
                             file_path_list=[
                                 "models/kolors/Kolors/text_encoder",
                                 "models/kolors/Kolors/unet/diffusion_pytorch_model.safetensors",
                                 "models/kolors/Kolors/vae/diffusion_pytorch_model.safetensors"
                             ])
pipe = SDXLImagePipeline.from_model_manager(model_manager)

# Load LoRA
"""
调用 load_lora 函数,将 LoRA 适配器注入到 pipe.unet 中。
指定 LoRA 的秩为 16,alpha 参数为 2.0,以及 LoRA 模型的路径。
"""
pipe.unet = load_lora(
    pipe.unet,
    lora_rank=16, # This parameter should be consistent with that in your training script.
    lora_alpha=2.0, # lora_alpha can control the weight of LoRA.
    lora_path="models/lightning_logs/version_0/checkpoints/epoch=0-step=500.ckpt"
)

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

第一行代码设置 PyTorch 的随机种子为 0,确保每次运行代码时都能得到相同的随机结果。这对于实验的可重复性非常重要。

  • pipe 是一个预先配置好的图像生成管道,它通常基于深度学习模型如扩散模型(diffusion models)。
  • prompt 参数指定了生成图像的描述:“二次元,紫色长发少女,穿着黑色礼服,连衣裙,在台上唱歌”。这个描述会引导模型生成相应的图像。
  • negative_prompt 参数指定了不希望出现在图像中的元素,例如“丑陋、变形、嘈杂、模糊、低对比度”,这有助于避免生成这些特征。
  • cfg_scale 参数控制了条件生成(conditional generation)的强度,值越大,生成的图像越接近 prompt 描述的内容。
  • num_inference_steps 设置了生成过程中迭代步骤的数量。更多的步骤通常意味着更精细的结果,但也需要更多的时间。
  • height 和 width 参数指定了输出图像的尺寸,这里为 1024x1024 像素。

最后一行代码将生成的图像保存为名为 "8.jpg" 的 JPEG 文件。

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
  • 使用列表推导式 (list comprehension) 来循环读取从 1.jpg 到 8.jpg 的图像文件。
  • 对于每一个图像文件,使用 Image.open() 函数打开图像。
  • 使用 np.array() 将每个图像转换为 NumPy 数组,以便于后续处理。
  • 使用 np.concatenate() 函数按顺序合并图像。
  • 首先,将每两个图像水平拼接在一起 (axis=1),形成四个条带。
  • 然后,将这四个条带垂直拼接在一起 (axis=0),形成最终的大图像。
  • 使用 Image.fromarray() 将 NumPy 数组转换回 Pillow 图像对象。
  • 使用 resize() 方法调整图像的尺寸到 1024x2048 像素。
  • 14
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CocosCreator是一款功能强大的游戏开发引擎,而塔游戏源码则是指使用CocosCreator开发的一款塔类游戏的源代码。 CocosCreator塔游戏源码通常包含游戏的各个模块,包括角色控制、战斗系统、地图生成以及游戏UI等。在这个源码中,开发者可以看到一套完整的塔游戏框架和逻辑。 角色控制是塔游戏源码中的重要部分。开发者可以看到玩家角色的移动、攻击以及技能释放等代码。通过阅读源码,开发者可以了解到游戏角色的行为逻辑,比如怪物移动的规则、装备系统的实现等。 另外,战斗系统是塔游戏源码中的关键内容。开发者可以通过查看源码,了解到游戏的攻击和防御计算方式、技能释放和效果表现等细节。这对于学习游戏战斗系统的设计与实现非常有帮助。 地图生成也是源码中的一个重要模块。通过阅读源码,开发者可以了解到地图生成的算法、随机事件的处理、宝箱、商店等游戏元素的放置和生成等细节。 游戏的UI设计也是塔游戏源码中不可缺少的一部分。开发者可以通过查看源码,了解到游戏UI的布局、按钮点击事件的处理、弹窗的实现等细节。 总之,通过研究CocosCreator塔游戏源码,开发者可以学习到游戏开发中常用的算法和设计思路,同时也可以培养自己的开发能力和创造力。在学习和借鉴源码的基础上,开发者还可以根据自身需求进行二次开发和优化,创作出属于自己的塔游戏作品。 ### 回答2: CocosCreator塔游戏源码是指使用CocosCreator开发的塔类游戏的程序代码。CocosCreator是一款基于Javascript的游戏开发引擎,通过它可以轻松创建多平台的游戏。 塔游戏源码通常包含了游戏的一些基本组成部分,如场景、角色、道具、怪物等。它们通过CocosCreator的节点和组件系统进行组织和管理。在源码中,开发者可以了解到游戏的逻辑、界面设计以及各个功能模块的实现方式。 通过使用CocosCreator塔游戏源码,开发者可以学习到如何实现一个完整的塔游戏。他们可以了解到游戏场景的建,通过编辑器创建地图和设置场景元素。他们可以学习到如何处理游戏角色的移动、攻击和受伤等操作,并实现相应的动画效果。另外,他们还可以了解到如何处理游戏道具的使用和怪物的生成与AI行为等。 塔游戏源码可以帮助开发者迅速上手游戏开发,节省大量的开发时间。通过对源码的学习和理解,开发者可以根据自己的需要进行二次开发和扩展,实现独具创意的塔游戏。 ### 回答3: CocosCreator塔游戏源码是基于CocosCreator游戏引擎开发的一种塔类游戏的代码。塔游戏是一种以策略和冒险为主题的角色扮演游戏,玩家需要在迷宫中探索、寻找宝物、打败敌人,最终达到最深层并击败最终BOSS。 CocosCreator塔游戏源码包含了游戏的基本逻辑、界面设计、角色控制、敌人AI、道具系统等各个方面的代码实现。通过阅读源码,我们可以了解到游戏是如何实现地图的生成与呈现、角色的移动和战斗、敌人的行为规则、道具的获取和使用等功能。同时,源码还提供了一些基本的游戏美术资源,如角色、地图瓷砖、敌人等,可以用于快速建游戏。 在实际使用源码的时候,我们可以根据自己的需求进行修改和扩展,比如添加新的关卡、设计新的敌人、增加新的道具等。同时,我们也可以根据源码学习到CocosCreator游戏开发的一些基本技巧与规范,例如场景管理、碰撞检测、UI设计等。 总之,CocosCreator塔游戏源码是一个可以让我们了解和学习塔类游戏开发的实际案例,可以通过对源码的学习和修改,快速建自己的游戏项目,并且还可以帮助我们掌握CocosCreator游戏引擎的使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值