GAN 如何打造人造名人身份?

news2024/11/13 11:25:54

在这里插入图片描述

GAN 如何打造人造名人身份?

文章目录

  • 一、介绍
  • 二、生成对抗网络(GAN)
  • 三、什么是发电机?
  • 四、什么是鉴别器?
  • 五、对抗性训练
  • 六、实现
  • 七、数据
    • 7.1 初始配置和设置
    • 7.2 数据加载器
    • 7.3 噪声产生
    • 7.4 发电机
    • 7.5 鉴别器
  • 八、训练
  • 九、可视 化
  • 十、结论

一、介绍

在人工智能时代,一个非凡的现象正在显现——生成对抗网络(GAN)正在巧妙地打造人工名人身份。这种技术与创造力的有趣融合催生了全新的数字名人。加入我们,踏上一段引人入胜的旅程,深入 GAN 世界,揭开创造迷人的虚拟领域的人造名人角色背后的魔力。GANs如何使这成为可能?让我们来探索这种数字艺术背后的秘密。

我们下文将学到:
生成对抗网络 (GAN) 的概念
如何训练生成器和鉴别器?
实现GAN模型的分步过程
通过对抗性训练深入了解 GAN 如何随着时间的推移而改进
本文是作为数据科学博客马拉松的一部分发表的。

二、生成对抗网络(GAN)

生成对抗网络 (GAN) 是一种深度学习模型,由 Goodfellow 提供。通过名称本身,我们可以理解这些 GAN 的用途。是的!我们将其用于生成目的。它是一个产生一些东西的网络。使用 GAN 生成合成数据。这些数据包括图像、文本、音频等,这与真实世界的数据类似。GAN包含两个神经网络。这些网络被称为生成器和鉴别器。在训练期间,这两个网络的训练方式使它们相互竞争并变得更好。

三、什么是发电机?

生成器是负责生成的神经网络。因此,要给出输出,它需要输入。发生器采用的输入是一些随机噪声。发生器接受这种随机噪声,并试图生成类似于真实数据的输出。每当它从鉴别器那里获得反馈时,它都会自我改进,并在下次生成更好的数据。例如,以图像生成为例,生成器将生成图像。随着它通过训练的改进,它从随机噪声开始,最终改进其输出,变得越来越逼真。第一次,它可能不会产生与原始数据最相似的数据。有时它甚至会生成根本不是图像的图像。随着训练的进行,会生成更准确、更准确的更好数据。

四、什么是鉴别器?

鉴别器是负责评估的神经网络。为了便于理解,我们可以称它为侦探。该生成器接收生成器生成的真实数据和虚假数据。它必须区分虚假数据和真实数据。简单来说,它涉及将实际数据与虚假数据进行分类。与生成器类似,随着训练的继续,它将能够更好地区分。它可能无法在第一次尝试时发挥出最佳效果。但是在训练过程中,它会变得越来越好,最后,它将能够区分大部分虚假数据。正如我所说,它必须像侦探一样工作。

五、对抗性训练

生成器和鉴别器都经过训练,称为对抗训练。正如我已经提到的,他们都从事竞技训练。我们知道生成器生成看起来像真实数据的假数据,而鉴别器试图区分假数据。在训练过程的下一步中,生成器旨在改进和生成虚假数据以欺骗鉴别器。同样,鉴别器检测假数据。这样,在训练过程中,他们俩在各自的任务中都变得更好。这个过程一直持续到生成器生成真实的数据,并且鉴别器无法将其与真实数据区分开来。至此,GAN已经达到了一种平衡,生成的数据与真实数据非常相似。

六、实现

让我们从导入所有必要的库开始。这主要包括一些火炬模块。我们将使用 matplotlib 进行可视化。

from __future__ import print_function
%matplotlib inline
import argparse
import os
import random
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.backends.cudnn as cudnn
import torch.optim as optim
import torch.utils.data
import torchvision.datasets as dset
import torchvision.transforms as transforms
import torchvision.utils as vutils
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from IPython.display import HTML

七、数据

对于此项目实施,我们将使用 CelebFaces 属性 (CelebA) 数据集。此数据集在 Kaggle 中可用。你可以从这里下载它。

