数据结构-图的应用算法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、最小生成树1.1 Prim算法1.2 Kruskal算法 二、最短路径2.1 Dijkstra算法2.2 Floyd算法 三、有向无环图描述表达式四、拓扑排序五、关键路径 一、最小生成树 最小生成树两种算法 1.1 Prim算法 算法步骤: 步骤一:树T初始状态为空; 步骤二:从图中任意选取一个点加入T; 步骤三:从图中找出能与T形成树的所有边,将代价最小的边加入T,形成新的树T; 步骤四:检查T中边的条数; 步骤五:如果条数小于n-1,返回步骤三,否则程序结束,T为最小代价生成树。 示例: 1.2 Kruskal算法 算法步骤: (1)将图G看做一个森林,每个顶点为一棵独立的树 (2)将所有的边加入集合S,即一开始S = E (3)从S中拿出一条最短的边(u,v),如果(u,v)不在同一棵树内,则连接u,v合并这两棵树,同时将(u,v)加入生成树的边集E’ (4)重复(3)直到所有点属于同一棵树,边集E’就是一棵最小生成树 示例: 二、最短路径 2.1 Dijkstra算法 算法步骤: 示例: 2.2 Floyd算法 算法步骤: 示例: 三、有向无环图描述表达式 有向无环图描述表达式 算法步骤: 1)把各个操作数不重复地排成一排 2)标出各个运算符的生效顺序(先后顺序优点出入无所谓,比如先算左边括号或者先算右边括号,当然是同级的情况) 3)按顺序加入运算符,不同的运算级别层次不同,过程中如果已经存在某部分,则直接用 4)最后生成的图就是有向无环图 示例: 四、拓扑排序 参考 算法步骤: ① 输入AOV网络。令 n 为顶点个数。 ② 在AOV网络中选一个入度为0的结点, 并输出之;(关键步) ③ 从图中删去该顶点, 同时删去所有它发出的有向 边; ④ 重复以上 ②、③步, 直到下面的情况之一出现: (1)全部顶点均已输出,拓扑有序序列形成,拓 扑排序完成; (2)图中还有未输出的顶点, 但已没有入度为0的 结点(说明网络中必存在有向环)。

python-opencv-使图片更清晰的几种方法

2023/3/6更新 很久没搞图像这块了,这个以后再改吧。全灰是因为读图像的时候就是读的灰的。。 img = cv2.imread(source, cv2.IMREAD_GRAYSCALE) 哪天想起来再改这篇吧。 所有代码已测试通过。 import cv2 import numpy as np def gamma(source,out): img = cv2.imread(source, cv2.IMREAD_GRAYSCALE) # 归1 Cimg = img / 255 # 伽玛变换 gamma = 0.7 O = np.power(Cimg, gamma) O = O * 255 # 效果 cv2.imwrite(out, O, [int(cv2.IMWRITE_PNG_COMPRESSION), 0]) def hist(source): img = cv2.imread(source, cv2.IMREAD_GRAYSCALE) # 求出img 的最大最小值 Maximg = np.max(img) Minimg = np.min(img) # 输出最小灰度级和最大灰度级 Omin, Omax = 0, 255 # 求 a, b a = float(Omax - Omin) / (Maximg - Minimg) b = Omin - a * Minimg # 线性变换 O = a * img + b O = O.

zookeeper集群启停及状态查看脚本(linux)

#! /bin/bash case $1 in "start"){ for i in hadoop110 hadoop111 hadoop112 do echo ======$i====== ssh $i "source /etc/profile && /opt/module/zookeeper-3.5.7/bin/zkServer.sh start" done };; "stop"){ for i in hadoop110 hadoop111 hadoop112 do echo ======$i====== ssh $i "source /etc/profile && /opt/module/zookeeper-3.5.7/bin/zkServer.sh stop" done };; "status"){ for i in hadoop110 hadoop111 hadoop112 do echo ======$i====== ssh $i "source /etc/profile && /opt/module/zookeeper-3.5.7/bin/zkServer.sh status" done };; esac 注意集群名称修改 启动传参start 停止传参stop 查看状态传参status

vue3中使用nextTick和forceUpdate+vue3 ts使用EventBus

一、 vue中使用forceUpdate 作用:在Vue官方文档中指出,$forceUpdate具有强制刷新的作用,迫使vue实例重新(rander)渲染虚拟dom,注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。 在vue2中使用 this.$forceUpdate() vue3中使用 import { getCurrentInstance } from 'vue' // 先引入 setup(){ // 解构赋值 设置别名that,也可不写:that,直接ctx let { ctx: that } = getCurrentInstance() that.$forceUpdate() } 这样使用的时候会报错 Property ‘ctx’ does not exist on type ‘ComponentInternalInstance | null’. 类型检测 const { ctx: that } = getCurrentInstance() as any 二、vue中使用$nextTick 作用:vue中的nextTick()是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用$nextTick(),则可以在回调中获取更新后的 DOM。 在vue2中使用 this.visible = false // 直接使用 this.$nextTick(() => { // 要执行的方法 this.visible = true }) 在vue3中使用

《解构领域驱动设计》- 领域驱动设计统一过程

更多内容关注微信公众号:fullstack888 领域驱动设计的核心是模型驱动设计,而模型驱动设计的核心又是领域模型,领域模型必须在统一语言的指导下获得。领域模型又可进一步细分为核心子领域、通用子领域和支撑子域。 系统上下文、限界上下文、分层架构和聚合都属于领域驱动设计的边界控制手段,他们的区别在于对业务划分的粒度和维度不同。 领域驱动设计统一过程 “人类是通过在问题空间中寻找解决方案来解决问题的” 同理,软件系统的构建实则是对问题空间的求解,以获得构成解空间的设计方案。 问题空间强调通过统一语言来描述需求问题,利用核心子领域、通用子领域和支撑子领域来分解问题空间。 解空间中,这些子领域将被映射到限界上下文,可以根据子领域类型的不同为限界上下文选择不同的建模方式。比如核心子领域可以选用领域建模,而支撑子领域的限界上下文可以选择事务脚本模式 注意:由此可见,子领域是问题空间中的概念,在拆分问题时,对问题进行分级;限界上下文是解空间中的概念,它跟问题空间中的子领域具有映射关系,可以基于子领域推导出限界上下文来 在限界上下文中要通过分层架构将领域模型独立出来,其目的是实现关注点分离,比如通过分层架构将技术与业务分离,保持两者的变化仅在其所在的层次内传递,防止两者复杂度的交织引发的更大范围的复杂度。 领域驱动设计战略设计阶段的核心模式是限界上下文,指导架构设计的核心模式是分层架构,前者决定了业务架构和应用架构,后者决定了技术架构。 领域驱动设计的核心诉求是让业务架构和应用架构形成绑定关系,同时降低与技术架构的耦合,使得在面对需求变化时,应用架构能够适应业务架构的调整,并隔离业务复杂度与技术复杂度,满足架构的演进性。 完整的领域驱动设计过程划分为三个重要的阶段: 1)全局分析阶段:对现实世界中问题的分析 2)架构映射阶段:解决现实世界与软件解决方案的桥接问题 3)领域建模阶段:对软件解决方案内部进行进一步的分析建模 全局分析阶段 目标:通过可视化的手段完成对问题空间的探索与分析 任务:通过执行价值需求分析和业务需求分析活动,深入剖析问题空间 活动:价值需求分析、业务需求分析 产物:全局分析规格说明书 价值需求分析 价值需求分析 利益相关者、系统愿景和系统范围共同组成了目标系统的价值需求,分属于 5W 模型中的 Who、Why 和 Where。 首先需要识别出目标系统的利益相关者(Who) 然后通过统一利益相关者的业务目标,明确目标系统的界限和方向 最终做到明确系统愿景(Why)和识别系统范围(Where) 模式:统一语言 方法:商业模式画布 利益相关者 支持者,比如组织、部门、员工和上游第三方合作伙伴 受益者,比如用户、下游第三方 注:上游指的是提供价值方,下游指消费价值方。 业务需求分析 价值需求分析指导业务需求分析。 业务需求由动态业务流程和静态的业务场景、业务服务组成,两者的结合依靠业务场景按照时间点和业务目标对业务流程进行拆分。 业务需求分析阶段可分三个层级对业务需求进行逐级的问题拆解,如下。完成问题拆解后,即可梳理出核心子领域、通用子领域和支撑子领域。 第一层:业务流程 第二层:业务场景 第三层:业务服务 模式:统一语言、核心子领域、通用子领域、支撑子领域 可视化方法:业务流程图、服务蓝图、业务服务图、事件风暴 业务流程 第一层级,在业务目标指导下梳理出提供业务价值的动态业务流程。属于 5W 模型中的 When。 业务流程的起点往往由一个角色想目标系统发起服务请求,而要完成整个流程,则需要多个角色共同参与协作。业务流程的特点是:1)具有时间属性 2)多角色参与 3)输出业务价值 识别业务流程的两个关键点是:完整和边界。完整是指要具有端到端的完整协作过程,体现一个完整的业务价值;边界仍然是从业务价值层面确定业务的范畴。 可视化方案:业务流程图、服务蓝图 业务场景 场景就是角色之间为了实现共同的业务目标进行互动的时空背景,通过角色在特定时间、空间内执行的活动来推动情景的发展,形成角色与目标系统之间的体验与互动 第二层级,按照时间对业务流程进行切分,划分出每个时间阶段的业务场景,每个业务场景时可以由多个角色参与的。 业务流程与业务场景的区别与联系 一个动态的业务流程是由一到多个静态的业务场景构成的,业务流程是端到端的完整协作过程,业务场景则是在业务目标的指导下在时间维度对业务流程的纵向切分。 可视化方案:用例图,例如: 业务服务 第三个层级,每个角色在业务场景下的一次功能性交互形成业务服务。业务服务是全局分析阶段的基本业务单元。属于 5W 模型中的 What。1)提供了目标系统的核心价值,满足了利益相关者的价值需求的业务服务,归入核心子领域 2)属于业务需求一部分,但是横向支撑了多个领域服务,不具有明显的个性特征的业务服务,则归入通用子领域 3)起支撑和辅助价值的业务服务,归入支撑子领域

【码蹄集】数据流中位数(vector,sort)

//该程序中,首先读入接收数据的次数n,然后根据n的值循环接收数据,如果操作符为“+”, //则将读入的数字添加到vector末尾; //如果操作符为“?”,则对vector进行排序,然后计算中位数, //如果vector长度为偶数,则取中间两个数的平均值。 #include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> nums; // 存储数据的列表 string op; // 操作符 int num; // 待添加的数字 int n; // 接收数据的次数 cin >> n; while (n--) { // 根据用户输入的次数循环接收数据 cin >> op; if (op == "+") { // 如果是添加操作 cin >> num; nums.push_back(num); // 添加到列表末尾 } else if (op == "?") { // 如果是查询中位数操作 int size = nums.size(); sort(nums.

【CSS】CSS 复合选择器 ② ( 子元素选择器 | 交集选择器 )

文章目录 一、子元素选择器1、语法说明2、代码分析3、代码示例 二、交集选择器1、语法说明2、代码示例 一、子元素选择器 1、语法说明 子元素选择器 可以选择 某个基础选择器 选择出的 元素组 的 直接子元素 ( 亲儿子元素 ) 中 使用基础选择器 选择 元素 ; 子元素选择器语法 : 父选择器 写在前面 , 子选择器 写在后面 , 两个选择器之间使用 > 大于号隔开 ; 父选择器>子选择器 { 属性名称1:属性值1; 属性名称2:属性值2; 属性名称3:属性值3; } 注意 : 子选择器 只能从 父选择器 选择出的标签 的 亲儿子元素 中选择 元素 ; 子选择器 只能 从 父选择器 选择出的元素的 亲儿子 元素 中选择 , 孙子元素 和 重孙子元素 选择不到 ; CSS 基础选择器 : 标签选择器类选择器ID 选择器通配符选择器 2、代码分析 在下面的代码中 ,

【Redis】的后台启动方法、相关数据类型、配置文件及Redis的测试

本文是在阿里云服务器上进行的学习redis,因此gcc等安装操作不需要进行,可以直接进行安装redis,在安装完成之后,我们进行以下的学习。本次学习的redis安装路径为/usr/local/bin,安装的步骤可以参照尚硅谷教程进行安装。 目录 1.Redis的后台启动(推荐) 2.Redis相关知识介绍 2.1 Redis 键(key) 2.2 Redis 字符串(String) 2.3. Redis 列表(List) 2.4. Redis 集合(Set) 2.5. Redis 哈希(Hash) 2.6. Redis 有序集合 Zset(sorted set) 3.配置文件 3.1 单位 3.2 INCLUDES 包含 3.3 网络相关配置 bind protected-mode 3.4 GENERAL 通用设置 3.5 SECURITY 安全 4.Redis 的发布和订阅 5.Redis 新数据类型 5.1 Bitmaps(位操作) 合理地使用操作位能够有效地提高内存使用率和开发效率。 5.2 HyperLogLog(统计) 5.3 Geospatial(经纬度) 6.Redis_Jedis_测试 创建maven工程后引入Jedis 所需要的 jar 包 6.1 操作key 6.2 完成一个手机验证码功能 04-概述和安装_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Rv41177Af?p=4&vd_source=7b32287884d43c4ae590e89cdf55a096 1.Redis的后台启动(推荐) [root@iZuf6085c1lnhffxqh52xzZ bin]# redis-server /etc/redis.conf [root@iZuf6085c1lnhffxqh52xzZ bin]# ps -ef | grep redis root 66433 1 0 19:42 ?

