Datawhale X 魔搭 AI夏令营第四期 AIGC方向 task02笔记

news2024/11/13 12:15:59

AI工具使用

  • 1. baseline 代码
  • 2. 使用通义千问理解代码
    • 2.1 工作流程
    • 2.2 逐行释意
  • 3. 使用通义千问生成 Prompt
      • 3.1 生成的 Prompt
      • 3.1 根据 Prompt 生成的图片

1. 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

2. 使用通义千问理解代码

2.1 工作流程

这段代码主要涉及了以下几个部分的工作流程:

  1. 环境设置与依赖安装
  • 使用!pip install命令安装一系列Python包,包括simple-aesthetics-predictor, data-juicer, peft, lightning, pandas, torchvision, 和 DiffSynth-Studio
  • 卸载并重新安装pytorch-lightning
  1. 数据集加载与预处理
  • 加载名为AI-ModelScope/lowres_anime的数据集,并指定子集和拆分类型为训练集。
  • 创建必要的目录结构用于存储图像和元数据。
  • 遍历数据集,将图像转换为RGB格式并保存到指定目录,同时构建包含文本描述和图像路径的元数据JSONL文件。
  1. 数据过滤与处理配置
  • 编写YAML配置文件,定义数据处理流程,包括过滤图像大小和长宽比,以及输出路径等参数。
  • 使用data_juicer工具根据配置文件处理数据集,生成处理后的结果文件。
  1. 数据整理与模型预测
  • 将处理后的数据整理成DataFrame,并将其保存为CSV文件。
  • 加载CLIP模型和处理器,对图像和文本进行编码,计算图像与文本之间的相似性分数。
  • 创建自定义PyTorch数据集和数据加载器,使用CLIP模型进行批量预测。
  1. 图像生成
  • 利用StableDiffusionPipeline生成基于给定提示(prompt)的二次元图像。
  • 指定不同的种子以生成不同的图像实例,同时设定负面提示(negative prompt)来避免某些不希望出现的特征。
  • 保存生成的图像,并组合多个图像成一个大图以便展示。

整个流程从数据集的加载开始,经过数据预处理、数据过滤、特征提取和相似性计算,最后通过文本到图像的生成模型产生新的图像。每一部分都紧密相连,共同完成了从数据到生成图像的完整工作流。

2.2 逐行释意

以下是逐行代码及对应的中文注释:

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

# 以可编辑模式安装data-juicer库,-v参数表示详细模式
!pip install -v -e data-juicer

# 卸载pytorch-lightning库,-y参数表示自动确认卸载
!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数据集,subset_name指定子集,split指定数据集划分,cache_dir指定缓存目录
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

# 创建目录用于存放训练图像,exist_ok参数设为True表示如果目录已存在则不抛出异常
os.makedirs("./data/lora_dataset/train", exist_ok=True)

# 创建目录用于存放data-juicer的输入文件
os.makedirs("./data/data-juicer/input", exist_ok=True)

# 打开metadata.jsonl文件用于写入,"w"表示写模式
with open("./data/data-juicer/input/metadata.jsonl", "w") as f:
    # 遍历数据集ds中的每一项,使用tqdm显示进度
    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")

