thefour--Love is like a tide

最后一部分了,要开始进行我们的训练了。

先上代码:

import os
import numpy as np
from tqdm import tqdm
import tensorflow as tf
from thetwo import NeuralStyleTransferModel
import theone
import thethree
#创建模型
model=NeuralStyleTransferModel()
#加载内容图片
content_image= thethree.load_images(theone.CONTENT_IMAGE_PATH)
#风格图片
style_image= thethree.load_images(theone.STYLE_IMAGE_PATH)
#计算出内容图片的内容特征备用
target_content_features = model([content_image,])['content']
target_style_features = model([style_image, ])['style']
M= theone.WIDTH * theone.HEIGHT
N=3
def _compute_content_loss(noise_features,target_features):
    """
    计算指定层上两个特征之间的内容loss
    :param noise_features: 噪声图片在指定层的特征
    :param target_features: 内容图片在指定层的特征
    :return:
    """
    content_loss=tf.reduce_sum(tf.square(noise_features - target_features))
    #计算系数
    x=2.*M*N
    content_loss=content_loss/x
    return content_loss
def compute_content_loss(noise_content_features):
    """
    计算当前图片的内容loss
    :param noise_content_features:噪声图片的内容特征
    :return:
    """
    #初始化内容损失
    content_losses=[]
    #加权计算内容损失
    for(noise_feature,factor),(target_feature,_) in zip(noise_content_features,target_content_features):
        layer_content_loss=_compute_content_loss(noise_feature,target_feature)
        content_losses.append(layer_content_loss*factor)
    return tf.reduce_sum(content_losses)
def gram_matrix(feature):
    """
    计算给定特征的格拉姆矩阵
    :param feature:
    :return:
    """
    #先交换维度,把channel维度提到最前面
    x=tf.transpose(feature,perm=[2,0,1])
    #reshape,压缩为2d
    x=tf.reshape(x,(x.shape[0],-1))
    #计算x和x的逆的乘积
    return x@tf.transpose(x)
def _compute_style_loss(noise_feature,target_feature):
    """
    计算指定层上的两个特征之间的风格损失
    :param noise_feature: 噪声图片在指定层的特征
    :param target_feature: 风格图片在指定层的特征
    :return:
    """
    noise_gram_matrix=gram_matrix(noise_feature)
    style_gram_matrix=gram_matrix(target_feature)
    style_loss=tf.reduce_sum(tf.square(noise_gram_matrix-style_gram_matrix))
    x=4.*(M**2)*(N**2)
    return style_loss/x
def compute_style_loss(noise_style_features):
    """
    计算并返回图片的风格loss
    :param noise_style_features:噪声图片的风格特征
    :return:
    """
    style_losses=[]
    for(noise_feature,factor),(target_feature,_) in zip(noise_style_features,target_style_features):
        layer_style_loss = _compute_style_loss(noise_feature,target_feature)
        style_losses.append(layer_style_loss*factor)
    return tf.reduce_sum(style_losses)
def total_loss(noise_features):
    """
    计算总损失
    :param noise_features: 噪声图片特恒数据
    :return:
    """
    content_loss=compute_content_loss(noise_features['content'])
    style_loss=compute_style_loss(noise_features['style'])
    return content_loss* theone.CONTENT_LOSS_FACTOR+style_loss* theone.STYLE_LOSS_FACTOR
optimizer=tf.keras.optimizers.Adam(theone.LEARNING_RATE)
noise_image=tf.Variable((content_image + np.random.uniform(-0.2, 0.2, (1, theone.HEIGHT, theone.WIDTH, 3))) / 2)
@tf.function
def train_one_step():
    """
    一次迭代过程
    :return:
    """
#求loss
    with tf.GradientTape() as tape:
        noise_outputs = model(noise_image)
        loss = total_loss(noise_outputs)
    #求梯度
    grad = tape.gradient(loss,noise_image)
    #梯度下降,更新噪声图片
    optimizer.apply_gradients([(grad,noise_image)])
    return loss
