PyTorch图像建模(图像识别、分割和分类案例)

news2025/5/24 15:11:26

文章目录

  • 图像分类技术:改变生活的智能之眼
  • 图形识别技术
    • 图像识别过程
    • 图像预处理
    • 图像特征提取
  • 图像分割技术
  • 练习案例:图像分类
    • 项目源码地址
    • 实现代码(简化版)
    • 训练结果(简化版)
    • 实现代码(优化版)
    • 训练结果(优化版)
    • 存在的问题

图像分类技术:改变生活的智能之眼

  • 图像分类技术已经深入我们的日常生活,应用场景越来越广泛。比如,手机相册能自动识别人物照片,社交平台可以精准识别照片中的好友和物体,自动驾驶汽车能实时检测道路状况……这些应用都表明,图像分类技术正成为我们生活中不可或缺的一部分。

  • 传统方法的局限:早期的图像分类技术主要依赖数字图像处理和机器学习方法。研究人员需要手动提取图像特征(如颜色、纹理等),再根据这些特征对图像进行分类。但这种方法有个明显缺点:适应性差。如果图像受到噪声干扰或部分残缺,分类效果就会大打折扣。

  • 进入大数据时代后,数据量爆炸式增长,传统算法的计算压力越来越大。这时,人工神经网络(ANN)成为了一种解决方案。然而,传统ANN也存在问题: 计算成本高:采用全连接结构,参数数量庞大,扩展性差; 忽略空间信息:未考虑像素之间的位置关系,而这对图像分析至关重要;层数限制:网络层数越多,表达能力越强,但误差反向传播难以超过3层,限制了性能提升。

  • 卷积神经网络(CNN)的突破:CNN的提出完美解决了上述问题,迅速成为计算机视觉的核心技术。它的设计灵感来自图像的特性:相邻像素之间具有强相关性。CNN通过局部连接和权值共享,大幅减少了无效计算,同时充分利用了像素的空间关系和梯度信息。


  • 简单来说,CNN就像一位“智能画家”,不仅能捕捉图像的细节,还能理解这些细节之间的联系,从而让图像分类更高效、更准确。正是这种优势,让它成为当今人工智能领域的重要基石。

图形识别技术

  • 图像识别指利用信息处理与计算机技术,采用数学方法,对图像进行处理、分析和理解的过程。图像识别技术的使用领域广泛,如指纹识别、虹膜识别、手写汉字识别、交通标志识别、手势识别、人脸识别、机器人视觉等,分类识别的事物种类丰富,被识别对象的内容复杂。例如,在交通管理系统中,通过使用车牌的自动识别来记录车辆的违章行为;在医学图像中,根据细胞的形状和颜色等分析是否发生病变;通过植物的颜色和形态长势判断何时需要浇水、施肥;通过气象观测的数据或利用卫星照片来进行天气预报等。

图像识别过程

  • 图像识别过程大致分为两个阶段:样本训练阶段和图像识别阶段。
  1. 样本训练阶段:对大量样本进行预处理、提取图像特征、进行模式分类,获取一个样本图像特征库。
  2. 图像识别阶段:对输入图形进行预处理、图像分析、图形分割、提取关注部分的图像特征、利用模式识别方法对特征和图像特征库中的特征进行相关处理。当图像匹配失败时,将其特征作为新的模式分类并入图像特征库。

图像预处理

  • 图像预处理服务于后续的图像识别服务。预处理过程包括灰度处理、归一化处理、低通滤波处理、均值滤波处理和中值滤波处理、高通滤波处理、边缘检测、边界检测、区域连接和门限等技术。
  • 彩色图像的灰度处理:方便分析图形内容。
  • 直方图归一化、低通滤波、均值滤波和中值滤波处理:可以减少图像在成像过程中收到的噪声污染。
  • 高通滤波处理:突出图像的细节特征。
  • 边缘检测、边界检测、区域连接和门限等技术:方便能够快速找到关注的图像部分。