数据集链接:https://www.kaggle.com/datasets/jessicali9530/celeba-dataset

该数据集包含 202,599 张不同名人的脸部图像。使用它来训练和测试人脸检测模型,尤其是那些能够识别特定面部特征的模型。

7.1 初始配置和设置

现在让我们在开始实际实现之前设置一些参数和配置。首先,我们必须提供数据集所在的路径。定义工作人员的数量。它表示数据加载程序的数据加载工作线程数。我们使用数据加载工作线程并行加载批量数据,从而加快训练期间的数据加载过程。定义批量大小和图像大小、训练图像中的通道数、潜在向量的大小、生成器中特征图的大小、鉴别器中特征图的大小、纪元数、学习率、Adam 优化器的 beta1 超参数。可用于训练的 GPU 数量。如果没有可用的 GPU,它将使用 CPU。该代码设置这些配置并打印所选设备(CPU 或 GPU)以及用于训练的 GPU 数量。在训练 GAN 模型时,必须严格控制这些设置。

# dataset
dataroot = r"C:\Users\Admin\Downloads\faces\img_align_celeba"
workers = 1
batch_size = 16
image_size = 64
nc = 3
# Size of z latent vector
nz = 64
# Size of feature maps in generator
ngf = 64
# Size of feature maps in discriminator
ndf = 64
num_epochs = 5
lr = 0.0001
beta1 = 0.2
ngpu = 1
device = torch.device("cuda:0" if (torch.cuda.is_available() and ngpu > 0) else "cpu")
torch.backends.cudnn.benchmark = True

print(device)
print(ngpu)

7.2 数据加载器

让我们为训练数据创建一个 PyTorch 数据集和数据加载器。使用 dset 创建数据集变量。ImageFolder 类。我们创建了这个 PyTorch 数据集类来加载组织到文件夹中的数据,这需要两个基本参数。我们对数据集中的每个图像应用了一系列图像更改,称为转换。

使用 torch.utils.data.DataLoader 创建 dataloader 变量。这负责批量加载数据。它采用定义的数据集和批量大小。除了它们,我们还必须提到用于数据加载的工作进程的数量以及是否对数据进行洗牌。我们之前定义了这个工人数量。若要确保模型不会在每个时期查看相同顺序的图像,必须在训练前对数据进行随机排序。

然后我们绘制一些训练图像,以了解我们的训练数据是什么样子的。

# Create the dataset
dataset = dset.ImageFolder(root=dataroot,
                           transform=transforms.Compose([
                               transforms.Resize(image_size),
                               transforms.CenterCrop(image_size),
                               transforms.ToTensor(),
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
                           ]))
# Create the dataloader
dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
                                         shuffle=True, num_workers=workers)

# Plot some training images
real_batch = next(iter(dataloader))
plt.figure(figsize=(8,8))
plt.axis("off")
plt.title("Training Images")
plt.imshow(np.transpose(vutils.make_grid(real_batch[0].to(device)[:64], 
           padding=2, normalize=True).cpu(),(1,2,0)))

7.3 噪声产生

现在让我们制造一些噪音。该噪声是GAN中发生器的输入。noise() 函数生成随机噪声。因此,让我们来定义它。它不接受任何参数,并创建一个形状的随机张量 (nz, ngf),其中包含从 0 到 1 之间的均匀分布中采样的值。此外,缩放随机张量,使值介于 -1 和 1 之间。它通过将随机张量乘以 2 然后减去 1 来实现这一点。该噪声张量可以与其他数据(例如标签或潜在向量)连接,并输入生成器以生成图像。

def noise():
  return 2*torch.rand(nz, ngf, device = device) - 1

7.4 发电机

是时候定义生成器了。为此,我们必须定义生成器类。接下来,指定构造函数方法。它接受 ngpu 输入,该输入指示有多少个 GPU 可用于训练。ngpu 参数用于处理多 GPU 训练,但在此代码中,未使用它。在构造函数中,定义了生成器体系结构。