#创建保存生成图片的文件夹
if not os.path.exists(theone.OUTPUT_DIR):
    os.mkdir(theone.OUTPUT_DIR)
#共训练theone.EPOCHS个epoch
for epoch in range(theone.EPOCHS):
    #使用tqdm提示训练进度
    with tqdm(total=theone.STEPS_PER_EPOCH, desc='EPOCH{}/{}'.format(epoch + 1, theone.EPOCHS)) as pbar:
        #每个epoch训练theone.STEPS_PER_EPOCH次
        for step in range(theone.STEPS_PER_EPOCH):
            _loss=train_one_step()
            pbar.set_postfix({'loss':'%.4f'%float(_loss)})
            pbar.update(1)
            #每个epoch保存一次图片
        thethree.save_image(noise_image, '{}/{}.jpg'.format(theone.OUTPUT_DIR, epoch + 1))

下面我们来分析代码:

model=NeuralStyleTransferModel()
#加载内容图片
content_image= thethree.load_images(theone.CONTENT_IMAGE_PATH)
#风格图片
style_image= thethree.load_images(theone.STYLE_IMAGE_PATH)
#计算出内容图片的内容特征备用
target_content_features = model([content_image,])['content']
target_style_features = model([style_image, ])['style']
M= theone.WIDTH * theone.HEIGHT
N=3

先看第一部分,也可以说是准备工作。

model=NeuralStyleTransferModel()

首先,我们创建了一个神经风格迁移的实例对象,也就是我们之前定义的类模型,负责处理风格迁移的相关工作,主要是加载与训练集。

content_image= thethree.load_images(theone.CONTENT_IMAGE_PATH)

接下来,我们加载我们的数据,也就是图像,这里我们使用的是我们自定义的函数,参数是图片路径。这个函数(我们自定义的加载图片函数)包含了对图片进行处理等操作。

style_image= thethree.load_images(theone.STYLE_IMAGE_PATH)

同时,我们也要加载风格图片。

target_content_features = model([content_image,])['content']

将内容图片的变量作为参数传递给模型,调用call函数进行处理,返回的是字典,其中包含两个键值对,键分别是content和style。而在代码中我们指定的是content,即输出处理后得到的不同类型的特征。这些内容特征通常会在后序的神经风格迁移中用到,用于调整生成图片的内容以匹配院士图片的内容。

同理,

target_style_features = model([style_image, ])['style']

我们也提取了风格图片的特征。

M= theone.WIDTH * theone.HEIGHT
N=3

M和N用于后序的计算中,N是通道数。

def _compute_content_loss(noise_features,target_features):
    """
    计算指定层上两个特征之间的内容loss
    :param noise_features: 噪声图片在指定层的特征
    :param target_features: 内容图片在指定层的特征
    :return:
    """
    content_loss=tf.reduce_sum(tf.square(noise_features - target_features))
    #计算系数
    x=2.*M*N
    content_loss=content_loss/x
    return content_loss

作用是计算指定层上两个特征之间的内容损失,接受的参数就是指定层上的特征,(噪声图片和内容图片)。

content_loss=tf.reduce_sum(tf.square(noise_features - target_features))

这段代码是计算内容损失的核心部分。参数noise_features和target_features是通过某种深度学习模型(很明显是卷积神经网络)在指定层次上提取的特征表示。

tf.square:计算了噪声图片特征与目标图片特征之间的差值,并将差值的每个元素取平方,然后通过td.reduce_sum()函数来进行求和,作为损失。

x = 2.0 * M * N 
content_loss = content_loss / x

这段代码是计算一个归一化系数即尺寸*通道数,再*2是为了增加一个权重因子,以调整损失的量级,使其更适合当前的优化目标。这种调整可以根据具体的任务和数据集来确定,以便更好的平衡损失的大小与优化过程的效率。