图像特征提取

  • 图像特征提取能保证图像的大小、位移及旋转的不变性,以提取到唯一标识图像特性的特征来为图像识别服务。
  • 图像特征提取实际上是图像表示问题,它的目的是减轻图像在识别过程中的负担。因为原始图像的数据维数非常高,通过特征提取给数据降维,从而提高识别效率和识别率,为节省资源、构造和设计特征分类器带来益处。

图像分割技术

  • 图像分类就是将图像分成若干个特定的、具有独特性质的区域并提取感兴趣的目标的技术和过程。主要的图形分割技术主要分为以下几类:基于阈值的分割方法、基于区域的分割方法、基于边缘的分割方法以及基于特定理论的分割方法等。
  1. 基于阈值的图像分割技术:最常用的并行分割技术,基于阈值的分割方法进行输入图像到输出图像的变换。关键点是确定阈值,确定阈值后将阈值与像素点的灰度值并行地逐个进行比较,分割的结果直接给出图像区域。
  2. 基于区域的分割技术:典型的串行区域分割技术,主要包括区域生长和分割合并两种方法。区域生长是从某个或者某些像素点出发,最后得到整个区域,进行实现目标提取;分割合并差不多是区域生长的逆过程,从整个图像出发,不断分割得到各个子区域,然后把前景区域合并,实现目标提取。
  3. 基于边缘的分割技术:检测灰度级或者结果有突变的地方,表明一个区域的终结(另一个区域的开始)。不同图像的灰度不同,边界处一般有明显的边缘,利用此特征可以分割图像。
  4. 基于特定理论的分割技术:如模糊集理论具有描述试图不确定性的能力,适合用于图像分割问题。模糊分割技术在图像分割方面的应用,一个显著特点就是它能和现有的许多图像分割方法结合,形成一系列的集成模糊分割技术,如模糊聚、模糊阈值、模糊边缘检测技术。

练习案例:图像分类

  • 数据集使用CIFAR10,数据集一共包含10个类别的RGB彩色图片,10个分类分别为飞机、汽车、鸟、猫、鹿、狗、蛙、马、船、卡车。图片尺寸为32×32,数据集中一共有50000正训练图片和10000张测试图片。

项目源码地址

  • image_classification_and_recognition

实现代码(简化版)

import matplotlib.pyplot as plt
import numpy as np
import torch
import torch.nn.functional as f
import torchvision
from torchvision.transforms import transforms

# 0 torchvision的数据集是基于PILImage,数值范围[0,1]需要转化范围为[-1,1]的张量
transform = transforms.Compose([
    transforms.ToTensor(),  # 将数据转化为张量
    # 归一化处理 均值0.5 标准差0.5
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
# 1 导入训练集和测试数据集 并设置数据加载参数 定义数据集中的类别名称
"""
torchvision.datasets.CIFAR10 定义CIFAR-10数据集
root='./data' 指定数据集的根目录
train=True 创建训练集
download=True 自动下载数据集 如果数据集不存在报错
transform=transform 应用数据预处理变换
"""
train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
"""
torch.utils.data.DataLoader 定义数据加载器 加载训练数据
train_dataset 加载的数据集对象 训练数据集
batch_size=4  每个批次包含的样本数量
shuffle=False 不在每个 epoch 开始时打乱数据顺序
num_workers=4 使用 4 个子进程加载数据(加快数据读取速度)
"""
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=4, shuffle=False, num_workers=4)

"""
torchvision.datasets.CIFAR10 定义CIFAR-10数据集
root='./data' 指定数据集的根目录
train=False 创建测试集
download=True 自动下载数据集 如果数据集不存在报错
transform=transform 应用数据预处理变换
"""
test_dataset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
"""
torch.utils.data.DataLoader 定义数据加载器 加载测试数据
train_dataset 加载的数据集对象 训练数据集
batch_size=4  每个批次包含的样本数量
shuffle=True 不在每个 epoch 开始时打乱数据顺序
num_workers=4 使用 4 个子进程加载数据(加快数据读取速度)
"""
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=4, shuffle=True, num_workers=4)
# 定义类别名
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')