顺序模块将一系列卷积运算、批量归一化和激活函数应用于输入 x。然后,我们定义生成输出图像的最终卷积层。那就是 self.toImage。它使用过去图层的特征图来创建所需的 3 通道图像。

接下来,我们必须定义正向方法。发电机的发电机前传由此方法定义。它接受输入 x。此 x 是噪声向量或潜在向量,并传递它通过构造函数中定义的层。结果是生成的图像。最初,输入 x 在通过潜在层后进行转换。然后通过定义的所有卷积层对其进行处理。在每个卷积层之后,特征图与相应层的特征图连接起来,然后再进行上采样。这有助于生成器捕获高级要素和空间细节。生成的图像是从最终卷积层的输出中获得的,并作为前向传递的结果返回。

# GeneratorCode

class Generator(nn.Module):
    def __init__(self, ngpu):
        super(Generator, self).__init__()
        self.ngpu = ngpu
        self.fromLatent = nn.Linear(ngf, (image_size*image_size//16)*ndf)
        self.dlayer1 = nn.Sequential(
            nn.Conv2d(ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True),
            nn.Conv2d(ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True)
        )
        self.dlayer2 = nn.Sequential(
            nn.Upsample(scale_factor=2),
            nn.Conv2d(2 * ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True),
            nn.Conv2d(ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True)
        )
        self.dlayer3 = nn.Sequential(
            nn.Upsample(scale_factor=2),
            nn.Conv2d(2 * ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True),
            nn.Conv2d(ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True)
        )
        self.toImage = nn.Conv2d(ndf, 3, 3, padding = 1) 

    def forward(self, x):
        x = self.fromLatent(x)
        x = x.view(x.size(0), ndf, image_size//4, image_size//4)
        h0 = x
        x = self.dlayer1(x)
        x = torch.cat([x, h0], dim=1)
        x = self.dlayer2(x)
        h0 = nn.functional.interpolate(h0, scale_factor=2, mode='nearest') 
        x = torch.cat([x, h0], dim=1)
        x = self.dlayer3(x)
        x = self.toImage(x)
        return x

7.5 鉴别器

为了识别真实和虚假的图像,我们必须构建一个类似于我们之前定义的生成器的鉴别器网络。在这种情况下,将存在一个鉴别器类。定义鉴别器类的构造函数方法。它接受 ngpu 输入,该输入指定可用于训练的 GPU 数量,就像生成器一样。

elayer1 包含三个卷积层,每层后面都跟着批量归一化和 ELU 激活函数。self.toLatent 是一个 FC 层,它获取卷积层的输出并将其映射到张量。self.fromLatent 是另一个 FC 层。它从生成器获取输出并将其映射到张量。

这些块类似于生成器中的块,但它们用于解码。这意味着图像生成。self.toImage 是生成输出图像的最后一个卷积层。它使用早期图层的特征图创建 3 通道图像。然后,forward 方法指定鉴别器的前向传递。它接受真实或生成的图像输入,并将其传递到构造函数中定义的层。结果是类似图像的输出。

7.5 代码实现

class Discriminator(nn.Module):
    def __init__(self, ngpu):
        super(Discriminator, self).__init__()
        self.ngpu = ngpu
        self.elayer1 = nn.Sequential(
            nn.Conv2d(nc, ndf, 3, padding = 1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True),
            nn.Conv2d(ndf, ndf, 3, padding = 1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True),
            nn.Conv2d(ndf, 2 * ndf, 3, padding = 1),
            nn.BatchNorm2d(2 * ndf),
            nn.ELU(inplace=True),
        )
        self.elayer2 = nn.Sequential(
            nn.MaxPool2d(2),
            nn.Conv2d(2 * ndf, 2 * ndf, 3, padding = 1),
            nn.BatchNorm2d(2 * ndf),
            nn.ELU(inplace=True),
            nn.Conv2d(2 * ndf, 3 * ndf, 3, padding = 1),
            nn.BatchNorm2d(3 * ndf),
            nn.ELU(inplace=True)
        )
        self.elayer3 = nn.Sequential(
            nn.MaxPool2d(2),
            nn.Conv2d(3 * ndf, 3 * ndf, 3, padding = 1),
            nn.BatchNorm2d(3 * ndf),
            nn.ELU(inplace=True),
            nn.Conv2d(3 * ndf, 3 * ndf, 3, padding = 1),
            nn.BatchNorm2d(3 * ndf),
            nn.ELU(inplace=True)
        )
        self.toLatent = nn.Linear((image_size*image_size//16)*3*ndf, ngf)

        self.fromLatent = nn.Linear(ngf, (image_size*image_size//16)*ndf)
        self.dlayer1 = nn.Sequential(
            nn.Conv2d(ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True),
            nn.Conv2d(ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True)
        )
        self.dlayer2 = nn.Sequential(
            nn.Upsample(scale_factor=2),
            nn.Conv2d(2*ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True),
            nn.Conv2d(ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True)
        )
        self.dlayer3 = nn.Sequential(
            nn.Upsample(scale_factor=2),
            nn.Conv2d(2*ndf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True),
            nn.Conv2d(nsdf, ndf, 3, padding=1),
            nn.BatchNorm2d(ndf),
            nn.ELU(inplace=True)
        )
        self.toImage = nn.Conv2d(ndf, 3, 3, padding = 1)
        
    def forward(self, x):
        x = self.elayer1(x)
        x = self.elayer2(x)
        x = self.elayer3(x)
        x = x.view(x.size(0), -1)
        x = self.toLatent(x)
        x = self.fromLatent(x)
        x = x.view(x.size(0), ndf, image_size//4, image_size//4)
        h0 = x
        x = self.dlayer1(x)
        x = torch.cat([x, h0], dim=1)
        x = self.dlayer2(x)
        h0 = torch.nn.functional.interpolate(h0, scale_factor=2, mode='nearest')
        x = torch.cat([x, h0], dim=1)
        x = self.dlayer3(x)
        x = self.toImage(x)
        return x

现在,创建一个名为 Generator 的类,并传递 ngpu 来构建生成器神经网络。如果有,您可以使用更多的 GPU 来提高训练效率。Discriminator 神经网络也是通过实例化一个名为 Discriminator 的类来创建的,类似于生成器。在下一步中启动损失函数。

接下来,我们必须创建一批称为 fixed_noise 的潜在向量。这些潜在向量通常是随机噪声向量,通常从正态分布中抽取。它们用于在训练期间从生成器生成假图像。然后,我们必须为生成器和鉴别器设置优化器。我们将对两者使用 Adam 优化器。Adam 是一种流行的优化算法。

# Create the generator
netG = Generator(ngpu).to(device)

# To handle multi-gpu
if (device.type == 'cuda') and (ngpu > 1):
    netG = nn.DataParallel(netG, list(range(ngpu)))

# Create the Discriminator
netD = Discriminator(ngpu).to(device)

# To handle multi-gpu
if (device.type == 'cuda') and (ngpu > 1):
    netD = nn.DataParallel(netD, list(range(ngpu)))
    
# Initiate Loss function
criterion = nn.L1Loss()

fixed_noise = noise()
# Setup Adam optimizers for both Generator and Discriminator
optimizerD = optim.Adam(netD.parameters(), lr=lr, betas=(beta1, 0.999))
optimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999)) 

八、训练

是时候训练我们的模型了。在此之前,我们必须创建一个名为 Timer 的类,该类将帮助您计算每个步骤的训练时间。创建一些必要的空列表,并定义一些必要的参数来存储训练期间的数据。在已设置的训练循环中,从数据加载器中循环访问预定数量的 epoch 和批次数据。鉴别器使用生成器生成的虚假数据进行训练。在整个训练过程中,生成器和鉴别器都会得到更新。同时,在训练过程中的每一步,都会打印出所有统计数据。它收集损失和生成的图像,以便在训练期间和之后进行分析和可视化。

import time

class Timer():
    def __init__(self):
        self.startTime = time.time()
        self.lastTime = time.time()
  
    def timeElapsed(self):
        auxTime = self.lastTime
        self.lastTime = time.time()
        return self.lastTime - auxTime

    def timeSinceStart(self):
        self.lastTime = time.time()
        return self.lastTime - self.startTime
        
# Training Loop
k = 0
gamma = 0.4
lambda_k = 0.005
img_list = []
G_losses = []
D_losses = []
iters = 0

print("Training Loop Started...")
timer = Timer()
for epoch in range(num_epochs):
    # For each batch in the dataloader
    for i, data in enumerate(dataloader, 0):
     
        netD.zero_grad()
        # Format batch
        real_cpu = data[0].to(device)
        b_size = real_cpu.size(0)
        # Forward pass real batch through D
        output = netD(real_cpu).view(-1)
        # Calculate loss on all-real batch
        errD_real = criterion(output, real_cpu.view(-1))
        # Calculate gradients for D in backward pass
        D_x = output.mean().item()

  
        fake = netG(noise())
        # Classify all fake batch with D
        output = netD(fake.detach()).view(-1)
        # Calculate D's loss on the all-fake batch
        errD_fake = criterion(output, fake.view(-1))
        # Calculate the gradients for this batch
        D_loss = errD_real - k * errD_fake
        D_loss.backward()
        D_G_z1 = output.mean().item()
        # Add the gradients from the all-real and all-fake batches
        optimizerD.step()

     
        netG.zero_grad()
        fake = netG(noise())
        output = netD(fake).view(-1)
        # Calculate G's loss based on this output
        errG = criterion(output, fake.view(-1))
        # Calculate gradients for G
        errG.backward()
        D_G_z2 = output.mean().item()
        # Update G
        optimizerG.step()

        delta = (gamma*errD_real - errG).data
        k = max(min(k + lambda_k*delta, 1.0), 0.0)
        
        # Output training stats
        if i % 50 == 0:
            print(
            '[%.4f] [%d/%d][%d/%d]\tLoss_D: %.4f\tLoss_G: %.4f\tD(x): %.4f\tD(G(z)): %.4f / %.4f'
                  % (timer.timeElapsed(), epoch, num_epochs, i, len(dataloader),
                     D_loss.item(), errG.item(), D_x, D_G_z1, D_G_z2))
        
        # Save Losses for plotting later
        G_losses.append(errG.item())
        D_losses.append(D_loss.item())
        
        if (iters % 1000 == 0) or ((epoch == num_epochs-1) and (i == len(dataloader)-1)):
            with torch.no_grad():
                fake = netG(fixed_noise).detach().cpu()
            img_list.append(vutils.make_grid(fake, padding=2, normalize=True))
            
        iters += 1   

九、可视 化

现在,让我们生成一个图来可视化 GAN 训练期间的生成器和鉴别器损失。

plt.figure(figsize=(10,5))
plt.title("Generator and Discriminator Loss During Training")
plt.plot(G_losses,label="G")
plt.plot(D_losses,label="D")
plt.xlabel("iterations")
plt.ylabel("Loss")
plt.legend()
plt.show() 

在这里插入图片描述

同样,让我们生成一个图,用于比较 GAN 生成的真实图像和虚假图像。为此,我们必须从数据加载器中获取一批真实图像。这些真实图像用于与GAN生成的图像进行比较。然后我们将绘制 GAN 生成的真实图像和虚假图像。这使您可以直观地将生成的图像的质量与真实数据进行比较。

# Grab a batch of real images from the dataloader
real_batch = next(iter(dataloader))

# Plot the real images
plt.figure(figsize=(15,15))
plt.subplot(1,2,1)
plt.axis("off")
plt.title("Real Images")
plt.imshow(np.transpose(vutils.make_grid(real_batch[0].to(device)[:64], 
           padding=5, normalize=True).cpu(),(1,2,0)))

# Plot the fake images from the last epoch
plt.subplot(1,2,2)
plt.axis("off")
plt.title("Fake Images")
plt.imshow(np.transpose(img_list[-1],(1,2,0)))
plt.savefig('fake_image.png')
plt.show()

在这里插入图片描述

十、结论

在本文中,我们在 CelebFaces 属性 (CelebA) 数据集上使用了生成对抗网络 (GAN),并生成了一些虚假的名人面孔。生成对抗网络 (GAN) 是一项了不起的技术突破。他们可以创建看起来非常真实的虚假数据。这有很多用途,并且非常有用,尤其是当项目需要大量数据时。它确实发展迅速,近年来被更多地使用。这项技术是人工智能领域的一个有趣的发展,因为它在许多不同的应用中都有广阔的前景。

关键要点

生成对抗网络 (GAN) 是一种革命性的 AI 技术,能够生成与真实数据非常相似的数据。
它由两个神经网络组成。一个是生成器,另一个是鉴别器。这两个网络正在进行对抗性训练。
GAN 在多个领域都有应用,包括图像生成、超分辨率、风格传输和数据增强。
GAN有很多种,它们各有优缺点,也有自己的应用。
GAN 可能会引发与深度伪造、虚假内容生成和侵犯隐私相关的道德问题。
本文中显示的媒体不归 Analytics Vidhya 所有,由作者自行决定使用。

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

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

相关文章

Appium自动化测试系列: 2. 使用Appium启动APP(真机)

历史文章:Appium自动化测试系列: 1. Mac安装配置Appium_mac安装appium-CSDN博客 一、准备工作 1. 安卓测试机打开调试模式,然后使用可以传输数据的数据线连接上你的电脑。注意:你的数据线一定要支持传输数据,有的数据线只支持充…

computed计算属性用法及方法对比

模板中的插值表达式虽然方便,但当要写复杂逻辑时就会变得臃肿,难以维护,遇上复杂逻辑时,推荐使用计算属性来描述以响应式状态的复杂逻辑。这里我们做个对比,先用表达式的方法进行计算,先把页面写好&#xf…

WIN10开机突然,过一会就自动重启蓝屏DRIVER_IRQL_NOT_LESS_OR_EQUAL

环境: Win10 专业版 DELL7080 问题描述: WIN10开机突然,过一会就自动重启蓝屏DRIVER_IRQL_NOT_LESS_OR_EQUAL 事件日志 解决方案: 1.找到MEMORY.DMP文件内容,分析一下 Microsoft (R) Windows Debugger Version 10…

rabbitmq集群创建admin用户之后,提示can access virtual hosts是No access状态

问题描述: 因业务需要使用的rabbitmq是3.7.8版本的,rabbitmq在3.3.0之后就允许使用guest账号的权限了,所以需要创建一个administrator标签的用户。 如下操作创建的用户: 创建完成之后就提示如下的报错: 注&#xff1a…

探索大模型:袋鼠云在 Text To SQL 上的实践与优化

Text To SQL 指的是将自然语言转化为能够在关系型数据库中执行的结构化查询语言(简称 SQL)。近年来,伴随人工智能大模型技术的不断进步,Text To SQL 任务的成功率显著提升,这得益于大模型的推理、理解以及指令遵循等能…

postman macOS版安装包

链接: https://pan.baidu.com/s/1Y7j4mxB1Otmf3Ku41e7v7w?pwdfy99 提取码: fy99 安装后的效果

【QT】窗口MainWindow

目录 窗口的组成 菜单栏 图形化创建菜单栏 代码创建菜单栏 给菜单设置快捷键 添加子菜单 添加分割线 添加图标 创建menuBar的细节 工具栏 设置工具栏出现的初始位置(上下左右) 设置工具栏允许停靠的位置 设置不允许浮动 设置不允许移动…

【STM32项目】基于嵌入式智能网控微嵌式远距操控平台(完整工程资料源码)

基于嵌入式智能网控微嵌式远距操控平台 目录: 前言: 一、项目前景调研 1.1 研究背景及意义 1.2 国内外发展现状及趋势 1.2.1 国内现状 1.2.2 国外发展现状 1.2.3 发展趋势 二、什么是嵌入式? 2.1 嵌入式系统概述 2.2 嵌入式系统的组成 2.3 嵌入式操作系统…

camera-qsc-crosstalk校准数据XTALK回写

问题背景 手机越做越紧凑,需要模组和芯片尺寸越做越小,在尺寸一定的基础上,高像素和大像素,对于手机摄像头来说,一直是一对矛盾的存在。 高像素:带来高分辨率画质大像素:带来暗态下高感光度和…

【java】力扣 反转链表

力扣 206 链表反转 题目介绍 解法讲解 先定义两个游标indexnull,prenull,反转之后链表应该是5,4,3,2,1,我们先进行2->1的反转,然后再循坏即可 让定义的游标index去存储head.n…

RocketMQ~消息的种类与生命周期(普通消息、延时定时消息、事务消息)

普通消息 普通消息一般应用于微服务解耦、事件驱动、数据集成等场景,这些场景大多数要求数据传输通道具有可靠传输的能力,且对消息的处理时机、处理顺序没有特别要求。 以在线的电商交易场景为例,上游订单系统将用户下单支付这一业务事件封…

im即时通讯系统有哪些?

IM即时通讯系统是一种通过互联网和移动通信网络实现实时通信的系统。在众多IM即时通讯系统中,WorkPlus作为企业级IM即时通讯系统,提供了全面的通讯和协作解决方案。本文将介绍几种常见的IM即时通讯系统,以及WorkPlus作为企业级IM即时通讯系统…

第三方配件也能适配苹果了,iOS 18与iPadOS 18将支持快速配对

苹果公司以其对用户体验的不懈追求和对创新技术的不断探索而闻名。随着iOS 18和iPadOS 18的发布,苹果再次证明了其在移动操作系统领域的领先地位。 最新系统版本中的一项引人注目的功能,便是对蓝牙和Wi-Fi配件的配对方式进行了重大改进,不仅…

【自动驾驶汽车通讯协议】UART通信详解:理解串行数据传输的基石

文章目录 0. 前言1. 同步通讯与异步通讯1.1 同步通信1.2 异步通信 2. UART的数据格式3. 工作原理3.1 波特率和比特率3.2 UART的关键特性 4. UART在自动驾驶汽车中的典型应用4.1 UART特性4.2应用示例 5. 结语 0. 前言 按照国际惯例,首先声明:本文只是我自…

html5——列表、表格

目录 列表 无序列表 有序列表 自定义列表 表格 基本结构 示例 表格的跨列 表格的跨行 列表 无序列表 <ul>【声明无序列表】 <li>河间驴肉火烧</li>【声明列表项】 <li>唐山棋子烧饼</li> <li>邯郸豆沫</li> <l…

pyinstaller教程(二)-快速使用(打包python程序为exe)

1.介绍 PyInstaller 是一个强大的 Python 打包工具&#xff0c;可以将 Python 程序打包成独立的可执行文件。以下会基于如何在win系统上将python程序打包为exe可执行程序为例&#xff0c;介绍安装方式、快速使用、注意事项以及特别用法。 2.安装方式 通过 pip 安装 PyInstal…

随笔-不是来养老的吗

来了有一个多月了&#xff0c;日子过得飞快。都以为我来养老的&#xff0c;一开始我也这么认为&#xff0c;结果6月份的日均工时&#xff0c;排在了部门第一。一个月做的需求比之前的三个月都多。 来之前&#xff0c;老徐让我多承担点&#xff0c;想着能有多少活嘛&#xff0c…

QT TCP多线程网络通信

学习目标&#xff1a; TCP网络通信编程 学习前置环境 运行环境:qt creator 4.12 QT TCP网络通信编程-CSDN博客 Qt 线程 QThread类详解-CSDN博客 学习内容 使用多线程技术实现服务端计数器 核心代码 客户端 客户端&#xff1a;负责连接服务端&#xff0c;每次连接次数1。…

sklearn之神经网络学习算法

文章目录 什么是神经网络人工神经网络的结构输入层输出层隐含层神经元的链接 近几年深度学习还是比较火的&#xff0c;尤其是在大语言模型之后&#xff0c;在本质上深度学习网络就是层数比较多的神经网络。sklearn并不支持深度学习&#xff0c;但是支持多层感知机&#xff08;浅…

安全测试理论

安全测试理论 什么是安全测试&#xff1f; 安全测试&#xff1a;发现系统安全隐患的过程安全测试与传统测试区别 传统测试&#xff1a;发现bug为目的 安全测试&#xff1a;发现系统安全隐患什么是渗透测试 渗透测试&#xff1a;已成功入侵系统为目标的的攻击过程渗透测试与安全…