通常情况下,损失函数的值越小越好,因为我们的优化目标通常是将损失最小化,但是有时候,如果损失值过小,可能会导致数值不稳定或者优化过程变得过于敏感,通过乘以一个适当的权重因子,可以调整损失的量级,使其更适合当前的优化过程。
content_loss = content_loss / x这一计算时将损失除以归一化系数,使其不受图像尺寸和通道数的影响,从而更好的用于神经风格迁移的优化过程。

def compute_content_loss(noise_content_features):
    """
    计算当前图片的内容loss
    :param noise_content_features:噪声图片的内容特征
    :return:
    """
    #初始化内容损失
    content_losses=[]
    #加权计算内容损失
    for(noise_feature,factor),(target_feature,_) in zip(noise_content_features,target_content_features):
        layer_content_loss=_compute_content_loss(noise_feature,target_feature)
        content_losses.append(layer_content_loss*factor)
    return tf.reduce_sum(content_losses)

for (noise_feature,factor),(target_feature,_)in zip(noise_content_features,target_content_features):
迭代噪声图片的内容特征和目标图片的内容特征,这两个特征在创建模型的call函数里面就已经论述过提取方法了。

layer_content_loss=_compute_content_loss(noise_feature,target_feature)
content_losses.append(layer_content_loss*factor)

调用函数来计算其中的损失,并通过和权重进行相乘,添加到内容损失列表中。权重因子是用来调整每个层级对总体内容损失的贡献度,通过内容损失加权,更好控制了每个层级对整体损失的影响程度。

return tf.reduce_sum(content_losses)

我们将列表中所有元素进行求和,得到一个标量值,表示了当前图片的总的内容损失。

def gram_matrix(feature):
    """
    计算给定特征的格拉姆矩阵
    :param feature:
    :return:
    """
    #先交换维度,把channel维度提到最前面
    x=tf.transpose(feature,perm=[2,0,1])
    #reshape,压缩为2d
    x=tf.reshape(x,(x.shape[0],-1))
    #计算x和x的逆的乘积
    return x@tf.transpose(x)

这段代码用于计算给定特征的格拉姆矩阵,参数是一个表示特征的张量。

x=tf.transpose(feature,perm=[2,0,1])这一行将特征张量的维度进行重新排列,将通道维度移动到最前面,参数perm=[2,0,1]表示将原始特征张量的通道维度(索引为2)放到最前面,其余维度保持不变。

x=tf.reshape(x,(x.shape[0],-1))

操作是将x张量进行重塑,x.shape[0]是取出张量x在第一个维度上的大小,通常表现的是批处理的大小。

这段代码的作用是将张量x重新塑造为一个二维张量,其中,第一个维度大小保持不变,即与原来张量的第一个维度大小相同(通常是指批处理的大小),而第二个维度则被设置为-1,这使得TensorFlow能够自动计算出第二个维度的大小。即剩下所有元素拉伸为单一的维度。这种操作通常用于准备特征张量以进行后续的矩阵运算或神经网络层的输入。

最后

return x@tf.transpose(x)

这段代码使用transpose函数来转置张量x,然后执行矩阵乘法操作。(两个维度是默认交换行和列的位置)。

在Python3.5以及以上的版本中@符号表示的是矩阵乘法操作,所以这一部分表示张量x与它的转置相乘。结果得到的是格拉姆矩阵,在神经网络中,格拉姆矩阵(Gram Matrix)用于捕捉特征之间的相关性,它的每个元素表示了相应特征之间的内积,从而反映它们之间的相似度和共同激活程度。

def _compute_style_loss(noise_feature,target_feature):
    """
    计算指定层上的两个特征之间的风格损失
    :param noise_feature: 噪声图片在指定层的特征
    :param target_feature: 风格图片在指定层的特征
    :return:
    """
    noise_gram_matrix=gram_matrix(noise_feature)
    style_gram_matrix=gram_matrix(target_feature)
    style_loss=tf.reduce_sum(tf.square(noise_gram_matrix-style_gram_matrix))
    x=4.*(M**2)*(N**2)
    return style_loss/x