# 2 搭建网络模型
class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 定义卷积层
        self.conv1 = torch.nn.Conv2d(3, 6, 5)
        self.pool = torch.nn.MaxPool2d(2, 2)
        self.conv2 = torch.nn.Conv2d(6, 16, 5)
        # 定义全连接层
        self.fc1 = torch.nn.Linear(16 * 5 * 5, 120)
        self.fc2 = torch.nn.Linear(120, 84)
        self.fc3 = torch.nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(f.relu(self.conv1(x)))
        x = self.pool(f.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = f.relu(self.fc1(x))
        x = f.relu(self.fc2(x))
        x = self.fc3(x)
        return x


"""
An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable.
"""

"""
image_show 显示图片
img: 接受一个图像张量img 
进行归一化处理,将其转化为Numpy数组,然后使用plt.imshow显示图像
"""


def image_show(img):
    """
    显示图片
    :param img:  要显示的图像
    :return: 无
    """
    # 对图像归一化操作
    img = img / 2 + 0.5
    # 转化为张量
    img_np = img.numpy()
    # 以正常通道顺序显示图片
    plt.imshow(np.transpose(img_np, (1, 2, 0)))


if __name__ == '__main__':
    # 创建Net实例
    net = Net()
    #  定义设备
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    net.to(device)  # 👈 添加这一行!

    # 3 训练网络模型
    # 定义交叉熵损失函数和随机梯度下降优化器(学习率为0.01 动量为0.9)
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

    # 循环训练
    nums_epoch = 2
    for epoch in range(nums_epoch):
        running_loss = 0.0
        # 一次循环 50000/4=12500次
        for i, (inputs, labels) in enumerate(train_loader, 0):
            inputs, labels = inputs.to(device), labels.to(device)
            optimizer.zero_grad()
            # RuntimeError: Input type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same 添加 net.to(device)  # 👈 添加 保证两个数据不在同一个设备上
            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item()
            if i % 3000 == 2999:
                print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 3000))
                running_loss = 0.0
    print("训练结束")

    # 应用网络模型

    # 迭代测试集加速器 抽取测试集中的4张图片 每个批次包含 4 张图像(因为 batch_size=4)
    data_iter = iter(test_loader)
    # 使用 next(data_iter) 获取第一个批次的数据,其中包含 4 张图像和对应的标签。
    images, labels = next(data_iter)
    # torchvision.utils.make_grid(images) 将这 4 张图像拼接成一个网格形式,便于显示
    image_show(torchvision.utils.make_grid(images))
    # 打印图片真实分类
    print('图像真实分类:', ' '.join('%5s' % classes[labels[j]] for j in range(4)))

    # 将图像images输入到模型net,得到模型输出
    outputs = net(images.to(device))
    # 获取模型预测结果 在输出的第一维(每个图像)上找到最大的值和索引 1表示在第一维上进行最大值搜索
    _, predicted = torch.max(outputs, 1)
    print('图像预测分类:', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))

    # 定义预测数量和总预测值初始化为0
    correct, total = 0, 0
    # 禁用梯度计算 进行测试
    with torch.no_grad():
        # 遍历测试集的数据和对应的标签
        for images, labels in test_loader:
            # 将图像输入到模型net,得到模型输出
            outputs = net(images.to(device))
            # 在输出的第一维(每个图像)上找到最大的值和索引 得到预测的类别predicted
            _, predicted = torch.max(outputs.data, 1)
            # 累计总预测数量total 通过labels.size(0) 获取标签数量
            total += labels.size(0)
            # 累计预测正确的数量correct 通过判断预测的类别predicted 是否等于标签labels .sum().item将张量转化为整数
            correct += (predicted == labels.to(device)).sum().item()
        # 打印测试集的准确率
        print('预测准确率: %d %%' % (100 * correct / total))