Umi使用百度地图服务

需求描述 需要在前端页面中使用地图定位功能,所以在前端umi项目中使用百度地图服务,由于umi项目默认没有入口的html文件,所以无法通过常规的在head中加入外链js的方式使用 百度ak zyqeLCzvQPCCNImRu9yRGOqWlEUicxxG react使用百度api 链接: 百度地图api链接 解法方法 看清楚有两种方法 第一种方式 :用umi-plugin 插件的方式把链接加到页面上 在src/page下 ,新建文件 plugins/customPlugin.js /** * customPlugin.js */ export default (api, opts) => { // 在HTML尾部添加脚本 api.addHTMLScripts(() => { return [ { // 百度地图 type:"text/javascript", src:"//api.map.baidu.com/api?type=webgl&v=1.0&ak=你的百度秘钥ak" } ] }) } 在umirc.ts中导入本地新建的插件文件customPlugin.js /** * umirc.ts,umi项目默认配置文件 */ import { defineConfig } from 'umi'; export default defineConfig({ nodeModulesTransform: {...}, dva: {}, routes: [...], fastRefresh: {}, plugins: ['./src/plugins/customPlugin.js'] //添加一个plugins插件 }); 新建一个jsx文件将你需要的代码填写到里面 注意!!! 使用npm方式安装react组件库,然后通过es模块加载 npm install react-bmapgl --save 因为本人使用的是tsx 所以会有下划线报错 import { Map } from 'react-bmapgl' function Example() { return ( <Map style={{ height: 450 }} center={new BMapGL.

Windows 10 / 11 环境变量 (用户变量与系统变量)

Windows 10 / 11 环境变量 (用户变量与系统变量) 1. 环境变量 (environment variables) 环境变量 (environment variables) 是在操作系统中用来指定操作系统运行环境的一些参数。环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所使用到的信息。Windows 和 DOS 操作系统中的 path 环境变量,当要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还应到 path 中指定的路径去找。用户通过设置环境变量,来更好的运行进程。 environment variables:环境变量 user variables:用户变量 system variables:系统变量 环境变量可分为用户变量与系统变量两类,在注册表中都有对应的项。 1.1 用户变量 用户变量所在位置:HKEY_CURRENT_USER\Environment 1.2 系统变量 系统变量所在位置:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment 在原有变量的基础上添加英文状态下的分号,然后添加路径名。不要删除原先的系统变量,只要用分号隔开,然后添加路径名,最后也要加上分号。 添加路径之后,要保存,再重启 cmd,确保生效。 1.3 Windows 10 - echo %path% Microsoft Windows [版本 10.0.17763.1158] (c) 2018 Microsoft Corporation。保留所有权利。 C:\Users\cheng>echo %path% C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\iCLS\;C:\Program Files\Intel\Intel(R) Management Engine Components\iCLS\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.

ChatGPT概述:从模型训练到基本应用的介绍

ChatGPT概述:从模型训练到基本应用的介绍 目录 本文是对ChatGPT的由来、训练过程以及实际落地场景的解释,主要内容包括如下三个方面: 1、ChatGPT是什么 2、ChatGPT的原理 3、ChatGPT的思考 4、ChatGPT的应用 ChatGPT是什么 ChatGPT可能是近期深度学习领域,讨论非常频繁的一个概念。但ChatGPT到底是一个什么,怎么给出一个定义呢。可以看下ChatGPT对自己的定义,如下图: 从定义以及我们使用过程中的感受,可以得到如下的结论: ChatGPT是一个语言模型 了解人类偏好的语言模型是一个大规模预训练的模型表现形式是具备高智能的对话能力 对此,新华社也给出了“新一代操作系统平台的雏形的”评价,可见ChatGPT的横空出世确实带来了一些改变。 模型具有对话能力不是很新奇的事,之前腾讯的混元、百度的ERNIE等大模型都具备对话能力,让ChatGPT出圈并持续火爆的是ChatGPT在如下的测试中也取得了让人惊讶的成绩: 上述的测试不是简单的对话能够解决的,但ChatGPT同样表现得非常出彩,那为什么ChatGPT能够这么优秀? ChatGPT的原理 过往大模型的发展方向,不外乎:更多的数据、更大的模型结构、更精细的处理方式以及更统一的输入输出等等。但这样训练的大模型,更像是一个图书馆,或者搜索引擎,只具备知识的储存能力和简单的检索能力。 我们以“女朋友生气了怎么办”这个问题为例,过往大模型从网络数据中经过预训练,得到许许多多的答案:你也生气;讲道理;沉默是金;快速认错……但具体哪个答案更符合人类的偏好和认知,模型是不知道的,模型只能根据网络上答案给出反馈。 但可能上述的答案上下文是故意作答、心理测试题、乱写等等情况下的答案,但这些过往的大模型是不知道的。 所以历史的大模型,在训练和使用阶段是没有人工参与的,没有学习到人类的认知和偏好:仅仅是历史数据(网络数据)是存储和检索。 ChatGPT出世前,OpenAI已经进行了一系列的探索,包括生成代码的codex系列和text-davinci系列。这一系列模型的探索过程,构成了指示学习,和RLHF学习方式叠加后,ChatGPT模型才终于横空出世。 监督学习+人工反馈+强化学习 -> ChatGPT 从OpenAI的官方博客,可以看出InstrctGPT和ChatGPT的训练过程如下,存在的差异非常细微: 训练数据上的差异base模型的差异 整体的训练思路,InstrctGPT和ChatGPT是相同的,均包括三个步骤: 微调模型:监督学习下的微调,通过收集问题后,进行人工答案的书写,来微调GPT基模型,得到SFT模型模型模型:在微调的基础上,通过模型对同一个问题产出不同答案,人工标注答案之间的优劣排序,得到RM模型RLHF:在SFT模型和RM模型的辅助下,通过强化学习的PPO策略,最终得到终极模型ChatGPT/InstrctGPT 微调 训练过程的第一步:微调。问题来源于早起的Platground的API,人工对问题进行答案的生成。和其他大模型的微调过程是一样的。 这一步的目的是得到后续优化的基模型,以及在强化学习过程中,提供损失函数的约束。 反馈模型 训练过程第二步:RM模型。在已经微调的SFT模型上,通过同一个问题的不同输出,进行人工优劣得分的标注,生成对应的序列。 例如对于问题P,得到的答案为A、B、C和D,人工对答案进行排序为:D>C>B=A,通过模型学习人工排序的结果。也就是让模型模仿人类排序的过程:对SFT模型的输出能够给出优劣的判断。 GPT是字粒度的输出,输出过程的每一步都是在概率分布上的采样,因此,同一个问题多次输入后,会得到不同的输出 RLHF 训练过程第三部:PPO策略的强化学习。在已有的SFT模型和RM模型上,结合PPO策略的强化学习,获得最终的ChatGPT/InstrctGPT。该步的大概流程如下: 输入问题后,目标模型(以SFT模型初始化获取)得到答案将问题和答案输入RM模型中,得到该答案的得分将该答案通过PPO策略,反馈给目标模型进行模型的更新 通过损失函数可以看出,在实际的训练过程中,RM模型和最终的目标模型,均存在参数的更新 上面的三个步骤,就是InstrctGPT/ChatGPT的大概训练流程。总结起来就是下图: ChatGPT的思考 将人类的偏好和认知引入模型训练,并不是ChatGPT或者OpenAI的首创,在2020年一篇做摘要的论文就提出了该思想。只能说是OpenAI的“钞能力”将该方法发扬光大了。 针对ChatGPT,目前其在聊天、翻译、脚本、代码、文案……等诸多领域已经崭露头角了,在ChatGPT表现其“无所不能”的同时,我们也可以考虑下其目前存在的问题有哪些呢。 目前来说, ChatGPT的准确性已经非常高,但对于特定问题可能在一本正经的胡说八道,当然目前其不具备联网更新能力,训练语料为2021年之前的,最新的知识可能更新是一方面的问题;关于逻辑性和数据的偏见,是目前大模型普遍存在的问题,期待后续模型能够在这方面带来惊艳的表现资源是限制ChatGPT普适性推广的核心关键,其训练数据规模、推理依赖的资源,都是海量的,在这些成本没有降低前,大模型应该还仅仅是固定厂商的利器。 ChatGPT的应用 随着ChatGPT的爆火,也带来了一些实际的落地应用,例如下面的几个应用,都是非常有意思的: 对话式PDF阅读助手:通过上传文档,然后对话沟通的方式,获取论文、文献的内容要点AI PPT生成:ChatGPT和AIGC结合产生的质变写作:写故事、写文案、写小说、写PPT,只要是文字范围的,一切皆有可能 总的来说,期待ChatGPT后续的表现。

给定正整数n,打印输出边长为n的平行四边形

#include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> 要求输出图形为 int main() { //整体思路:将平行四边形分为上下两部分,n行就是【1~2*n-1】,上下两部分单独进行循环。 int i,star1,star2,space1,space2,n; printf("请输入行数:\n"); scanf("%d",&n); for(i=1;i<=2*n-1;i++) { // 上半部分的循环: star1 = i; while(star1 && star1<=n) { printf(" * "); star1--; } space1 = n-i; while(space1 && space1>0) { printf(" "); space1--; } 下半部分的循环。 if(i<=n) printf("\n"); if(i>n) { space2 = i-n; star2 = n-space2; while(space2) { printf(" "); space2--; } while(star2) { printf(" * "); star2--; } printf("\n"); } } return 0; } 最后的运行结果是

香橙派5使用NPU加速yolov5的实时视频推理(一)

前言: 寒假里,博主完成了树莓派4B搭载yolofastest-V2的ncnn加速,效果挺不错的,但总感觉还是稍微差点意思,于是就购买了一块香橙派5,想要用RK3588芯片自带的NPU来加速深度学习的部署,在2023年3月4日也是完成了香橙派5的NPU加速深度学习部分,其效果也确实非常可观,在画质较低的情况下,运行速度达到了100fps以上,下面是我在B站发布的效果视频点我跳转。这篇博客也是为了总结一下玩香橙派5的时候遇到的坑。 准备材料: 1、香橙派5 2、一台windows10或windows11的电脑 3、一个内部带有Ubuntu20.04的移动硬盘(如果没有,也可以用VMware安装个虚拟机也行)。 3、USB摄像头(某宝上有卖的,啥都可以)用来做视频识别 4、64G内存卡(烧录了官方的Debian11系统)、HDMI线、显示屏、官方的电源线、键鼠套装 5、香橙派5官方提供的无线网卡(其他网卡应该也行,只不过当时我买了,即使安装了驱动也没上成网) 6、散热壳(也是某宝买的,不是官方的) 说明: 关于RKNN,官方给出了两种思路,一种是关于C的,另一种是关于Python的,这里我只介绍Python有关部分。 在接下来的操作中,一和二是在windows系统上进行操作的,三是在Ubuntu20.04系统上进行的,四是在香橙派5上操作的,大家注意区分!!! 一、使用官方指定的yolov5版本去训练: 不瞒大家,对于yolov5来说,博主本人在寒假之前也没用过,这个寒假才学会了yolov5的训练和应用,在此之前,我甚至都不知道yolov5还分为多个版本,RKNN官方教程 进入教程后,首先点击框内链接跳转至yolov5的GitHub仓库 博主这里跳转过后是403,没关系,我们直接点击yoloV5官方库跳转至如下界面。 点击左上角箭头所指区域,搜索c5360f6e7009eb4d05f14d1cc9dae0963e949213,跳转至如下界面,按顺序点击箭头所指区域 进入如下界面后,点击Browse file 这样,我们就找到了正确的版本了 把代码保存到本地,接下来,我们点击Releases · ultralytics/yolov5 · GitHub,进入如下界面 滚动滑轮大概在界面的中部位置,点击箭头所指区域 进入如下界面 滑动滚轮到页面底部,下载我们的预训练模型yolov5s.pt 然后就是开始我们的yolov5的简单训练了,这里我参考的是这篇博客,这位博主写的很好,对小白很友好小白YOLOv5全流程-训练+实现数字识别_yolov5数字识别_牛大了2022的博客-CSDN博客 当然了,我们因为选择了不同的版本,会出现一点小的问题,这里我也记录了下来。 1、这里一定要采用单引号,否则就会报出这个错误ValueError: too many dimensions ‘str‘ 2、当出现OSError: [WinError 1455] 页面文件太小,无法完成操作,一般是要去给Anaconda所在的盘符分配一定的虚拟内存,同时把train.py里的'--batch-size'选项调小,我是轻薄本,于是就改成了4,虚拟内存分配了50G,此外,如果多次输出这个错误的话,就尽量不要用python终端去执行命令了,直接修改train.py里面的参数,然后运行train.py 3、当出现如下错误的时候,不要慌张,可以把所有的np.int修改成np.int_即可 4、如果以上错误都解决了的话,已经开始训练了,结果出现下面的错误 这样的话,就要进入loss.py函数,修改两个地方,第一个地方: for i in range(self.nl): anchors = self.anchors[i] 改为如下所示: for i in range(self.nl): anchors, shape = self.anchors[i], p[i].shape 第二个地方: indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1))) # image, anchor, grid 改为:

2023《操作系统原理》实习一(实习中进行过的操作以及遇到的问题)

目录 实习题目 软件准备 VirtualBox安装 题目一 Windows11安装 Ubuntu安装 题目二 题目三 题目三已经提前发布了,操作流程在该链接中 在此提出几个最近常被问到的问题和解决办法: 1.编辑完成后启动时内核崩溃显示类似如下界面: 2.串口输出日志为空 题目四 实习题目 1、在一台机器上(真机或虚拟机)安装ubuntu和windows双系统。 2、练习linux常用命令,在报告中简述不少于20个命令的作用及示例。 3、通过在Grub中修改Ubuntu内核启动参数,获取Ubuntu启动日志,在Ubuntu的系统初始化一开始输出:操作系统原理实习一-班学号-姓名。 4、增加系统功能调用sys_syscall_XXXXXXX并建立简单用户程序进行调用测试,在内核日志中输出:操作系统原理实习一-班学号-姓名。XXXXXXX为班学号 软件准备 实习之前需要准备虚拟机,以及windows和ubuntu各一个镜像文件。毕竟这么一个看上去就容易崩系统的课设,还是不要折腾自己的电脑了。 老师提供了如下软件下载链接: VirtualBox: Downloads – Oracle VM VirtualBox VMWare:VMware Workstation 17 Player 中文版-官方免费版虚拟机软件丨简而易网 Ubuntu:Enterprise Open Source and Linux | Ubuntu Windows11:Download Windows 11 (下载ISO) Windows10:下载 Windows 10(先下载MediaCreationTool22H2.exe,再选择为另一台电脑创建安装介质,即可获得ISO) 就我个人而言,电脑上一直是有装VM的,里面有一个ubuntu18。但是我对它的印象一直是:软件很大、有时报错重装、功能复杂(可能是第一次使用时啥也不会,带来的痛苦回忆)。所以很久没用了,依稀记得最后一次使用时候有个网络问题没解决。然后我简单了解了一下VirtualBox,发现这个软件令人惊喜的小。启动也很快,直接就是一个更换阵地的操作。 VirtualBox安装 点击链接进入官网之后就是这个界面: 最好还是不要使用自动翻译,不然容易导致自己不认识,点击画出来的链接就是下载windows使用的版本。同样的,它下面则是其它平台使用的版本。 下载好后就打开开始安装: 接下来的步骤基本用不着调整,除了调整默认安装位置。当时安装的时候没截图,这里偷个懒,借用一下其它博客的图片: 原文链接:VirtualBox的下载与安装_virtualbox下载教程_角落遗失的眼泪的博客-CSDN博客 由于这个博客所用的VB比较老,界面有所差别。调整的话就是点浏览(Browse)然后将地址前面的C改成你想存到的盘,比如D:\Program Files\Oracle\VirtualBox\。 安装完成后可以参考以下步骤对虚拟机文件夹所在位置进行调整 原文链接:虚拟机VirtualBox下载与安装、安装Ubuntu超详细图文步骤,对一些配置问题也有所写。_virtualbox安装_橙木博客的博客-CSDN博客 题目一 题目要求装双系统,因为我本来电脑上装了个Ubuntu虚拟机,所以第一时间想到的是搜搜怎么在Ubuntu上装Windows,但是搜完之后一是博客少,而且看上去超级难,就罢了,在此放一篇Ubuntu上装windows的博客: [详细教程] 在现有Ubuntu系统上安装Windows 10 (双系统)_ubuntu安装windows_宇内虹游的博客-CSDN博客 Windows11安装 从官网上可以直接下载windows11的镜像文件,链接在上面有给(但是是真的慢,可以考虑从别的途径下载)。有了镜像文件之后,打开virtualbox新建 名字自己随意定一个就可以,ISO Image那里选你下载好的win11镜像文件 ,把下面的skip我几次建虚拟机都是直接选上了,省些步骤,目前没发现什么问题。然后next

ACL的基本原理与配置

目录 一、ACL概述1.ACL的工作原理 二、ACL的组成1.规则编号2.通配符 二、ACL的分类与标签三、基本ACL与高级ACL四、ACL的匹配机制五、ACL的匹配顺序及匹配结果1.ACL的匹配位置2.入站(Inbound)及出站(Outbound)方向 六、ACL的实验配置 一、ACL概述 ACL,中文名称是“访问控制列表”,它由一系列规则(即描述报文匹配条件的判断语句)组成。这些条件通常被称为五元组-分别是报文的源地址、目的地址、源端口、目的端口、端口号等。这样解释ACL,大大家肯定听不懂,那么我打个比喻,ACL相当于一个过滤器,ACL规则就是过滤器的滤芯,安装什么样的滤芯(即根据报文特征匹配的一系列ACL规则),ACL就能过滤出什么样的报文了。 ACL是由一系列permit或deny语句组成的、有序规则的列表。ACL是一个匹配工具,能够对报文进行匹配和区分。 1.ACL的工作原理 ACL的工作原理:当数据包从接口经过时,由于接口启用了ACL,此时路由器会对报文进行检查,然后做出相应的处理。 二、ACL的组成 ACL由若干条permit或deny语句组成。每条语句就是该ACL的一条规则,每条语句中的permit或deny就是与这条规则相对应的处理动作。 1.规则编号 2.通配符 子网掩码:1的含义是精确匹配,0的含义是忽略匹配通配符掩码:1的含义是忽略匹配,0的含义是精确匹配 二、ACL的分类与标签 三、基本ACL与高级ACL 四、ACL的匹配机制 五、ACL的匹配顺序及匹配结果 配置顺序(config模式) 1.ACL的匹配位置 ACL在接口上的应用: 在入口上:数据包从入口进路由器,就会被路由器处理。 在出口上:数据包在经过路由器处理后,才会让它从出口出去。 ACL的应用原则: 基本ACL,尽量用在靠近目的点。 高级ACL,尽量用在靠近源的地方。 应用规则 1、一个接口的同一个方向,只能调用一个ACL 2、一个ACI里面可以有多个rule规则,按照规则ID从小到大排序,从上往下依次执行 3、数据包一旦被某rule匹配,就不再继续向下匹配 4、用来做数据包访问控制时,默认隐含放过所有(华为设备) 2.入站(Inbound)及出站(Outbound)方向 有测匹配,无则放行接口响应配置,要被调用 六、ACL的实验配置 一、实现第一个目标:仅允许PC1访问192.168.2.0/24网络(即仅允许PC1访问PC3) <Huawei>sys [Huawei]sysname AR1 [AR1]int g0/0/0 [AR1-GigabitEthernet0/0/0]ip address 192.168.1.254 24 [AR1-GigabitEthernet0/0/0]int g0/0/1 [AR1-GigabitEthernet0/0/1]ip address 192.168.3.254 24 [AR1-GigabitEthernet0/0/1]int g0/0/2 [AR1-GigabitEthernet0/0/2]ip address 192.168.2.254 24 [AR1-GigabitEthernet0/0/2]q [AR1]acl 2000 [AR1-acl-basic-2000]rule permit source 192.168.1.10 0 [AR1-acl-basic-2000]rule deny [AR1-acl-basic-2000]q [AR1]int g0/0/2 [AR1-GigabitEthernet0/0/2]traffic-filter outbound acl 2000 [AR1-GigabitEthernet0/0/2]q 1、配置路由器R1

Kubernetes中配置livenessProbe、readinessProbe和startupProbe

livenessProbe、readinessProbe和startupProbe作用 kubelet使用livenessProbe(存活探针)来判断何时重启容器。例如,当程序中产生死锁的时候,程序还在运行,通过livenessProbe可以检测到程序已不能正常提供服务。这种情况下重启容器可以让程序恢复可用的状态(虽然程序中存在会导致死锁的bug)。如果没有配置livenessProbe,则默认状态为Success。 kubelet使用readinessProbe(就绪探针)来判断容器何时准备好了接受流量。当Pod中的所有容器都准备好时,Pod就被认为准备好了。最重要的用途是用来控制哪些pod被用作服务的后端。当一个Pod未准备好时,在负载均衡中会被移除。如果没有配置readinessProbe,则默认状态为Success。 Kubernetes从1.17版本开始新增了startupProbe(启动探针),kubelet使用startupProbe来判断容器应用程序何时启动。如果配置了startupProbe,等启动成功后才会进行livenessProbe和readinessProbe。这样可以避免应用程序在启动过程被livenessProbe和readinessProbe影响。如果没有配置startupProbe,则默认状态为Success。 k8s中的四种健康检查方式 livenessProbe、readinessProbe和startupProbe都可以称为健康检查,这几种健康检查类型都支持四种检查方式:exec命令、httpGet、tcpSocket和grpc。其中exec命令行方式通用性最强,适用于大部分场景,tcpSocket方式适用于TCP类型的服务,httpGet方式适用于http类型的服务,grpc方式适用于grpc类型的服务。 exec:可以将自定义的健康检查方法封装成命令行(CLI)工具使用exec来执行,如果检测结果是正常,命令行返回0值,否则返回非0值。 httpGet:通过容器的IP地址、端口及服务提供的http接口路径,发起一个HTTP Get请求,如果响应的状态码大于等于200且小于400,则认为服务是健康的。 tcpSocket:通过容器的IP地址和端口,发起一个tcp请求,能建立连接则认为服务是健康的。 grpc:通过容器的IP地址和端口,发起一个grpc请求(前提是服务实现了grpc健康检查协议),返回服务健康的结果正常则认为服务是健康的。 配置探针的常用可选参数如下: 参数名称 默认值 最小值 描述 initialDelaySeconds 0秒 0秒 容器启动后多久开始进行第一次探测。 periodSeconds 10秒 1秒 探测频度,频率过高会对pod带来较大的额外开销,频率过低则无法及时反映容器真实情况。 timeoutSeconds 1秒 1秒 探测超时时间。 failureThreshold 3 1 处于成功状态时,探测连续失败几次可被认为失败。 successThreshold 1 1 处于失败状态时,探测连续成功几次,被认为成功。 配置示例 livenessProbe、readinessProbe和startupProbe的配置方法基本类似,下面就以配置livenessProbe为例。 exec方式 apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-exec spec: containers: - name: liveness image: registry.k8s.io/busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600 livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5 httpGet方式

假设二叉树采用二叉链表存储结构,试设计一个算法求二叉树的叶子结点数,总结点数和二叉树的高度。

#include <stdio.h> #include <stdlib.h> typedef struct Bitnode //定义二叉树 { char data; struct Bitnode *lchild,*rchild; }Bitnode,*Bitree; void createBitree(Bitree &T) //创建二叉树 { char ch; ch=getchar(); if(ch==' ') T=NULL; else { T=(Bitree)malloc(sizeof(Bitnode)); T->data=ch; createBitree(T->lchild); createBitree(T->rchild); } } int high(Bitree T) //求二叉树高度函数 { int h,h1,h2; if(!T) h=0; else if(!T->lchild&&!T->rchild) h=1; else { h1=high(T->lchild); h2=high(T->rchild); h=(h1>h2?h1:h2)+1; } return h; } int leaf(Bitree T) //求叶子结点个数函数 { int l,lc,rc; if(!T) l=0; else if(!T->lchild&&!T->rchild) l=1; else {

15、正则表达式