定义计算风格损失函数,接受的参数是噪声图片在指定层的特征和风格图片在指定层的特征。

noise_gram_matrix=gram_matrix(noise_feature)格拉姆矩阵是用来衡量特征之间相关性的重要工具,通常用于计算风格损失,在风格迁移中,格拉姆矩阵捕捉了特征之间的相关性和共同激活程度,从而反映了风格的特征。这段代码的意思是将给定特征张量表示转化为格拉姆矩阵的形式,计算特征之间的相关性。

同理,下一句是将风格图片的特征张量转化为格拉姆矩阵。

然后计算表示噪声图片的格拉姆矩阵和表示风格图片的格拉姆矩阵之间的平方差。

归一化系数x,这里很明显是计算内容损失系数的平方,这个系数的计算是基于格拉姆矩阵的形式,格拉姆矩阵的计算设计特征之间的内积,这意味着其值与特征的数量有关。很明显,获得的风格损失矩阵是相比内容损失矩阵的二维拉伸,所以用于归一的系数也要二维拉伸。

同样我们返回归一化后的结果。

def compute_style_loss(noise_style_features):
    """
    计算并返回图片的风格loss
    :param noise_style_features:噪声图片的风格特征
    :return:
    """
    style_losses=[]
    for(noise_feature,factor),(target_feature,_) in zip(noise_style_features,target_style_features):
        layer_style_loss = _compute_style_loss(noise_feature,target_feature)
        style_losses.append(layer_style_loss*factor)
    return tf.reduce_sum(style_losses)

进行各层的风格损失汇总,类似于内容损失。

def total_loss(noise_features):
    """
    计算总损失
    :param noise_features: 噪声图片特恒数据
    :return:
    """
    content_loss=compute_content_loss(noise_features['content'])
    style_loss=compute_style_loss(noise_features['style'])
    return content_loss* theone.CONTENT_LOSS_FACTOR+style_loss* theone.STYLE_LOSS_FACTOR

计算总损失,content_loss=compute_content_loss(noise_features['content'])调用compute-content_loss函数计算总损失。下句同理。

返回的是将内容损失和风格损失加权之后求和的结果。

optimizer=tf.keras.optimizers.Adam(theone.LEARNING_RATE)

开始定义优化器喽:使用TensorFlow创建一个Adam优化器对象,Adam是一种常用的优化算法,使用羽于训练神经网络和深度学习模型。

在TensorFlow中,通过tf.keras.optimizers模块可以访问各种优化器,Adam优化器是一种自适应学习率优化算法,它能够在训练过程中自动调整学习率。参数是优化器的学习率,学习率决定了每次参数更新时所应用的步长大小,这通常是神经网络模型中事先定义好的超参数。

noise_image=tf.Variable((content_image + np.random.uniform(-0.2, 0.2, (1, theone.HEIGHT, theone.WIDTH, 3))) / 2)

这段代码创建一个TensorFlow变量noise_image,将其随机初始化为一个噪声图像,该图像是基于图像content_image而生成的。

np.random.uniform(-0.2, 0.2, (1, theone.HEIGHT, theone.WIDTH, 3))是一个NumPy函数调用,用于生成一个指定范围内均匀分布的随机数组,其形状为(1,theone.HEIGHT,theone.WIDTH,3)。

(-0.2,0.2)指定了随机数的范围,在这个例子中,随机数是从范围-0.2(包含)到0.2(不包含)之间的。数组中的元素是在-0.2到0.2之间的均匀分布的随机数,这个数组通常用于图像的随机噪声,用于引入一些随机性以便于训练模型。

@tf.function
def train_one_step():
    """
    一次迭代过程
    :return:
    """
#求loss
    with tf.GradientTape() as tape:
        noise_outputs = model(noise_image)
        loss = total_loss(noise_outputs)
    #求梯度
    grad = tape.gradient(loss,noise_image)
    #梯度下降,更新噪声图片
    optimizer.apply_gradients([(grad,noise_image)])
    return loss