训练结果(简化版)

[1,  3000] loss: 2.146
[1,  6000] loss: 1.778
[1,  9000] loss: 1.606
[1, 12000] loss: 1.511
[2,  3000] loss: 1.423
[2,  6000] loss: 1.374
[2,  9000] loss: 1.327
[2, 12000] loss: 1.288
训练结束
图像真实分类:   cat deer deerplane
图像预测分类:  bird deerhorse ship
预测准确率: 55 %

实现代码(优化版)

  1. 优化点1:使用ResNet18预训练模型
  2. 优化点2:增大batch_size = 256
  3. 优化点3:预先加载数据prefetch_factor=2
  4. 优化点4:使用更合适的优化器(如 Adam)并调整学习率。
  5. 优化点5:使用混合精度scaler = torch.amp.GradScaler('cuda')
  6. 优化点6:
import os
import matplotlib.pyplot as plt
import numpy as np
import torch
import torchvision
from torch.amp import autocast
from torchvision.transforms import transforms
import torchvision.models as models

# 0 torchvision的数据集是基于PILImage,数值范围[0,1]需要转化范围为[-1,1]的张量
transform = transforms.Compose([
    # 优化4 在数据预处理阶段添加数据增强操作,提高模型泛化能力。
    transforms.RandomHorizontalFlip(),  # 随机水平翻转
    transforms.RandomRotation(10),  # 随机旋转
    transforms.ToTensor(),  # 将数据转化为张量
    # 归一化处理 均值0.5 标准差0.5
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
batch_size = 256
# 1 导入训练集和测试数据集 并设置数据加载参数 定义数据集中的类别名称
"""
torchvision.datasets.CIFAR10 定义CIFAR-10数据集
root='./data' 指定数据集的根目录
train=True 创建训练集
download=True 自动下载数据集 如果数据集不存在报错
transform=transform 应用数据预处理变换
"""
train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
"""
torch.utils.data.DataLoader 定义数据加载器 加载训练数据
train_dataset 加载的数据集对象 训练数据集
batch_size=4  每个批次包含的样本数量
shuffle=True 在每个 epoch 开始时打乱数据顺序
num_workers=4 使用 4 个子进程加载数据(加快数据读取速度)
"""
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4,
                                           pin_memory=True,prefetch_factor=2)

"""
torchvision.datasets.CIFAR10 定义CIFAR-10数据集
root='./data' 指定数据集的根目录
train=False 创建测试集
download=True 自动下载数据集 如果数据集不存在报错
transform=transform 应用数据预处理变换
prefetch_factor=2 提前加载2个batch_size
"""
test_dataset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
"""
torch.utils.data.DataLoader 定义数据加载器 加载测试数据
train_dataset 加载的数据集对象 训练数据集
batch_size=4  每个批次包含的样本数量
shuffle=False 不在每个 epoch 开始时打乱数据顺序
num_workers=4 使用 4 个子进程加载数据(加快数据读取速度)
prefetch_factor=2 提前加载2个batch_size
"""
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=4,
                                          pin_memory=True,prefetch_factor=2)
# 定义类别名
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

"""
image_show 显示图片
img: 接受一个图像张量img 
进行归一化处理,将其转化为Numpy数组,然后使用plt.imshow显示图像
"""
def image_show(img):
    """
    显示图片
    :param img:  要显示的图像
    :return: 无
    """
    # 对图像归一化操作
    img = img / 2 + 0.5
    # 转化为张量
    img_np = img.numpy()
    # 以正常通道顺序显示图片
    plt.imshow(np.transpose(img_np, (1, 2, 0)))


