目录
一.简介
二.静态调度
1.SDFG
2.单处理器调度(PASS)
3.多处理器调度(PAPS)
三.SDF应用
一.简介 同步数据流(SDF,Synchronous Data Flow)概念来源于1987年,建议阅读同年论文《Static Scheduling of Synchronous Data Flow Programs for Digital Signal Processing》和《Synchronous Data Flow》。
以下是数据流图&同步数据流图的两个简单示例。图中α、β、γ三个节点均代表不同功能,有向边代表的是数据流向。
当每个节点的输入输出数据个数已知时,就是本文主要介绍的同步数据流图。值得注意的是,同步数据流图中的节点并不存在固定的调度顺序(即不存在完全的节点相关,只要某节点调度所需的数据足够,该节点就会被执行execute,或者叫被触发fire)。
二.静态调度 1.SDFG 同步数据流图(SDFG,Synchronous Data Flow Graph)可以被表示为一个拓扑矩阵。
如下图所示,矩阵的每一行代表弧,每一列代表节点。图中有三个节点,两条边,则产生的拓扑矩阵为两行三列。矩阵中的每个数值(x,y)代表x节点在y弧上产生或消耗的数据个数。SDF图中的两条弧上的三个长方形代表缓冲区,SDFG中每个周期的调度应该对缓冲区不产生影响,也就是每个最小调度周期结束后,所有节点产生的数据刚好等于消耗的数据。
比如第一行第一列数值为2,表示节点1在弧1上产生了2个数据。
比如第二行第三列数值为-1,表示节点3在弧2上消耗了1个数据。
2.单处理器调度(PASS) periodic admissible sequential schedule
所求q向量就是最小周期内每个节点最少调度次数。下图中得出v1=1,v2=v3=2.简单计算不难得出,当节点u调度1次,在缓冲区1中产生两个数据;节点mul调度两次,在缓冲区2中共产生两个数据;节点三调度两次,刚好消耗掉所产生的数据。总体满足上述我们提到的所有节点产生的数据刚好等于消耗的数据。
由于同步数据流图仅展示部分功能,所以默认有外部输入数据的节点都是直接可以无限次触发的(可以理解为外部数据无限次供应),图中的节点u和节点mul就是仅需要外部数据就可以触发,所以一直处于可执行状态,而节点add就需要有足够的数据才能触发。
计算出q向量的结果之后,得到的是每个节点的执行次数(1,2,2),但并不是具体的调度次序。采取的方案是执行每个能够执行的节点,首先节点1仅仅只有外部输入数据就可以执行,所以先执行节点1,;然后同理执行节点2,可执行两次;最后执行节点3,可执行两次。得到最终的最小周期调度次序(U,Mul,Mul,Add,Add)。
3.多处理器调度(PAPS) periodic admissible parallel schedule
上图是一个简单的多处理器调度,J代表的是展开因子,不同的展开因子将会影响并行调度的效率。当J=1时,可以看到处理器2是有空闲的时间片在的;当J=2时,两个处理器都没有空闲时间,这说明处理器得到了最大的利用,是一个完美的调度方案。需要注意的是SDFG中每个节点都是self-loop自循环的,即不允许两个处理器同时执行同一个节点,不允许两个处理器同时访问同一缓冲区。
三.SDF应用 数字信号处理:
应用于音频处理、视频处理、无线电通信等领域,能够有效地处理时变信号,并通过流水线实现高效的并行处理。
图像处理:
实现卷积神经网络、图像分割、目标检测等算法,可以实现基于并行计算的图像处理算法,从而提高算法的效率和性能。 嵌入式系统设计:
SDF常用于嵌入式系统设计中,因为SDF的数据流特性非常适合描述嵌入式系统中的任务并发性和实时性。通过对SDF图的静态分析,可以确保系统中任务的实时性和正确性。
数据准备 import torch import spacy from torchtext.data import Field,BucketIterator from torchtext.datasets import Multi30k #加载文本、建立分词器 de_seq=spacy.load("de_core_news_sm") en_seq=spacy.load("en_core_web_sm") def src_token(text): return [word.text for word in de_seq.tokenizer(text)] def trg_token(text): return [word.text for word in en_seq.tokenizer(text)] #源端和目标端的操作 SRC=Field(tokenize=src_token, init_token="<sos>", eos_token="<eos>", lower=True) TRG=Field(tokenize=trg_token, init_token="<sos>", eos_token="<eos>", lower=True) #定义数据集、建立词表 train_data,val_data,test_data=Multi30k.splits(exts=(".de",".en"), fields=(SRC,TRG)) SRC.build_vocab(train_data,min_freq=2) TRG.build_vocab(train_data,min_freq=2) #建立迭代器 device=torch.device("cuda" if torch.cuda.is_available() else "cpu") batch_size=128 train_iter,val_iter,test_iter=BucketIterator.splits( (train_data,val_data,test_data), batch_size=batch_size, device=device ) #测试 for example in train_iter: break print('1:源数据设备,目标数据设备',example.src.device,example.trg.device,len(example)) print('2:源数据shape,目标数据shape',example.src.shape,example.trg.shape) print('3:源数据',example.src) print('4:目标数据',example.trg) 结果:
一、预备知识 概念 数组是存放在连续内存空间上的相同类型数据的集合。
特性 数组下标都是从0开始的;
数组内存空间的地址是连续的;
数组的元素不能删除,只能覆盖;
因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。
如果使用C++的话,要注意vector 和 array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。
注意:C++中二维数组是连续分布的,而Java中是不连续分布的。
二、二分查找 题目描述 题解 1)法一:(时:o(logn),空:o(1)) 注意循环不变量原则:在while寻找中每一次边界的处理都要坚持根据区间的定义来操作。
注意的知识点 1)left + (right - left) / 2防溢出;
2)vector容器:只有C++11以上才可利用列表初始化;.size()可以获取容器大小;
三、移除元素 题目描述 题解 1)法一:暴力解法(时:o(n^2),空:o(1)) 双层for循环,一个for循环遍历查找要删除的数组元素 ,第二个for循环更新数组。
2)法二:双指针法(时:o(n),空:o(1)) 快指针用于查找新的数组元素(即无需删除的元素),慢指针指向要删除的数组元素。
注意的知识点 1)数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖;
四、有序数组的平方 题目描述 题解 1)法一:暴力解法(时:O(n+nlogn),空:O(1)) 每个元素平方后进行排序。
2)法二:双指针法(时:O(n),空:o(1)) 数组本来有序, 只不过负数平方之后可能影响次序,故数组平方的最大值就在数组的两端,不是最左边就是最右边。
注意的知识点 1)vector向量,可理解为“变长数组”(即“长度根据需要而自动改变的数组);
2)iterator迭代器,可理解为一种类似指针的东西,可以通过 *it 来访问vector里的元素;
3).begin()函数: 取首元素地址;.end()函数:取尾元素地址的下一个地址,作为迭代器末尾标志,不存储任何元素;
4)vector<int> a(n, 0)创建大小为n且元素初始值为0的容器;
五、长度最小的子数组 题目描述 题解 1)法一:暴力解法(时:O(n^2),空:o(1)) 两层for循环依次遍历寻找合适的子序列。
2)法二:滑动窗口(时:o(n),空:o(1)) 根据当前子序列和大小的情况,不断调节子序列的起始位置。当前窗口的值>=target时,窗口就要向前移动(即向后调整窗口的起始位置);窗口的结束位置为遍历数组的指针,也就是for循环里的索引。
注:时间复杂度看每一个元素被操作的次数。每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。
3)法三:前缀和+二分法(时:o(nlogn),空:o(1)) 新建一个数组sums用于存储前i个元素的和,可以将寻找target的子序列转换为寻找和为sums[i]-target的前缀和,利用二分法在sums中寻找满足<=该前缀和的下标(即子序列起始位置的前一位)。
注意的知识点 1)INT32_MAX可表示初试最大值;
想使用深度学习结合影像的高程信息进行一些分类,就像尝试着试试RGB+DSM的影像会不会增加分类的精度,所以使用到了ArcGIS中的波段合成功能将无人机正射影像(RGB三波段)+DSM生成四波段的影像:
在融合的时候对正射影像要以单波段的形式加载,然后进行融合。
关于临床预测模型的基础知识,小编之前已经写过非常详细的教程,包括了临床预测模型的定义、常用评价方法、列线图、ROC曲线、IDI、NRI、校准曲线、决策曲线等。
全都是免费获取的代码和数据:R语言临床预测模型合集
临床预测模型进阶系列目前已推出随机生存森林系列推文:
随机生存森林模型构建和结果解读随机生存森林的Risk Score和生存曲线随机生存森林的决策曲线分析(DCA)随机生存森林的校准曲线(上)随机生存森林的校准曲线(下)随机生存森林的NRI和IDI以决策树为例演示超参数调优的基本方法(上)以决策树为例演示超参数调优的基本方法(下)随机生存森林的超参数调优随机生存森林变量选择 临床预测模型系列推文
R语言临床预测模型合集简单易懂:什么是临床预测模型?Cox回归列线图(nomogram)的4种绘制方法Logistic回归列线图的4种绘制方法列线图的本质一文搞懂临床预测模型的评价!区分度评价:C-statistic的计算C-statistic的显著性检验临床预测模型之二分类资料ROC曲线绘制临床预测模型之生存资料的ROC曲线绘制R语言画多时间点ROC和多指标ROC曲线生存资料ROC曲线的最佳截点和平滑曲线ROC(AUC)曲线的显著性检验ROC阳性结果还是阴性结果?ROC曲线纯手工绘制R语言计算AUC(ROC曲线)的注意事项多指标联合诊断的ROC曲线净重新分类指数NRI计算综合判别改善指数IDI的计算二分类资料的DCA决策曲线分析生存资料的决策曲线分析DCA只会logistic和cox的决策曲线?来看看适用于一切模型的DCA!二分类资料校准曲线的绘制生存资料校准曲线的绘制tidymodels不能画校准曲线?mlr3的校准曲线也是一样画!使用tidymodels搞定二分类资料多个模型评价和比较使用workflow一次完成多个模型的评价和比较使用mlr3搞定二分类资料的多个模型评价和比较Fine-Gray检验、竞争风险模型、列线图绘制tidymodels支持校准曲线了3d版混淆矩阵可视化logistic校准曲线(测试集)的6种实现方法
本博客属于赋值内容,原文请看以下连接(亲测有用):
【OpenCV-Python】29.OpenCV的特征检测——特征匹配_opencv 特征匹配 python_机器视觉小学徒的博客-CSDN博客
一、关键点获取并画图 # -*- coding: utf-8 -* import cv2 import matplotlib.pyplot as plt # 1.读取灰度图像 image1 = cv2.imread("p1.png") image2 = cv2.imread("p2.png") gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) # 2.SIFT实例化 orb = cv2.ORB_create() #可以选择不同特征点,见后者 # 3.检测关键点 kq1, dst1 = orb.detectAndCompute(gray1, None) kq2, dst2 = orb.detectAndCompute(gray2, None) # 4.绘制关键点 cv2.drawKeypoints(image1, kq1, image1, (0, 0, 255),flags=1) # flags=1 决定特征点的大小 cv2.drawKeypoints(image2, kq2, image2, (0, 0, 255),flags=1) # flags=1 决定特征点的大小 # 绘制图像 fig, axes = plt.
目录
摘要:
卷积神经网络(CNN)的介绍:
长短期记忆网络(LSTM)的介绍:
CNN-LSTM:
Matlab代码运行结果:
本文Matlab代码+数据分享: 摘要: 本文使用CNN-LSTM混合神经网络对时间序列数据进行回归预测。本模型的输入数据个数可以自行选择,可以为多输入、也可以为单输入,使用Matlab自带的数据集进行训练,可以轻松的更换数据集以实现自己的功能。首先使用CNN网络对输入数据进行深度特征提取,然后将提取到的抽象特征进行压缩,将压缩后的数据输入后续的LSTM网络进行回归预测。相比一般的单层网络结构,本文所提出的CNN-LSTM包含了三层CNN和三层LSTM网络,因此本文网络预测的准确度有了一定的提升。
本文代码结构清晰,实现效果很好,出图美观,适合初学者进行模仿学习或用于数学建模方面。
有关于CNN-LSTM进行多输入特征分类的代码,可以看我之前发的文章。
卷积神经网络(CNN)的介绍: 卷积神经网络(ConvolutionalNeuralNetworks,CNN)能有效的提取二维图像和高维数据的特征。卷积神经网络具有减少内存占用、减少网络参数、缓解过拟合问题等优势,因此基于卷积神经网络时间序列预测模型。
卷积神经网络由输入层、隐含层和输出层组成,其中隐含层又分为卷积层、池化层和全连接层。结构如图:
(1)输入层:
输入层的作用是预处理输入的图像或数据。预处理方法能够减少数据量纲的差异对模型的影响,可以提高模型的学习效率。
(2)隐含层:
隐含层包括卷积层、池化层、全连接层,作用是完成特征的提取和学习。
(a)卷积层:卷积层中最重要的是卷积核。卷积核的个数、大小和形状,需要根据数据或图像的实际情况确定。一维卷积通常用来处理一维、二维数据或图像,二维卷积常用于二维数据矩阵的卷积操作,三维卷积常用于医学及视频处理领域的三维数据。步长是指进行卷积计算时,每次移动的格数。即步长为几时,卷积核每次向右移动几个格子。在模型训练时,可以根据需要改变步长、卷积核的大小和数量。卷积操作的具体步骤以图举例说明。图中左侧的4×4的矩阵代表输入,中间3×3的矩阵为卷积核,步长设为1,则右侧的矩阵为特征结果图。卷积操作过程为:将卷积核在输入数据或图像上每次先向右平移一个步长,将卷积核矩阵和输入数据对应位置矩阵进行内积计算,输出一个数值,放在特征结果图的对应位置上。水平方向完成卷积计算后再向下移动一个步长,重复卷积计算步骤,最终得到输入数据或图像的特征结果图,
(b)池化层:池化层也称采样层,主要作用是采样降维,即在不改变数据或图像特征的前提下,将数据的维数尽可能地降低。通过池化函数,将特征图某点替换为其相邻输出的全局特征。按照滤波器映射范围内像素点取值的不同,可分为平均池化和最大池化。平均池化:计算所有非零数据的平均值并用作输出。以2×2池化为例,左侧为卷积操作后得到的特征结果图,池化滤波器在特征结果图上每次平移两个步长,得到特征结果图被划分成四部分,分别计算非零像素点的平均值,并作为该位置的输出。
(c)全连接层:全连接层的作用是将特征映射到样本标记空间。通过全连接层将神经元权重连接,并向下一层网络传递数据信息。即通过矩阵乘法对特征向量加权求和计算,并通过激活函数得到全连接层的输出
(3)输出层:
增加一层回归层,并将全连接层的输出值输入到回归层中,得到神经网络的最后输出,即神经网络非线性映射的非线性变换结果。
长短期记忆网络(LSTM)的介绍: LSTM和循环神经网络都是链式结构,其特殊性在于LSTM加入门结构来存储细胞的状态。因为门结构的存在,随着迭代层数的增加,激活函数的反向误差仍能向下传递,避免长期依赖问题
LSTM是RNN的一种变形,隐含层加入忘记门、输入门和输出门使其不仅能接受上一层神经元的输出,还能通过门结构选择性的保留历史时刻的有用信息。
LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为它可以记忆不定时间长度的数值,区块中有一个gate能够决定input是否重要到能被记住及能不能被输出output。
最左边函数依情况可能成为区块的input,右边三个会经过gate决定input是否能传入区块,左边第二个为inputgate,如果这里产出近似于零,将把这里的值挡住,不会进到下一层。左边第三个是forgetgate,当这产生值近似于零,将把区块里记住的值忘掉。第四个也就是最右边的input为outputgate,他可以决定在区块记忆中的input是否能输出。
CNN-LSTM: 考虑到CNN和LSTM分别在提取高维数据特征信息和处理时间序列数据方面的优势,设计CNN-LSTM模型来预测实现序列。
卷积神经网络特有的卷积核池化操作能很好的提取数据的特征信息,而长短期记忆神经网络具有很强的记忆性,对序列化数据处理效果较好。基于两种神经网络模型的优势考虑,将两种模型组合。
Matlab代码运行结果: 本文Matlab代码+数据分享:
0 引言
在之前的博客 图像增强, 傅里叶变换(OpenCV)中都有用到过傅里叶变换,但一直都不是特别理解,现系统地学习一下。先来看一个视频 傅里叶级数与傅立叶变换,我们了解到任何周期函数都可以表示为不同频率的正弦函数和/或余弦函数之和,其中每个正弦函数和/或余弦函数都乘以不同的系数。如何找到是哪些频率组成的该周期函数?可以看一下这篇文章 从傅里叶变换进阶到小波变换。学习傅里叶还是要踏踏实实弄清楚公式和概念,没有捷径,接下来我们来推导公式。
1 傅里叶级数
周期为T的 连续变量t的 周期函数f(t),可表示为乘以适当系数的 正弦函数和余弦函数之和。 这个和就是 傅里叶级数,其形式为
式中,C n 是傅里叶级数
从上式可知, 若要将一个周期信号展开为傅里叶级数形式,实际上就是确定级数,接下来我们讨论如何求出cn。
1.1 三角函数正交性
三角函数是周期函数,其在-π到π的积分必定为0,即
由三角函数的积化和差公式,可以继续推导出下列公式
因为三角函数在-π到π内的积分为0,因此当m≠n时上面三个式子必定为0,因此可以得出以下结论, 频率不同的三角函数相乘在一个周期内(-π到π)的积分必定为0。
假设一函数f(t)由一个直流分量和若干正余弦函数组成
在上式两边同时乘以sin(kωt),并对它们在一个周期内进行积分,可得
化简得
因此,可得 bn,同理也可得 an
1.2 欧拉公式与傅里叶级数
根据 欧拉公式
当θ=nωt和θ=-nωt时,
将这两项代入傅里叶级数
当n=0时,代入上一小节得到的a0
当n=1,2,3,...时,代入an,bn
当n=-1,-2,-3,...时,代入an,bn
可以看出, 对于任意的n,所有Cn的表达式都是一样的,傅里叶级数最终可以写为:
得证。
2 傅里叶变换 2.1 连续傅里叶变换
傅立叶级数是针对周期函数的,而 傅里叶变换针对非周期函数, 一个非周期函数可以看做周期无限大的函数。当T趋于无穷大时,频率间隔 ω=2π/T趋于无穷小; Δω=(n+1)ω-nω=ω=2π/T,因此 Δω也趋于0, 1/T=Δω/2π;ΣΔω可以写成积分的形式 ∫dω。我们以 nω为变量,当 ω不等于0时, nω为离散值,,但当 ω趋于无穷小时, nω就变成连续的量 ,令 nω=W。
我们将这个式子中标红的部分称作 函数f(t)的傅里叶变换,记作F(w),即
而原始函数f(t)可以写为
我们称之为 傅里叶反变换。
二维连续函数f(x,y)的傅里叶正变换为
Android应用开发学习笔记——目录索引
本章介绍App project的基本结构和其常用配置。
一、App Project目录结构 App Project分为两个层次,第一个层次是项目,另一个层次是模块。
AndroidStudio依次选择菜单File→New→New Project即可创建新项目。
另一层次是模块(Module),依次选择菜单File→New→New Module即可在当前项目中创建一个模块,模块依附于项目,每个项目至少有一个模块,也能拥有多个模块。
一般所言的“编译运行App”,指的是运行某个模块,而非运行某个项目,因为模块才对应实际的App。
App项目的目录说明 App项目下面有两个分类:app(代表app模块)、Gradle Scripts。
app下面又有3个子目录,功能说明如下:
manifests子目录
存放AndroidManifest.xml,它是App的运行配置文件
java子目录
存放当前模块的Java源代码
res子目录
存放当前模块的资源文件
GradleScripts下面主要是工程的编译配置文件:
build.gradle
该文件分为项目级与模块级两种,用于描述App工程的编译规则
proguard-rules.pro
该文件描述了Java代码的混淆规则
gradle.properties
该文件配置了编译工程的命令行参数,一般无须改动
settings.gradle
该文件配置了需要编译哪些模块,以及依赖库的仓库地址
local.properties
它是项目的本地配置文件
编译配置文件build.gradle App项目的build.gradle分为两个级别,一个是Project项目级别的build.gradle,另一个是Module模块级别的build.gradle。如我项目中有3个Module,build.gradle如下图所示:
项目级别的build.gradle指定了当前项目的总体编译规则。
// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { id 'com.android.application' version '7.4.2' apply false id 'com.android.library' version '7.4.2' apply false } 模块级别的build.gradle对应于具体模块,每个模块都有自己的build.gradle,它指定了当前模块的详细编译规则。
plugins { id 'com.
二、面向对象编程(一) 2.1面向对象概述 面向对象的三种基本特征:继承、多态和封装。Java因为满足这三种面向对象的特征,被称为纯粹的面向对象程序设计语言。其完全以对象为中心,Java的最小单位是类,整个Java程序由一个一个类组成。
java完全支持使用对象、类、继承、封装、消息等基本概念来进行程序设计,允许从现实世界客观存在的事物出发构造软件系统,在构造中尽可能运用人类的思维方式。面向对象的方式实际上是由OOA(面向对象分析)、OOD(面向对象设计)、OOP(面向对象编程)三个部分有机组成。其中,OOA、OOD的结构需要使用一种方式来描述记录,目前业界统一使用UML(统一建模语言)来描述记录OOA、OOD的结果。关于UML,这里不过多解释,感兴趣的同学可以查看以下网页或者查阅资料了解。
https://baike.baidu.com/item/%E7%BB%9F%E4%B8%80%E5%BB%BA%E6%A8%A1%E8%AF%AD%E8%A8%80/3160571
目前软件开发领域用两种主流的开发方法:结构化开发方法和面向对象开发方法。面向对象语言与面向结构化语言相比优点是可重用性、可扩展性和可维护性。
2.2类和对象 类是封装对象的属性和行为的载体,而在Java语言中对象的属性以成员变量形式存在,对象的方法以成员方法形式存在。
java中定义类的简单语法如下:
[修饰符] class 类名 { 零个到多个构造器…… 零个到多个成员变量…… 零个到多个方法…… } 在上面的语法格式中修饰符可以是public、final、abstract,或者完全省略这三个修饰符。类名只要是一个合法的标识符即可。
每个文件只能有一个修饰符为public的类。
被final修饰的类不可被继承;
abstract修饰抽象类,我们后面会介绍。
类里各成员之间的定义顺序没有任何影响,各成员之间可以相互调用,但是static修饰的变量不能访问没有static修饰的成员。
构造器是一个类创建对象的根本途径,如果一个类没有构造器,这个类通常无法创建实例。为此,java提供了一个功能:如果一个程序员没有为一个类创建构造器,系统会创建一个自动的构造器。但如果程序员创建了一个构造器,系统则不提供该构造器。
(1)成员变量 在Java中,对象的属性也称成员变量,成员变量可以是任意类型,成员变量就是普通变量可以为其初始化,也可以不初始化。以下是定义一个成员变量的语法:
[修饰符] 类型 成员变量名[=默认值]; 修饰符:可省略,也可以是public,static,protect,private,final其中public,protect,private只能出现其中之一,可以与static,final共同修饰成员变量。
类型:类型可以是Java语言允许的任何数据类型,包括基本类型和现在介绍的引用类型。
成员变量名只要是一个合法的标识符即可;
默认值:定义成员变量还可以指定一个可选的默认值。
(2)成员方法 定义方法的语法格式如下
[修饰符] 方法返回值类型 方法名(形参列表) { //方法体 } 修饰符:public,private,protect,static,final,abstract。修饰符的其他要求与成员变量相似,但final、abstract两者只能出现一次。
返回值类型:如果方法没有返回值,则必须使用void来声明没有返回值。如果有返回值,则方法体内必须有return语句返回。
形参列表:形参列表用于定义该方法可接受的参数,形参列表由零到多组”参数类型 形参名“组合而成多组参数之间以英文逗号隔开(,)。
static是一个特殊的关键字,它可用于修饰方法、成员变量等成员。static修饰的成员表明它属于这个类本身,,而不属于这个类的单个实例,因此通常把static修饰的变量和方法也成为类变量、类方法。不使用static修饰的普通方法、成员变量则属于这个类的单个实例,而不属于该类。因此把不用static修饰的称为实例变量、实例方法。
(3)权限修饰符 private,protected,public,这些修饰符控制着对类和类的成员变量以及成员方法的访问.如果一个类的成员变量和成员方法被修饰为private,则该成员变量只能在本类中被使用,在子类或者其他包的类是不可见的。如果一个类的访问权限设置为private,这个类将隐藏其内的所有数据,以免用户直接访问它。如果一个类需要使类中的数据被子类或其他包中的类调用,可以将这个类设置为public访问权限。如果一个类使用protected修饰符,那么只有本包内的该类的子类或其他类可以访问此类中的成员变量和方法。
访问包位置
类修饰符
private
protected
public
本类
可见
可见
可见
同包其他类或子类
不可见
可见
可见
其他包的类或子类
不可见
不可见
可见
当声明类时不使用public、protected和private修饰符设置类的权限,则这个类预设为包存取范围,即只有一个包中的类可以访问这个类中的成员变量或成员方法。
例如,在项目的com.mr包下创建AnyClass类,该类使用默认的访问权限。
package com.mr; class AnyClass{ public void doString() ……//方法体 } 在上述代码中,由于类的修饰符为默认修饰符,即只有一个包内的类或其他子类可以对该类进行访问,而AnyClass类中的doString()方法却又被设置为public访问权限,即使这样,doString()方法的访问权限,即使这样doString()方法访问权限依然与AnyClass类的访问权限相同。
【深度学习】FPN(特征金字塔):Feature Pyramid Networks for Object Detection 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论
博文目录 【深度学习】FPN(特征金字塔):Feature Pyramid Networks for Object Detection前言一、FPN论文1.论文信息2 内容简介3.FPN结构详解 二、代码解析` 提示:具体代码解析将在目标检测Fast RCNN等应用中具体详细展现,后续会做补充` 总结 前言 特征金字塔是处理多尺度物体检测问题的一个基础组成部分,论文主要是用来解决Faster RCNN物体检测算法在处理目标物体多尺度变化问题时的不足,通过构造一种独特的特征金字塔来避免图像金字塔的计算量过高的问题,同时能较好的处理物体检测中的多尺度变化问题。
一、FPN论文 1.论文信息 论文名称: Feature Pyramid Networks for Object Detection发表时间: 2016 Computer Vision and Pattern Recognition下载地址: https://arxiv.org/pdf/1612.03144.pdfgithub地址: https://github.com/unsky/FPN 2 内容简介 识别大小不同的物体是计算机存在的一个挑战,主要在于卷积过程中小目标的特征消失现象,因此如何处理大范围尺度变化的物体是计算机视觉中的一个基本问题。
Featurized image pyramid(图像金字塔)
,将图像缩放到不同的尺度,然后在不同尺度的图像上生成对应的特征并在此基础上进行预测。缺点在于增加了计算和时间成本,效率低。Single feature map(单个高层特征图)
在最终的特征图上进行预测,即仅采用网络最后一层的特征。缺点在于小目标、不同遮挡程度目标检测能力差。Pyramidal feature hierarchy(金字塔型特征层级)
没有上采样过程的多尺度特征融合方式,即从网络不同层抽取不同尺度的特征做预测,不会增加额外的计算量。缺点在于精度较低。Feature Pyramid Network(特征金字塔)
顶层特征通过上采样和低层特征做融合,将不同特征图的特征进行了融合并在融合后的特征图上分别进行预测。相比其他几种方案精度更高。 3.FPN结构详解 概括为一句话:自底向上,自顶向下,横向连接。
step1(自底向上):过程和普通的CNN没有区别,按照输出特征图分辨率大小划分为不同的stage,前后相邻的stage之间特征图的尺度比例缩小一半,通道数则增加一倍。step2(自顶向下):通过2倍上采样(up-sampling)放大高stage的特征图分辨率,与低stage的特征图分辨率大小保持一致。上采样方式采用邻近插值算法。step3(横向连接):底层特征图通过进行一个1x1卷积操作与高层经过上采样放大后的特征图保持通道数一致,最后用相加的方法进行融合。 二、代码解析 提示:具体代码解析将在目标检测Fast RCNN等应用中具体详细展现,后续会做补充 总结 为了处理物体大小差异十分明显而导致的多尺度变化检测的诸多问题,论文提出了特征金字塔的网络结构,能在增加极小的计算量的情况下,处理好物体检测中的多尺度变化问题
提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论
双击port,进入配置界面
配置界面: 需要注意一下outline这个窗口,是大纲的意思,你关于port的一些配置都是可以通过这里快速切换的;然后在注意一下set,这是我们主要需要配置的内容 ConfigVariant 配置变量 VariantPreCompile只有预编译时的配置参数
VariantPostBuild混合了预编译和后编译时间的配置参数
如果配置变量 = VariantPreCompile,应该使用 Port_Cfg.h 和 Port_Cfg.c 文件
如果配置变量 = VariantPostBuild,应该使用 Port_Cfg.h 和 Port_PBcfg.c 文件
一般都选择Post,因为我们的代码肯定是编译之后,在代码里运行的。
换一个大佬的理解:(CSDN雪云飞星)
Port配置参数 点击portcontaineer,你会发现右边的outline同步进行了切换,这就前面说的进行快速切换配置界面的方法。
下面咱们就根据右边的树来了解
点击:portcontaineer_0,你可以选择哪个引脚,这里默认是pin1
点击:portpin,是一个总览,看到你配置了几个引脚
点击+×是可以自己添加的
然后点击你配置的引脚,就可以正儿八经的配置引脚参数了
而且你配置的每一个参数,都会在右边实时更新,方便观察。比如这里改成上拉。
更细节的操作,有机会继续更新。
malloc 是 C 标准库中的函数,用于动态分配内存。它的函数原型如下:
void *malloc(size_t size); 其中,size 是需要分配的字节数,函数返回值为分配内存的起始地址,如果分配失败,则返回 NULL。
下面是一个使用 malloc 动态分配内存的例子:
#include<stdio.h> #include<stdlib.h> int main() { int n; scanf("%d", &n); // 使用 malloc 分配长度为 n 的整型数组空间 int* arr = (int*) malloc(n * sizeof(int)); if (arr == NULL) { printf("Allocation failed.\n"); return-1; } // 对数组赋值 for (int i = 0; i < n; i++) { arr[i] = i + 1; } // 输出数组内容 for (int i = 0; i < n; i++) { printf("
“能否简述下你未来5年的职业规划呢?”
相信大多数求职者在面试的时候都会被问到过这个问题。
实际面试时,HR和业务部门的面试考核维度不同,这也代表着公司评估一个应聘者的能力不仅仅是技术能力,还可能是稳定性、沟通、价值观等等综合因素。
简单来说,HR无非是想知道你对自己的认知、你的个人规划是否与公司发展方向一致?你能在公司干几年?
本文将从以上三个方面来分析,怎样如何描述自己的职业规划比较合适。
1 你对自己的定位? 在做职业规划时,我们要对自己的能力、擅长、优势、兴趣等有一个清晰的认识,根据这些认识,来判断自己适合做哪些工作,也就是常说的“自我定位”。
想要获得更好的工作机会,最好是去做你擅长、有优势的事情。因为你不擅长,就说明你不会,或者是掌握得不够,公司要付出额外的成本去培养你,这样的情况下是不太容易获得较好的工作机会的。
之所以要结合自己的兴趣,是因为只有自己感兴趣的东西,才会有想要拥有的欲望,而这个欲望恰恰是促使自己去“获得”的驱动力。
很多时候,“兴趣”也是优势的一种。因为只有你喜欢了,才有竭尽全力去做好这件事情的热情,并且这股热情能持续很久很久。
以这些为据,选择合适的工作岗位,以后的职业道路相比会容易走很多。
2 你的职业目标是什么? 通过职业目标,可以看出面试者的个人发展是否与公司发展需要相一致。
举个例子来说明:
“我有2年的运营相关的工作经验,对一些新媒体平台运营规则比较熟悉,目前想专注于某音平台运营,但是我最近在学习测试内容,还报班进行系统的学习,希望以后2年内能从运营转测试。”
虽然“我”有说明自己在岗位的优势,还表明自己愿意为了目标,还报班进行系统的学习,可以看出是个比较努力、上进的人。
但这与公司发展需求出现严重分歧,公司需要的是一个能把运营做好的人,但绝不是一个一心只想转测试的运营!
3 你能在公司待多久? 不要再抱有“实力,可以忽略换工作的频率”之类的天真想法啦~
虽然跳槽已成为当代青年涨薪的主要途径之一,但是你换得勤了,HR也不敢来撩你呀。
因为从员工的招聘,到入职,到完全上手,公司要付出时间、金钱、资源等一系列成本,启用一个稳定性不高的求职者是存在很大风险的。
“你能在公司待多久?”这种问题HR不会直接问,因为问了也没有太大的参考价值,毕竟口头承诺不能信。
波士顿大学教授弗兰克·帕森特曾在一本《选择一个职业》书里提出了职业设计三要素模式,其中最重要的是了解各种职业必备条件及所需的知识,在不同的工作岗位上所占有的优势、不足和补偿、机会、前途。
简单来说:就是了解自身规划是否与岗位、企业发展一致。
人与职业互相匹配,是职业选择的焦点所在,所以HR会通过职业规划与公司发展的契合度,来间接判断求职者的稳定性。
4 对于如何回答的几点建议 因为“职业规划”属于偏人性化的题目,没有什么正确答案,也不建议大家上网去背模板,这很容易被有点经验的HR看破。
在这里,我总结几点建议供大家参考,实际则要根据自身的实际情况来回答:
围绕岗位来叙述自己的职业目标,最好是能把个人发展和公司的发展结合起来,来表达自身的价值规划;
做自我规划时,难免会谈及自己不会或者不熟悉的东西,这时候要尽量避免面试官将注意力放到你的弱项上,突出自己会做什么,包括自己储备的知识、掌握的技能、积累的人脉等等,这会很加分的。
可以适当突出自己对工作的期望。HR是很希望求职者能明确的目标和发展方向的,希望求职者能在工作岗位上,充分利用公司提供的资源、平台,大展身手,展示自己的能力。
其实对于大多数求职者来说,HR并不想了解你所谓的理想抱负,他们想知道的是你对自己,以及当前这份工作所要求的能力水平有清晰的认知,并且愿意朝着既定的目标去努力。
很多人可能会觉得职业规划没什么用,计划永远赶不上变化,毕竟未来的事情谁又能说得准呢?未来3~5年内,你可能会因为行业兴起衰退、年龄家庭、职业瓶颈等等原因,而从事另一份完全不一样的工作。
但我们心里也清楚的知道:
找准自己定位的人,能取得最大的成功;
做自己喜欢的事情的人,做到极致,最容易成功。
而职业规划恰恰就是能帮助我们,从兴趣出发,找准自己的定位,朝着某个既定的方向前进,让我们的职业生涯不迷茫。
所以,就算不为面试,不为求职,大家也要认真做好职业规划,对自己的未来负责哦~
最后,祝大家万事顺意,找到自己满意的工作!
最后: 下方这份完整的软件测试视频学习教程已经整理上传完成,朋友们如果需要可以自行免费领取 【保证100%免费】
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!
问题 平时都是用①③这两个工具修剪我的obj模型,今天处理一批有点问题的obj模型(有些点是孤点没有组成面)时发现用平时选中再删除的方法不能删除孤立点
如图所示:选中删除之后仍有孤立点
解决办法 左上角提示按钮①这个套索工具有两种模式,默认是选中面,按T选中点
先在默认选中面模型按Q选中面,按T切换到选中点模式,按Q选中点,这时候区域内的所有点和面都被选中了。再用按钮②删除
选中面
选中点
1、创建动态属性 在标准C++中,为了保证封装性,我们经常声明一个私有变量,然后声明两个公有函数,即set函数和get函数。在Qt中我们可以使用宏Q_PROPERTY()宏来实现这些。一个属性可以使用常规函数QObject::property()和QObject::setProperty()进行读写,不用知道属性所在类的任何细节,除了属性的名字。
Q_PROPERTY()原型:
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓
// 中括号中的内容为可选项 Q_PROPERTY( type name //属性的类型 名字 (READ getFunction [WRITE setFunction] | MEMBER memberName [(READ getFunction |WRITE setFunction)]) [RESET resetFunction] [NOTIFY notifySignal] //通知的信号名 [REVISION int] //版本号 [DESIGNABLE bool] //当前该属性可不可以在设计模式设置 [SCRIPTABLE bool] //可以不可以被脚本访问 [STORED bool] //属性值是否存储 [USER bool] //是否提供给用户编辑权限 [CONSTANT] //常量 [FINAL] //不能被重写 ) 2、Q_PROPERTY宏参数类型 1. type name
属性类型可以是QVariant支持的任何类型,也可以是用户定义的类型;
2. READ 和 MEMBER
如果没有MEMBER,则必须要有READ。
READ 后面定义获取属性值的函数,该函数是const;
WRITE 设置属性值,是可选的;
MEMBER 如果一个属性不需要 READ ,但又想使用属性系统,可以使用MEMBER来注册,MEMBER后面是成员变量的名字;
3. RESET
可选,将属性设置为默认值,该RESET函数必须返回void并且不带参数。
4. NOTIFY
一般在使用u盘重装系统的时候,我们需要插入启动盘进电脑,然后开机按启动快捷键进入u盘启动pe系统内重装系统。那么重装系统按键是什么呢?下面,小编就把电脑重装系统按什么键的步骤分享给大家。
工具/原料:
系统版本:win10
品牌型号:联想yoga13
方法/步骤:
方法一:进入启动项菜单按下F8以及F12
1、在重装电脑的时候需要在重启的时候进入启动选项的菜单,一般是按下F8或者F12快捷键打开;或者是进入电脑的BIOS界面,然后选择进入启动菜单;使用键盘的上下方向键进行选择,定位到【Boot Device Configuration】选项,再按一下Enter键进入子选项;
2、在其中的【First Boot Device】的选项中选择为USB,选择完成之后按一下保存,一般为【F10】,再按一下【Enter】重启即可;
方法二:需要按键F12就能进入启动管理菜单
1、大多数的联想电脑是在启动时按F12或Fn+F12热键;
2、此时会出现启动管理菜单Boot Manger,其中DVD选项为光盘,USB HDD或U盘名称为U盘启动项,移动光标选择按回车即可。
总结:以上就是重装系统按键的具体操作。大家可以酌情参考使用。
文章目录 Models CorpusRoBERTa: A Robustly Optimized BERT Pretraining ApproachELECTRA: PRE-TRAINING TEXT ENCODERS AS DISCRIMINATORS RATHER THAN GENERATORSRTD, Replaced Token DetectionWeight SharingSmaller GeneratorsTraining Algorithms DeBERTa: Decoding-enhanced BERT with Disentangled AttentionDISENTANGLED SELF-ATTENTIONENHANCED MASK DECODER ACCOUNTS FOR ABSOLUTE WORD POSITIONSSCALE INVARIANT FINE-TUNING,SiFT DeBERTaV3: Improving DeBERTa using ELECTRA-Style Pre-Training with Gradient-Disentangled Embedding SharingDeBERTa with RTDToken Embedding Sharing in ELECTRAGradient-Disentangled Embedding Sharing Models Corpus RoBERTa: A Robustly Optimized BERT Pretraining Approach 论文连接: https://arxiv.org/pdf/1907.11692.pdf
与BERT主要区别在于:
加入ASFF与detect结合:
涨点技巧:Detect系列---Yolov5/Yolov7加入特征金字塔融合方法ASFF,涨点明显_AI&CV的博客-CSDN博客
原始结构vs加入ASFF
[[17, 20, 23], 1, Detect, [nc, anchors]] [[17, 20, 23], 1, ASFF_Detect, [nc, anchors]] 结果展示:
map和可视化结果
项目介绍:最近在阅读游双的《linux高性能服务器编程》,看到后面跟着里面的代码敲了一个webserver。该项目采用同步模拟的proactor框架,采用半同步半异步的并法模式,用epoll实现io多路复用。
(1)locker.h文件是一个线程同步机制包装类,封装了sem_t,pthread_mutex_t,pthread_cond_t 三个用于线程同步的机制。
(2)threadpool.h 为线程池类,成员变量主要有任务队列m_workqueue 和线程数组 m_threads。各个线程通过竞争sem_t 信号量来从 任务队列获得任务,执行任务对象的process()函数来处理http请求与写http响应。
(3)http_conn.h 为任务类,主要封装了如何处理http请求 与 如何写http响应,主要流程为将读入的http请求写入缓存区m_read_buf,通过对m_read_buf 的操作来获得请求的信息。在对请求的信息判断正确后,将http响应报文写入 m_write_buf ,然后发送该响应报文来完成与浏览器的交互。 http_conn.cpp文件中的doc_root为网站根目录,将文件放入该根目录中即可被访问。
编译:先在终端输入如下指令生成 server 可执行文件
g++ -o server main.cpp http_conn.cpp -lpthread -g 运行:
./server ip地址 端口号 Locker.h /线程同步机制包装类 #ifndef LOCKER_H #define LOCKER_H #include <exception> #include <pthread.h> #include <semaphore.h> //封装信号量的类 class sem { public: sem() { if(sem_init(&m_sem, 0, 0) != 0) { throw std::exception(); } } //销毁信号量 ~sem() { sem_destroy(&m_sem); } //等待信号量 bool wait() { return sem_wait(&m_sem) == 0; } bool post() { return sem_post(&m_sem) == 0; } private: sem_t m_sem; }; class locker { public: locker() { if(pthread_mutex_init(&m_mutex, NULL) !
javaScript 是一种单线程语言,它的执行模型决定了同一时间只能有一个任务执行。但是在 Web Workers API 的帮助下,我们可以在浏览器中实现多线程。
Web Workers API 允许我们在后台运行一个脚本,而不影响页面的性能和用户界面。这个脚本运行在与主线程不同的线程中,可以执行一些计算密集型的操作。在主线程和工作线程之间通信可以通过消息传递来完成。
下面是一个使用 Web Workers API 创建一个工作线程的示例:
// 创建一个工作线程 const worker = new Worker('worker.js'); // 向工作线程发送消息 worker.postMessage({ type: 'add', data: [1, 2] }); // 监听从工作线程返回的消息 worker.onmessage = function(event) { console.log('Received message from worker:', event.data); }; 在上面的示例中,我们创建了一个工作线程,通过 postMessage 向工作线程发送了一个包含类型为 add,数据为 [1, 2] 的消息。工作线程执行加法操作,然后通过 postMessage 向主线程发送了一个包含结果的消息。主线程通过监听 onmessage 事件来接收从工作线程返回的消息。
下面是一个 worker.js 文件的示例,它实现了加法操作:
// 监听从主线程发送的消息 self.onmessage = function(event) { if (event.data.type === 'add') { const sum = event.
无人机仿真—PX4编译,gazebo仿真及简单off board控制模式下无人机起飞 前言 在上篇记录中,已经对整体的PX4仿真环境有了一定的了解,现如今就要开始对无人机进行起飞等仿真环境工作,在整体虚拟环境中如果程序能够安稳起飞降落,即可对无人机进行实飞操作。需要做的是,通过PX4官网提供的基本程序包,在ROS工作空间下新建程序包对其进行运行,再打开仿真环境即可 PX4编译 cd /Firmware #进入PX4文件夹内 make px4_sitl_default gazebo # 编译固件并加载仿真环境 如果想进行自动起飞,可运行以下命令
commander takeoff 利用ROS启动仿真环境(正式) 老规矩先加载ROS,运行命令
roscore 出现红色警告,说明ROS本地缓存大于1GB,可以忽视,如果需要清理可以使用
rosclean purge 在PX4文件夹内用mavros连接到本地ros,运行以下命令打开gazebo仿真环境
roslaunch px4 mavros_posix_sitl.launch 编写外部程序包 首先需要在ROS工作空间下,在src目录下新建功能包
cd ~/catkin_ws/src catkin_create_pkg offboard roscpp mavros geometry_msgs //catkin_create_pkg 是ROS命令,新建一个功能包 //offboard 功能包名字 //roscpp mavros geometry_msgs功能包依赖 //命令格式catkin_create_pkg <package_name> [depend1] [depend2] [depend3] 在offboard功能包src目录下新建cpp文件,将外部程序控制文件写入保存
新建cpp文件
touch offboard_node.cpp 将以下程序写入到cpp文件,此程序参考的是PX4官网给出的例程。
/** * @file offb_node.cpp * @brief Offboard control example node, written with MAVROS version 0.19.x, PX4 Pro Flight * Stack and tested in Gazebo SITL */ #include <ros/ros.
引言-开启机器学习海洋大冒险 引言——机器学习是数学?程序设计?还是...与现实世界有着千丝万缕的联系的哲学?我将背起我的小背包,在机器学习的海洋中探索冒险,然后筑建一个属于我的世界or城市。maybe你想和我一起吗?
本系列博客参考书:大名鼎鼎的西瓜书!(周志华机器学习)
原始工具-机器学习术语 机器学习的海洋有它自己的语言,学习术语当然是生存的第一步啦!
First,初来乍到,这片海洋中有各种各样的新事物,于是我就得从不同维度观察它们的属性特征来认识这些新事物——这就产生了“特征向量”,我观察的属性特征的个数就是“维数”。那我们观察新事物肯定不会只盯着一个看吧,我肯定看看这个,再看看那个,慢慢我就能用大脑这个学习器对它们去分类啦,那在这之前被我观察的那些事物就是训练样本,加在一起就构成了一个数据集,也是我的训练集。
既然已经说到了分类这件事,那就从这里继续下去吧。不管你这么想,分类绝对不是件简单的事。举个栗子,我们如何定义一个人的好坏?有的人认为诚实的就是好的,而也可能有人反驳说乐于助人才算好人。当然我们去定义的时候肯定不止有一个标准,也许我们观念里"好人"的品质是一样的——诚实,乐于助人,有所贡献,balabala......但是!这些品质在我们每个人的评价体系里肯定是不同的,就像刚刚说到的那样,那也就是说,不同的品质在不同的评价体系里有着不一样的权重,也就体现着我们各自的“归纳偏好”。maybe我们可以认为,不同的归纳偏好就形成了不同的评价体系,但这有时候是件麻烦事,比如我们去评判一个人是否有罪,那就是一万个人眼里一万个哈姆雷特的事情啦,所以我们需要法律来制定一个规范的标准是吧。在机器学习的海洋里也有一个类似的标准,虽然并不绝对,但大多数时候我们都会去遵循,就是Occam's razor(奥卡姆剃刀),听名字好像很高大上,其实就是一切从简的意思。西瓜书的原文是这样说的“若有多个假设与观察一致,选最简单的那个。”
这里就该有一个新的问题了。我要在机器学习的海洋里构建我的世界,那为了维持秩序我肯定要建立这样那样的法则呀,那我怎么知道我制定的这些法则是否可行,还有如果我有多个法则,我应该选择哪一个?——这不就是所谓的模型评估与选择嘛!
构建生存法则-模型评估与选择 我的具体开工思路参照了我的西瓜书大宝典——经验误差与过拟合-评估方法-性能度量-比较检验
经验误差/过拟合 首先来说经验误差和过拟合。先甩个原文。
这段话其实很好理解呀,就和概率论是很接近的思路,相当于你在对新事物的认识中认对了和认错了分别是两个基本事件,然后对应了两个概率,加起来就是1。只不过说在机器学习海洋里我们给它分别起来名字——"精度","错误率"。
要怎么理解这个误差呢,本领航员认为,误差其实是对错误率的进一步解释和划分。你看它被细分成了训练误差(经验误差)和泛化误差,对应着我后文中会提到的经验错误率和泛化错误率。
我们假设机器学习海洋里马上要有一场海洋大作战,初来乍到的explorer在参与这场大战前需要一些训练——至少得知道敌方“来者何人”吧!于是乎我们就开始了紧张的战前准备,这时候我们一个个的都变成了学习器。那如果我们消极怠工,选择躺平,这在机器学习当中就会造成“欠拟合”,不过想要成为成功的explorer肯定是不能这样的啦,这个问题也很容易解决,只要强化我们的学习能力就可以了。比较难解决的是和欠拟合相对的——"过拟合"。过拟合是什么呢,就是说你的学习能力太强啦,关注了一些过于刁钻的细节,这就有一丝"白马非马"的意味了,就是说你忽略了事物的特异性,导致你这个泛化的能力变差了。
评估方法 继续说我们的机器学习海洋大战。前面说我们在大战前做准备,这个属于什么呢——属于训练。那怎么知道我们训练的效果怎么样呢?这就需要测试,对吧。那这样一来我们就认识了两个新概念:训练集和测试集。我们要讨论的是怎么划分这两个东西。
留出法就很简单啊,直接固定地拿一部分出来当测试集。不过为了保持数据分布的一致性——这个怎么说呢,我们先跳出这个海洋大战的情景,想想你学生时代和考试的无数场大战。刷题你得所有题型都练吧,考试它也不能专挑一个章节的内容考叭,如果你只拿着前7章的资料复习,考试却只考你后三章的内容,那就凉凉了,当然这肯定是不合理的,所有就要有数据分布一致性啦。为了达到这个目的,我们一般会用“分层抽样”的办法划分,一般会选择留2/3~4/5作为测试集,这个还得具体情况具体分析啦。
留出法感觉不是那么聪明的话,就看看k折交叉验证吧!其实也很简单,k折交叉验证就是把数据集划分成了k个子集,然后把它们依次作为测试集,其余的作为训练集去训练。
还有一个自助法,一般在数据集较小且难以有效划分时使用。(这里我就不多说啦)
性能度量 哎呀是不是有偏题了,我们还在海洋大战呢。大战这件事不可马虎,我们肯定得挑选所谓“精英部队”出战叭,那要用什么标准来选择所谓“精英”呢,当然是性能度量啊!
对回归任务的性能度量不难(是不是没有说过回归任务的概念,补充一下,你预测的是连续值那就是回归任务,比如说你要预测敌方的战斗力,那如果在此基础上你要对战斗力划分区间和等级,去判断它的战斗力属于哪个级别,这就是分类)。对于回归任务最常用的就是均方误差。
对于数据分布D和概率密度函数p(·),它还能表示成:
对分类任务的性能度量就没有那么简单啦。错误率和精度前面已经提过啦,就先从查全率查准率开始说叭。
查全率和查准率 这里我们画一个混淆矩阵
很好理解的。还是用我们挑选精英部队作为例子,假如说客观上确实存在一个分层标准,这时候你主观地去划分。查准率是什么呢,是你挑出来10个精英,其中有9个是真的精英,那你的查准率就是9/10。而查全率是说,这些人里面有11个精英,被你挑出来的有10个,那你的查全率就是10/11。
一般来说查全率和查准率这东西就是鱼和熊掌不可兼得。
我说什么来着,指定法则和标准是个很重要的事情嘛,既然查全率和查准率不可兼得我们就得对它们进行综合度量,综合度量不就有需要有指标了嘛。这里我挑比较常用的一个讲:
当β=1的时候其实就是F1度量,只不过(还记得我们的归纳偏好嘛?)实际情况下查全率和查重率的重要程度是不一样的,所以就需要给它加一个权重。
ROC/AUC AUC-ROC曲线是针对各种阈值设置下的分类问题的性能度量。ROC是概率曲线,AUC表示可分离的程度或测度,它告诉我们多少模型能够区分类别。AUC越高,模型在将0预测为0,将1预测为1时越好。
比较检验--假设检验 假设检验应该是个很耳熟的概念,好像哪里都有它(那当然是因为他真的很重要啦!)让我先来bing一下统计学中假设检验的概念(搜索)(复制)(黏贴)——“假设检验(hypothesis testing),是用来判断样本与样本、样本与总体的差异是由抽样误差引起还是本质差别造成的统计推断方法。显著性检验是假设检验中最常用的一种方法,也是一种最基本的统计推断形式,其基本原理是先对总体的特征做出某种假设,然后通过抽样研究的统计推理,对此假设应该被拒绝还是接受做出推断。”
那我在机器学习大海洋里假设的是什么呢?在完成前面的任务后我得到了一个叫做测试错误率的东西,还记得吧,现在我要在这个基础上,去猜泛化错误率。年少无知的我当然也曾误以为会找到泛化错误率的值,然后发现无路可走无砖可搬——在又一个天才出现之前,我们能探索的大概暂时只是泛化错误率的分布可能情况。
熟悉吧,学过概率论的little_explorer应该都认识它,二项分布示意图。有了它下一步就很明确啦,我们可以用二项检验去检验我们的假设。
当然我们不止有二项检验一个工具,t检验也是很好用的!关门放公式!
一个优秀的explorer该具备什么品质呢——观察啊!(所谓万物皆可观察法,我说的。)k值增加,代表交叉验证的次数增加,从上图就看到临界值随之降低,图上体现出来的就是泛化错误率的分布趋于集中了。
本explorer有些疲倦(bushi),休息一下再来继续探索吧!下一期是线性模型!
win10系统多个版本区别
版本更改时的具体操作
=系统版本更改时如果需要采用密钥形式时,万万=不可选择pxx的0.99
一、js多线程 1.ConcurrentThread 在webworker之前,js只有单线程,但是有一些方法可以模拟多线程。
一个日本人开发的库 ConcurrentThread.js,他模拟多线程的原理是:
假设我有一个while循环,把它扔到 Concurrent 方法的回调函数中,他把你的回调函数取函数体,然后对函数体进行类似 AST 分析,然后把while循环替换成 requestAnimationFrame 之类的异步方法。
它的另一种做法是在 <script type="text/x-script.multithreaded-js"> 内写代码,实际上道理类似,对标签内部做 AST 分析。
2.webworker webworker能够开辟一个新的对象,不占用window对象,所以它有自己的一个线程。所以死循环也不会造成页面阻塞。
⚠️webworker需要服务启动页面。
在html中:
// index.js是业务js const worker = new Worker('./index.js'); worker.onmessage = function ({ data }){ // 获得返回的值 console.log(data); // 关闭这个worker self.close(); }; // 通知 message 开始 worker.postMessage('worker post-message start'); 在业务js中:
onmessage = function (){ // 开始 let i = 0; // 处理一个非常占用线程的同步任务 for (; i < 1000000000; i++) {} // 通知worker对象同步任务已经完成 postMessage(i); }; 在上述代码中,业务js的for循环不会造成主线程阻塞。
题目:
题解:
思路:本题在比赛时没思路,主要是没想到可以用异或做,也没有想到如何转变到异或,然后用经典的 hashmap 套路。
1)由于每次都要减去两个数的 2^k,那么所有数中 2^k 的次数之和一定是偶数。也就是说,所有数的异或和必须是 0。那么就可以使用前缀异或和来计算数组中所有元素的前缀和了。2)由 1 分析可知,美丽子数组的前缀异或和为 0。因此 pre[l]^pre[r] = 0 表示原数组 a 中区间 [l,r-1] 的异或和为0,也就是美丽子数组。 pre[l]^pre[r] = 0 等价于 pre[l] = pre[r],所以我们只用统计 pre 中相同数的对数就是美丽子数组的个数了。使用经典的两数之和套路,hashmap 先查询再计数。 代码如下:
using LL = long long; class Solution { public: // 思路:使用前缀异或和,由于每次都要减去两个数的 2^k,那么所有的数中 2^k 的次数之和一定是偶数。也就是说,所有数的异或和必须是 0。pre[i]=a[0^...^i-1],使用左闭右开区间,区间[l,r)的异或和为 pre[r]^pre[l]=a[l^...^r-1] long long beautifulSubarrays(vector<int>& a) { int n=a.size(); vector<int> pre(n+1); for(int i=1;i<=n;i++)pre[i]=pre[i-1]^a[i-1]; LL res=0; // 使用 hashmap 来进行计数。由于只有子数组的异或和为 0,才能构成美丽子数组。所以 pre[l] ^ pre[r] = 0,那么说明 pre[l] = pre[r],也就是说区间数组中 [l,r-1] 的异或和为 0。 // 所以我们只用统计前缀异或和数组中相同数的对数即可,采用先查询再计数的方法。 unordered_map<int,int> cnt; for(int x:pre){ res+=cnt[x]++; } return res; } };
VM虚拟机的三种网络连接模式,桥接,NAT,仅主机区别。网卡vmnet0,vmnet1,vmnet8区别 引言: 在VMware中,虚拟机的网络连接主要是由VMware创建的虚拟交换机(也叫做虚拟网络)负责实现的,VMware可以根据需要创建多个虚拟网络。
VMware的虚拟网络都是以"VMnet+数字"的形式来命名的,例如 VMnet0、VMnet1、
VMnet2……以此类推(在Linux系统的主机上,虚拟网络的名称均采用小写形式,例如 vmnet0 )。
交换机是互联同一局域网的设备,进行简单的存储、转发,不对数据进行任何更改。
所以,虚拟机的网络连接(与本地主机的通讯等等,,虚拟机与虚拟机之间的通信),都是由虚拟交换机实现的。
三种网卡的区别总结 ①Adapter=VMnet1=eth0(host-only) 仅主机 虚拟机与虚拟机之间互访
主机与虚拟机之间互访
但虚拟机无法访问外网。
外网也无法访问虚拟机。
②Adapter2=VMnet8=eth8(nat) NAT网络地址转换 虚拟机之间互访
主机与虚拟机之间互访。
虚拟机可以通过主机*访问外网
外网无法访问虚拟机。
使用NAT网络模式,在宿主机安装多台虚拟机,和宿主组成一个小局域网,宿主机,虚拟机之间都可以互相通信,虚拟机也可访问外网,例如 搭建 hadoop 集群,分布式服务
③Adapter3=VMnet0=eth2(Bridged)桥接模式 虚拟机之间互访
主机与虚拟机之间互访。
虚拟机**可以通过主机访问外网
外网可以访问虚拟机。
虚拟机相当于一台实体机,可以自由访问与被访问及上网。
我的电脑访问举例 安装VMware workstation的时候,默认会安装3块虚拟网卡,分别是VMnet0、VMnet1、VMnet8。
虚拟机虚拟网卡-----------连接--------对应的虚拟网络-------------连接------------本地主机网卡
这样就可以通讯了。
1.我的本地电脑的 在VMnet8虚拟网络上的ip是 192.168.111.1
!](https://img-blog.csdnimg.cn/ff0d41d58e4945289a1e862334201574.png)
2.我的ubuntu虚拟机(选用的模式是nat模式,对应的也是在VMnet8网络)的网络ip是192.168.111.128
3.可以看一下虚拟网络编辑器
虚拟网卡名网络属性定义VMnet0物理网卡Bridge桥接Vmnet1虚拟网卡host-only仅主机VMnet8虚拟网卡NAT 下面是电脑各个地方出现的ip—分析 1.桥接模式
由于无线网卡不能桥接的原因。
实际上并没有信息,window下也没有对应的vmnet0网卡,ubuntu下也没有ip,也不能上网,
经提示:无线网卡虚拟机可以桥接的,Vmware0是虚拟机默认进入的虚拟网络,打开虚拟网络编辑器把Vmware0桥接到具体的无线网卡上,再打开网卡设置选择桥接模式即可。
2.NAT模式下
window下VMnet8: IPv4 地址 . . . . . . . . . . . . : 192.168.195.1
ubuntu下:inet… 192.
要用Python求解微分方程组,需要使用一些数值求解工具库,例如Scipy库。以下是一个使用Scipy库解决微分方程组的简单示例:
首先,安装Scipy库:
pip install scipy
然后,导入必要的库:
import numpy as np
from scipy.integrate import solve_ivp
接下来,定义微分方程组。例如,假设要求解以下的 Lorenz 方程:
dx/dt = sigma * (y - x)
dy/dt = rho * x - y - x * z
dz/dt = -beta * z + x * y
其中 sigma,rho 和 beta 是常数。
你可以将这个微分方程组转换为一个函数,让 solve_ivp() 函数对它进行求解。例如:
def lorenz(t, xyz, sigma, rho, beta):
x, y, z = xyz
dxdt = sigma * (y - x)
Appium Appium是一个开源的移动测试工具,支持iOS和Android,它可以用来测试任何类型的移动应用(原生、网络和混合)。作为一个跨平台的工具,你可以在不同的平台上运行相同的测试。为了实现跨平台的功能,Appium使用了供应商提供的Android UI框架来实施测试:在iOS中使用XCTest,在Android中使用UIAutomator或Instrumentation。它将这些供应商框架封装到Selenium WebDriver中,这使得使用Appium的开发者可以编写各种类型语言的测试:Java、Objective-C、JavaScript、PHP、Ruby、Python等等。这也使得编写Appium测试与编写Selenium测试非常相似。
WebDriver最初是为web测试创建的,Appium用额外的API方法扩展了WebDriver,使得它更适合于移动自动化。
以下是一些有用的Appium特性:
不需要在设备上安装任何东西。不需要重新编译或改变应用程序来匹配Appium。Appium有一个非常大而活跃的社区。Appium附带一个扫描和分析应用程序的UI组件的工具——Appium UI Inspector。开发人员也可以使用Android Studio的UI Automator Viewer。如果你需要为iOS和Android编写测试,而你是一个Selenium的爱好者的话,Appium将是一个很好的选择。 Calabash Calabash是由Xamarin公司开发和维护的一款开源的移动测试工具,支持iOS和Android上的原生和混合应用。Calabash测试支持手势识别(gesture)、断言(assertions)和屏幕截图(screenshots)等功能,通常与驱动开发测试工具Cucumber一起集成使用。
Xamarin在2017年宣布,它将对Calabash停止继续开发。鉴于此决定,你可以将Calabash作为一个不太理想的备选测试解决方案。
Espresso Espresso是谷歌的一个Android UI框架。它是一个轻量级的、针对应用程序开发人员的白盒工具,这意味着要充分利用它,测试开发人员必须充分熟悉并且会使用应用程序代码。Espresso的测试非常可靠,并且运行速度很快,由于Espresso可以访问UI对象的内部,它可以用于测试WebView,即混合应用程序的开发。
Espresso的缺点是,它一次只能测试一个应用程序,而且无法访问设备资源。然而,通过使用UI Automator创建的联合测试可以很容易地解决这个问题。
Sauce Labs支持Espresso的真实设备测试。
UI Automator UI Automator是由谷歌开发和维护的移动测试Android UI框架,它的主要功能包含了跨应用程序的功能测试,即测试多个应用程序和在已安装与系统应用程序之间的切换的功能。
UI Automator是一个黑盒测试工具,也就是说测试开发人员不需要知道内部的应用程序结构,可以完全依赖于可见的UI元素。UI Automator的测试是用Java编写的,由两组api组成:其一为UI Automator APIs,是控制应用程序的UI组件;其二为device state APIs,用于访问和执行设备上的操作(如改变设备旋转,按方向键按钮,按返回,Home或者菜单按钮等)。它还附带了一个非常有用的UI Automator Viewer,这是一个可以扫描和分析当前配置在设备上的UI组件的图形用户界面工具。
UI Automator的缺点是不支持构建在混合Android应用程序之上的WebView,因此,UI Automator只支持原生的Android应用程序。
Robotium Robotium是一个开源的Android UI框架,它诞生于2010年,现在已经是一个非常成熟和稳定的工具。其最近的一个版本是5.6.3,发布于2016年9月。在最新的几个版本中,其测试可读性和测试执行的速度都有了显著提高。
大多数涉及到Robotium的技术博客、教程和课程都是黑盒测试类型的。但实际上,它算是灰盒测试的,因为编写Robotium测试需要了解内部应用程序结构。
以下是Robotium的部分主要特性:
支持本机和混合应用程序。可以在真实设备和模拟器上运行测试。支持完整的Android UI工具:活动、按钮、菜单、toast、对话框等。支持手势。有一些设备控制功能:改变设备方向,截屏,解锁屏幕等。Robotium recorder是一个付费的Android Studio和Eclipse插件。这是一个很好的工具,可以快速的启动和运行测试。可以作为持续集成的一部分运行。Robotium的选择语言是Java。 Robotium得到了Sauce Labs的支持,可以用于真实设备的测试。
结语 为您的项目选择正确的Android UI框架是一项很有挑战性的工作,在某些情况下,您可能需要使用多种工具来达到正确的平衡,这就是像Sauce Labs这样的支持多种测试框架的测试网格大受欢迎的原因。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取
文章目录 vue2、vue3基于js给后端接口返回的数据(如以json数据为元素的数组)添加新的json字段1、 res为后端接口的响应2、 获取后端接口返回的数据3、 vue2 向数组中添加一个元素,在{}对象中添加一个字段(属性)1. vue2 向 tableData 添加字段1.1. 向 tableData 中添加一个新json元素( {"time", "2023-02-09"} )1.2. tableData 添加新元素后 tableData 的值 2. vue2 向 tableData 的元素添加字段2.1. 向 tableData 中的每个元素添加一个新json元素( {"age", "20"+i} )2.2. 向 tableData 中的每个元素添加一个新json元素后tableData 的数据 4、 vue3 向数组中添加一个元素,在{}对象中添加一个字段(属性)1. vue3 向 tableData 添加字段1.1. 向 tableData 中添加一个新json元素( {"time", "2023-02-09"} )1.2. tableData 添加新元素和替换元素后 tableData 的值 2. vue3 向 tableData 的元素添加字段2.1. 向 tableData 中的每个元素添加一个新json元素( {"age", "20"+i} )2.2. 向 tableData 中的每个元素添加一个新json元素后tableData 的数据 vue2、vue3基于js给后端接口返回的数据(如以json数据为元素的数组)添加新的json字段 1、 res为后端接口的响应 res.
定义 规范化 将一个低一级的关系模式通过模式分解可以转换为若干个高一级范式的关系模式的集合,这种过程就叫规范化。
第一范式 作为一个二维表,关系要符合一个最基本的条件:每一个分量必须是不可分的数据项。满足了这个条件的关系模式就属于第一范式(1NF)。
第二范式 若 R ∈ 1 N F R∈1NF R∈1NF,且每一个非主属性完全函数依赖于任何一个候选码,则 R ∈ 2 N F R∈2NF R∈2NF。
第三范式 设关系模式 R < U , F > ∈ 1 N F R<U,F>∈1NF R<U,F>∈1NF,若 R R R中不存在这样的码 X X X,属性组 Y Y Y及非主属性 Z ( Z ∉ Y ) Z(Z\notin Y) Z(Z∈/Y),使得 X → Y X→Y X→Y, Y → Z Y→Z Y→Z成立, Y → X Y→X Y→X不成立,则称 R < U , F > ∈ 3 N F R<U,F>∈3NF R<U,F>∈3NF。
文章目录 0 前言1 主要功能2 硬件设计(原理图)3 核心软件设计4 实现效果5 最后 0 前言 🔥
这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。
为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是
🚩 毕业设计 基于单片机的智能语音药箱系统(源码+硬件+论文)
🥇学长这里给一个题目综合评分(每项满分5分)
难度系数:3分工作量:3分创新点:4分 🧿 项目分享:
https://gitee.com/sinonfin/sharing
1 主要功能 利用STC90C516单片机、8个按键、LCD1602液晶显示屏、蜂鸣器、LED发光二极管等设计一个家庭用智能药盒。
该系统硬件部分由单片机最小系统、按键电路、液晶显示电路、声光报警电路组成,
系统能完成时间的实时显示、每天四次定时、每次用药四种药用量提醒的功能。
系统基本功能如下:
(1)显示
采用LCD1602显示实时时间、用药量、 调设信息显示等。
(2)定时时间与用药量的设定
系统须实现每天四次时间的定时,每次用药时须对四种药做出用量的提醒,通过6个按键完成,1个功能键,1个调节键,
4次定时对应的4个定时按键。
(3)实时时间调节
实时时间通过另外2个按键进行调节,其中之一为功能键,另一个为调节键。
(4)报警功能
实时时钟运行到定时时间时,LCD1602显示此次用药量,蜂鸣器响起,LED闪烁,提醒用药时间到。
2 硬件设计(原理图) PCB
3 核心软件设计 下图是闹铃提醒的程序流程图, STM32 从 TF 卡中读取 512 字节数据, 按顺序传输给VS1003 进行音频转换和播放。 然后, 依次读取下一个扇区的 512 个字节进行播放。 如果播放过程中检测到药箱打开, 则停止闹铃并退出。
下图是闹铃提醒的程序流程图, STM32 从 TF 卡中读取 512 字节数据, 按顺序传输给VS1003 进行音频转换和播放。 然后, 依次读取下一个扇区的 512 个字节进行播放。 如果播放过程中检测到药箱打开, 则停止闹铃并退出。
Maxwell 介绍 Maxwell 是由美国 zendesk 开源,用 java 编写的 Mysql 实时抓取软件, 其抓取的 原理也是基于 binlog。 官网 https://maxwells-daemon.io/ Maxwell 和 canal 工具对比 ➢ Maxwell 没有 canal 那种 server+client 模式,只有一个 server 把数据发送到消息队列 或 redis。如果需要多个实例,通过指定不同配置文件启动多个进程。 ➢ Maxwell 有一个亮点功能,就是 canal 只能抓取最新数据,对已存在的历史数据没有办 法处理。而 Maxwell 有一个 bootstrap 功能,可以直接引导出完整的历史数据用于初 始化,非常好用。 ➢ Maxwell 不能直接支持 HA,但是它支持断点还原,即错误解决后重启继续上次点儿读 取数据,canal也支持。 ➢ Maxwell 只支持 json 格式,而 Canal 如果用 Server+client 模式的话,可以自定义格 式。 ➢ Maxwell 比 Canal 更加轻量级。 安装使用 前提开启了mysql的binlog在cannel使用的时候已经讲解
前提 创建保存断点续传的数据库,并且创建maxwell用户密码为123456,对于shishimaxwell数据库给maxwell授予权限
mysql -uroot -p123456 CREATE DATABASE shishimaxwell ; #maxwell是用戶名 GRANT ALL ON shishimaxwell.
标签宽度不固定,想要实现超出一行后就自动折叠,并在后面跟上折叠/展开按钮,当标签总长度不足一行时不显示按钮,超过一行时折叠并显示按钮
话不多说,直接上代码
<template> <ul class="sub-nav"> //这块的v-show显示条件是data,isFold(属于展开状态)||(或者)index(下标)<data.foldIndex(当前我所记录单行可以展示的数量) <li v-for="(item,index) in data.keywordList" :key="index" v-show="index < data.foldIndex||data.isFold" :class="data.keyword==item?'active-li sub-nav-list':'sub-nav-list'" @click="handleCutKey(item)"> {{item}} </li> <li class="btn" ref="fold" @click="data.isFold=!data.isFold" :style="data.isFold?{position:'unset'}:{position:'absolute'}"> {{data.isFold?'折叠':'展开'}}<img :style="{transform:data.isFold?'rotate(90deg)':'rotate(-90deg)'}" src="@/assets/image/返回键.png" alt=""> </li> </ul> </template> <script setup lang="ts"> const data = reactive({ // 关键词分类 keywordList: string[] = []; // 当前选中的关键词 keyword: string = ''; // 是否折叠关键词 isFold: boolean = false; // 折叠展示到的下标 foldIndex: number = 100; }) const fold = ref < HTMLElement | null > (null) onMounted(() => { getData() }) // 获取数据 const getData = () => { data.
广域网宽带接入技术四EPON技术 二、EPON技术1、EPON的网络体系结构2、EPON基本原理2.1、EPON帧结构2.2、下行数据流2.3、上行数据流3、EPON关键技术3.1、EPON层次结构3.1.1、EPON的物理层3.1.2、EPON的数据链路层3.1.3、MPCP协议3.1.4、LLID和MPCP的PDU格式3.2、EPON系统的工作机制3.2.1、ONU注册 二、EPON技术 APON/BPON二层采用的是ATM封装和传送技术,因此存在带宽有限、带宽损失大、数据包开销大、协议转换复杂、承载IP业务效率低、技术复杂、设备价格高、不同厂家兼容问题。一直没有得到广泛应用。APON/BPON下行速率622Mbps,上行速率155Mbps,除去ATM开销后,实际可用带宽只有448Mbps。
2004年,正式发布EPON(以太网无源光网络)技术标准IEEE802.ah。IEEE制定EPON标准的基本原则是尽量在802.3体系结构内进行EPON的标准化工作,最小程度地扩充标准以太网的MAC协议。
EPON(Ethernet Passive Optical Network,无源网络)的E指的是互联以太网,所以EPON诞生之初就是要求能够同互联网直接无缝衔接,所以EPON的码流走的是以太网的帧格式。当然,为了适应光纤上传输,所以在以太网帧格式的帧的外面,包了一层EPON定义的帧格式。
在EPON系统中,按照单纤双向全双工的方式以点到多点(P2MP)的方式传送数据。可以提供1.25 Gbit/s的上下行带宽,传输距离可达10-20 km,支持最大光分路比1:64,采用无源光网络可大大降低OLT和主干光纤的成本压力(OLT与ONU之间仅有光纤、光分路器等光无源器件,无需租用机房、无需配备电源、无需有源设备维护人员,因此,可有效节省建设和运营维护成本)。与以太网成熟技术结合,在IP/Ethernet占主要的市场上得到广泛应用。成为了非常适合IP业务的宽带接入技术。
在接入网中EPON不需任何复杂的协议,光信号就能准确地传送到最终用户,来自最终用户的数据也能被集中传送到中心网络。在物理层,EPON使用1000BASE的以太PHY,同时在PON的传输机制上,通过新增加的MAC控制命令来控制和优化各光网络单元(ONU)与光线路终端(OLT)之间突发性数据通信和实时的TDM通信,在协议的第二层,EPON采用成熟的全双工以太技术,使用TDM,由于ONU在自己的时隙内发送数据报,因此没有碰撞,不需CDMA/CD,从而充分利用带宽。另外,EPON通过在MAC层中实现802.1p来提供与APON/GPON类似的QoS。
1、EPON的网络体系结构 无源光网络的构成:
OLT(Optical Line Terminal)-光线路终端POS(Passive Optical Splitter,无源光分光器)ONU(Optical Network Unit)-光网络单元ODN(Optical Distribution Network)-光分配网 OLT与前端(汇聚层)交换机用网线相连,转化成光信号,通过单根光纤与分光器和的ONU互联,OLT与POS、ONU都属于光电设备。OLT设备是重要的局端设备,它实现的管理、测距等功能。
EPON的传输距离,OLT(光线路终端)到达ONU(光网络单元)最大距离不超过20km,中间有一级POS(无源光分光器)、二级POS(无源光分光器)设备。EPON系统中的光网络被称为“无源”,是由ODN网络中的连接设备“无源分光器”决定的。称其无源,是因为分光器中不需要供电。
2、EPON基本原理 OLT(光线路终端)作为整个网络/节点的核心和主导部分,完成ONU注册和管理、全网的同步和管理以及协议的转换、与上联网络之间的通信等功能;
ONU作为用户端设备在整个网络中属于从属部分,完成与OLT之间的正常通信并为终端用户提供不同的应用端口;
ODN在网络中的定义为从OLT-ONU的线路部分,包括光缆、配线部分以及POS(分光器)全部为无源器件,是整个网络信号传输的载体。POS(分光器)可以从1:2-1:32可选(1:64的分光器因成本原因基本上在现网上没进行使用,OLT到ONU之间的传输距离一般10km-20km,原则上是10KM用1:32的分光器,20KM用1:16,因为分光器分光比例越高,光衰耗越大。
EPON中使用单芯光纤,在一根光纤上使用不同波长的两个光路,来分别实现上、下行数据传输,这种机制叫做单纤双向传输机制。单纤双向传输机制指EPON采用WDN(Wavelength Division Multiplexing,波分复用)技术,实现单纤双向传输。提供上/下行对称速率1.25Gbps的带宽,为了上、下行两个方面可以同时传输数据而不冲突,采用两种复用技术,下行数据流采用广播技术,上行数据流采用TDMA(Time Division Multiple Access,时分多址)技术。下行采用针对不同用户加密广播传输的方式共享带宽。
在一根芯上转送上下行两个波,上行波长:1310nm,下行波长:1490nm,另外还可以在这个芯上下行叠加1550nm的波长(有线电视1550nm的光信号送入EPON光纤中实现共用一根纤芯)。上行方向采用时分多址接入(TDMA)方式,把光纤的占用按一定时间长度分成时段,在每一个时段,只有一台ONU能够占用光纤向OLT发送数据,其余ONU则关闭激光器。OLT通过发送控制数据包指定ONU发送数据的时段,来避免冲突的发生。
2.1、EPON帧结构 在EPON中,数据的传输遵照IEEE 802.3以太网协议,采用可变长度的分组格式进行,分组的最大长度为1518字节。没有改变以太网帧的结构,只是利用以太网帧的前8个字节的前缀对数据帧作了标识。
在EPON系统中,按照单纤双向全双工的方式以点到多点的方式传送数据。OLT和ONU之间采用以太网封装方式,传输的是以太网帧结构,所以EPON是基于802.3的帧格式。从EPON帧结构图可以看出,在前导码第6、7个字节中携带了LLID(Logical Link Identifier,逻辑链路标记)信息,用于在OLT上标识ONU,第3个字节SPD(或称SLD,LLID定界符 在EPON中为0XD5),第3个字节标识它不是普通以太网帧而是一个EPON帧。EPON定义了广播LLID(LLID=0xFF)作为单拷贝广播(SCB)信道,用于高效传输下行视频广播/组播业务。
2.2、下行数据流 OLT启动后,根据OLT广播(时分复用技术TDM)允许接入信息,主动发起注册请求,OLT通过对ONU的认证,允许ONU接入,并给请求注册的ONU分配一个OLT端口惟一的一个LLID(逻辑链路标志)。
在ONU注册成动后分配一个唯一的LLID;在每一个分组开始之前添加一个LLID,替代以太网前导符的最后两个字节;OLT接收数据时比较LLID注册列表,ONU接收数据时,仅接收符合自己的LLID的帧或者广播帧。 2.3、上行数据流 OLT接收数据前比较LLID注册列表;每个ONU在由局方设备统一分配的时隙中发送数据帧;分配的时隙补偿了各个ONU距离的差距,避免了各个ONU之间的碰撞。
上行信号:分时突发发送,采用测距技术保证上行数据不发生冲突。OLT时钟恢复时间400ns,ONU开关时间512ns。 对于上行,采用时分多址接入技术(TDMA)分时隙给ONU传输上行流量。当ONU在注册时成功后,OLT会根据系统的配置,给ONU分配特定的带宽,(在采用动态带宽调整时,OLT会根据指定的带宽分配策略和各个ONU的状态报告,动态的给每一个ONU分配带宽,动态带宽调整的进一步说明见后面)。带宽对于PON层面来说,就是多少可以传输数据的基本时隙,每一个基本时隙单位时间长度为16ns。在一个OLT端口(PON端口)下面,所有的ONU与OLT PON端口之间时钟是严格同步的,每一个ONU只能够在OLT给他分配的时刻上面开始,用分配给它的时隙长度传输数据。通过时隙分配和时延补偿,确保多个ONU的数据信号耦合到一根光纤时,各个ONU的上行包不会互相干扰。
区别下行TDM方式上行TDMA方式波长下行波长1490上行波长1310数据方向OLT到ONUONU到OLT特点ONU只接收发给自己的数据、丢弃其它数据无需冲突检测、报文不需要分片 3、EPON关键技术 IEEE802.ah定义的EPON技术在原有的802.3上作了最小的改动。
3.1、EPON层次结构 3.1.1、EPON的物理层 从物理层看,EPON从电气、机械、规程、功能特性等功能基本上采纳了Ethernet的GE或1000BASE的标准,包含物理层协议 PHY(Physical Layer Protocol)和物理媒介协议PMD(Physical Medium Dependence Protocol)两大子层功能。在物理层,EPON使用1000BASE的以太网物理层协议PHY,无源光纤传输方式。
包含RS子层、PCS子层、PMA子层、PDM子层。物理层通过GMII接口与RS层相连,担负着为MAC层传送可靠数据的责任。
物理层的主要功能:数据编成合适的线路码;完成数据的前向纠错;将数据通过光电、电光转换完成数据的收发。数据光–>电–>光转换完成数据收发。
同千兆以太网的物理层相比,唯一不同的是EPON的物理层多了一个前向纠错子层(FEC),其它各层的名称、功能、顺序没有太大的变化。前向纠错子层完成前向纠错的功能。这个子层是一个可选的子层,它处在物理编码子层和物理媒体附属子层中间。它的存在引入使我们在选择激光器、分光器的分路比、接入网的最大传输距离时有了更大的自由。从宏观上讲,除了FEC层和PMD层以外,各子层基本上可以同千兆以太网兼容。
PCS层与MAC层的接口定义为GMII(Gigabit Medium Independent Interface),是字节宽度的数据通道。
一.准备工作 配置申请地址 https://open.alipay.com/platform/home.html(开发对接中需要以下参数,参数请务必妥善保管,不可泄露)
详细接口或参数说明,以支付宝官方文档为准, 支付宝API网址(https://opendocs.alipay.com/apis)
//支付宝网关地址:https://openapi.alipay.com/gateway.do //支付宝申请的APPID //商户应用私钥(与支付宝数据交互时,保证数据安全,防止数据被篡改) //支付宝公钥(与支付宝数据交互时,保证数据安全,防止数据被篡改) //签名算法类型(RSA2或者RSA,支付宝推荐使用RSA2) //编码格式(utf-8,gb2312,gbk) 二.导入支付宝依赖(https://mvnrepository.com) <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.9.124.ALL</version> </dependency> 三.代码实现 1.1 H5支付 //网关地址,APPID,商户应用私钥,数据格式,编码格式,支付宝公钥,签名算法类型 AlipayClient alipayClient = new DefaultAlipayClient(aliPayGateway,appID,rsa_private_key,format,charset,alipayPublicKey,signType);//不同支付类型需使用不同的请求对象 AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest(); //请求参数集合对象,除了公共参数之外,所有参数都可通过此对象传递(不同支付类型需使用不同的请求参数对象) AlipayTradeWapPayModel model = new AlipayTradeWapPayModel(); //订单描述 model.setBody("订单描述"); //订单标题 model.setSubject("显示效果见于下图的标题"); //商户订单号 model.setOutTradeNo(orderNo); //订单的过期时长(取值为5m - 15d,即五分钟到十五天) model.setTimeoutExpress("30m"); //订单总金额 model.setTotalAmount(String.valueOf(cashNum)); //产品码 QUICK_WAP_WAY:无线快捷支付产品 model.setProductCode("QUICK_MSECURITY_PAY"); //用户付款中途退出返回商户网站的地址 model.setQuitUrl("https://wwww.baidu.com"); request.setBizModel(model); //支付成功后的跳转地址 request.setReturnUrl("支付成功之后的跳转地址"); //支付成功后的回调地址(此地址必须为公网地址,用于支付宝收到用户付款之后,通知我们的服务端,我们可以在此接口中更改订单状态为已付款或后续操作) request.setNotifyUrl(aliPayNotifyUrl); String orderStr = ""; AlipayTradeWapPayResponse responseH5 = null; try { //获取支付宝返回格式,当前是以表单的方式进行返回,可以设置为 url 的方式返回 支付连接 responseH5 = alipayClient.
毕业论文知识点记录(八)——环境数据下载之DEM 还是利用GEE下载DEM数据。
1、GEE可下载的各种DEM数据 下面表格是我整理的GEE里面关于DEM数据的分辨率整理:
数据分辨率DEM ETOPO1 : NOAA/NGDC/ETOPO1一弧分(1855m)DEM GTOPO30 : USGS/GTOPO30半弧分(927.67 m)DEM ALOS DSM: JAXA/ALOS/AW3D30_V1_130mDEM GMTED2010: USGS/GMTED20107.5弧秒(231.92 m)DEM SRTM: USGS/SRTMGL1_00330mDEM ASTER GED: NASA/ASTER_GED/AG100_003100mDEM CRYOSAT2: CPOM/CryoSat2/ANTARCTICA_DEM1000mDEM GIMP: OSU/GIMP/DEM30mDEM HydroSHEDS03 : WWF/HydroSHEDS/03CONDEM15弧秒(463.83 m)/30弧秒(927.67 m) 这里面ANTARCTICA_DEM只有南极地区的DEM。
这次下载分辨率为30弧秒的 USGS/GTOPO30。
2、关于 USGS/GTOPO30 (1)将全球分为 33 个区块,如下图所示,北纬 90 度到南纬 60 度分为 3 份,每份纬向 50 度,经向 40 度,共计 3*9=27 个 区块;南极附近为南纬 60 度到 90 度,经向 60 度,计 6 个区块,共计 33 个区块。
(2)采样间隔 30 弧秒,即 0.008333333333333 度,全球分为 21600 行、43200 列。
1、需求 2、工具 pip install pycryptodomex #用Cryptodome.Cipher里的AES加密
3、url和参数以及加密过程查找 点栈元素,跳到sources,在光标处设置断点重新刷新。
所以要找的参数实际上是:params=>encText,encSecKey=>encSecKey
需要找到加密的处理函数。
剩余三个参数可以看是什么值。
找到处理加密过程,即找window.asrsea(参数,…)
固定i的值。
4、处理加密过程爬取评论及解析 # comprehensive case # 爬取网易云评论 import json import requests import base64 from Cryptodome.Cipher import AES import jsonpath import re # 需求: # 1.找到未加密的参数 #通过window.asrsea(参数,...)进行加密 # 2.按照原来的加密方式把参数进行加密,实际上:params=>encText,encSecKey=>encSecKey # 3.请求url拿到数据 url = "https://music.163.com/weapi/comment/resource/comments/get?csrf_token=" #真实的参数 data = { #字典 "csrf_token": "", "cursor":"-1", "offset": "0", "orderType": "1", "pageNo": "1", "pageSize": "20", "rid": "R_SO_4_29004400", "threadId": "R_SO_4_29004400" } # 处理加密过程,即找window.asrsea(参数,...)源头 # d = JSON.
一、效果演示 1. 起点终点选择 2. 地址搜索 二、准备工作 1. 获取高德地图key 1.1 访问高德地图官网注册完成后登录,进入控制台
1.2 左侧 应用管理-我的应用,点击创建新应用
1.3 点击添加
1.4 选择Web端(JS API) 1.5 创建完成,得到key和安全密钥
2. 引入高德地图npm包 npm i @amap/amap-jsapi-loader --save 三、正式开始写代码 提示:以下代码全部在*.vue文件中编写,无其他文件
1. 设置key和安全密钥,初始化地图 把xxxxxxxxxxxxxxxxxxx换成自己申请的
<script> import AMapLoader from "@amap/amap-jsapi-loader"; // 设置安全密钥 window._AMapSecurityConfig = { securityJsCode: 'xxxxxxxxxxxxxxxxx', } export default { mounted() { this.initMap(); }, data(){ return { //提交表单 form:{}, //地图实例 map: null, //路径坐标点集合 coordinateList: [], //起点坐标 startCoordinate: {}, //终点坐标 endCoordinate: {}, //起点坐标描述 startCoordinateDescription: '经度:请选择起点' + ', 纬度:请选择起点' , //终点坐标描述 endCoordinateDescription: '经度:请选择终点' + ', 纬度:请选择终点', //选择起点 isStart: true, //起点Marker startMarker: null, //终点Marker endMarker: null, //搜索点Marker searchMarker: null, // 搜索提示 AutoComplete: null, // 搜索关键字 keywords: "
预处理: 一、时间矫正
点击SliceTiming
图像观察软件:MRIcroN
打开fMRI图像数据
Windows->information
Number of Slices:
TR:
TA:根据公式TR-(TR/Number of Slices)
eg:Slice order:1:2:36 2:2:36
Reference Slice:一般是选中间层 Number of Slices/2 (除不尽向下取整)
Filename Prefix:前缀 即出来的图像的前缀是什么
RUN
二、头动校正:Realign(Est&Res)
Data->Session->选中刚才时间矫正过的文件 过滤处填a->done
其余参数不需要改动,因为前人已经验证过参数是最有效的。
头动大的话就把数据去掉。
运行结束后生成一个txt文件,记录在每一个时间点头动的情况,把txt文件导入到matlab里面去读取就可以看到头动的变化。
RUN
三、空间配准:
功能像配准到结构像 Coregister
Reference Image:T1像(空间分辨率比较高)
Source Image:刚刚做过头动校正的那些文件选中,头动校正之后不会生成新的文件,还是a开头的功能像。
RUN
结构像配准到功能像 Normalise
把像配准到标准空间 Normalise->Est&Wri Image to Align -> T1像 (mean)
Image to Write -> 刚才配准完的图像
Affine Regularisation -> East Asian brains (亚洲脑)emmm亚洲的比一定比欧洲的好用
RUN
结构像 anat
四、空间平滑:
平滑前wr开头
swr是平滑后
公众号致力于点云处理,SLAM,三维视觉,高精地图等领域相关内容的干货分享,欢迎各位加入,有兴趣的可联系dianyunpcl@163.com。未经作者允许请勿转载,欢迎各位同学积极分享和交流。
segmentation模块
PCL(Point Cloud Library)中的分割模块提供了一系列用于对点云数据进行分割算法。
主要内容
pcl::ConditionalEuclideanClustering是基于欧几里得距离对点云进行聚类分割,可以实现不同大小、形状和密度的物体分离,ConditionalEuclideanClustering算法可以设置条件参数,可以实现更加精细的点云分割。例如在欧几里得距离上设置条件限制,从而只聚类距离相近的点云,达到更好的分割效果。
pcl::CPCSegmentation是一个用于平面分割的模块,它是基于凸包的几何方法实现的,可以在复杂场景中快速高效地进行平面分割,原理是基于点云的局部凸包构建的,它首先将点云划分为多个局部区域,然后对每个区域构建凸包,最后将凸包进行分割,得到平面的集合。
pcl::EuclideanClusterExtraction 是用于对欧几里得聚类(Euclidean Clustering)的实现,它将输入点云中的点分割为不同的聚类,每个聚类由一组近邻的点组成。
pcl::LabeledEuclideanClusterExtraction可以用于从点云数据中提取聚类,并为每个聚类分配唯一的标签,它是pcl::EuclideanClusterExtraction的扩展,增加了对点云中噪声点和离群点的处理,并且可以为每个聚类分配唯一的标签,该模块基于欧几里得距离聚类,通过设置距离阈值和最小聚类大小来控制聚类的粒度,聚类的过程中,还可以设置聚类的范围,比如只聚类点云数据中的一个区域,这样可以避免处理无关的点云数据。
pcl::ExtractPolygonalPrismData 是 PCL 库中的一个滤波器,用于提取多边形的柱状体(Polygonal Prism)内的点云数据。其主要原理是在 3D 空间中定义一个多边形,并且指定其高度,然后提取多边形的柱状体内的所有点。
pcl::GrabCut是一个基于图像分割的算法,用于对点云进行分割。该算法基于机器学习方法,结合了颜色和空间信息,能够对点云中的目标进行精确分割。算法步骤:
1. 初始化:首先,对点云中的每个点进行标记,将其标记为前景或背景。这一步可以通过手动标记或者基于物体边界框进行自动标记来完成。
2. 能量函数:能量函数包括数据项和平滑项。数据项表示每个点在当前标记下属于前景或背景的概率,由高斯模型计算得出。平滑项表示相邻点之间标记不同的代价。
3. 图割算法:使用图割算法求解能量函数的最小割,即找到一个最优的标记方式,使得数据项和平滑项的代价最小。
4. 迭代优化:根据当前标记结果,重新计算高斯模型,并重新求解能量函数的最小割。迭代进行,直到达到收敛条件。
pcl::segmentation::detail::RandomWalker用于实现基于随机游走的分割算法,它的原理是将点云分割成多个区域,并将每个区域分配一个标签,分割的过程基于随机游走算法,它会计算点云中所有点之间的距离,并通过比较距离来决定哪些点应该属于同一区域,在分割的过程中,RandomWalker将点云看作是一个图形,每个点作为一个节点,相邻的点之间的距离作为边。通过计算每个节点到其他节点的距离,可以得到一个节点与节点之间距离的权重矩阵,然后根据这个权重矩阵来运行随机游走算法。
pcl::LCCPSegmentation用于将点云数据分割为不同的聚类,LCCP代表Local Convexity Concavity Preserving。该模块使用基于图的凸凹保持的方法进行分割,可以识别出由凸面、凹面和平面构成的聚类。
基本原理:该方法使用了一种基于图的分割方法,通过构建一个基于图的表示来对点云数据进行分割,算法的核心是在局部区域中进行凸凹性分析,以保持聚类的局部凸凹性质,具体来说,该算法使用点云数据的曲率信息和邻域信息来计算每个点的凸凹性质,并使用这些信息来构建基于图的表示,然后,使用图论中的标签传播算法,将点云数据分割为不同的聚类,在分割过程中,保留局部凸凹性质,以获得更加准确的聚类结果。
pcl::RegionGrowing使用了一种基于区域增长的方法来分割点云数据,该算法使用一种增长策略,将种子点作为开始点,不断将邻近点添加到同一个区域中,它的主要思路是对于每个种子点,寻找与之相邻的所有点,并将这些点与种子点放在同一个区域中,这样就得到了一个较大的区域,然后,对于每个边缘点,判断它是否应该属于当前区域,并将其添加到区域中,当没有边缘点可以添加到区域时算法结束。
pcl::RegionGrowingRGB是基于RGB颜色信息进行区域生长分割的模块,它基于局部颜色相似性度量邻域内点之间的相似性,并在此基础上将相似的点合并成一个聚类。
pcl::SACSegmentation用于估计点云中符合特定模型的参数以及对应的点集。它支持对于多种基础的模型进行拟合,如平面、球、圆柱、圆锥等,SACSegmentation采用随机抽样一致性(RANSAC)算法来实现,可以在噪声点云数据中快速鲁棒地估计模型参数。该模块使用时主要涉及到以下几个步骤:
1. 选择模型类型:通过设置SACSegmentation对象的模型类型,如SACMODEL_PLANE(平面)、SACMODEL_SPHERE(球)等,来指定需要估计的模型类型。
2. 设置点云数据:将需要进行模型拟合的点云数据通过setInputCloud()函数设置进去。
3. 设置模型拟合参数:通过setModelType()函数来设置模型类型后,可以通过setMethodType()函数来设置模型拟合所采用的方法类型,如SAC_RANSAC(随机抽样一致性)或SAC_LMEDS(最小中值平方差)等。此外,还需要设置一些其他的参数,如采样的最大迭代次数、采样时随机选择的最小点数、距离阈值等。
4. 进行模型拟合:通过调用SACSegmentation对象的segment()函数来进行模型拟合。
5. 获取拟合结果:可以通过调用SACSegmentation对象的getResult()函数来获取拟合的结果,包括拟合的模型参数以及对应的点集等信息。
pcl::SACSegmentationFromNormals用于从带有法向量信息的点云数据中分割出一个特定模型,该模块的原理是基于采样一致性(Sample Consensus,SAC)算法的。
pcl::SeededHueSegmentation是一个基于色调的点云分割算法,它可以根据种子点(seed)和颜色信息将点云分割成多个颜色相似的部分。
pcl::SegmentDifferences它可以用于对两个点云数据进行分割,找出它们之间的差异部分,该模块可以接收两个点云数据,分别为源点云和目标点云,找出两者之间的差异点云。原理是将目标点云数据逐个点与源点云数据进行比较,找出不同点云数据,将不同点云数据打上标记。标记可以是一些自定义的颜色或者其它形式,以便于后续的分析处理。
pcl::SupervoxelClustering是PCL库中用于超像素分割的模块,它基于传统的区域生长方法实现,旨在将3D点云数据分割为连续的超像素群体,以便在处理大规模点云数据时提高计算效率。原理:该算法基于颜色空间中的RGB值和3D坐标信息计算每个超像素的特征,使用k-means算法对特征进行聚类,将相邻的超像素合并到一起形成连续的超像素群体,其中,颜色空间中的RGB值和3D坐标信息是可以自定义的,可以根据不同应用场景自行选择特征信息。
资源
自动驾驶及定位相关分享
【点云论文速读】基于激光雷达的里程计及3D点云地图中的定位方法
自动驾驶中基于光流的运动物体检测
基于语义分割的相机外参标定
综述:用于自动驾驶的全景鱼眼相机的理论模型和感知介绍
高速场景下自动驾驶车辆定位方法综述
Patchwork++:基于点云的快速、稳健的地面分割方法
PaGO-LOAM:基于地面优化的激光雷达里程计
多模态路沿检测与滤波方法
多个激光雷达同时校准、定位和建图的框架
动态的城市环境中杆状物的提取建图与长期定位
非重复型扫描激光雷达的运动畸变矫正
快速紧耦合的稀疏直接雷达-惯性-视觉里程计
基于相机和低分辨率激光雷达的三维车辆检测
用于三维点云语义分割的标注工具和城市数据集
ROS2入门之基本介绍
本文为Python实现,C++实现链接模型量化
若还没有配置环境(CUDA,CUDNN,TensorRT),请移至C++实现中查看环境配置方法
支持三种不同精度的量化
模型单精度量化 (FP32)
模型半精度量化 (FP16)
模型Int8量化 (INT8)
经测试yolov5,yolov6,yolov7,yolov8转化成功
yolov5: https://github.com/ultralytics/yolov5
yolov6: https://github.com/meituan/YOLOv6
yolov7: https://github.com/WongKinYiu/yolov7
yolov8: https://github.com/ultralytics/ultralytics
注意:若使用INT8量化,需要额外的文件,这里是calibrator.py
main.py文件 import tensorrt as trt import os from calibrator import Calibrator LOGGER = trt.Logger(trt.Logger.VERBOSE) def buildEngine(onnx_file, engine_file, quantification, batch_size, FP16_mode, INT8_mode, img_height, img_wdith, calibration_images, calibration_cache): builder = trt.Builder(LOGGER) network = builder.create_network(1<<int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)) parser = trt.OnnxParser(network, LOGGER) config = builder.create_builder_config() parser.parse_from_file(onnx_file) config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 16*(1<<20)) if FP16_mode == True: config.set_flag(trt.BuilderFlag.FP16) elif INT8_mode == True: config.
watchEffect函数的作用: 传入的一个函数,当依赖项变化的时候,重新执行改函数。
watchEffect函特性: 与watch相似都可以监听一个数据源。
但是watchEffect会在初始化的时候调用一次,与watch的immediate类似。
watchEffect使用 watchEffect(() => { console.log(`当${sum.person.age}的值变化的时候调用,初始化 的时候也调用一次 `) }) //打印结果 //18 的值变化了!初始化调用 //19 的值变化了依赖项调用 watchEffect接收一个副作用函数 watchEffect(onInvalidate => { console.log(`${sum.person.age} 的值变化了!`) onInvalidate(() => { console.log('清除副作用函数执行了!') }) }) //打印结果 //18 的值变化了! //清除副作用函数执行了! //19 的值变化了! onInvalidate清除副作用函数注意点 1.该函数总是在watchEffect执行的时候再次执行 2.当组件被销毁的时候该函数再次执行 3.该函数总是优先于watchEffect中的同步/异步代码执行 4.Promize函数的执行应该在该函数下面 onInvalidate清除副作用函数的执行时机由flush控制 watchEffect(onInvalidate => { console.log(`${sum.person.age} 的值变化了!`) onInvalidate(() => { console.log('清除函数执行了!') }) },{ //'pre' 在组件更新更新前运行,默认为'pre' //'post'在组件更新更新后运行 //'sync'强制效果始终同步触发。然而,这是低效的,应该很少需要。 flush:'post' })//打印结果 //18 的值变化了! //清除函数执行了! // 19 的值变化了! watchEffect侦听器调试 watchEffect(() => { console.
前几课时,我先后讲到了微服务架构下的单元测试、集成测试、组件测试和契约测试。今天我来讲解下分层测试策略的最顶层——端到端测试。
端到端测试详解 定义 端到端测试(End-to-end Test)是一种用于测试整个应用程序的流程是否符合预期的测试技术。 它模拟用户真实的使用场景,通过用户界面测试应用程序,如图所示:
与其他类型的测试相反,端到端测试是面向业务的,其目的是验证应用程序系统整体上是否符合业务目标。为了实现这一目标,该系统通常被视为黑盒子:尽可能完整地部署系统中的微服务,并主要通过 GUI 和 API 等公共接口对其进行操作。
GUI:Graphical User Interface,又称图形用户界面或图形用户接口。它是采用图形方式显示的计算机操作用户界面,是一种人与计算机通信的界面显示格式,允许用户使用鼠标等输入设备操纵屏幕上的图标或菜单选项,以选择命令、调用文件、启动程序或执行其他一些日常任务。
API:Application Programming Interface,又称呼应用程序编程接口或应用程序接口。它是一组定义、程序及协议的集合,通过 API接口实现计算机软件之间的相互通信。API 的一个主要功能是提供通用功能集,同时也是一种中间件,为各种不同平台提供数据共享。
由于微服务架构包含多个具有相同行为的活动部件,因此端到端测试为服务之间传递消息的正确性提供了更多的信心,而且还可以确保正确配置了其他网络基础结构,例如防火墙、代理或负载均衡等。
测试范围 通过微服务的分层测试策略可知,端到端测试的范围比其他类型的测试大得多。
分层测试策略-测试范围
绝大多数情况下,微服务应用系统会依赖一个或多个由外部管理的微服务。通常,这些外部服务包含在端到端测试范围内。 但是,在极少数情况下,也可以主动排除它们。因为如果外部服务由第三方管理,可能会经常出现稳定性和可靠性问题,这会导致端到端测试因不可控的原因而失败。
微服务应用的典型示例 比如,某个应用程序系统依赖公安部门的背景审查服务,通过调用该服务来查询用户是否有过违法前科。首先这样的服务通常会按调用次数付费(每次 5-10 元),具有较高的测试成本,其次背景审查服务不总是稳定可用的。在这种情况下,通过服务虚拟化技术模拟背景审查服务是个不错的选择,这虽然多少会降低端到端测试的信心,但增加了测试用例套件的稳定性。
测试入口 因为端到端测试是面向业务的,那么测试时要从真实用户的使用场景来进行测试,根据应用程序系统是否有 GUI,可以分为两种情况:
应用程序系统有 GUI,这种情况下用户可以直接操作 GUI 来使用系统,那么诸如 Selenium WebDriver 之类的工具可以帮助驱动 GUI 触发系统内的特定行为。
应用程序系统没有 GUI,这种情况下,使用 HTTP 客户端通过其公共的 API 直接操作微服务。没有真实的 GUI,不能直观地看到业务功能行为,但可以通过后台数据来确定系统的正确性,比如 API 的返回结果、持久化数据的变化情况,等等。
测试设计 确定测试范围和测试入口后,可以进一步梳理出要测试的功能列表或用例集,并对其按业务能力、优先级、重要性等维度进行分组。这样可以将它们拆分为较小的任务,以便整个团队可以排序处理,比如可以首先实施优先级较高的用例组,或按紧急程度处理关键的用例,这有助于我们尽早消除潜在的障碍。
另外,由于端到端测试的目标是完全集成后的系统的行为,使得编写和维护测试用例会比其他类型的测试更加困难:
端到端测试涉及的活动部件比其他测试多得多;
端到端测试须考虑系统中的异步处理。
这些因素都可能给端到端测试带来挑战,比如测试过程不稳定、测试时间过长、测试用例集的维护成本高,等等。因此,应尽可能以最粗粒度进行端到端的测试设计。
如何开展端到端测试? 熟悉了端到端测试的基本内容,我们来看下如何开展端到端测试,主要有如下几类:
UI 自动化
对于带有 GUI 的应用程序系统,在进行端到端测试时,可以通过 UI 自动化的方式进行。如果 GUI 是 Web 形式,则 Selenium 是首选工具;如果 GUI 是 Native 形式,则可以使用 Appium。
存储过程(无参,多个输入参数,多个输出参数) 存储过程:
1、减少编译次数
2、简化操作
3、减少了变异次数减少了和数据库的链接次数,提高效率 关于存储过程的方法:
1、删除存储过程
DROP PROCEDURE 存储过程的名称;
2、查看存储过程信息
show create procedure 存储过程名称;
3、没有存储过程的修改
创建语法:
CREATE PROCEDURE 存储过程名称(参数列表) BEGIN 方法体(存储过程体)一组方法语句; END ⭐⭐⭐⭐注意:参数列表包括三部分
1、参数模式 参数名 参数类型
eg: IN stuname varchar(20)
参数模式
IN : 该参数可以作为输入,也就是需要调用方传入值
OUT: 该参数作为输出,也就是该参数可以作为返回值
INOUT: 既可以作为输入参数,也可以作为输出参数
2、如果存储过程提仅仅只有一句话,那么BEGIN END 可以省略
3、存储过程中的每一条sql语句的结尾都必须加封号,需要申明结尾符号 DELIMITER 重新设置
以下在创建的过程中使用DELIMITER $开始,DELIMITER ;结束,是因为mysql是以;结束的,此处创建存储过程的时候需要指定结尾符号为$,整个存储过程执行完成后,再还原为mysql的结束符;即可
一、空参存储过程
DELIMITER $ CREATE PROCEDURE test1() BEGIN INSERT INTO admin(username,`password`) VALUES ('JOHN1','000001'); INSERT INTO admin(username,`password`) VALUES ('JOHN2','000002'); INSERT INTO admin(username,`password`) VALUES ('JOHN3','000003'); INSERT INTO admin(username,`password`) VALUES ('JOHN4','000004'); INSERT INTO admin(username,`password`) VALUES ('JOHN5','000005'); END $ 调用:CALL test1();
一、数据类型 1.1整数类型 Java中的整数类型简称整形,即没有小数部分的整数。当然,它表示的数可正可负。整形数据根据它所占内存大小的不同,分为byte、short、int、long4种类型。它们具有不同的取值范围。
数据类型
内存空间(8位等1字节)
取值范围
byte
8位
-128~127
short
16位
-32768-32767
int
32位
-2147483648-21474883647
long
64位
-9223372036854775808-923372036854775807
以下是博主个人对这四种数据类型的介绍:
int型 定义int型变量有以下四种语法:
int x; //定义一个int型变量x; int x,y; //同时定义两个int型变量x,y; int x=0,y=1; //定义同时赋值; int x=5+23; //赋计算结果初值。 int变量在内存中占4字节,也就是32位,在计算机中bit是由0和1来表示的,所以int类型在计算机中在计算机中是这样表示的:
00000000 00000000 00000000 000001010 int类型是Java整形类的默认数值。当多个尚未定义数据类型的整形运算时,默认结果为整型:
System.out.print(23+34); 输出结果为整形。
byte型、long型、short型的定义方法与int型定义方法相似,不再过多介绍。
1.2 浮点类型 浮点类型简称浮点型,用来存储含有小数部分的数值。Java语言中浮点类型分为单精度浮点类型(float)和双精度浮点类型(double),它们具有不同的取值范围。
数据类型
内存空间(8位等于1字节)
取值范围
float
32位
1.4E-45~3.4028235E38
double
64位
4.9E-324~1.797693138623157E308
*浮点值属于近似值,在系统中运算后的结果可能与实际有偏差。
在那默认情况下,小数都被看做double类型。使用float型小数则需要在小数后面添加F或f。另外,同样的,也可以加d或D声明这是一个double类型。
Java语言的浮点型有两种表示形式:
十进制数形式:简单的浮点数,例如2.56、6.534、546.0。浮点数必须包含一个小数点,否则会被当成int型处理;
2、科学计数法形式:例如5.25e2(即5.25*10^2)。
需要提一下的是:只有浮点类型的数值才能用科学计数法形式表示。
1.3字符类型 char类型
char类型用于存储单个字符,占用16位的内存空间。在定义字符串型时要以单引号表示,如’s‘表示单个字符。
char x='a'; 由于字母a在Unicode表中的排序位置是97,因此允许将上面的语句写成:
char x=97; 2、String类型
目录
一、下载
二、配置初始化文件my.ini
请注意:这里的配置是什么含义呢?
三、安装mysql
四、配置环境变量
编辑
五、cmd命令提示符 常用指令
总结 一、下载 Mysql官网下载https://www.mysql.com/cn/downloads/
点击链接,下载
例如我的下载路径为D:\Program Files\mysql-8.0.32-winx64,在后面的配置系统环境变量以及使用cmd命令提示符还会用的到。
解压
解压到你想要的位置,请记住你解压后文件的路径, 例如我的下载路径为D:\Program Files\mysql-8.0.32-winx64,在后面的配置系统环境变量以及使用cmd命令提示符还会用的到。
二、配置初始化文件my.ini 这里很多CSDN上诸多帖子都是mysql.ini或者my.ini,虽然自己可以设置更方便记忆的名称都是可以的。但是博主本人搜了一下相关的资料,MySQL 的默认配置文件是 my.cnf 或者 my.ini,具体文件名取决于操作系统和 MySQL 版本。在 Unix/Linux 系统中,通常使用 my.cnf;在 Windows 系统中,通常使用 my.ini。但是,用户可以根据需要将配置文件名更改为其他名字,只要在 MySQL 启动时使用正确的配置文件即可。
一般来讲当大家要接触到管理配置文件的时候会在cmd使用这两个指令etc\my.cnf(Linux)或者etc/my.ini(Windows),但是大家用咱们的方式直接设置配置文件的话,以后想要管理配置文件就可以直接在这里点开了,或者在cmd中这样做
效果和直接点开my.ini文件是一样的
注意:INI文件是一种初始化文件,通常被用于存储和配置应用程序、操作系统和其他系统组件的设置和选项。其名称来源于“Initialization”(初始化)这个单词的缩写。INI文件通常是文本文件,其格式是基于键值对的。每个键值对由一个键(即名称)和一个值组成,它们之间用等号或冒号分隔。INI文件通常包含多个节(Section),每个节包含多个键值对。INI文件被广泛应用于Windows系统中,例如在Windows注册表中,也被许多编程语言和应用程序所支持。
[mysqld]
# 设置3306端口
port=3306
# 设置mysql的安装目录 ---是你的文件路径---
basedir=D:\Program Files\mysql-8.0.32-winx64
# 设置mysql数据库的数据的存放目录 ---是你的文件路径data文件夹自行创建---
datadir=D:\Program Files\mysql-8.0.32-winx64\data
# 允许最大连接数
max_connections=200
# 允许连接失败的次数。
max_connect_errors=10
# 服务端使用的字符集默认为utf8mb4
character-set-server=utf8mb4
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 默认使用“mysql_native_password”插件认证
#mysql_native_password
default_authentication_plugin=mysql_native_password
[mysql]
编译过程: 下载源码->搭建编译环境->编译源码->解决编译报错->生成编译固件包
编译环境 本文使用的是下载好的Android8.1源码,搭建好的虚拟机Ubuntu14.0/Ubuntu16.0(建议分配300G及以上的内存)
下载git
sudo apt-get install git 配置自己的user.name及user.email
git config --global user.email “fys@163.com” git config --global user.name “fys” 下载jdk1.8
sudo add-apt-repository ppa:openjdk-r/ppa sudo apt-get update sudo apt-get install openjdk-8-jdk 开始编译 进入android源码目录初始化编译环境 source build/envsetup.sh 初始化完成之后执行lunch选择编译目标 lunch 输入想要编译的目标号即可
这里如果是自己兴趣开发使用,随便玩玩一般选择1或2即可
开发人员需要自行选择自己项目具体的编译目标
make开启编译 通过make指令进行代码编译,该指令通过-j参数来设置参与编译的线程数量,以提高编译速度
make -j4 >build.log >build.log 代表输出编译日志可以在源码根目录直接查到,编译过程中的报错可以在log中查找
解决编译报错 编译报错一般会在命令行最后提示如下:
[0;31m#### failed to build some targets (11:11 (mm:ss)) ####[00m 报错1:/bin/bash: m4: command not found 解决方法:
sudo apt-get install m4 报错2: /bin/bash: xmllint: command not found 解决方法:
默认的模拟器中打开浏览器,访问百度IP202.108.22.5没问题,输入www.baidu.com无法正常显示。 说明模拟器中DNS有问题。 解决步骤如下: 1.在模拟器中找到网络中心,找到默认的AndroidWifi网络,记住其ip地址及默认网关
2.能够看到原本的DNS有问题
3.在自己电脑中找到网络中心,查看本地的DNS服务器
4.在模拟器中,修改AndroidWiFi网络,IP设置为静态,自己填入之前的ip与网关,将默认的DNS更换为上一步查到的本地DNS服务器。更改完网络后保存。
5. 最关键的一步,在通知栏有一条系统通知,一定要点击!! 6.在通知里点击不再询问,YES。至此,网络恢复正常。 7.无线网图标处感叹号已经消失,百度可正常访问!!! 自己刚开始忽略了通知栏的通知,耗费了大量时间做无用功,希望能对大家有帮助。

文章目录 指定文件类型多文件选择自定义样式通过 click() 方法使用隐藏的 file input 元素使用 label 元素来触发一个隐藏的 file input 元素 基本上传方式访问文件传统的 DOM 选择器访问一个已经被选择的文件通过 change 事件访问被选择的文件动态添加change监听器 Ajax 上传监测上传进度分割上传拖拽上传 文件上传是 Web 开发常见需求,上传文件需要用到文件输入框。 指定文件类型 一个以英文句号(“.”)开头的合法的不区分大小写的文件名扩展名。例如:.jpg、.pdf 或 .doc。
一个不带扩展名的 MIME 类型字符串。
字符串 audio/*,表示“任何音频文件”。
字符串 video/*,表示“任何视频文件”。
字符串 image/*,表示“任何图片文件”。
accept 属性的值是包含一个或多个(用逗号分隔)唯一文件类型说明符的字符串。例如,一个文件选择器需要能被表示成一张图片的内容,包括标准的图片格式和 PDF 文件,大概是这样的:
<input type="file" accept="image/*,.pdf" /> 可以用 accept 属性指定可接受的文件类型,它是一个以逗号间隔的文件扩展名和 MIME 类型列表。一些例子如下所示:
accept=“image/png” 或 accept=“.png”——接受 PNG 文件。accept=“image/png, image/jpeg” 或 accept=“.png, .jpg, .jpeg”——接受 PNG 或 JPEG 文件。accept=“image/*”——接受任何带有 image/* MIME 类型的文件。(许多移动设备也允许用户在使用它时用摄像头拍照。)accept=“.doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document”——接受类似于 MS Word 文档的任何文件。 capture 属性是一个字符串,如果 accept 属性指出了 input 是图片或者视频类型,则它指定了使用哪个摄像头去获取这些数据。值 user 表示应该使用前置摄像头和(或)麦克风。值 environment 表示应该使用后置摄像头和(或)麦克风。如果缺少此属性,则用户代理可以自由决定做什么。如果请求的前置模式不可用,则用户代理可能退回到其首选的默认模式。