这是神经风格迁移算法中的一次迭代过程。

@tf.function

是TensorFlow中的装饰器,用于将Python函数转化为TensorFlow计算图的一部分,以便提高计算效率。被@tf.function修饰的函数被编译为TensorFlow图,以便进行更有效的计算。

with tf.GradientTape() as tape:

这是TensorFlow中用于计算梯度的上下文管理器。在这个上下文中的操作会被记录下来,以便后序计算梯度。tf.GrandientTape()创建了一个新的梯度带,梯度带的作用是跟踪TensorFlow操作执行过程中所涉及的所有可训练变量的操作,并且能根据这些操作计算相对于这些变量的梯度。

with语句用于创建一个上下文环境,在这个环境中,所有的操作都会被记录在梯度带tape中,当退出这个上下文环境时,梯度带tape将被释放,其中的操作记录也将被删除,这样可以节省内存并提到效率。

noise_outputs = model(noise_image)

是得到噪声图像的输出,类型为字典,其中包括内容输出和风格输出。

loss = total_loss(noise_outputs)

用来计算总损失。

grad = tape.gradient(loss,noise_image)
#梯度下降,更新噪声图片
optimizer.apply_gradients([(grad,noise_image)])
return loss
grad = tape.gradient(loss,noise_image)

这行代码计算损失loss相对于噪声图片noise_image的梯度,在上下文的梯度带中,我们使用tape记录了计算损失的过程,以便TensorFlow能够自动计算相对于noise_image的梯度。

optimizer.apply_gradients([(grad,noise_image)])

这是TensorFlow中用于应用梯度下降步骤的方法,优化器会根据计算得到的梯度来更新模型参数,以使损失函数尽可能小。[(grad,noise_image)]是一个由梯度-变量对构成的列表,每个对都是一个元组,其中包含了要应用的梯度和相应的变量。在这里,(grad,noise_image)表示要将梯度grad应用于变量noise_image上。当调用apply_gradients()方法时,优化器会使用梯度下降算法或者其他优化算法,根据给定的梯度更新相应变量的值。这个过程是优化模型参数的关键步骤,它使模型能够逐渐的优化损失函数,提高模型的性能和准确性。

return loss

最后返回计算得到的损失值,以便在训练过程中进行监控和记录。

if not os.path.exists(theone.OUTPUT_DIR):
    os.mkdir(theone.OUTPUT_DIR)
#共训练theone.EPOCHS个epoch
for epoch in range(theone.EPOCHS):
    #使用tqdm提示训练进度
    with tqdm(total=theone.STEPS_PER_EPOCH, desc='EPOCH{}/{}'.format(epoch + 1, theone.EPOCHS)) as pbar:
        #每个epoch训练theone.STEPS_PER_EPOCH次
        for step in range(theone.STEPS_PER_EPOCH):
            _loss=train_one_step()
            pbar.set_postfix({'loss':'%.4f'%float(_loss)})
            pbar.update(1)
            #每个epoch保存一次图片
        thethree.save_image(noise_image, '{}/{}.jpg'.format(theone.OUTPUT_DIR, epoch + 1))
if not os.path.exists(theone.OUTPUT_DIR):
    os.mkdir(theone.OUTPUT_DIR)

代码首先检测是否存在指定的输出目录,如果不存在该目录,则使用os.mkdir函数创建该目录,这个目录用于 保存训练过程中生成的图片。

with tqdm(total=theone.STEPS_PER_EPOCH, desc='EPOCH{}/{}'.format(epoch + 1, theone.EPOCHS)) as pbar:

tqdm()函数用于创建一个进度条,用于显示训练进度。total参数设置了进度条的总步数。

desc参数设置了进度条的描述,格式化字符串'EPOCH{}/{}'.format(epoch+1,theone.EPOCHS)显示当前EPOCH序号和epoch的数量。

for step in range(theone.STEPS_PER_EPOCH):
    _loss=train_one_step()
    pbar.set_postfix({'loss':'%.4f'%float(_loss)})
    pbar.update(1)