if __name__ == '__main__':
    # 设置模型保存路径
    model_dir = "./data"
    os.makedirs(model_dir, exist_ok=True)

    # 指定模型文件路径
    model_path = os.path.join(model_dir, "resnet18-f37072fd.pth")

    # 如果模型不存在,则自动下载到指定路径
    if not os.path.exists(model_path):
        # 下载模型权重到指定路径
        resnet18_url = "https://download.pytorch.org/models/resnet18-f37072fd.pth"
        torch.hub.load_state_dict_from_url(resnet18_url, model_dir=model_dir, progress=True,
                                           file_name="resnet18-f37072fd.pth")

    # 加载 ResNet18 并指定本地权重路径
    state_dict = torch.load(model_path)
    net = models.resnet18(weights="IMAGENET1K_V1")
    net.load_state_dict(state_dict)

    # 使用 ImageNet 预训练的 ResNet18 并修改输出类别数
    net.fc = torch.nn.Linear(net.fc.in_features, 10)  # 修改最后的全连接层

    #  定义设备
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print("使用设备:", device)
    #  保证两个数据不在同一个设备上
    net.to(device)

    # 3 训练网络模型
    # 优化3 使用更合适的优化器(如 Adam)并调整学习率。
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(net.parameters(), lr=0.001)

    # 混合精度 scaler
    scaler = torch.amp.GradScaler('cuda')

    # 循环训练
    nums_epoch = 10  # 优化2:增加训练轮数
    for epoch in range(nums_epoch):
        net.train()
        running_loss = 0.0
        # 一次循环 50000/128=390次
        for i, (inputs, labels) in enumerate(train_loader, 0):
            inputs, labels = inputs.to(device), labels.to(device)
            optimizer.zero_grad()
            with autocast(device_type="cuda"):
                outputs = net(inputs)
                loss = criterion(outputs, labels)

            scaler.scale(loss).backward()
            scaler.step(optimizer)
            scaler.update()

            running_loss += loss.item()
            if i % 50 == 0:
                print('[%d, %5d] loss: %.3f' % (epoch, i, running_loss / 100))
                running_loss = 0.0
    print("训练结束")

    # 应用网络模型

    # 迭代测试集加速器 抽取测试集中的4张图片 每个批次包含 36 张图像(因为 batch_size=4)
    data_iter = iter(test_loader)
    # 使用 next(data_iter) 获取第一个批次的数据,其中包含 36 张图像和对应的标签。
    images, labels = next(data_iter)
    # torchvision.utils.make_grid(images) 将这 36 张图像拼接成一个网格形式,便于显示
    image_show(torchvision.utils.make_grid(images))
    # 打印图片真实分类
    print('图像真实分类:', ' '.join('%5s' % classes[labels[j]] for j in range(batch_size)))

    # 将图像images输入到模型net,得到模型输出
    outputs = net(images.to(device))
    # 获取模型预测结果 在输出的第一维(每个图像)上找到最大的值和索引 1表示在第一维上进行最大值搜索
    _, predicted = torch.max(outputs, 1)
    print('图像预测分类:', ' '.join('%5s' % classes[predicted[j]] for j in range(batch_size)))

    # 定义预测数量和总预测值初始化为0
    correct, total = 0, 0
    # 开启模型评估模式,关闭 BatchNorm 和 Dropout
    net.eval()
    # 禁用梯度计算 进行测试
    with torch.no_grad():
        # 遍历测试集的数据和对应的标签
        for images, labels in test_loader:
            # 将图像输入到模型net,得到模型输出
            images, labels = images.to(device), labels.to(device)
            outputs = net(images)
            # 在输出的第一维(每个图像)上找到最大的值和索引 得到预测的类别predicted
            _, predicted = torch.max(outputs.data, 1)
            # 累计总预测数量total 通过labels.size(0) 获取标签数量
            total += labels.size(0)
            # 累计预测正确的数量correct 通过判断预测的类别predicted 是否等于标签labels .sum().item将张量转化为整数
            correct += (predicted == labels).sum().item()
        # 打印测试集的准确率
        print('预测准确率: %d %%' % (100 * correct / total))

    # 保存模型
    torch.save(net.state_dict(), 'resnet18_cifar10.pth')