目录 一、元字符 二、限定修饰符 一、元字符 正则表达式通常被用于判断语句中,用来检查某一字符串是否满足某一格式。正则表达式是含有一些具有特殊意义字符的字符串,这些特殊字符称为正则表达式的元字符。例如,“\\d”表示数字0~9中的任何一个,“\d”就是元字符。正则表达式中元字符及其意义如 注意:在正则表达式中“.”代表任何一个字符,因此在正则表达式中如果想使用普通意义的点字符“.”,必须使用转义字符“\”。 在正则表达式中可以使用方括号括起若干个字符来表示一个元字符,该元字符可代表方括号中的任何一个字符。例如,reg = "[abc]4",这样字符串a4、b4、c4都是和正则表达式匹配的字符串。方括号元字符还可以为其他格式。如: [^456]:代表4、5、6之外的任何字符。[a-r]:代表a~r中的任何一个字母。[a-zA-Z]:可表示任意一个英文字母。[a-e[g-z]]:代表a~e或g~z中的任何一个字母(并运算)。[a-o&&[def]]:代表字母d、e、f(交运算)。[a-d&&[^bc]]:代表字母a、d(差运算)。 二、限定修饰符 在正则表达式中允许使用限定修饰符来限定元字符出现的次数。例如,“A*”代表A可在字符串中出现0次或多次。限定修饰符的用法如表 例:在项目中创建类Judge,在主方法中实现使用正则表达式来判断指定的变量是否为合法的E-mail地址 public class Judge { public static void main(String[]args) { //定义要匹配E-mail地址的正则表达式 String regex="\\w+@\\w+(\\.\\w{2,3})*\\.\\w{2,}"; String s1="aaa@"; //定义要进行验证的字符串 String s2="aaaaa"; String s3="1111@111ffyu.dfg.com"; if(s1.matches(regex)) { //判断字符串变量是否与正则表达式匹配 System.out.println(s1+"是一个合法的E-mail地址格式"); } if(s2.matches(regex)) { //判断字符串变量是否与正则表达式匹配 System.out.println(s2+"是一个合法的E-mail地址格式"); } if(s3.matches(regex)) { //判断字符串变量是否与正则表达式匹配 System.out.println(s3+"是一个合法的E-mail地址格式"); } } } 运行结果 上面例子正则表达式分析: 通常情况下E-mail的格式为“X@X.com.cn”。字符X表示任意的一个或多个字符,@为E-mail地址中的特有符号,符号@后还有一个或多个字符,之后是字符“.com”,也可能后面还有类似“.cn”的标记。总结E-mail地址的这些特点,因此可以书写正则表达式“\\w+@\\w+(\\.\\w{2,3})*\\.\\w{2,3}”来匹配E-mail地址。字符集“\\w”匹配任意字符,符号“+”表示字符可以出现1次或多次,表达式“(\\.\\w{2,3})*”表示形如“.com”格式的字符串可以出现0次或多次。而最后的表达式“\\.\\w{2,3}”用于匹配E-mail地址中的结尾字符,如“.com”。

STM32使用SPI+DMA(标准库)

DMA DMA原理 DMA通道资源分配 SPI+DMA配置 主函数编写如下 DMA原理 1.CPU配置好DMA。 2.SPI发出DMA请求。(在DMA_Mode_Normal模式下,该请求实际上需要CPU命令SPI发出请求) 3.若该通道有多个请求,DMA控制器通过仲裁器判断,根据配置的优先级,选择先回应该通道高优先级的请求,再回应低优先级的请求。(此过程不需要CPU参与) 4.DMA控制器回应请求后,自动根据配置,进行数据传输。(此过程不需要CPU参与) DMA请求CPU释放总线,当DMA传输完成后,DMA归还总线给CPU DMA通道资源分配 DMA1通道 DMA2通道 SPI+DMA配置 既然使用的是SPI+DMA,必定要使能SPI,详细请参考 SPI配置 配置完SPI后,配置DMA,如下 void dma_init(unsigned int SendBuff,unsigned int buffer_size) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); DMA_DeInit(DMA1_Channel3); /*DMA配置*/ DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR; //SPI数据寄存器地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuff; //内存地址(要传输的变量的指针) DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //方向(从内存到外设) //DMA_DIR_PeripheralSRC为从外设到内存 DMA_InitStructure.DMA_BufferSize = buffer_size; //传输内容的大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址自增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte ; //外设数据单位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte ; //内存数据单位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //DMA模式:一次传输 DMA_InitStructure.

FFmpeg解码的软解及硬解(cuda和qsv)使用方法

本次使用的ffmpeg版本是4.2,解码的调用方式为: int32_t iRet = -1; // 最后一个包解码完成后,需要取完解码器中剩余的缓存帧; // 调用avcodec_send_packet时塞空包进去,; // 解码器就会知道所有包解码完成,再调用avcodec_receive_frame时,将会取出缓存帧; // AVPacket packet; // av_init_packet(&packet); // pkt.data = NULL; // pkt.size = 0; // avcodec_send_packet(ctx, pkt); iRet = avcodec_send_packet(ctx, pkt); if (iRet != 0 && iRet != AVERROR(EAGAIN)) { get_ffmepg_err_str(iRet); if (iRet == AVERROR_EOF) iRet = 0; return iRet; } while (true) { // 每解出来一帧,丢到队列中; iRet = avcodec_receive_frame(ctx, frame); if (iRet != 0) { if (iRet == AVERROR(EAGAIN)) {

视觉学习笔记4——学习研究ORB-SLAM3

文章目录 一、ORB-SLAM3是什么?二、配置安装ORB-SLAM31.运行环境2.配置Pangolin环境3.配置opencv 环境4.配置Eigen3环境4.配置boost环境4.配置DBoW2 和 g2o环境5.安装编译OBR-SLAM3 1.0版本6.安装编译ROS 三、OBR-SLAM3与ROS调试1.使用ROS usb_cam调用USB摄像头2.初试ORB-SLAM3 1.0版本3.转战OBR-SLAM3 0.3版本4.ORB-SLAM3 0.3版本运行单目USB摄像头5.再战ORB-SLAM3 1.0版本6.ORB-SLAM3 1.0版本运行单目USB摄像头7.ORB-SLAM3 1.0版本运行双目摄像头8.双目参数标定 一、ORB-SLAM3是什么? ORB-SLAM3是第一个能够让单目、立体和RGB-D相机和针孔和鱼眼镜头模型解耦进行视觉、视觉惯性和多地图SLAM的系统。第一个主要的创新是一个基于特征的紧密集成视觉惯性SLAM系统,它完全依赖于最大后验概率(MAP)估计,甚至在IMU初始化阶段也是如此。第二个主要的创新是一个多地图系统,它依赖于一种新的位置识别方法和改进的召回。多亏了它,ORB-SLAM3能够在长时间的不良视觉信息下生存:当它丢失时,它会启动一个新的地图,当重新访问地图区域时,它将与以前的地图无缝地合并。与只使用最后几秒信息的视觉里程计系统相比,ORB-SLAM3也是第一个能够在所有算法阶段重用所有先前信息的系统。这允许在BA优化中使用历史的共视关键帧,即使这些关键帧来自很久以前的地图或者不同子图。该系统在小型和大型,室内和室外环境中都能稳定地运行,并且比以前的方法精确2到5倍。 开源地址 论文地址 二、配置安装ORB-SLAM3 1.运行环境 i7GTX 1660 TIubuntu18.04 2.配置Pangolin环境 查看ORB-SLAM3的项目要求,要求安装Pangolin 1. 安装Pangolin所需要的依赖 查了一下其他大佬的方法 终端逐条运行以下命令: sudo apt install libgl1-mesa-dev sudo apt install libglew-dev CMake sudo apt install cmake sudo apt install libpython2.7-dev sudo apt install pkg-config sudo apt install libegl1-mesa-dev libwayland-dev libxkbcommon-dev wayland-protocols sudo apt-get install cmake libeigen3-dev libsuitesparse-dev qtdeclarative5-dev qt5-qmake libqglviewer-dev sudo apt-get install libboost-dev

如何学习计算机视觉?初学者怎么入门?

学习计算机视觉需要一定的数学、编程和机器学习基础。以下是一些学习计算机视觉的步骤和资源: 如何学习计算机视觉?初学者怎么入门? 学习编程语言:计算机视觉的主要编程语言包括Python和C++。可以学习Python或C++编程,掌握基本语法和编程思想。 学习数学基础:计算机视觉需要用到很多数学知识,例如线性代数、微积分、概率论和统计学等。可以先学习一些基础的数学知识,为后续学习打好基础。 学习机器学习:机器学习是计算机视觉的重要组成部分。可以学习机器学习的基本概念、算法和实践技巧。 学习计算机视觉基础:可以学习计算机视觉的基本概念、原理和算法,例如图像处理、特征提取、目标检测、物体识别等。 实践项目:可以找一些计算机视觉的实践项目,例如图像分类、目标检测、人脸识别等,通过实践提升自己的技能和经验。 以下是一些学习计算机视觉的资源: 在线课程:有很多在线课程可以学习计算机视觉,例如Coursera、Udacity和edX等。 书籍:有很多经典的计算机视觉书籍,例如《计算机视觉:算法与应用》、《Python计算机视觉编程》等。 开源项目:有很多计算机视觉的开源项目,例如OpenCV、TensorFlow和PyTorch等,可以通过这些项目学习计算机视觉的实践技能。 社区论坛:可以加入一些计算机视觉的社区论坛,例如GitHub和Stack Overflow等,与其他开发者交流经验和技能。 免费分享一些我整理的人工智能学习资料给大家,整理了很久,非常全面。包括一些人工智能基础入门视频+AI常用框架实战视频、计算机视觉、机器学习、图像识别、NLP、OpenCV、YOLO、pytorch、深度学习与神经网络等视频、课件源码、国内外知名精华资源、AI热门论文等。 下面是部分截图,点击文末名片关注我的公众号【AI技术星球】发送暗号 321 领取(一定要发暗号 321) 目录 一、人工智能免费视频课程和项目 二、人工智能必读书籍 三、人工智能论文合集 四、机器学习+计算机视觉基础算法教程 五、深度学习机器学习速查表(共26张) 学好人工智能,要多看书,多动手,多实践,要想提高自己的水平,一定要学会沉下心来慢慢的系统学习,最终才能有所收获。 点击下方名片,扫码关注公众号【AI技术星球】发送暗号 321 免费领取文中资料。

ESP8266连接OneNet服务器

配置ESP8266为客户端,连接公网,连接上OneNet服务器,通过MQTT协议与服务器进行交互。 一 准备工作 OneNet平台上创建自己的产品设备信息。 对MQTT协议进行一定了解。 准备一块ESP8266,通过串口进行ESP8266的配置。 二 配置ESP8266 1.AT 验证硬件是否正常 硬件正常返回:AT OK 2.AT+RST 模块复位 3.AT+CWMODE=3 设置模块工作在AP和STA模式 返回:AT+CWMODE=3 OK 4.AT+CWSAP="ESP8266","1234567890",1,4 设置AP模式下SSID(WIFI)为ESP8266密码1234567890通道为1,加密方式4 返回:AT+CWSAP="ESP8266","1234567890",1,4 OK 5.AT+CWLAP 搜索当前可链接的WIFI信息 返回:AT+CWLAP +CWLAP:(3,"HUAWEI-0400CQ",-42,"94:e4:ba:a5:a3:0c",1,-16,0) +CWLAP:(4,"TP-LINK_2.4G_C62E",-78,"d0:76:e7:4a:c6:2e",11,-29,0) +CWLAP:(4,"ChinaNet-V5e6",-57,"ec:f0:fe:4e:b2:f8",4,-14,0) +CWLAP:(3,"NVR9ca3a910d32c",-51,"9c:a3:a9:10:d3:2c",14,-27,0) OK 6.AT+CWJAP="TP-LINK_2.4G_C62E","plht12345" 作为客户端时,去连接的SSID(WIFI)名称为TP-LINK_2.4G_C62E去连接的wifi密码为plht12345 返回:WIFI CONNECTED WIFI GOT IP OK 7.AT+CIPSTA? 连接WIFI成功后的IP地址 返回:AT+CIPSTA? +CIPSTA:ip:"192.168.1.108" +CIPSTA:gateway:"192.168.1.1" +CIPSTA:netmask:"255.255.255.0" OK 8.AT+CIPSTART="TCP","183.230.40.39",6002 在连接wifi成功后,去连接连接OneNet服务器,183.230.40.39为服务器地址,6002为服务器端口号 返回:AT+CIPSTART="TCP","183.230.40.39",6002 CONNECT OK 9.AT+CIPMODE=1 设置为透传模式,发送AT+CIPSEND则可开始透传,发送+++不发送回车换行然后发AT+CIPMODE=0,则可退出透传 10.AT+CWJAP? 当前连接的WIFI信息 三 与服务器进行交互 OneNet相关信息,使用时需用自己对应的注册信息。 产品名称:ESP8266 产品ID:571548 接入协议:MQTT 设备ID:1048790685 鉴权信息:esp8266 数据流名称:temp 连接服务器 1.Commect: 10 27 00 04 4D 51 54 54 04 C2 00 78 00 0A 31 30 34 38 37 39 30 36 38 35 00 06 35 37 31 35 34 38 00 07 65 73 70 38 32 36 36

JDK动态代理

JDK动态代理 反射JDK动态代理接口:InvocationHandler类:Proxy示例 反射 反射指计算机程序在运行时(runtime)可以访问、检测和修改它本身状态或行为的一种能力。[1]用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为。 —来自《维基百科》 在java 中,我们能够观察和修改的内容,大致可以分成三类:类(Class)、方法(Method)、参数(args) Method method; // 用于结合理解InvocationHandler method.invoke(Class, args); JDK动态代理 接口:InvocationHandler // 接口内容:仅声明了一个invoke方法。 // 方法签名中存在三个参数,第二三个对应反射中所提到的:方法,参数 public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; } 类:Proxy public class Proxy implements java.io.Serializable { protected InvocationHandler h; // interfaces:指定了需要代理的方法 // h:赋值给成员变量h public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) { ... } } 示例 public interface Age { void age(Integer age); } public interface Animal { void type(); void sex(String sex); } public class Dog implements Animal, Age{ public void type() { System.

计算机网络中的原码、反码、补码

写在前面 原码、反码、补码是计算机组成原理中的概念,是计算机网络的基础知识之一。这些概念是为了处理二进制数的符号位而引入的,常用于计算机中的整数运算,也常用于数据存储和传输等领域。因此,了解和掌握这些概念对于理解计算机网络和计算机组成原理都是非常重要的。 目录 写在前面 初步认识 发展历程 为什么要使用 有什么作用 如何计算 原码、反码、补码 例题 初步认识 在计算机中,整数通常使用原码、反码和补码表示。这三种表示方式都是用二进制位表示数字,但有不同的规则来表示正负号。 原码(sign-magnitude representation):最高位表示符号位,0表示正数,1表示负数,其余位表示数值大小。例如,+5的原码是00000101,-5的原码是10000101。 反码(ones' complement):正数的反码和原码相同,负数的反码是将原码中除符号位外的所有位按位取反。例如,+5的反码是00000101,-5的反码是11111010。 补码(two's complement):正数的补码和原码相同,负数的补码是将原码中除符号位外的所有位按位取反后加1。例如,+5的补码是00000101,-5的补码是11111011。 补码表示法是计算机中最常用的表示带符号整数的方式,其好处是可以用同一种方式进行加减运算,且减法可以转换成加法。例如,5-3可以转换成5+(-3),即00000101+11111101=00000010。此外,补码可以用来表示0,而原码和反码都会出现两个0的情况,分别对应+0和-0。 发展历程 在计算机的发展过程中,原码、反码和补码的概念逐渐形成和发展。 最早的计算机采用的是原码表示带符号数,即用二进制的最高位表示符号位,0表示正数,1表示负数。但是原码表示法存在着两个0的表示,即正数的0和负数的0。 为了解决这个问题,人们又发明了反码表示法。反码表示法是将负数的符号位不变,其他位按位取反,这样便能够解决正数和负数0的问题。但是反码表示法存在着减法运算的问题,即在进行减法运算时需要将被减数的符号位取反再加上减数的符号位。 后来,人们又发明了补码表示法。补码表示法是将负数的符号位不变,其他位按位取反再加1,这样既解决了0的问题,也能够解决减法运算的问题,因此成为了计算机中最常用的带符号整数表示法。 总的来说,原码、反码和补码是带符号整数的三种不同表示方法,随着计算机的发展,补码表示法逐渐成为了计算机中最常用的带符号整数表示法。 为什么要使用 计算机使用原码、反码和补码来表示带符号整数,主要是因为计算机中的运算是基于补码进行的。 在计算机中,加法和减法都是通过对二进制数的补码进行运算来实现的,这样可以将加法和减法转化为相同的运算。同时,补码的表示范围与原码相同,而且可以避免原码的符号位运算问题,使得运算更加方便。 另外,补码还有一个特点,就是它只有一个零,而原码和反码有正零和负零之分,这样会给计算带来很多问题,例如在比较大小时需要进行特殊的处理。而补码只有一个零,可以避免这些问题。 因此,使用原码、反码和补码可以使计算机进行带符号整数的运算更加方便、准确和统一,避免了很多计算问题。 有什么作用 常见的有符号整数表示方法包括原码、反码和补码。 1. 原码是一种最基本的数值表示方法,用于表示有符号的整数。在原码中,数值的最高位用于表示符号,0表示正数,1表示负数。例如,+7的原码为0000111,-7的原码为1000111。原码的表示方法最直观,计算机也最容易实现,但是它存在一些缺陷,主要体现在以下几个方面: 加减法不方便:在原码中,加减法需要分别考虑符号位和数值部分,这样计算起来比较繁琐。例如,对于+7和-5进行相加,需要先将它们的符号位进行运算,然后再对它们的数值部分进行运算,最终得到的结果为+2,其计算过程为:0000111 + 1000101 = 1001100,即7 - 5 = 2。0有两种表示方法:在原码中,0既可以表示为0000000,也可以表示为1000000。这种情况下,计算机在进行运算时需要特殊处理,否则会导致运算结果错误。为了解决原码存在的问题,人们提出了反码和补码的概念。 2. 反码是一种表示带符号整数的方式,它是在原码的基础上进行改进的。与原码相同的是,反码的二进制数最高位仍然用来表示符号,0表示正数,1表示负数。但是,对于负数的表示,反码做了一些特殊处理。 具体来说,正数的反码与原码相同。例如,+5的原码和反码都是00000101。但是,对于负数,反码是符号位不变,其余各位取反。例如,-5的原码是10000101,那么它的反码就是11111010。 反码的加减法只需要进行二进制的加法即可。例如,计算+3-2,可以将3和2的反码相加,再将结果取反得到最终的反码。具体过程如下: +3的反码:00000011 -2的反码:11111101 相加得到:00000010 取反得到:11111101 所以,+3-2的结果的反码为11111101,对应的十进制数是-1。 反码的缺点是0还是有两种表示方法,分别是00000000和11111111。这是因为在原码中,0的符号位为0,在反码中,0的符号位为1,其余各位为0。因此,正零的反码为00000000,负零的反码为11111111。这种情况在计算机中可能会引起混淆,因此出现了补码的表示方式,它能够避免这个问题。 3. 补码是在反码的基础上进行了改进,主要解决了反码的问题,如反码的加减法中出现的溢出问题。补码的加减法与二进制的加减法是一致的,不需要考虑符号位。正数的补码和原码相同,负数的补码是其反码加1。 举个例子,假设要将数-5表示为补码形式。首先,将-5的绝对值表示为二进制形式,即0101,然后将其按位取反得到反码1010,最后将反码加1得到补码1011。因此,-5的补码为1011。 在计算机中,补码广泛应用于计算机算术运算和数据存储中。由于补码的加减法和二进制的加减法一致,可以方便地实现算术运算。此外,使用补码还可以避免0的两种表示方法,简化了计算机的处理。 总的来说,原码、反码和补码都是计算机中用于表示有符号整数的方法。它们的区别在于对于负数的表示方式不同,以及0的表示方法的差异。 原码是最简单的表示方法,使用二进制数的最高位表示符号。正数的原码和二进制数相同,负数的原码是其绝对值的二进制表示在最高位加上符号位1。原码的缺点是加减法不方便,需要单独考虑符号位,而且0有两种表示方法。 反码在原码的基础上改进,正数的反码和原码相同,负数的反码是符号位不变,其余各位取反。反码的加减法只需要进行二进制的加法即可,但是0还是有两种表示方法。 补码在反码的基础上进一步改进,正数的补码和原码相同,负数的补码是其反码加1。补码的加减法可以直接进行二进制的加法,且0只有一种表示方法,因此补码被广泛应用于计算机中。 在计算机中,一般使用补码表示有符号整数。因为补码具有很好的加减法性质和唯一的0表示方法,同时还能够方便地进行位运算和处理溢出等问题。 如何计算 原码、反码、补码 在计算机中的数据通常都是用二进制位来存储,其中的0和1都是比特,8个比特可以组成一个字节,一个字节可以表示256种不同的状态,可以用来表示整数、字符等数据类型。而原码、反码、补码,就是带有符号的整数。与字节有着密不可分的关系。 在计算之前我们先要学习进制转换 2的零次方=1,2的一次方=2,2的二次方=4,2的三次方=8,2的四次方=16,2的五次方=32,2的六次方=64,2的七次方=128, 00000000 ——对应上面的次方

C语言定义的数据类型/声明内容的理解(int *p[]与int (*p)[])

前言 本文主要涵盖了以下三部分的内容: C语言中的运算优先级. C语言中的声明优先级 C语言下怎么理解声明内容. 本文是一些我自己关于C语言定义的数据类型的理解,希望能解开C语言初学者对于一些较复杂的数据类型(如int *p[] , int (*p)[])等内容的一些疑惑。 一、了解C语言的运算符优先级 如果一个表达式中的两个操作数具有相同的优先级,那么它们的结合律(associativity)决定它们的组合方式是从左到右或是从右到左。 优先级 运算符 结合律 1 后缀运算符:[] () · -> ++ --(类型名称){列表} 从左到右 2 一元运算符:++ -- ! ~ + - (正负号) * & sizeof_Alignof 从右到左 3 类型转换运算符:(类型名称) 从右到左 4 乘除法运算符:* / % 从左到右 5 加减法运算符:+ - 从左到右 6 移位运算符:<< >> 从左到右 7 关系运算符:<<= >>= 从左到右 8 相等运算符:== != 从左到右 9 位运算符 AND:& 从左到右 10 位运算符 XOR:^ 从左到右 11 位运算符 OR:|

清理bib文件(删除重复项,仅保留tex中引用的条目)

在写latex文件的过程中,经常会遇到添加了一堆文献的bibtex到bib文件中,有时候文章一长同一篇文献用不同的cite-key引用了多次,同时也会有一些文献最后并没被正文引用,这就需要对bib文件进行清理。 删除重复项 可以用JabRef 在JabRef中打开需要处理的bib文件在"Quality"中选择“Find Duplicates” 根据弹出来的界面选择吧 Mac上可以用BibDesk直接打开要处理的bib,cite-key重复的条目会直接标红,删除不想要的即可,但是如果是像删除内容一样但是cite-key不一样的,bibdesk不算很方便(也可能是我自己没发掘出来这个功能),我一般选择将cite-key重复的删除之后,再按照标题按序排列,人工扫一遍 只保留tex中引用的条目 可以用JabRef 打开需要处理的bib文件在"Tools"中找到"New sublibrary based on AUX file" Browse加载bib对应文档的aux文件,如main.tex对应的main.aux,加载后点Parse,如图 点击"Generate",此时JabRef中会出现一个untitled的文件,左上角保存即可 也可以用bibexport在命令行中直接生成想要的bib bibexport -o extracted.bib main.aux 但是我没运行成功,命令行一直显示bibexport不是内部或者外部命令 参考链接 Creating .bib file containing only the cited references of a bigger .bib file 【LaTeX小技巧01】将论文引用的文献导出到单独的.bib文件

RFID高频读写器在STM32中的应用

文章目录 一、RFID简述二、产品参数及硬件连接三、模块测试四、RFID读写操作五、项目源码 一、RFID简述 RFID是Radio Frequency Identification的缩写,是一种无接触自动识别技术,利用射频信号及其空间耦合传输特性,实现对静止的或移动中的待识别物品的自动识别 。RFID系统则由两个部分组成,即电子标签和阅读器。 阅读器是将标签中的信息读出,或将标签所需要存储的信息写入标签的装置。根据使用的结构和技术不同,阅读器可以是读/写装置,是RFID系统信息控制和处理中心。阅读器 (问答器) 可放置在一固定地点,如:入口/出口,销售网点、仓库、货栈、大商场;阅读器同样可在移动的范围中使用。 电子标签由收发天线、AC/DC电路、解调电路、逻辑控制电路、存储器和调制电路组成。分为无源电子标签-passive tag,对应无源RFID系统;半无源电子标签-semi-passive tag,对应于半无源RFID系统;有源电子标签—active tag,对应于有源RFID系统; 工作原理 RFID技术的基本工作原理并不复杂:在标签进入磁场后,接收解读器发出的射频信号,凭借感应电流所获得的能量发送出存储在芯片中的产品信息,或者主动发送某一频率的信号;解读器读取信息并解码后,发送至中央信息系统进行有关数据处理。 一套完整的RFID系统,是由阅读器与电子标签也就是所谓的应答器及应用软件系统三个部份所组成,其工作原理是阅读器发射一特定频率的无线电波能量给应答器,用以驱动应答器电路将内部的数据送出,此时阅读器便依序接收解读数据,送给应用程序做相应的处理。 以RFID卡片阅读器及电子标签之间的通讯及能量感应方式来看大致上可以分成,感应偶合(InductiveCoupling)及后向散射偶合(BackscatterCoupling)两种,一般低频的RFID大都采用第一种式。 RFID主要应用领域: 门禁、考勤控制现代物流交通领域产品装配线身份识别… 二、产品参数及硬件连接 与单片机直接连接采用UART TTL接口,模块的TXD引脚接单片机RXD引脚,模块的RXD引脚接单片机TXD引脚,GND与单片机的GND相连形成共地,需3.3-5V电源给模块供电。 三、模块测试 四、RFID读写操作 本篇对RFID模块的应用为:通过串口俩者进行通信,由开发板通过串口发送指定指令读取到 卡片ID号,并将卡片号显示在oled显示屏上,然后通过向RFID模块发送 写入块命令,将指定数据写入缓存区中,再向RFID模块发送读块命令,将缓存区中的数据读出来,一并显示在液晶显示屏上。 读IC卡ID号(卡号) //ReadId():读IC卡ID号(卡号) //参数:*idout,读取的卡号保存到它所指向的存储空间 //返回值:0:成功读取卡号,1:读卡号失败 unsigned char ReadId(unsigned char *idout) { unsigned char status; unsigned char i; Cmd_Read_Id[5] = 0x01;//开启蜂鸣器提示 //Cmd_Read_Id[5] = 0x00;//关闭蜂鸣器提示 TxCheckSum(Cmd_Read_Id,Cmd_Read_Id[1]); //计算校验和 Uart2_Send_Data(Cmd_Read_Id,Cmd_Read_Id[1]); //发送读卡号ID命令 Delay(1600000);//等待模块返回数据,大于150MS if(Rx2Flag == 1) { Rx2Flag = 0; status = RxCheckSum(Uart2RxBuf,Uart2RxBuf[1]);//对接收到的数据校验 if(status != STATUS_OK) //判断校验和是否正确 { return STATUS_ERR; } status = Uart2RxBuf[4]; if(status !

使用蛋白ID如何进行KEGG和GO富集分析

事由起因 昨天,有个童鞋咨询如何使用蛋白ID进行功能富集分析,功能富集分析主要是KEGG和GO。 思路 蛋白ID转UniProt数据库IDUniProt数据库ID转KEGG和GO号使用KEGG和GO号进行富集分析 教程(实操开始) 蛋白ID数据类型 蛋白ID的数据是的使用;进行隔分的,如果要整理成一列数据,我最开始想到的就是使用sed进行处理。 注:个人还是建议使用fa序列进行mapping,但是只要获得正确的结果,也无所谓。 1. 蛋白ID转UniProt数据库ID 使用UniProt数据库的工具UniProtKB ID Mapping(https://www.uniprot.org/uploadlists/) 1. 直接将数据复制-粘贴到过来即可,无需操作。 2. 选择UniProtKB AC/ID To KEGG Pathway,如下图所示。 3. 选择好后直接点解Map即可。 等待一段时间,即可完成Completed 4. Download数据 格式选择其中一种即可。 获得结果 目前,已经获得UniProt数据库ID。那么,我们可以直接试用其进行转换即可,方法有两种,一种是直接在KEGG数据库中进行转换,一种是使用云平台进行转换。 KEGG数据库中机芯富集https://www.genome.jp/kegg/mapper/color.html,自己做了没成功。 2.使用云平台进行转换(我们的童鞋使用基迪奥云平台进行转换,获得如下结果) 依旧是你喜欢的样子,GO号和KEGG号都有,可以直接使用。 方式二: 使用R语言进行转换 我们在这里尝试很多方式,依旧是没有成功!需要同学们的帮助,如果你有好的建议或方式,欢迎进行交流,这个问题一直留个大家讨论!!!! 代码一 安装R包 install.packages("UniprotR") install.packages("KEGGREST") install.packages("clusterProfiler") ## # 如果安装不了换成BiocManager::install()安装 ##'@加载 library(UniprotR) library(KEGGREST) library(clusterProfiler) 加载数据 ##'@加载蛋白ID数据 protein_ids <- read.table("test.02.txt",header = F) #protein_ids <- sapply(protein_ids, as.character) protein_ids <- as.character(protein_ids$V1) head(protein_ids) > head(protein_ids) [1] "N1PAF1" "G2WAT7" "C8Z5A3" "C7GN09" "

使用spm预处理fMRI数据

新手学习,记录学习笔记,欢迎交流~ 1.基本概念 Volume(容积/体积)/frame/time point(因为4d文件是包含时间的,可以称为时间点)/scan/一个TR即一帧(frame)采集到的图像称为一个volume,每一帧图像都是一个3D全脑 TR:重复时间,即得到一个完整大脑所需时间 TA:一次全脑扫描中,最后一层与第一层的时间间隔; TA=TR-(TR/扫描层数) slice timing:扫描层数。扫描大脑是一层一层扫描的,通常是隔层扫描,因为信号可能会受到相邻层的影响,所以需要隔层扫,比如先扫1 3 5 7再倒回去扫2 4 6 8层这样。然后再把这些层重建成一个完整的3D大脑。 Run/Session: 一次4D-fMRI数据采集,整个4D-fMRI的采集时间;推荐参数:至少6分钟,8分钟及以上最优。一般静息态是1个,如果是任务态,那么可能中途要休息一次分两次扫描,session就是2个。 Reference slice:时间层校正的参考层,也就是TR/2对应的层数 时间层校正后的文件带有a开头,表示校正后。 2.预处理流程--NARWSDCF N:格式转换,把存储原始fMRI信息的数据转换为NIFTI格式 A:时间层校正,变为a开头文件 R:realign--estimate&res头动校正:统计分析需要假设每个体素在各个时间点都对应大脑的同一个位置。头动校正是去除头动的干扰 W:分为一步配准和两步配准,这里是两步配准: ·normalize--estimate&write空间标准化:将个体的BOLD图像转化到标准空间 ·coregister配准:把高分辨率、高灰质/白质对比度的T1像配准到BOLD空间,结构像与功能像配准 ·segement:分割灰质,白质和脑脊液 S:smooth:空间平滑 D:detrend去除线性趋势:去除大时间尺度上,非神经活动引起的BOLD信号的偏移 C:nuisance coviriates regression 回归协变量 F:filter 滤波:滤出BOLD信号所处的频率段的数据。目的是降噪。BOLD信号所处0.01~0.08hz 然后 (1)首先是格式转换:使用dcm2niigui,将原始数据文件夹整个拖进去 或者使用microGL(既可看图又可转换文件) (2)第二步是A:时间层校正, 打开spm,点击slice timing--data--点击session 导入进nii文件,注意把右下角的1换为inf(无限的意思),然后右键--select all (可以提前把matlab的路径设置成存放文件的路径,这样方便选择) frame:1 --第一帧的图像 ,一般写成inf(无穷,可以包含所有的图像) filter旁边的白色长空格可以输入文件名来筛选文件 选完点done 扫描层数:33层 填写TA 扫描顺序:1是首项,2是步长,33是尾项;两个等差数列之间用空格隔开(会自动判断是否结束)。翻译过来就是1 3 5 7层 ... 2 4 6 8层...这样的扫描顺序 参考层:中间层的层数(第33层) 填好了然后点绿色的符号开run! (3)R:realign 头动校正 双击 只筛选以a为开头的文件(上一步生成的时间校正后的文件) 文件选中就可以运行了。Num passes 后面的register to mean:选中to fist 与第一张图象对齐,to mean,就是与平均的对齐

C# 自定义常用的代码片段

一、Visual Studio 配置路径:工具=》代码片段管理器=》语言选择CSharp 和 VisualC#;就能看到代码片段的配置文件夹。可以复制一个到桌面来作为模板修改。 task.snippet <?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <Title>task</Title> <Shortcut>task</Shortcut> <Description>task</Description> <Author>bear coding</Author> <SnippetTypes> <SnippetType>Expansion</SnippetType> <SnippetType>SurroundsWith</SnippetType> </SnippetTypes> </Header> <Snippet> <Code Language="csharp"><![CDATA[Task.Run(()=>{ $selected$ $end$ });]]> </Code> </Snippet> </CodeSnippet> </CodeSnippets> taska.snippet <?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <Title>taska</Title> <Shortcut>taska</Shortcut> <Description>taska</Description> <Author>bear coding</Author> <SnippetTypes> <SnippetType>Expansion</SnippetType> <SnippetType>SurroundsWith</SnippetType> </SnippetTypes> </Header> <Snippet> <Code Language="csharp"><![CDATA[Task.Run( async ()=>{ $selected$ $end$ });]]> </Code> </Snippet> </CodeSnippet> </CodeSnippets> class.snippet 已经有默认的了,不过可以替换掉 <?xml version="1.0" encoding="

selenium无头模式(--headless)怎么添加使用?

有一些兄弟姐妹执行selenium的UI测试用例的时候,都会出现每次执行一条测试用例都会打开一个浏览器吧?是不是有时候觉得很麻烦、不美观、占内存?那我们应该怎么来解决这个问题呢? 那就要用到selenium里面的一个无头模式,具体如何使用,请往下看~~ 第一步:引入无头模式的包: from selenium.webdriver.chrome.options import Options (这个需要前提引入的,就想时间等待一样) 第二步:不管是谷歌/火狐浏览器,需要在初始页面添加这段代码(参数): #第一步输入这个:去除开头警告 warnings.simplefilter('ignore',ResourceWarning) #控制台打印 print("开始执行你的测试用例!") #第二个输入这个:隐藏式启动谷歌浏览器执行UI测试用例 chrome_options = Options() chrome_options.add_argument('--headless') self.driver = webdriver.Chrome(options=chrome_options) #注意输入了这代码之后,不需要输入打开浏览器的代码了!(driver = webdriver.Chrome())这一行代码不需要输入了! 第三步:运行你的代码,后面再加上断言之类的,一个无头模式的UI测试用例就完成了:

机器学习与目标检测作业:安装pytorch

机器学习与目标检测作业:安装pytorch 一、 进入官网复制下载命令二、 下载的过程2.1 conda命令运行三、 测试pytorch是否安装成功 安装pytorch教程 一、 进入官网复制下载命令 进入官网复制下载命令如下图所示 二、 下载的过程 下载的过程如下图所示 2.1 conda命令运行 conda命令运行如下所示 conda install pytorch torchvision torchaudio cpuonly -c pytorch 选择y进行安装 三、 测试pytorch是否安装成功 测试pytorch是否安装成功如下图所示 输入Python命令然后输入 import torch torch.__version__ 出现如下情况,则说明安装成功 '1.11.0'

如何一步一步设置VMware Workstation 11.1的 NAT模式网络连接(与虚拟机共享主机的IP地址),使虚拟机可以正常访问外网?

系统要求: VMware Workstation 11.1 ; 操作系统为Windows 10 64位版本; 1. 查看 VMware Workstation 版本 (其他版本设置方式大同小异) 2. 查看主机的网络连接情况: 3. VMware Network Adapter VMnet1 的 IP 设置情况: 4. VMware Network Adapter VMnet8 的 IP 设置情况: 5. 打开VMware WorkStation 的编辑菜单,打开虚拟网线编辑器,并进行如下设置: VMnet0 设置: 6. WMnet1 设置: WMnet1 DHCP 设置: 7. WMnet8 设置: WMnet8 的NAT 设置: WMnet8的DNS设置: WMnet8的DHCP设置: 8. 在左边导航栏中右键你的虚拟机名,选择”设置”,在硬件选项卡中选择”硬件”,再选择”网络适配器”, 做如下设置: 9. 启动虚拟机,打开虚拟机的网络连接,设置网卡属性: 10. 设置完成,测试网络,ping网址一切正常: 11. 访问网页正常:

java之多线程抢火车票

一、创建线程的方法是实现runnable,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法 *********************************/ //多个线程同时操作一个类 //火车票 public class TestTread4 implements Runnable{ //票数 private int ticketNums = 10; @Override public void run() { while (true) { if (ticketNums <= 0) { break; } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"--->拿到了第"+ticketNums-- +"张票"); } } public static void main(String[] args) { TestTread4 testTread4 = new TestTread4(); new Thread(testTread4, "小明").start(); new Thread(testTread4,"老师").start(); new Thread(testTread4,"黄牛").start(); } } 发现问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱. 加上锁就搞定 public class TestTread4 implements Runnable{ //票数 private int ticketNums = 10; @Override public synchronized void run() { while (true) { if (ticketNums <= 0) { break; } try { Thread.

js获取图片原始宽高

使用HTML5属性 (naturalWidth, naturalHeight)获取 提示:适用于Firefox/IE9/Safari/Chrome/Opera浏览器 var img = document.getElementById("imgDom") var width = img.naturalWidth var height = img.naturalHeight 使用Image对象异步获取 let image = new Image(); image.onload = function () { var width=img.width var height=img.height }; image.onerror = function () { console.log("获取失败") }; image.src = "./1.png"; 兼容的写法 // async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。 // await 是在等待一个Promise的异步返回 // 得到图片原始的宽高 async function getImageSize(img) { if (img.naturalWidth) { // 适用于Firefox/IE9/Safari/Chrome/Opera浏览器 return { width: img.naturalWidth, height: img.

如何使用 Apache IoTDB 中的 UDF

本篇作者: IoTDB 社区 -- 廖兰宇 本文将概述用户使用 UDF 的大致流程,UDF 的详细使用说明请参考官网用户手册: https://iotdb.apache.org/zh/UserGuide/Master/Operators-Functions/User-Defined-Function.html 1编写 UDF IoTDB 为用户提供编写 UDF 的 JAVA API,用户可以自主实现 UDTF 类,IoTDB 将通过类加载机制装载用户编写的类。 1.1Maven 依赖 如果您使用 Maven,可以从 Maven 库中搜索下面示例中的依赖。请注意选择和目标 IoTDB 服务器版本相同的依赖版本,本文中使用 1.0.0 版本的依赖。 <dependency> <groupId>org.apache.iotdb</groupId> <artifactId>udf-api</artifactId> <version>1.0.0</version> <scope>provided</scope> </dependency> 1.2实现接口 UDTF 目前有如下接口: 在一个完整的 UDTF 实例生命周期中,各个方法的调用顺序如下: 1. void validate(UDFParameterValidator validator) throws Exception 2. void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) throws Exception 3. void transform(Row row, PointCollector collector) throws Exception // 或者 void transform(RowWindow rowWindow, PointCollector collector) throws Exception 4.

工作中常用且容易遗忘的css样式整理,建议收藏

1. 文字超出部分显示省略号 单行文本的溢出显示省略号(一定要有宽度) p{ width:200rpx; overflow: hidden; text-overflow:ellipsis; white-space: nowrap; } 多行文本溢出显示省略号 p { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; } 2.中英文自动换行 word-break:break-all;只对英文起作用,以字母作为换行依据 word-wrap:break-word; 只对英文起作用,以单词作为换行依据 white-space:pre-wrap; 只对中文起作用,强制换行 white-space:nowrap; 强制不换行,都起作用 p{ word-wrap: break-word; white-space: normal; word-break: break-all; } //不换行 .wrap { white-space:nowrap; } //自动换行 .wrap { word-wrap: break-word; word-break: normal; } //强制换行 .wrap { word-break:break-all; } 3.文字阴影 text-shadow 为网页字体添加阴影,通过对text-shadow属性设置相关的属性值。 属性与值的说明如下: text-shadow: [X-offset,Y-offset,Blur,Color]; X-offset:指阴影居于字体水平偏移的位置。Y-offset:指阴影居于字体垂直偏移的位置。Blur:指阴影的模糊值。color:指阴影的颜色; h1{ text-shadow: 5px 5px 5px #FF0000; }

从MIT协议谈契约精神

以前看到过李笑来讲的发生在他身上的故事,说他当年 ( 2001年 ) 住在双榆树,经常去双安商场的地下超市买东西,有一次买了个什么东西觉得不好,要退,超市服务员说按规定,该类商品售出一概不能退,李笑来大怒,说你把书面规定拿出来,有的话我就不退了,如果没有,那我就一定要退,最后叫来了超市经理,经理一看这来者不善啊,也吵不过李笑来,就给退了。 讲这个故事想说明什么呢,其实我们都明白,20多年前的中国超市,很多管理规定都是口头上的,怎么会写成白纸黑字呢。 从超市服务员的角度看,李笑来这行为就是捣乱,是胡搅蛮缠;李笑来则肯定觉得是在维护自己正当的消费者权益;最受震动的应该是超市管理层,如果是我,我会立刻要求起草一个关于退换货的规定,我可真不想再遇到下一个这样的人。 这就是契约精神,说好的,都写下来,写下来的,我都认。 现在说MIT协议。 MIT协议就是大名鼎鼎的开源软件许可协议The MIT License,又称MIT许可证。 有人在两年前专门做过分析1,MIT是Github上使用率最高的许可证,第二名到第五名是Apache 2.0、GPL 2.0、GPL 3.0和bsd-3-clause。 注:本文中,“MIT协议”和“MIT许可证”等同。 什么是开源许可证? 开源许可证是这样的,我把源码放网上了,如果还不错,就有很多人问我了,说你那个代码能不能让我用用?你那个代码我能不能放在我的产品里啊?你那个代码我用了,怎么那么多Bug啊?你那个代码我想当作教学案例使用,请问是不是可以啊?还有,你那个代码我用了,感觉不错,而且我还改了很多地方,我也把它放网上了,而且我还改了个名,你没有意见吧?你有意见我也准备改名了,因为现在这个软件中,我写的代码,比你写的多多了! (这都是比较有版权意识的,怕不问你就用以后惹上官司。) 我可懒得回答这么多问题,我把这些可能问到的问题,都写成一段话,放在我的代码里,意思就是说: 我允许你们XXX,我许可你们XXXX,你们可以XXXX,但是,你们必须XXXX,如果你们XXXX了,你们就必须XXXX,对了,对于XXXX这些情况,我可不负责。 你要同意,就用,不同意就别用。如果你用了,但违反了许可证的要求,我可能会告你啊! 这就是许可证。 你可以自己写一个许可证,但是如果你很懒的话 ( 一般人都很懒 ) ,你可以用别人写的比较好的许可证。 写的比较好的开源许可证有很多种,比如GPL、BSD、MIT、Apache等等,MIT只是其中的一个。 你可以挑一个合你胃口的,这些许可证模版都是免费的,毕竟也没人指望这个卖钱。 至于它们的区别,可以看看下面这张图接受一下科普。 “新蜂商城”事件 前段时间有一个叫做“新蜂商城”(简称“新蜂”)的开源项目有点新闻,它使用了MIT许可证,其作者被人告知说,哎,你的开源软件被人在网上卖哎,你不管管吗? 作者一看,还真是,有up主在b站上卖,有人在闲鱼上卖,虽然卖的也不贵,有卖300的,有卖几十的,但一眼望过去,很显然卖的就是自己的“新蜂”嘛! 然后就有点热闹,有人说这是侵权,要声援作者,控诉有人如此无耻;有人说这不算侵权,MIT是很宽松的协议,基本上你什么都可以干,只要保留作者版权即可。 作者倒是没有想去怎么处理,作者只是觉得“我抽出下班时间,断断续续写了半年的项目,不是心血也算是我的小作品吧,开源出去就是给你这么玩的?佩服。” 大概作者还是比较年轻,不懂人世间的险恶吧! 其实这应该是预料中的事。 不应该有任何心理波澜。 更何况,MIT许可证,允许别人卖你的源码! 从契约精神讲,说好允许别人做,就让别人做吧。 这里面有个新手不太能想明白的问题,为啥有许可证允许别人卖自己的开源软件? 这要谈到开源的精神了。早期玩开源的人,开源自己的代码,大多不是为了卖软件,大多都有着开放、共享、自由、打破垄断等等比较理想化的情结,唯一可图的大概也就是个“名”,所以几乎所有许可证都要求保留作者名字。 为了更好地传播自己的代码,开源作者通常允许别人卖自己的源码。初期会考虑这样的情况:如果有人把Linux源码刻录成光盘发放,是不是应该收点成本费呢,再或者服务费? 那如果有人以此牟取暴利呢,岂不是很亏?通常不会。因为既然能在网上免费下载源码,明白人就不会再去花大价钱去买。 而且,如果作者发现真有人能使用自己的源码牟取暴利,完全可以不授权让他从中牟利,改许可证就可以了。这种事也不是没有发生过,而且还不是个例。 比如开源云原生SQL数据库CockroachDB宣布修改开源协议,从原本的Apache-2.0协议修改为BSL ( Business Source License ) ,该协议要求用户唯一不能做的是在没有取得授权的情况下以商业形式用 CockroachDB 提供数据库即服务 ( DBaaS ) 。 BSL由MySQL的开发者迈克尔·蒙蒂·维德纽斯 ( Michael "Monty" Widenius ) 在2013年设计。它有三个主要特点,一是非商业性使用没有限制,商业性使用有限制;二是许可证中可以附加使用者自己的要求;三是有一个change date,自此时间开始,源码将会由BSL转变为作者指定的其他许可证,如GPL等开源许可证。 依我看,闲鱼上把“新蜂”卖个几十块钱,还搭上售后服务,也算正常吧。

video(倍速播放,暂停,播放,逐帧播放,关闭音量,倒放,前进多少秒,进度条)功能

<template> <div style="height: 100vh;"> <video ref="vid" width='1000px' height='560px'> <source src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/97ac2dcc1367e03ac580204d6ca9a724.mp4" /> </video> <div class="jdt"> <div class="jd" ref="jdt"> <div style="background-color: green;height: 100%;border-radius: 8px;" :style="`width: ${currentTime / duration * 1000}px`"> </div> </div> </div> <div class="vid"> <i :class="play" @click="changePlay"></i> <svg @click="back" t="1677726468265" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2790" width="36" height="36"> <path d="M0 512c0 282.8 229.2 512 512 512s512-229.2 512-512S794.8 0 512 0 0 229.2 0 512z m99.2 174.4C75.8 631.2 64 572.

web前端学习-CSS

web前端学习-CSS 1 CSS基础1.1 CSS的基础认知1.2 CSS基础选择器1.2.1标签选择器1.2.2 类选择器1.2.3 id选择器1.2.4 通配符选择器 1.3 文字和文本样式 2 CSS的进阶2.1 CSS的选择器2.1.1 选择器-后代2.1.2 选择器-子代2.1.3 选择器-并集2.1.4 选择器-交集2.1.5 选择器-伪类(hover)2.1.6 emmet语法 2.2 背景元素相关2.2.1 背景-背景色2.2.1 背景-背景图2.2.1 背景-背景平铺2.2.1 背景-背景位置2.2.1 背景-background2.2.1 背景图和img的区别 2.3 元素的显示模式2.3.1 显示模式-块2.3.2 显示模式-行内2.3.2 显示模式-行内块2.3.4 显示模式-转换2.3.5 显示模式-标签嵌套 2.4 CSS特性2.4.1 CSS的继承性2.4.2 CSS的层叠性 2.5 CSS的三大特性2.5.1 优先级2.5.2 权重叠加计算2.5.2.1 权重叠加计算介绍2.5.2.2 练习案例 2.5.2 谷歌排错工具 2.6 PxCook的基本使用2.7 盒子模型2.7.1 盒子模型的介绍2.7.2 内容的width和height2.7.3 border使用方法2.7.4 border-当方向设置2.7.5 padding2.7.6 盒子模型(C3)-内减模式2.7.7 盒子模型-外边距2.7.8 盒子模型 -版心居中2.7.9 盒子模型-外边距问题 2.8 CSS浮动2.8.1 结构伪类选择器2.8.2 伪元素2.8.3 标准流2.8.4 浮动2.8.4.1 浮动的作用2.8.4.2 浮动的特点 2.9 清除浮动2.9.1 清除浮动场景搭建2.

RTP时间戳概念

RTP协议不依赖于底层协议,由于UDP包的快速、时实性高的特点,它通常和UDP结合在一起,作为UDP的上层载体数据的形式传播。 typedef struct _rtp_header_t { uint32_t v:2; /* protocol version */ uint32_t p:1; /* padding flag */ uint32_t x:1; /* header extension flag */ uint32_t cc:4; /* CSRC count */ uint32_t m:1; /* marker bit */ uint32_t pt:7; /* payload type */ uint32_t seq:16; /* sequence number */ uint32_t timestamp; /* timestamp */ uint32_t ssrc; /* synchronization source */ } rtp_header_t; 这是一个RTP头,很简单,并没有你想象的那么复杂,对不对?我们来看几个主要的参数,他们也是RTP的灵魂: (1)payload。payload表示了此RTP包的数据是那种类型的数据,不同的数值表示不同的类型。如0是PCMU,8是723,24是视频263等等。 (2)SSRC,这个东西并不常用,实际上它是一个随即生成的ID,表示了一个RTP连接。在应用的时候,确保这个ID唯一就可以了。 (3)sequence number。也就是序列号,它表示了当前包是第几个包。发送方每发送一个包,就把这个数值加一。接受放可以根据这个数值来重新组合包顺序,判断包是否丢失等操作。注意:它只是表示了包的先后顺序,它不能表示时间上的任何其它信息。这个请和后面的时间戳比较。 (4)timestamp。时间戳,它的概念稍微有点复杂,我用稍微通俗点的理解去解释它,虽然这样有点不太正确。时间戳顾名思义,它表示了一个数据产生的时间,和我们邮递的邮戳一样,它是个时间标记(至于这个时间干什么用,我后面会详细的说),通常表示RTP数据包中,第一个字节数据产生的时间(至于你是不是这么用就是你写程序的问题了)。 如果你上面理解了,那么我们更进一步:实际上,时间戳增加一并不是我们通常意义上的过了一个微秒,而是增加了一个采样间隔那么长的时间。举个例子来说。不同的采集有不同的采样频率,比如一般的音频是8K的采样频率,也就是一毫秒采集8次数据,也就是每次采样间隔是1/8MS,而timestamp增加1也就意味着增加了一个采样间隔。也就是过了1/8MS。换个例子,如果令一种编码的采样频率是16K,那么timestamp增加1也就意味着系统过了1/16MS。也就是说,再同一个系统中,对不同编码,虽然使用同一个时钟,但timestamp的增长速度是不同的,在这个例子中,采样频率是16K的编码要比8K的快两倍,请记住这个区别。 RTCP

写给go开发者的gRPC教程-protobuf基础

gRPC是谷歌开源的一款高性能、支持多种开发语言的服务框架,对于一个rpc我们关注如下几方面: 序列化协议。gRPC使用protobuf,首先使用protobuf定义服务,然后使用这个文件来生成客户端和服务端的代码。因为pb是跨语言的,因此即使服务端和客户端语言并不一致也是可以互相序列化和反序列化的 网络传输层。gRPC使用http2.0协议,http2.0相比于HTTP 1.x ,大幅度的提升了 web 性能。 Protobuf IDL 所谓序列化通俗来说就是把内存的一段数据转化成二进制并存储或者通过网络传输,而读取磁盘或另一端收到后可以在内存中重建这段数据 1、protobuf协议是跨语言跨平台的序列化协议。 2、protobuf本身并不是和gRPC绑定的。它也可以被用于非RPC场景,如存储等 json、 xml都是一种序列化的方式,只是他们不需要提前预定义idl,且具备可读性,当然他们传输的体积也因此较大,可以说是各有优劣 所以先来介绍下protobuf的idl怎么写。protobuf最新版本为proto3,在这里你可以看到详细的文档说明:https://protobuf.dev/programming-guides/proto3/ 定义消息类型 protobuf里最基本的类型就是message,每一个message都会有一个或者多个字段(field),其中字段包含如下元素 类型:类型不仅可以是标量类型(int、string等),也可以是复合类型(enum等),也可以是其他message 字段名:字段名比较推荐的是使用下划线/分隔名称 字段编号:一个message内每一个字段编号都必须唯一的,在编码后其实传递的是这个编号而不是字段名 字段规则:消息字段可以是以下字段之一 singular:格式正确的消息可以有零个或一个字段(但不能超过一个)。使用 proto3 语法时,如果未为给定字段指定其他字段规则,则这是默认字段规则 optional:与 singular 相同,不过您可以检查该值是否明确设置 repeated:在格式正确的消息中,此字段类型可以重复零次或多次。系统会保留重复值的顺序 map:这是一个成对的键值对字段 保留字段:为了避免再次使用到已移除的字段可以设定保留字段。如果任何未来用户尝试使用这些字段标识符,协议缓冲区编译器就会报错 标量值类 标量类型会涉及到不同语言和编码方式,后续有机会深入讲 .proto TypeGo TypeNotesdoublefloat64 floatfloat32 int32int32使用可变长度的编码。对负数的编码效率低下 - 如果您的字段可能包含负值,请改用 sint32。int64int64使用可变长度的编码。对负数的编码效率低下 - 如果字段可能有负值,请改用 sint64。uint32uint32使用可变长度的编码。uint64uint64使用可变长度的编码。sint32int32使用可变长度的编码。有符号整数值。与常规 int32 相比,这些函数可以更高效地对负数进行编码。sint64int64使用可变长度的编码。有符号整数值。与常规 int64 相比,这些函数可以更高效地对负数进行编码。fixed32uint32始终为 4 个字节。如果值通常大于 2^28,则比 uint32 更高效。fixed64uint64始终为 8 个字节。如果值通常大于 2^56,则比 uint64 更高效。sfixed32int32始终为 4 个字节。sfixed64int64始终为 8 个字节。boolbool stringstring字符串必须始终包含 UTF-8 编码或 7 位 ASCII 文本,并且长度不得超过 232。bytes[]byte可以包含任意长度的 2^32 字节。 复合类型 数组 message SearchResponse { repeated Result results = 1; } message Result { string url = 1; string title = 2; repeated string snippets = 3; } 枚举 message SearchRequest { string query = 1; int32 page_number = 2; int32 result_per_page = 3; enum Corpus { UNIVERSAL = 0; WEB = 1; IMAGES = 2; LOCAL = 3; NEWS = 4; PRODUCTS = 5; VIDEO = 6; } Corpus corpus = 4; } 服务 定义的method仅能有一个入参和出参数。如果需要传递多个参数需要定义成message

MeterSphere的前后置脚本代码模版说明

一、背景 在做接口测试的时候,不可避免的会碰到需要使用脚本操作,可能是把上一个接口的变量通过脚本转换为下一个接口需要的类型,也可能是生成环境变量; MeterSphere会提供代码模板出来供测试人员直接使用,包含到API测试、自定义变量、项目环境、自定义代码片段、异常处理 二、代码模版 1、API测试 这个代码模版可以把接口定义处的单接口以脚本的形式复制到前后置脚本或自定义脚本中,当运行后,可以在控制台看到打印的返回体,证明这个脚本化的接口是正常状态的 这时候就可以在脚本最后加一些自定义的内容,比方如果需要把脚本接口的返回体提参,就在后面加上 JSONObject data = JSONObject.parse Object(data); String token = data.get(“token”).toString(); 2、自定义变量 获取变量 vars.get(“variable_name”) 用于获取提取参数里的变量,这个很普遍 log.info(vars.get(“token”)); //打印获取的token变量 设置变量 vars.put(“variable_name”, “variable_value”) 用于设置提供给后续需要使用的接口新的变量 以上的参数必须是字符串类型,如果是非字符串使用vars.getObject和vars.putObject 获取响应 prev.getResponseHeaders() //获取响应头 prev.getResponseCode() //获取响应码 prev.getResponseDataAsString() //获取响应结果 控制台输出内容可以用脚本进行处理,比如提取键值对供后面的接口使用 3、项目环境 设置环境参数 vars.put(${__metersphere_env_id}+“key”,“value”); 当一个运行环境需要给多个场景使用时,不一定合适把所有接口都加入一个自动化场景中;可以将生成token的接口可以单独运行,也可以做出定时执行,无论在CASE中还是接口自动化中,后续不同场景使用这个运行环境,就无须每次都跑一遍生成token的步骤。 后续使用这个运行环境的接口只需要写入变量${org}即可 4、自定义代码片段 自定义代码片段 在脚本需要反复使用的场景中,自定义代码片段是体现价值的时候。 首先需要在项目设置-更多选项-自定义代码片段,创建脚本文件 写好的脚本可直接执行,查看返回是否正常 回到接口测试,接口定义CASE或接口自动化处处,在前后置脚本、自定义脚本或运行环境中的全局前后置脚本、脚本断言都可以在自定义代码片段处插入写好的脚本 例如获取signature这个脚本,当放在运行环境中的全局前置脚本-所有场景步骤前执行时,使用这个环境的接口自动化场景都会自动执行生成signature供场内接口使用 5、异常处理 ctx.getEngine().stopThreadNow(ctx.getThread().getThreadName()); 可以用于判断接口请求结果,当接口调用失败时,就会停止此线程,后续的接口也不再执行了 也可以用于断言中 三、总结 上述只是关于脚本编写时,MeterSphere提供的一些内置模版。当然使用图形化点击的方式操作进行提取参数、断言也是可以的,MeterSphere功能很多,提供了灵活的自主编写脚本的方式和简单的图形操作方式,可以供测试人员任意选择

QT QTabWidget 使用

简介 QTabWidget 为选项卡小部件,提供一个选项卡栏(参见 QTabBar)和一个“页面区域”,用于显示与每个选项卡相关的页面。默认情况下,选项卡栏显示在页面区域的上方,但是可以使用不同的配置(请参见 TabPosition)。每个选项卡都与不同的小部件(称为页面)相关联。页面区域中只显示当前页面;其他所有页面都隐藏。用户可以通过单击其选项卡或按 Alt+ 字母快捷键(如果有)来显示不同的页面。 使用 QTabWidget 的正常方法是执行以下操作: 创建一个 QTabWidget。 为选项卡对话框中的每个页面创建一个 QWidget,但不要为它们指定父窗口小部件。 将子窗口小部件插入页面窗口小部件,使用布局将其定位为正常位置。 调用addTab()或insertTab()将页面小部件放入选项卡小部件,为每个选项卡提供一个带有可选键盘快捷键的合适标签。 先看最下面的示例代码的执行效果图: 属性相关方法 // 返回选项卡栏中的选项卡数 int count() const // 返回当前选项卡页的索引位置 int currentIndex() const // 返回当前选项卡页的索引位置 void setCurrentIndex(int index) // 如何省略选项卡栏中的文本 void setElideMode(Qt::TextElideMode mode) // 设置选项卡栏中图标的大小 void setIconSize(const QSize &size) // 设置用户是否可以在选项卡栏区域内移动选项卡 void setMovable(bool movable) // 设置为true,则当选项卡栏包含少于2个选项卡时,它将自动隐藏 void setTabBarAutoHide(bool enabled) // 设置选项卡在此选项卡小部件中的位置 void setTabPosition(QTabWidget::TabPosition position) // 设置选项卡小部件中选项卡的形状 void setTabShape(QTabWidget::TabShape s) // 设置是否将关闭按钮自动添加到每个选项卡,默认为false void setTabsClosable(bool closeable) // 当选项卡栏有许多选项卡时,此属性决定是否应使用按钮滚动选项卡 void setUsesScrollButtons(bool useButtons) 增删选项的方法 // 添加选项卡 int addTab(QWidget *page, const QString &label) int addTab(QWidget *page, const QIcon &icon, const QString &label) // 插入选项卡 int insertTab(int index, QWidget *page, const QString &label) int insertTab(int index, QWidget *page, const QIcon &icon, const QString &label) // 清空选项卡 void clear() // 移除选项卡 void removeTab(int index) 选项栏和内容控件 // 获取内部的TabBar QTabBar * tabBar() const // 获取指向具有给定索引的页面小部件 QWidget * widget(int index) const // 查找小部件的索引位置 int indexOf(QWidget *w) const // 获取当前选择tab指向的子页面 QWidget * currentWidget() const // 获取角落控件 QWidget * cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const // 设置角落控件 void setCornerWidget(QWidget *widget, Qt::Corner corner = Qt::TopRightCorner) 选项修改 // 设置tab使能 bool isTabEnabled(int index) const // 是否可用 void setTabEnabled(int index, bool enable) // 是否可见 bool isTabVisible(int index) const // 设置可见 void setTabVisible(int index, bool visible) // 获取tab上的图标 QIcon tabIcon(int index) const // 设置tab上的图标 void setTabIcon(int index, const QIcon &icon) // 获取tab的文本 QString tabText(int index) const // 设置tab的文本 void setTabText(int index, const QString &label) // 获取tab的ToolTip QString tabToolTip(int index) const // 设置tab的ToolTip void setTabToolTip(int index, const QString &tip) 示例代码 void Widget::initTabWidget() { QHBoxLayout* lay = new QHBoxLayout(this); QTabWidget *pTabWidget = new QTabWidget(this); pTabWidget->setTabsClosable(true); pTabWidget->setMovable(true); pTabWidget->setTabPosition(QTabWidget::North); pTabWidget->setTabShape(QTabWidget::Rounded); //梯形tab QWidget *w1 = new QWidget; w1->setStyleSheet("

解决Sql WorkBench中数据库不能重命名的问题

解决Sql WorkBench中数据库不能重命名的问题 mysql不支持直接重命名数据库1. 连接到数据库2. 打开菜单,选择==迁移向导==3. 点击==Start Migration==4. 填写源数据库的相应参数5. 填写目标数据库的响应参数6. 稍等片刻,点击==Next==7. 选择你要迁移的数据库。8. 进入一个加载页面,完了之后再点==Next==9. 选择要源数据库中要迁移的表10. 新页面之后再==Next==11. 命名新数据库的名称12. 直接==Next==就行13. 再==Next==14. 接下来一路==Next== 谢谢! mysql不支持直接重命名数据库 MySQL 不支持直接重命名数据库,但可以通过创建新数据库,并将老数据库的所有内容复制到新数据库,然后删除老数据库来实现重命名数据库的目的。 我想重命名project001这个数据库,下面是操作步骤。 1. 连接到数据库 2. 打开菜单,选择迁移向导 英文: Migration Wizard 3. 点击Start Migration 4. 填写源数据库的相应参数 一般自动生成了,先检查一遍再点击Next 5. 填写目标数据库的响应参数 也就是要迁移的新数据库的主机地址、端口号、用户名以及密码之类的参数,一般和源数据库一致。 点击Next。 6. 稍等片刻,点击Next 7. 选择你要迁移的数据库。 也就是源数据库。这里我要迁移project001: 8. 进入一个加载页面,完了之后再点Next 9. 选择要源数据库中要迁移的表 默认是迁移全部的表。所以如果要迁移所有的表,直接点Next就行。 10. 新页面之后再Next 11. 命名新数据库的名称 这里是重点!!! 左边的列是源数据库,右边才是目标数据库。它默认是源数据库名,所以需要重命名,不然报错!!! 怎么重命名??? 注意重命名不是右键目标数据库的名称!!! 左键单击选中目标数据库后,再点击一下!!!就可以重命名了。 之后==Next=。 12. 直接Next就行 13. 再Next 14. 接下来一路Next 最后点击Finish,会自动断开数据库连接。重新连接之后会发现多出了新数据库。表从源数据库成功迁移了过来。就可以删了源数据库了!!! 谢谢! 好久没写过博客了! 回看之前写的博客,虽然是些很简单的内容,但是也帮助了不少的朋友。很高兴!

tomcat 闪退/一闪而过 问题

结论 去官网重新下载对应JDK的新版本tomcat,安装解压即可使用。无需配置路径。 资源 tomcat官网下载地址 JDK对应版本 实际经验 原来装好能用的tomcat,上课打开就闪退。 各种查bug找的解决方案都没用,除开最常见的尝试配环境变量和路径,还有查看startup.bat报错内容:win+R打开cmd,将tomcat安装地址bin目录下startup.bat拖进去,即可显示错误提示。 最后解决是直接下载更新的小版本,解压后直接点击startup.bat执行,访问localhost:8080,小猫你好。 当然解压后进入idea使用也能成功:创建java项目–添加框架支持–编辑配置–添加tomcat 本地服务器–配置添加应用服务器–部署添加工件–运行访问localhost:8080。

【头歌答案】03-3 Python程序设计入门2-基本输入输出、字符串、内置函数(EduCoder)

简介 答案查询的入口网页版https://edaser.github.io/答案获取的方法简介见这里 并不是所有的关卡都有答案,有些只有部分关卡有 03-3 Python程序设计入门2-基本输入输出、字符串、内置函数-视频学习 >>>查看 第2关:python当做计算器 解题思路1 第3关:如何输出3.14% 解题思路1 解题思路2 第5关:内置函数 解题思路1

Java——岛屿数量

题目链接 leetcode在线oj题——岛屿数量 题目描述 给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外,你可以假设该网格的四条边均被水包围。 题目示例 输入:grid = [ [“1”,“1”,“1”,“1”,“0”], [“1”,“1”,“0”,“1”,“0”], [“1”,“1”,“0”,“0”,“0”], [“0”,“0”,“0”,“0”,“0”] ] 输出:1 输入:grid = [ [“1”,“1”,“0”,“0”,“0”], [“1”,“1”,“0”,“0”,“0”], [“0”,“0”,“1”,“0”,“0”], [“0”,“0”,“0”,“1”,“1”] ] 输出:3 题目提示 m == grid.lengthn == grid[i].length1 <= m, n <= 300grid[i][j] 的值为 ‘0’ 或 ‘1’ 解题思路 定义一个isUsed数组,记录遍历过的位置 使用深度优先搜索,将与一个位置连接的所有“1”都记录为以遍历,最后统计总数即可 定义一个DFS方法,参数分别是:grid数组,行数,列数,当前所在行,当前所在列,isUsed数组 将当前的位置的isUsed数组位置更新为已遍历,并且分别遍历其上下左右四个位置,如果没有越界,并且还是“1”,那么继续递归其他位置 代码 class Solution { int[][] nextPosition = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; void DFS(char[][] grid, int row, int col, int curX, int curY, boolean[][] isUsed){ isUsed[curX][curY] = true; //确定下一个位置 for (int i = 0; i < 4; i++) { int newX = curX + nextPosition[i][0]; int newY = curY + nextPosition[i][1]; //判断是否越界 if(newX >= row || newX < 0 || newY >= col || newY < 0){ continue; } if(grid[newX][newY] == '1' && !