进一步观察内部循环:

_loss=train_one_step()

进行了一步模型参数的更新。

pbar.set_postfix()方法更新了进度条的后缀,在这里,将损失值_loss格式化为四位小数,并将其作为进度条后缀,以便在训练过程中实时监控损失值变化。

之后使用pbar.update(1)的方法更新进度条,表示完成了当前的训练步骤,进度条的进度增加1。

最后一步了:

thethree.save_image(noise_image, '{}/{}.jpg'.format(theone.OUTPUT_DIR, epoch + 1))

!!!

使用thethree.save_image来保存生成的图片,该函数中有对张量转化为图像的操作,第二个参数是文件名,文件的路径是创建的文件夹下面加上轮数。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从零开始写 Docker(三)---基于 cgroups 实现资源限制

本文为从零开始写 Docker 系列第三篇,在mydocker run 基础上基于 cgroups 实现容器的资源限制。 完整代码见:https://github.com/lixd/mydocker 欢迎 Star 如果你对云原生技术充满好奇,想要深入了解更多相关的文章和资讯,欢迎关注…

C# Post数据或文件到指定的服务器进行接收

目录 应用场景 实现原理 实现代码 PostAnyWhere类 ashx文件部署 小结 应用场景 不同的接口服务器处理不同的应用,我们会在实际应用中将A服务器的数据提交给B服务器进行数据接收并处理业务。 比如我们想要处理一个OFFICE文件,由用户上传到A服务器…

紫罗兰栽培养护简单,这些要点多注意——花园传说

紫罗兰,以其独特的芬芳和优雅的花姿,历来备受人们的喜爱。无论是摆放在室内还是庭院中,紫罗兰都能为生活增添一份别样的雅致。那么,如何将紫罗兰成功栽培到家中呢?下面就为大家详细介绍紫罗兰的养殖方法及养护要点。 选…

《Spring Security 简易速速上手小册》第3章 用户认证机制(2024 最新版)

文章目录 3.1 认证流程3.1.1 基础知识详解认证流程的核心概念认证流程的步骤 3.1.2 主要案例:内存用户认证案例 Demo:快速启动你的 Spring Boot 守护程序 3.1.3 拓展案例 1:数据库用户认证案例 Demo:让数据库守护你的秘密 3.1.4 拓…

Django学习笔记-ModelForm使用(完全依赖)

1.创建模型 ,code,name,sex,entrydate 2.模型映射 python manage.py makemigrations myapp01,python manage.py migrate 3.创建模型表单,继承forms.ModelForm,Meta:元数据,models需引入,fields填写引用的模型变量 4.创建testModelForm.html,添加urls 5.views编写testmodelfo…

【Python笔记-设计模式】模板方法模式

一、说明 模板方法模式是一种行为设计模式,就是继承和多态的使用,将通用操作在父类中实现,不同操作的细节在子类中具体实现,父类只声明接口。 (一) 解决问题 减少相似逻辑的重复代码,提高代码复用性提高代码逻辑性&…

深入探讨Python中的os模块:基础大总结与实战【第109篇—os模块】

深入探讨Python中的os模块:基础大总结与实战 在Python编程中,操作系统(os)模块是一个强大的工具,它提供了与操作系统交互的各种功能,使得开发者能够轻松地执行文件和目录操作、获取系统信息以及执行系统命令。在本篇技术博客中&a…

React中对表格实现列表的拖拽排序