训练结果(优化版)

...
[8,     0] loss: 0.003
[8,    50] loss: 0.161
[8,   100] loss: 0.163
[8,   150] loss: 0.179
[9,     0] loss: 0.003
[9,    50] loss: 0.141
[9,   100] loss: 0.156
[9,   150] loss: 0.155
预测准确率: 81 %

存在的问题

  • 训练时gpu占用显存较小,不到2GB
  • 训练时间较长,大部分时间可能用于数据传输,GPU高负载时间较短
  • window平台无法使用 Triton加速

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

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

相关文章

Ubuntu Desktop 24.04 常用软件安装步骤

文章目录 Ubuntu Desktop 24.04 常用软件安装步骤Snipaste F1快捷截图(超方便 | 我6台电脑每台都用)搜狗输入法快速浏览工具 | 空格键快速预览文件壁纸工具 | varietySSH 工具 | Termius 终端分屏工具 | TmuxCaffeine | 避免息屏小工具 一些设置将启动台…

Linux iSCSI存储共享实验指南

实验介绍 1、在Linux平台上通过iSCSI协议实现IP-SAN存储共享 2、掌握存储导出(export)和存储导入(import)的配置方法 3、学习iSCSI存储的发现、连接、断开和管理操作 1、实验环境 两台同网段的Linux虚拟机(无需物理交换机) 操作系统:Lin…

git入门之HEAD介绍

目录 前言一、HEAD 的含义与作用二、游离状态的触发场景及特征1. 触发条件2. 游离状态的特征 三、游离状态的常见使用情况1. 临时查看历史代码2. 保留游离状态的提交 四、注意事项与最佳实践1. 风险防范2. 状态检测技巧 总结 前言 本文介绍Git核心概念HEAD的定义,作…

车道线检测:自动驾驶的“眼睛”

在自动驾驶技术的庞大体系中,车道线检测扮演着至关重要的角色,它就像是自动驾驶汽车的“眼睛”,帮助车辆感知道路边界,从而实现安全、准确的行驶。今天,我们就来深入探讨一下车道线检测的奥秘,看看它是如何…

力扣面试150题--填充每个节点的下一个右侧节点指针 II

Day 45 题目描述 思路 初次做法:考虑到每一节点都要指向它右边的第一个节点,那么我们需要从根向下,最好每次提前处理根节点指向它右边的节点,那么符合这样的遍历方法,很容易i想到前序遍历,但是前序遍历是…

使用openvino和onnxruntime的SDK部署yolo11检测模型

这里的代码参考ultralytics代码库里面的examples文件夹下面的openvino和onnxruntime使用案例部署yolo11检测模型的代码。这两种部署框架和前面的tensorRT框架都是类似的,只是使用的接口不太一样。 PART A -- onnxruntime的使用 1.下载onnxruntime的推理框架 (1) …

C 语言学习笔记(指针4)