# 定义data_juicer的配置字符串,包含了数据处理的参数
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
"""

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

# 调用dj-process命令,--config参数指定配置文件路径
!dj-process --config data/data-juicer/data_juicer_config.yaml

# 导入pandas库
import pandas as pd

# 再次导入os和json模块(已经导入过,此处重复)
import os, json

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

# 创建目录用于存放处理后的图像
os.makedirs("./data/data-juicer/output/images", exist_ok=True)

# 打开result.jsonl文件,读取处理后的数据
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,列名为"text"和"file_name"
df = pd.DataFrame({"text": texts, "file_name": file_names})

# 将DataFrame保存为CSV文件,index=False表示不保存索引
df.to_csv("./data/data-juicer/output/result.csv", index=False)

# 显示DataFrame的内容
df

# 从transformers导入CLIPProcessor和CLIPModel类
from transformers import CLIPProcessor, CLIPModel

# 导入torch库
import torch

# 从预训练模型加载CLIP模型
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")

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

# 加载图像并使用processor预处理图像和文本
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

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

# 定义一个自定义数据集类CustomDataset
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

# 使用CustomDataset和DataLoader创建数据集和数据加载器
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)

# 导入torch库(已经导入过,此处重复)
import torch

# 从diffusers导入StableDiffusionPipeline类
from diffusers import StableDiffusionPipeline

# 设置随机种子,确保生成过程的一致性
torch.manual_seed(1)

# 从预训练模型加载StableDiffusionPipeline模型
pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v-1-4", torch_dtype=torch.float16)

# 将模型移动到CUDA设备上
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

# 导入numpy和Image模块(numpy已经导入过,此处重复)
import numpy as np
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")

# 加载多个图像,使用numpy转换为数组
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.fromarray(image).resize((1024, 2048))

# 显示最终拼接的图像
image

这段代码涵盖了从数据集的加载、图像预处理、模型预测、数据集封装、图像生成到图像拼接的整个工作流程。

3. 使用通义千问生成 Prompt

3.1 生成的 Prompt

基于你的要求,这里是每张图片的生图提示词:

  1. 仙侠,水墨画,一个黑发飘逸的少女,全身着装白色仙门弟子服,手持长剑,在清晨的山巅,朝阳映照下,正对着东方初升的太阳练习剑法,全身,背景是雾气缭绕的山峰和松柏。

  2. 仙侠,动态描绘,少女脚踏飞剑,衣袂飘飘,凌空飞翔于云海之上,全身,背景是辽阔的天空和下方连绵起伏的山脉。

  3. 仙侠,细腻描绘,少女站在山门之前,背着行囊,准备下山,目光坚定,上半身特写,背景是宏伟的山门和远方的村落。

  4. 仙侠,紧张氛围,一群狰狞的妖怪在村庄中肆虐,房屋倒塌,火光冲天,全身,背景是混乱的村庄和村民们四散奔逃的景象。

  5. 仙侠,英勇战斗,少女挥舞长剑,与妖怪激战,剑光闪烁,全身,背景是被破坏的村庄一角,妖怪的尸体散落周围。

  6. 仙侠,温馨场景,少女被一群感激的村民围绕,接受他们的鲜花和食物,上半身,背景是重建中的村庄和欢乐的村民。

  7. 仙侠,归来时刻,少女身着尘土飞扬的旅装,重新踏上通往山门的道路,全身,背景是夕阳下的山路和逐渐消失在视线中的村庄。

  8. 仙侠,循环不息,少女回到山顶,再次拿起长剑,对着同一棵木桩,开始新的一轮剑术练习,全身,背景是熟悉的院子和远处的山峦。

这些描述结合了仙侠元素、动作、人物和环境,可以作为生成图像的依据。如果需要调整任何细节,请随时告知!

3.1 根据 Prompt 生成的图片

12
34
56
78

相关链接

  1. Datawhale活动页面
  2. 通义千问
  3. 魔搭体验网址
  4. Scepter与WebUI,一站式生成编辑工具箱
  5. 《AIGC未来已来》
  6. AI绘画的发展历史(GAN、diffusion、VAE…)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2038297.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker的基本管理和应用

1、概念 docker是一个开源的应用容器引擎&#xff0c;基于go语言开发的。 docker是运行在linux的容器化工具&#xff0c;可以理解为轻量级的虚拟机。 可以在任何主机上轻松创建的一个轻量级、可移植的、自给自足的容器 2、设计的理念 鲸鱼——宿主机 集装箱——独立运行的…

07:【stm32】中断一:NVIC的配置

中断 1、中断的简介1.1、什么是中断1.2、为什么需要中断 2、中断的优先级2.1、中断优先级的表示方法 3、NVIC3.1、什么的NVIC3.2、NVIC的内部结构3.3、中断向量表3.4、程序实现①开启中断源②配置NVIC③中断响应函数 1、中断的简介 1.1、什么是中断 正在进行的事务被突发事件打…

1688商品详情API返回值中的供应商信息

在使用1688&#xff08;阿里巴巴中国站&#xff09;的商品详情API时&#xff0c;API的返回值中通常会包含丰富的产品信息&#xff0c;包括供应商&#xff08;卖家&#xff09;的信息。不过&#xff0c;具体的返回值内容可能会根据API的版本、调用参数以及API的更新情况有所不同…

什么是国际网络组网?

国际网络组网是指通过互联网技术将全球各地的不同网络相互连接&#xff0c;以实现信息交换与资源共享的过程。在这一过程中&#xff0c;涉及到数据传输、协议转换、跨网络通信等多个技术领域&#xff0c;旨在实现全球信息的无缝互联互通。国际网络组网的主要目标是扩大网络覆盖…

半导体RFID识别系统134.2K低频读写器|读写头JY-V610之SECS协议通信说明

什么是SECS协议&#xff1f; SECS&#xff08;Semiconductor Equipment Communication Standard&#xff09;协议是半导体设备通讯标准&#xff0c;用来统一各个生产设备之间以及生产设备和控制设备之间的通讯&#xff0c;由SEMI&#xff08;Semiconductor Equipment and Mate…

手搓滑动窗口

前言&#xff1a;好久没写滑动窗口&#xff0c;导致一些边界问题处理不好&#xff0c;back和top的初始值都搞不好 #include<bits/stdc.h> using namespace std;const int N (int)1e65; int n,m; int a[N],b[N]; int back,top;int main(){cin >> n >> m;for(…

【前端设计方案】H5 图片懒加载 SDK

实现思路 定义<img srcloading.png data-srcxxx.png/>页面滚动&#xff0c;图片露出时&#xff0c;将 data-src 赋值给 src 注意事项&#xff1a;滚动要节流 技术要点 获取图片的位置 elem.getBoundingClientRect() 图片 top < window.innerHeight 时&#xff0c;图片…

【学习笔记】爱立信SPO 1400 CRAFT软件基础知识9——Bridge(网桥)显示参数

一、前期准备 条件1.确认已正确使用爱立信SPO 1400 CRAFT软件通过网络登录设备&#xff08;以下简称NE&#xff09; 具体登录教程参考&#xff1a;使用爱立信SPO 1400 CRAFT软件通过网络登录设备的详细过程 二、学习内容&#xff1a; 提示&#xff1a;学习爱立信SPO 1400 CRA…

阿里员工:33岁,房贷还剩223万,每月还1.5W,失业中

中年失业 中年失业&#xff0c;真的很难。 虽然人到中年&#xff0c;一般多少都会有些储蓄&#xff0c;但也意味着会有更多的支出。 最近&#xff0c;一位阿里员工&#xff08;这会可能是前阿里员工了&#xff09;在社区分享到自己的经历。 贴主 33 岁&#xff0c;作为已结婚有…

搬瓦工日本软银线路VPS测评

搬瓦工日本VPS支持softbank/软银&#xff0c;Japan: Osaka (Softbank) &#xff0c;网络在2.5Gbps-10Gbps之间&#xff0c;底层为KVM虚拟、纯SSD阵列、支持在多机房之间切换。搬瓦工软银来国内的网络情况怎么样&#xff1f;测评数据大致如下&#xff1a; CPU具体型号不知道&…

深入了解指针(6)

文章目录 1.函数指针数组2.转移表3.回调函数 1.函数指针数组 存放函数指针的数组 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int add(int x, int y) {return x y; } int sub(int x, int y) {return x - y; }int main() {int (*p1)(int x, int y) add;int (…

基于python的百度迁徙迁入、迁出数据分析(八)

副标题&#xff1a;从百度迁徙数据看——重大公共卫生事件的影响 先来回顾一下&#xff0c;迁徙规模指数定义&#xff1a;反映迁入或迁出人口规模&#xff0c;城市间可横向对比。 2019年—2022年的部分春运数据已经不可查&#xff0c;用的环哥的数据&#xff0c;可参考环哥的…

LVS原理及相关配置

1. 描述以及工作原理 1. 什么是 LVS linux virtural server 的简称&#xff0c;也就是 linxu 虚拟机服务器&#xff0c;这是一个 由章文嵩博士发起的开源项目&#xff0c;官网是 http://www.linuxvirtualserver.org,现在 lvs 已经是 linux 内核标 准的一部分&#xff0c;使用…

用python的manim库实现表格格式操作【table 下】

1.Table 是 Manim 中用于创建一个包含文本或其他 数学符号的表格的类 Table 是 Manim 中用于创建一个包含文本或其他 数学符号的表格的类它能够帮助你在场景中清晰地展示数据或信息。 参数解释 table: 一个二维数组或列表&#xff0c;表示表格中的内容。每个子列表代表表格的…

zigbee笔记:十一、设备网络类型展示与按键实验

一、设备网络类型展示 利用开发板上的三个LED灯来显示设备当前的网络类型&#xff08;协调器、路由器、终端&#xff09;。 1、添加LED灯的初始化代码 1&#xff09;开发板LED原理图 2&#xff09;在模板工程的...Projects\zstack\Samples\smartHomeApp\Source目录下新建两个文…

【TabBar嵌套Navigation案例-发现页面-按钮上的图片旋转 Objective-C语言】

一、接下来,我们来做这个,点击以后,让它出一个蓝色的View 1.就是我们示例程序的这种效果, 一点击,让这个按钮旋转,然后呢,再让它出来一个蓝色的View, 首先,我们要去监听它的点击事件,这是第一,我点击以后,我要做一些什么样的操作,要有点击事件, 所以呢,我要把…

Processing中库和导出PDF内容

一.库 1.使用库的方式 从菜单栏&#xff08;Sketch Menu)选择导入库(import labrary),选择一个我们要添加或者成需要用到的库。 例如&#xff1a;当我们需要添加PDF扩展库时&#xff0c;需要将下面这段代码添加到草图中。 import processing.pdf.*; 除了processing里的库&…

ElasticSearch聚合操作详解

文章目录 聚合操作聚合的分类测试数据Metric AggregationBucket Aggregation获取job的分类信息限定聚合范围Range & Histogram聚合聚合嵌套 Pipeline Aggregation聚合的作用范围排序ES聚合分析不精准原因分析聚合性能优化启用 eager global ordinals 提升高基数聚合性能插入…

【Unity-本地化】简单的游戏本地化处理方案

目录 0 前言1 多语言配置2 本地化实现2.1 读取多语言文本的通用方法2.2 动态文本本地化2.3 静态文本本地化 3 方案扩展3.1 LanguageText扩展3.1.1 展示Excel里对应ID的文本3.1.2 自动填充ID3.1.3 同步prefab的修改3.1.4 完整代码 3.2 自动LanguageText挂载 4* 内嵌文本图片的本…

AI预测福彩3D采取888=3策略+和值012路或胆码测试8月14日新模型预测第56弹

好长时间没进行总结了&#xff0c;今天咱们做一个总结&#xff0c;总结一下最新模型经过50多期的测试结果&#xff1a; 经过近50多期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率…