1. 效果:推拽手柄列 2. 实现: react中我们需要两个包来实现 ‘array-move’‘react-sortable-hoc’Installation Use npm $ npm install react-sortable-hoc --save 引入 import { arrayMoveImmutable } from array-move import { SortableContainer, SortableElement, Sort…

具身智能计算系统,机器人时代的 Android | 新程序员

【导读】具身智能作为一种新兴的研究视角和方法论,正在刷新我们对智能本质及其发展的理解:传统的 AI 模型往往将智能视为一种独立于实体存在的抽象能力,而具身智能则主张智能是实体与其环境持续互动的结果。 本文深度剖析了具身智能计算系统…

Unity(第十六部)声音和视频

声音 1、听声音 创建相机的时候,相机自带Audio Listener 多个相机的时候,我们只保留一个Audio Listener就可以 2、声音源,环境音 添加Audio Source就行中文叫声音源 3、脚本执行的声音 using System.Collections; using System.Collection…

如何用ai智能写作?推荐5款优秀的AI写作神器

写作是件繁琐的事情,也是需要耗费精力和时间的,还好目前有了ai写作神器的出现,帮助我们解决了不少的写作难题。这些AI写作工具不仅可以帮助我们提高写作效率,还能够生成高质量的内容。在本文中,我将向你推荐5款优秀的A…

CentOS 定时调度

文章目录 一、场景说明二、脚本职责三、参数说明四、操作示例五、注意事项 一、场景说明 本自动化脚本旨在为提高研发、测试、运维快速部署应用环境而编写。 脚本遵循拿来即用的原则快速完成 CentOS 系统各应用环境部署工作。 统一研发、测试、生产环境的部署模式、部署结构、…

深度学习 精选笔记(7)前向传播、反向传播和计算图

学习参考: 动手学深度学习2.0Deep-Learning-with-TensorFlow-bookpytorchlightning ①如有冒犯、请联系侵删。 ②已写完的笔记文章会不定时一直修订修改(删、改、增),以达到集多方教程的精华于一文的目的。 ③非常推荐上面(学习参考&#x…

当无人机飞手真的有前途吗?无人机工作怎么找,感觉找不到太难了?无人机飞手未来的出路在哪里?

无人机飞手这个职业的前途很大程度上取决于市场需求和行业发展趋势。随着无人机技术的不断进步和应用领域的扩大,无人机飞手的需求量也在逐渐增加。然而,这个职业的发展也受到政策法规、技术更新换代等因素的影响,因此需要不断学习新技术和适…

Fastjson2 <== 2.0.26反序列漏洞

根据Y4TACKER师傅在2023-03-20发布了一篇关于Fastjson原生反序列化的文章,文章中引入注目的是利用条件限制条件,不常常关注漏洞预警或者内容的几乎都是未发觉Fastjson2 到Fastjson2 2.0.26版本都有问题,其实如果单独去使用一些关键词去搜索&a…

python 小游戏《2048》字符版非图形界面

参考链接: 闲谈2048小游戏和数组的旋转及翻转和转置 目录 2048 一、方阵类 二、随机插入1或2 三、 合并和递增 四、 判断和移动 五、 键盘控制 完整源代码 玩法过程 2048 上回说到2048小游戏中数组的各种旋转、翻转的方法,就是为代码编程作准…

单词规律00

题目链接 单词规律 题目描述 注意点 pattern只包含小写英文字母s只包含小写英文字母和 ’ ’s不包含任何前导或尾随对空格s中每个单词都被 单个空格 分隔 解答思路 本题与上一次同构字符串类似,思路可以参照同构字符串 代码 class Solution {public boolean …

C++——内存管理(new和delete)详解

目录 C/C内存管理 案例:变量在内存中到底会在哪? New和delete Operator new和operator delete函数 New和delete的原理 对内置类型 对自定义类型 定位new New/delete和malloc/free的区别 C/C内存管理 C/C内存管理分布图:(从…

C语言while 语句的基本格式是什么?

一、问题 C语⾔中有三种循环语句,while 语句是其中的⼀个,它的基本格式是怎样的呢? 二、解答 while 语句的⼀般形式为: while(表达式) 语句; 其中,表达式是循环条件,语句为循环体。 注意: …

uni-app 微信小程序:启用组件按需注入

原文地址:uni-app 微信小程序:启用组件按需注入 - 掘金 只需添加以下代码"lazyCodeLoading": "requiredComponents"