内容提要 指针 函数指针与指针函数二级指针 指针 函数指针与指针函数 函数指针 定义 函数指针本质上是指针,是一个指向函数的指针。函数都有一个入口地址,所谓指向函数的指针,就是指向函数的入口地址。(这里的函数名就代表…

MySQL的相关操作

目录 一. 字符串函数 二. group by分组 2.1 作用 2.2 格式 2.3 举例 三. order by排序 3.1 格式 3.2 举例 四. limit 4.1 作用 4.2 举例 五. having 5.1 作用 5.2 举例 六. 正则表达式 七. 多表查询 7.1 定义 7.2 子查询 7.3 联合查询 纵向合并 7.4 交叉连…

鸿蒙HarmonyOS多设备流转:分布式的智能协同技术介绍

随着物联网和智能设备的普及,多设备间的无缝协作变得越来越重要。鸿蒙(HarmonyOS)作为华为推出的新一代操作系统,其分布式技术为实现多设备流转提供了强大的支持。本文将详细介绍鸿蒙多设备流转的技术原理、实现方式和应用场景。 …

XXE(外部实体注入)

目录 学习xxe前提:了解xml格式 1. XML基础 2. XXE基础知识 2.1. 结构 2.2. 定义与原理 2.3. XML实体类型 2.4. 攻击类型 2.5. 防御措施 3. pikachu靶场xxe练习 学习xxe前提:了解xml格式 1. XML基础 文档结构包括XML声明、DTD文档类型定义&…

jenkins凭据管理

用途: 存储构建需要与其他系统认证所使用的账户或者密码信息. Username with password类型存储Harbor或者其他系统的用户名和密码。GitLab API token类型存储Gitlab的用户API token。Secret text类型可以用来存储OpenShift等系统中的token。Certificate类型可以用户存储证书&am…

驱动开发硬核特训 · Day 31:理解 I2C 子系统的驱动模型与实例剖析

📚 训练目标: 从驱动模型出发,掌握 I2C 子系统的核心结构;分析控制器与从设备的注册流程;结合 AT24 EEPROM 驱动源码与设备树实例,理解 i2c_client 与 i2c_driver 的交互;配套高质量练习题巩固理…

【python】局域网内通过python远程重启另一台windows电脑

👉技__能👈:C/C/C#/Python/Java/PHP/Vue/Node.js/HTML语言 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。 局域网内通过python远程重启另一台windows电脑 目录 局域网内通过python远程…

超越感官的实相:声、光、气味的科学与哲学探微

在人类的感官世界中,声、光、气味是日常生活中最直接的现象:我们聆听音乐、观赏光影、呼吸花香。然而,若深入探究它们的本质,科学与哲学竟以截然不同的视角,揭示了一个超越感官的实相世界。本文将从经典物理学、佛教哲…

什么是VR场景?VR与3D漫游到底有什么区别

在数字化时代,虚拟现实(Virtual Reality, 简称VR)场景与3D漫游作为两种前沿技术,改变着人们的生活方式和体验模式。通过计算机模拟真实或假想的场景,让用户仿佛身临其境,并能与虚拟环境进行互动。尽管VR场景…

python学习day2:进制+码制+逻辑运算符

进制 Python 中的进制表示与转换 进制的基本概念 二进制、八进制、十进制、十六进制的定义与特点不同进制在计算机科学中的应用场景 Python 中的进制表示 二进制表示:使用 0b 前缀八进制表示:使用 0o 前缀十六进制表示:使用 0x 前缀示例…

【分布式文件系统】FastDFS

1.简介 讲这个之前,相信很多人特别是学java的,肯定在做苍穹外卖的时候肯定接触过一个东西,叫做阿里云OSS,他们的功能都差不多,但是阿里云的这个是要付费的,而FastDFS是免费开源的,是由淘宝资深…

word为章节标题添加自动编号

问题: 如何为word文档中的多级标题添加自动编号? 方法: 1、首先为文档各级标题设置格式样式,一级标题使用样式中的“标题 1”,二级标题使用“标题 2”,三级使用“标题 3”,也就是直接在开始—…

无人机飞行间隔安全智能评估、安全风险评估

无人机空中安全飞行评估需结合改进碰撞模型、蒙特卡洛仿真、安全间隔反推及动态避障策略,通过多机型分类与实时数据融合,实现从理论建模到实际部署的全流程管控,为城市低空密集飞行提供安全保障。 需求 无人机飞行间隔安全智能评估 无人机…

【VLNs篇】03:VLMnav-端到端导航与视觉语言模型:将空间推理转化为问答

栏目内容论文标题End-to-End Navigation with Vision-Language Models: Transforming Spatial Reasoning into Question-Answering (端到端导航与视觉语言模型:将空间推理转化为问答)核心问题如何利用大型视觉语言模型(VLM)实现端到端的机器人…