java.lang.NoClassDefFoundError: org/gradle/api/internal/plugins/DefaultConvention

1.从github上面拉取了Spring的源码,使用idea 版本2018.3,gradle-7.4.2 构建springboot项目报错:,build出现如下问题: java.lang.NoClassDefFoundError: org/gradle/api/internal/plugins/DefaultConvention at org.jetbrains.plugins.gradle.tooling.builder.ProjectExtensionsDataBuilderImpl.buildAll(ProjectExtensionsDataBuilderImpl.groovy:50) at org.jetbrains.plugins.gradle.tooling.internal.ExtraModelBuilder.buildAll(ExtraModelBuilder.java:67) at org.gradle.tooling.provider.model.internal.DefaultToolingModelBuilderRegistry$BuilderWithNoParameter.build(DefaultToolingModelBuilderRegistry.java:264) at org.gradle.tooling.provider.model.internal.DefaultToolingModelBuilderRegistry$UserCodeAssigningBuilder.lambda$build$0(DefaultToolingModelBuilderRegistry.java:374) at org.gradle.configuration.internal.DefaultUserCodeApplicationContext$CurrentApplication.reapply(DefaultUserCodeApplicationContext.java:109) at org.gradle.tooling.provider.model.internal.DefaultToolingModelBuilderRegistry$UserCodeAssigningBuilder.build(DefaultToolingModelBuilderRegistry.java:374) at org.gradle.tooling.provider.model.internal.DefaultToolingModelBuilderRegistry$LockSingleProjectBuilder.lambda$build$0(DefaultToolingModelBuilderRegistry.java:304) at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$withProjectLock$2(DefaultProjectStateRegistry.java:408) at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:270) ... 2.原因:idea2008.3与gradle-7.4.2 不兼容导致 解决方案: (1)idea2008.3 下载不同gradle版本尝试解决,2008.3版本兼容gradle-5.6.4版本 (2)升级idea的版本至2020以上 3.使用2中的方案(1)来解决一下,不用去下新版本的idea。 配置按照项目spring-framework/gradle/wrapper/gradle-wrapper.properties 修改为:

lotus windowPoSt 手动触发时空证明计算

系列文章目录 lotus lotus windowPoSt 系列文章目录前言一、windowPoSt1.测试网 参考 前言 lotus windowPoSt 手动触发时空证明计算 一、windowPoSt 1.测试网 # lotus-miner --version lotus-miner version 1.16.0-rc1+calibnet+git.5a67bb0f6 # lotus-miner proving compute window-post 0 Took 2m40.699973548s [{"Deadline":0,"Partitions":[{"Index":0,"Skipped":[0]}],"Proofs":[{"PoStProof":8,"ProofBytes":"l/7tiDkdFpTp6XqIj5tzkufXEuhy4kx2+Qfj9WlrOoHkFlDKRf5bTsyRkLNMX+pvh4wb3adBeCb1Lfuq327PBq/Bre5QjMoKPvOJf+2AVhZ8g3jn0oqDkPGzGCav2JFOBGRwIpSx09uulzcr3kN70wOAPA8QSpiCd43wEbxJen1nddvbV7L3gYcwA5BD9xN4g/v7EEVnS4HmJeiCe6A6cCqbAbzPHkdXXoZqZDq4goxVpubFQUrbdP0quBqD08T6"}],"ChainCommitEpoch":0,"ChainCommitRand":null}] # lotus-miner proving compute windowed-post 0 Took 2m44.259500116s [{"Deadline":0,"Partitions":[{"Index":0,"Skipped":[0]}],"Proofs":[{"PoStProof":8,"ProofBytes":"hGuPqIe6Ql8JNn6UrL5waXVwLsJjR5uXohvPnmeDzaq/Tq2XcKMAUbKBYLpU/Nxotb3nWfoivj+kOQBNGIK+eSn26T8OtqQdR5kIjoG/9QME4xfJjFe7cac57ulwt7GpEDukYyq5G71vk6yCbkvrBnRu6EP+jjM8okGJ2T3Ysv7J+8py0iIj3L2z6TNP1fBVpd2YA2xP44wsn/92zLIZEBm50YyzacbooL5nFhRW55wnx2JMvvD6CCuXmtzhyt6c"}],"ChainCommitEpoch":0,"ChainCommitRand":null}] 参考 windowPoSt computation

lotus 扇区报错 PreCommitFailed CommitFailed SealPreCommit2Failed 更新扇区状态

lotus 扇区报错 PreCommitFailed 1,lotus 扇区报错 PreCommitFailed2,扇区重新运行PreCommitting删除扇区3,CommitFailedCommitFailedSealPreCommit2Failed 1,lotus 扇区报错 PreCommitFailed # lotus version Daemon: 0.9.0+git.8f35a5c0.dirty+api0.16.0 Local: lotus version 0.9.0+git.8f35a5c0.dirty 查看扇区PreCommitFailed # lotus-miner sectors list 94 PreCommitFailed lotus-miner storage find 94 lotus-miner sectors status --log --on-chain-info 94 扇区已经完成PreCommit2 ,PreCommitting报错参考:扇区状态 /* * Empty <- incoming deals | | | v *<- WaitDeals <- incoming deals | | | v *<- Packing <- incoming committed capacity | | | v *<- PreCommit1 <--> SealPreCommit1Failed | | ^ ^^ | | *----------++----\ | v v || | *<- PreCommit2 --------++--> SealPreCommit2Failed | | || | v /-------/| * PreCommitting <-----+---> PreCommitFailed | | | ^ | v | | *<- WaitSeed -----------+-----/ | ||| ^ | | ||| \--------*-----/ | ||| | | vvv v----+----> ComputeProofFailed *<- Committing | | | ^--> CommitFailed | v ^ | SubmitCommit | | | | | v | *<- CommitWait ---/ | | | v | FinalizeSector <--> FinalizeFailed | | | v *<- Proving | v FailedUnrecoverable UndefinedSectorState <- ¯\_(ツ)_/¯ | ^ *---------------------/ */ 2,扇区重新运行PreCommitting lotus-miner sectors update-state --really-do-it 94 PreCommitting # lotus-miner sectors status --log --on-chain-info 94 [event;sealing.

U盘损坏和文件修复(前方高能!!!)

利用量产的方法进行U盘的恢复和修复 前言方法一(洒洒水)方法二(无效或只处理一般问题)第三步(终极救命教程) 前言 因为我的U盘的各种USB串口都运行正常,但是查看事件显示 数据迁移,无媒体,无介质等等… 方法一(洒洒水) 打开右下角的“运行” 输入:diskmgmt.msc 进入到磁盘管理页面 找到自己的磁盘:单击属性: 选中卷: 这就是个磁盘分区:参考博客 博客 方法二(无效或只处理一般问题) Ⅰ.快捷键window+i打开设置 选择设备 点击"已连接设备" 删除设备 重新插入U盘即可! (有点点误人子弟,不管用) Ⅱ.利用disk命令(只解决一般问题) 第一步: 进入cmd 若是管理权限不足,那就打开 输入diskpart,再输入list disk 记住容量跟自己U盘一致的磁盘 输入select disk 1 输入online disk 第二步:下载一个DiskGenius 选择自己U盘,右键快速分区即可(这就i是一个坑) 修复命令:先输入命令:clean(清理),再输入create partition primary(为选择的U盘创建主分区),最后输入active(为选择的U盘激活分区) 快速格式化U盘: 比如格式化为 FAT32 文件系统 命令:format fs=fat32 quick 第三步(终极救命教程) 实际上就是量产U盘。 首先需要知道U盘的产商和型号,我使用的是chipeasy,地址如下 链接:https://pan.baidu.com/s/1f0MDyA0tmyvLDPcTkZqcWg 提取码:2w0i 插入U盘后,会显示: 知道U盘的厂商和型号就可以去网上找响应型号的U盘量产工具,比如我找的工具umptool(这个工具有坑!!!看下面) 链接:https://pan.baidu.com/s/1f2cIpoFGEUD60krfCaSvxg 提取码:v5hv 知道自己U盘的芯片型号之后:下载FC1178BC的量产工具。 重要提示:不要相信那些论坛,下载网站的下载,请直接到Club.liangchanba.com找到厂商对应的程序(量产吧!) 我就是下载了4,5个地方的软件,量产过程都报错了或者不识别,最后终于在量产吧找到了FirstChip的最新版本,才量产成功的。 FirstChip中要修改的地方不多:主要就是修改以下Bin(改为U盘实际大小,产品设定(感觉不需要修改也可以) 就像我,我的是SMI(慧荣) (PS:我不知道现在的量产部落还要钱,我下载的SMI文件在我的blog地址可以下载) 【博客编辑修改时间于:2022年6月23日10时38分】 我就下载的是下载次数最多的一个文件: 运行之后: 它会自动检测你的U盘: 读条完成后,把勾选上,点击STAR就行啦。 因为我已 经修复了,所以页面显示不到。 这是修复成功之后的截图!!! 看到此条博客的友友,用到了记得点个赞诺~

简单网页计算器代码

注:本人为初学者,欢迎各位大神指教 在线试一试 简单计算器实现效果: HTML代码counter.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>计算器</title> <link rel="stylesheet" type="text/css" href="css/counter.css" /> <script type="text/javascript" src="js/counter.js"></script> </head> <body> <div class="counter"> <div class="counter_top" > <form> <input type="text" id="top" value="" /> </form> </div> <div class="counter_down"> <form> <input type="button" class="CE" value="清屏" onclick="cl(this.value)" /> <input type="button" class="CE" value="退格" onclick="cl(this.value)"/> <div class="down_right" id="cou"> <input type="button" class="cou" value="÷" onclick="eva(this.value)"/> <input type="button" class="cou" value="×" onclick="eva(this.value)"/> <input type="button" class="cou" value="-" onclick="eva(this.value)"/> <input type="button" class="cou" value="

RT-Thread uart2串口dma idle接收不断帧

硬件STM32F407,IDE使用RT-Thread Studio。 uart2串口使用这两个引脚: 功能IO端口UART2-TXPA2UART2-RXPA3 UART2 - DMA接收配置 先使能DMA接收,RX缓冲区可以稍微调大些。 board.h 中添加宏,来使能 RX_DMA。 既然都打开了 board.h,再顺便把时钟源改为外部晶振。 编写 UART2 DMA 接收测试代码。 发生接收事件后,会触发回调。回调内记录本次接收的消息长度,并发送信号量。线程内接收到信号量后开始执行后续的任务,调试输出接收到的长度和内容。 main.c #include <rtthread.h> #define DBG_TAG "main" #define DBG_LVL DBG_LOG #include <rtdbg.h> #include "drivers/serial.h" rt_device_t u2_dev = RT_NULL; struct serial_configure u2_cfg = RT_SERIAL_CONFIG_DEFAULT; struct rt_semaphore u2_rx_sem; rt_thread_t u2_recv_thread; rt_size_t u2_rx_len = 0; rt_err_t u2_rx_callback(rt_device_t dev, rt_size_t size) { u2_rx_len = size; // 记录消息长度 rt_sem_release(&u2_rx_sem); return RT_EOK; } void u2_recv_entry(void *parameter) { char rx_buf[256]; rt_size_t len = 0; while (1) { rt_sem_take(&u2_rx_sem, RT_WAITING_FOREVER); // 等待信号量 len = rt_device_read(u2_dev, 0, rx_buf, u2_rx_len); rx_buf[len] = '\0'; rt_kprintf("

中国地图的shp文件获取,包含省级

1、下载地图json文件 网址:http://datav.aliyun.com/portal/school/atlas/area_selector http://datav.aliyun.com/tools/atlas/index.html 2、点击下载文件 3、点开https://mapshaper.org/ 选择文件并输出 export

PCB板框的绘制——AD19

pcb板框的绘制当然首先要切换到keep out 层才行 找到设置,找到keep out 假如我们要绘制一个矩形的板框,我们选择线径就可以 手动绘制一个矩形的板框 我们需要让我们的板子边框按照我们所绘制的走线来定义。记得先选中我们绘制的边框(整个框选后再点击设计找到“按选择对象定义”) 这样就好了,我们可以切换到3d效果查看一下 按数字键3即可,返回按2 我们还可以放置4个固定孔上去 孔径我选择3mm焊盘用3mm孔也设置为3mm 先在左下角绘制一个参考线我们将固定孔的中心对准这个参考线交点即可,等之后调整好固定孔的位置后,可以将绘制的参考线删除掉。 我们选中目标按下m键,将其移动到指定位置即可 就像上面这样,记得删除掉参考线。 其余3个固定孔可以使用ctrl+c 然后选择参考点最后Ctrl+V来实现,可以使用空格调整方向 以上仅是记录不做交流

Long类型转换精度丢失问题解决

在后台返回给前端的时候 默认的情况下是由JACKSON进行转换成JSON的,但是数据还是Long类型所以给前端变成了丢失精度。只要在后台返回给前端的时候数据为字符串就可以解决这个问题了。 由此我们可以采用的方式有两种: 1. 全局设置 全局设置 之后 所有的返回给前端都是返回了字符串 2. 局部设置一个序列化器 在哪里使用哪里添加即可 第一种: package com.it.common.jackson; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @Configuration public class JacksonConfig { /** * Jackson全局转化long类型为String,解决jackson序列化时传入前端Long类型缺失精度问题 */ @Bean public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { Jackson2ObjectMapperBuilderCustomizer cunstomizer = new Jackson2ObjectMapperBuilderCustomizer() { @Override public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) { //变成字符串 jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance); } }; return cunstomizer; } } 第二种(定义序列化器): package com.it.common.util; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.

Excel-VBA 快速上手(一、宏、VBA、过程、类型与变量、函数)

文章目录 一、Excel VBA 介绍1.1. 宏1.2. Visual Basic 编辑器 二、VBA - 定义过程三、VBA - 类型与变量四、VBA - 函数1. 普通函数2. 可选参数的函数3. 参数有默认值的函数4. 调用函数时指定参数名称传值5. 不定长参数列表的函数 一、Excel VBA 介绍 VBA(Visual Basic for Applications),是一种用来扩展 Microsoft Office 功能的编程语言,常见的是用来扩展 Excel 功能,为 Excel 添加自动化脚本,而从提高 Excel 的办公效率 1.1. 宏 宏是录制 Excel 操作过程,然后自动生成 VBA 代码的工具,通过宏可以避免编写大量的 VBA 代码,能更简单的实 现 Excel 自动化,但是宏具有局限性,当要实现逻辑更复杂的功能时,还是需要编写 VBA 代码 1. 录制宏 Microsoft Office 中自带 VBA 相关插件, 但是本文使用的是 WPS Office,需要自行安装插件才能支持 VBA 功能, 如果找不到插件的下载地址,可以留言邮箱 WPS 中录制宏很简单,按下面步骤操作即可: 在 Excel 中点击 开发工具 -> 录制新宏从这一刻开始,对 Excel 的操作都会被录制下来,想停止时点击结束录制即可 附上一张 WPS 中录制宏的完整操作动图,录制的内容是,为 C1 单元格添加 =SUM(A1,B1) 表达式:

springboot+flowable工作流三三来迟

springboot集成flowable工作流之梅开三度,常言道温故而知新,咱也回故一下。 1、使用flowable-ui制作流程图 运行flowable-6.6.0官方demo,打开网址:http://localhost:8080/flowable-ui,输入账号admin/test登录即可,如下 进入APP.MODELER.TITLE创建流程,之后可以导出流程到项目中直接使用。 流程图如下 导出的工作流文件如下 <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef"> <process id="leave4" name="请假审批" isExecutable="true"> <startEvent id="start" name="开始" flowable:formFieldValidation="true"></startEvent> <userTask id="student" name="学生" flowable:assignee="${studentId}" flowable:formFieldValidation="true"> <extensionElements> <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete> </extensionElements> </userTask> <userTask id="teacher" name="老师" flowable:assignee="${teacherId}" flowable:formFieldValidation="true"> <extensionElements> <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete> </extensionElements> </userTask> <exclusiveGateway id="gate1"></exclusiveGateway> <userTask id="header" name="校长" flowable:assignee="${headerId}" flowable:formFieldValidation="true"> <extensionElements> <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete> </extensionElements> </userTask> <exclusiveGateway id="gate2"></exclusiveGateway> <endEvent id="end" name="结束"></endEvent> <sequenceFlow id="flow1" sourceRef="start" targetRef="student"></sequenceFlow> <sequenceFlow id="

dim层-商品表设计

设计总线矩阵 开始分析相关的维度表比如商品维度表,如果它们只有个别的事实表需要的维度比如支付方式就可以通过维度退化减少操作减少空间 dim-商品维度的建表语句 DROP TABLE IF EXISTS dim_sku_full; CREATE EXTERNAL TABLE dim_sku_full ( `id` STRING COMMENT 'sku_id', `price` DECIMAL(16, 2) COMMENT '商品价格', `sku_name` STRING COMMENT '商品名称', `sku_desc` STRING COMMENT '商品描述', `weight` DECIMAL(16, 2) COMMENT '重量', `is_sale` BOOLEAN COMMENT '是否在售', `spu_id` STRING COMMENT 'spu编号', `spu_name` STRING COMMENT 'spu名称', `category3_id` STRING COMMENT '三级分类id', `category3_name` STRING COMMENT '三级分类名称', `category2_id` STRING COMMENT '二级分类id', `category2_name` STRING COMMENT '二级分类名称', `category1_id` STRING COMMENT '一级分类id', `category1_name` STRING COMMENT '一级分类名称', `tm_id` STRING COMMENT '品牌id', `tm_name` STRING COMMENT '品牌名称', `sku_attr_values` ARRAY<STRUCT<attr_id :STRING,value_id :STRING,attr_name :STRING,value_name:STRING>> COMMENT '平台属性', `sku_sale_attr_values` ARRAY<STRUCT<sale_attr_id :STRING,sale_attr_value_id :STRING,sale_attr_name :STRING,sale_attr_value_name:STRING>> COMMENT '销售属性', `create_time` STRING COMMENT '创建时间' ) COMMENT '商品维度表' PARTITIONED BY (`dt` STRING) STORED AS ORC -- ORC 有利于统计分析 LOCATION '/warehouse/gmall/dim/dim_sku_full/' TBLPROPERTIES ('orc.

踩坑-Tomcat(servlet)在启动(加载)是执行两次

博客 不知道大家在使用Tomcat时,有没有遇到过运行或者启动项目时,页面被执行了两次的问题。 可能发生过,但是你没有发现。 首先看一下问题是怎么样的。 问题演示 这是一段jsp代码,说实话这玩意有点老了,不懂jsp的请听我解释这一段代码。 我们定义一个全局变量i,i = 0。 我们定义一个无参无返回值方法,void add(),这个方法中使用i++来自加。 我们在下一句,add()调用这个方法。 然后将i的值输出在页面。 我刚开始觉得答案肯定是1,也必须是1。 但是,当我运行起来发现。 ????居然是2? 我甚至怀疑是代码的问题...... 于是我在add()方法里面输出一下日志。 我发现,这不是之间将i变成了2,而是add()方法被调用了两次! 可是代码里面明明只调用一次啊? 我去浏览器搜索相关案例,发现还真有几例,哈哈哈,浏览器万能。 经过一系列排查,发现是Tomcat针对你的项目运行了两次。 原因 为什么会运行两次呢? 因为你的项目本来就放在Tomcat的默认webapp目录下(tomcat在启动时肯定会加载1次),然后又在server.xml中做了配置,为了达到访问根就可以访问你的项目(这样Tomcat就又加载1次),结果,Tomcat就会加载两次。 你可能也并没有将项目放到webapp目录下,但是你的IDEA工具给你了个项目映射,将你的项目映射到了webapp下。 也可以这样说,Tomcat启动时,先加载appBase中配置的webapps目录下的项目,然后再去加载docBase中配置的项目,因为docBase的相对路径(/xxx)是在webapps目录下,所以会被加载两次。 总的来说,就是Tomcat的sever.xml的配置做了一次无用功,导致运行了两次。 如何解决? 首先,我们有三种方法,我们一个个说。 先记住这两个是啥: docBase是web应用和本地路径,path是Tomcat访问这个应用的URL路径。 第一个方法 办法1、不要将 hello 应用放在Tomat的默认webapp目录下,把它移出去,然后在server.xml中修改docBase的值为项目所在位置的绝对路径就可以了。 在Tomcat中的conf目录中,在server.xml中的,<host/>节点中添加: <Context path="项目的URL路径" docBase="Web应用和本地路径" debug="0" privileged="true"> </Context> 第二个方法 删除掉server.xml中 Context 的手动配置,这样就不会加载两次,因为项目在webapp下,所以在访问时,就只能是:http://ip:port/项目地址 这样来访问了。 如果说,你项目已经移入了webapp目录,但是还是一样,那你IDEA配置应该还是映射状态。 就像这样: 这样仍然处于映射状态,至于怎么配置请自行研究,我是直接去Tomcat的bin里面启动的。 第三个方法 在Tomcat的conf目录中,新建 Catalina(注意大小写)\localhost目录,在该目录中新建一个xml文件,名字可以随意取,只要和当前文件中的文件名不重复就行了,该xml文件的内容为: <Context path="项目的URL路径" docBase="Web应用和本地路径" debug="0" privileged="true"> </Context> 尾述 jsp是一个很老的技术,我不是特别喜欢,但是找到一个问题是对自己很好的一个提升,所以我觉得这个时间很值,尽管这个技术不是特别重要。 好的程序是改出来的,好的bug是找出来的。

Java jdk1.8如何配置环境变量

在安装好了JDK之后,就要配置环境变量 进入环境变量后,需要在系统设置中安设三步 1.系统变量框下的新建中,加入: JAVA_HOME C:\Program Files\Java\jdk1.8.0_65 其中变量名是固定的,变量值的话就是你所安装的jdk的路径,如果默认就是下面这个,如果安装jdk路径修改了的话,就要改成你安装的绝对路径 复制的路径就是 变量值 2. Path中新建两项:(新建第一项也可) %JAVA_HOME%\bin %JAVA_HOME%\jre\bin 上移至第一,是为了防止不同版本JDK的环境变量导致java和javac的版本不一致,而无法正常编译成功 3. 系统变量框下的新建中,加入: CLASSPATH .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar; 其中.表示当前目录 类似与第一步一样(变量值是一致的,可以直接复制,不要有多余的空格) 检验是否安装成功 在命令提示符中(win+R快捷键在输入cmd)输入java -version和javac -version(两个出现的版本需要一致) 如果java 和javac版本不同,因为在安装这个版本之前,安装了其他版本,并且先前配置环境变量操作不当。 解决方案一般是在配置环境变量的第二步中的第三小步中没有把当前系统变量移到第一。 Dos编译Java程序 另外配置好了环境变量之后就可以编译Java程序了,在dos窗口中编译Java程序 如:编译D盘Test文件目录下的 HelloWorld.java 1. 切换到需要编译文件的文件目录中,输入D:回车,然后 输入 cd Test 2. 进行编译 输入 javac HelloWorld.java (生成字节码文件) 3. 运行 输入 java HelloWorld

【已解决】--go_out: protoc-gen-go: Plugin failed with status code 1.

解决:--go_out: protoc-gen-go: Plugin failed with status code 1. 方法一 1. option参数 ​ 在.proto文件中添加 option go_package = "./;ProtoModel"; // 对应:生成位置;包名 2. go install ​ 下载Go语言的protoc插件 go install github.com/golang/protobuf/protoc-gen-go@latest ​ 会在<GOPATH>/bin下生成protoc-gen-go.exe文件,这也是导致抛出以上异常的原因。 3. 成功!

Vue3 nextTick 源码分析

Vue3 nextTick 源码分析 vue版本 3.2.37 前言 在之前的Vue2分析中,提到了Vue2的nextTick是维护了一个callbacks数组,每次更新过程中只插入一个微任务,执行放在callbacks数组中的回调。 而Vue3不同,Vue3的nextTick和Promise基本没什么区别,set过程的更新看似也不再依赖,nextTick进行。仅仅只是将创建一个resovled状态的Promise,将传入的函数放入回调中罢了。以下是vue3的nextTick源码: const resolvedPromise = /*#__PURE__*/ Promise.resolve(); let currentFlushPromise = null; function nextTick(fn) { const p = currentFlushPromise || resolvedPromise; return fn ? p.then(this ? fn.bind(this) : fn) : p; } 正因为如此,同样的代码,在Vue2和Vue3中会有不同的表现。参考以下代码: Promise.resolve().then(()=>{ console.log('开始的Promise回调') }) this.$nextTick(()=>{ console.log('第一次nextTick的回调') }) Promise.resolve().then(()=>{ console.log('修改数据之前的Promise回调') }) this.name = 'kirito' // 这里进行赋值操作 Promise.resolve().then(()=>{ console.log('修改数据之后的Promise回调') }) this.$nextTick(()=>{ console.log('最后的nextTick的回调') }) 以上代码的运行结果,在Vue2中是: 开始的Promise回调 第一次nextTick的回调 最后的nextTick的回调 修改数据之前的Promise回调 修改数据之后的Promise回调 只要调用了nextTick或者对数据进行了变更,那么放在之后的Promise回调,一定是排在后面执行的。 而同样的代码: const name = ref('yuuki') const test2 = () => { Promise.

基站组网架构

1、基站的概念 基站即公用移动通信基站是无线电台站的一种形式,是指在一定的无线电覆盖区中,通过移动通信交换中心,与移动电话终端之间进行信息传递的无线电收发信电台。 简单的来说,基站用来保证我们在移动的过程中手机可以随时随地保持着有信号,可以保证通话以及收发信息等需求。基站需要通过天线来进行消息的收发。在移动通信网络中基站的作用负责接收、处理与发送无线信号、以及将无线信号转换成易于传输的光/电有线传输信号。 2、4G基站设备的组网架构 为了降低端到端时延,4G采用了扁平化的网络架构。将原来的3级网络架构“扁平化”为2级:分为eNodeB和核心网。 如图所示每一个4G基站eNodeB的构成主要包含基带单元BBU和射频单元RRU两部分,两者之间采用光纤接口进行连接。 4G基站基本采用分布式基站的架构。同时,中国移动提出并推动的C-RAN架构也逐渐推广。C-RAN架构将BBU的功能进一步集中化、云化和虚拟化,每个BBU可以连接10-100个RRU,进一步降低网络的部署周期和成本。 与传统的分布式基站不同,C-RAN打破了远端无线射频单元和基带处理单元之间的固定连接关系。每个远端无线射频单元不属于任何一个基带处理单元实体。每个远端射频单元上发送和接收信号的处理都是在一个虚拟的基带基站完成的,而这个虚拟基站的处理能力是由实时虚拟技术分配基带池中的部分处理器构成的。 3、5G基站的组网架构 5G网络考虑业务多样性,对网络的灵活部署提出了更高的需求,为满足5G网络的需求,运营商和主设备厂商等提出多种无线网络架构。按照协议功能划分,3GPP标准化组织提出了面向5G的无线接入网功能重构方案,将由4G BBU、RRU两级架构演进到CU、DU和RRU/AAU三级架构,如图所示。在此架构下,5G的BBU基带部分拆成CU和DU两个逻辑网元,而射频单元以及部分基带物理层底层功能与天线构成AAU。天线侧采用Massive MIMO技术,射频模块与天线结合,一体化集成。 对于CU/DU部署方案,由于DU难以实现虚拟化,CU虚拟化目前存在成本高、代价大的挑战;分离适用于mMTC小数据分组业务,分离有助于避免NSA组网双连接下路由迂回,而SA组网无路由迁回问题。因此5G部署初期,采用CU/DU合设部署方案。CU/DU合设部署方案可节省网元,减少规划与运维复杂度,降低部署成本,减少时延(无须中传),缩短建设周期。 未来随着5G垂直行业等新业务需求,可基于MEC边缘云,后续采用CU-DU分离方式。CU-DU分离架构优势显著,但也存在一定问题。CU-DU分离架构的三大显著优势为:实现基带资源的共享,提升效率;降低运营成本和维护费;更适用于海量连接场景。CU-DU分离架构可能遇到的三大问题包括: 1)单个机房的功率容量有限; 2)网络规划及管理更复杂; 3)时延问题。 基于显著的优劣势对比,运营商在5G建设初期会以CU-DU合设的部署方案为主,未来将视业务的需要选择是否向分离架构演进。对于几大设备商来说,目前两种架构都已可以实现,早期阶段CU-DU 合设方案在技术上更为成熟。

K8s 管理工具 kubectl 详解

文章目录 一、陈述式管理1. 陈述式资源管理方法2. k8s 相关信息查看2.1 查看版本信息2.2 查看资源对象简写2.3 查看集群信息2.4 配置kubectl自动补全2.5 查看日志2.6 基本信息查看2.6.1 查看master节点状态2.6.2 查看命名空间 2.7 命名空间操作2.7.1 查看default命名空间的所有资源2.7.2 创建命名空间app2.7.3 删除命名空间app 2.8 deployment/pod操作2.8.1 在命名空间kube-public创建副本控制器(deployment)来启动Pod(nginx-test)2.8.2 描述某个资源的详细信息2.8.3 查看命名空间kube-public中pod信息2.8.4 登录容器2.8.5 删除(重启)pod资源2.8.6 若无法删除,总是处于terminate状态,则要强行删除pod2.8.7 扩缩容2.8.7.1 扩容2.8.7.2 缩容 2.8.8 删除副本控制器 2.9 增加/删除label2.9.1 增加label2.9.2 删除label 3. K8S模拟项目3.1 项目的生命周期3.2 创建kubectl run命令3.3 发布kubectl expose命令3.3.1 Service的作用3.3.2 Service的类型3.3.3 查看Pod网络状态详细信息和Service暴露的端口3.3.4 查看关联后端的节点3.3.5 查看service的描述信息3.3.6 查看负载均衡端口3.3.7 访问查看3.3.8 查看访问日志 3.4 更新kubectl set3.4.1 获取修改模板3.4.2 查看当前nginx的版本号3.4.3 将nginx版本更新为1.153.4.4 监听pod状态3.4.5 查看pod的ip变化3.4.6 重新查看nginx版本号 3.5 回滚kubectl rollout3.5.1 查看历史版本3.5.2 执行回滚到上一个版本3.5.3 执行回滚到指定版本3.5.4 检查回滚状态 3.6 删除kubectl delete3.6.1 删除副本控制器3.

Java 多人聊天室

Java实训做的多人聊天室,效果如图: 功能: 能够实现多个客户端之间的互相聊天,服务端来负责接收数据和转发数据。每个客户端可以自己设置和修改自己的名称,并传给服务器让其他客户端知道。当有客户端加入和退出时,群聊里每个客户端都有提示。(优化了异常检测,意外断开终止时也能不报错并提示用户xxx退出聊天室)当服务器异常断开或正常退出,客户端都可以提示并且程序不报错。服务端能够实时的显示在线的人数、 关键技术: 集合(服务端并不是对一个客户端进行操作,是多个客户端之间来回通信充当转发数据的功能。服务端需要创建一个集合用来存放服务端连接对象。这样只要监听到客户端发送过来的数据,就可以遍历整个集合,转发给每一个客户端)多线程(客户端通过主线程来发送数据,还需要再启动一个线程来不断循环接收服务端转发过来的消息。服务端主线程使用while循环来不停的接收socket连接,然后为每个客户端的socket通道分配一个子线程接收)网络TCP传输的嵌套字socket(实现客户端和服务端之间的数据传输,选择TCP更安全可靠)IO流(通道间的数据传输需要用到io流) 服务端代码: import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.ArrayList; import java.util.Iterator; public class ServerChar extends JFrame { private static final int PORT = 8888; JTextArea jta = new JTextArea(); JScrollPane jsp = new JScrollPane(jta); private JPanel south = new JPanel(); //面板 private JLabel jb = new JLabel(); private JButton stopBtn = new JButton("

原生DOM与虚拟DOM

首先,我们需要搞清楚两个概念,什么是原生dom,什么是虚拟dom?传统的开发模式原生JS或JS操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程。在一次操作中,我需要更新10个DOM节点,浏览器收到第一个DOM请求后并不知道还有9次更新操作,因此会马上执行流程,最终执行10次。虚拟DOMWeb界面由DOM树(树的意思是数据结构)来构建,当其中一部分发生变化时,其实就是对应某个DOM节点发生了变化。一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。虚拟DOM的好处用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。

MyBatis如何实现多表查询

目录 写在前面 手动处理映射关系(xml配置方式) 数据库表及关系 一对一查询 一对多查询 Mybatis注解实现多表查询 基本注解的分类 注解中的 一对一映射 注解中的 一对多映射 写在前面 在数据库中表与表的关系可以分为: 一对一、一对多、多对多、多对一。在Mybatis中,多对一的关系可以看成一对一的关系。 这里我会把一对一和一对多的关系用xml配置方式以及注解方式总结一下如何实现多表查询。 手动处理映射关系(xml配置方式) 数据库表及关系 我们以学校中老师和课程之间的关系为例,一个老师可以教多门课程,一个课程对应的老师是一个。所以老师对课程一对多关系,课程对老师是一对一关系(我的表格关系是这样)。表如下图所示: 一对一查询 一对一查询步骤如图所示: 首先我们在课程实体类中加入老师成员变量表示一对一映射。 在课程接口中提供查询所有方法findAllCourse(),以便加载时调用。 然后配置课程层的xml文件使用resultMap标签,注意一对一的关系映射使用的是association 最后通过测试类找到与每一个课程相关的授课老师 一对多查询 一对多查询步骤如图所示: 在老师实体类中加入课程集合成员变量,表示一对多映射关系。 在老师接口中提供查询老师教授的所有课程的方法以便加载时调用。 然后再配置老师层的xml文件使用resultMap标签,注意一对多的关系映射使用的是collection 最后通过测试类找到与一个授课老师教授的多个课程 Mybatis注解实现多表查询 基本注解的分类 可以在接口文件中直接利用注解中的增删改查对应关键字语句,简化了配置文件,如下图所示: 注解中的 一对一映射 一对一使用one属性的@One注解 property代表实体类中声明的属性,column代表传入后面select语句中的参数 select代表查询本条数据时所用的方法的全限定名 注解中的 一对多映射 一对多使用many属性的@Many注解 注意:mapper.xml和注解可以共存搭配使用,但xml中的resultMap和注解中的results不能同时附给同一条SQL语句

uniapp webSocket聊天功能

<template> <view class="content"> <view class="cul-wrapper"> <block v-for="(item,index) in msgs" :key="index"> <view class="cul-date">{{formatDate}}</view> <view :class="item.isme?'msg-me':'msg-service'" :id="'msg-'+index"> <view class="msg-text"> <view class="msg-text-content"> <text>{{item.msg}}</text> </view> </view> </view> </block> </view> <view class="operation"> <input type="text" v-model="msgInfor"/> <image src="../../static/image/voice.png" style="width: 48rpx;height: 48rpx;" :style="{'margin':msgInfor ? '0 30rpx' : '0 40rpx'}"></image> <image v-show="!msgInfor" src="../../static/image/moreOption.png" style="width: 48rpx;height: 48rpx;"></image> <button v-show="msgInfor" class="btn" type="default" @click="sendMsg">发送</button> </view> </view> </template> <script> import {mapGetters, mapState} from 'vuex'; export default { data() { return { msgInfor:'', msgs: [ { isme:'1', msg:'我是客户' }, { isme:'', msg:'我是客服' } ],//消息列表 socketOpen:false, //是否连接 path:"

Vue-uniapp笔记

一、Pages生命周期 uni-app 支持如下页面生命周期函数: 函数名说明平台差异说明最低版本onInit监听页面初始化,其参数同 onLoad 参数,为上个页面传递的数据,参数类型为 Object(用于页面传参),触发时机早于 onLoad百度小程序3.1.0+onLoad监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参),参考示例onShow监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面onReady监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发onHide监听页面隐藏onUnload监听页面卸载onResize监听窗口尺寸变化App、微信小程序、快手小程序onPullDownRefresh监听用户下拉动作,一般用于下拉刷新,参考示例onReachBottom页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据。具体见下方注意事项onTabItemTap点击 tab 时触发,参数为Object,具体见下方注意事项微信小程序、QQ小程序、支付宝小程序、百度小程序、H5、App、快手小程序、京东小程序onShareAppMessage用户点击右上角分享微信小程序、QQ小程序、支付宝小程序、字节小程序、飞书小程序、快手小程序、京东小程序onPageScroll监听页面滚动,参数为Objectnvue暂不支持onNavigationBarButtonTap监听原生标题栏按钮点击事件,参数为ObjectApp、H5onBackPress监听页面返回,返回 event = {from:backbutton、 navigateBack} ,backbutton 表示来源是左上角返回按钮或 android 返回键;navigateBack表示来源是 uni.navigateBack ;详细说明及使用:onBackPress 详解 (opens new window)。支付宝小程序只有真机能触发,只能监听非navigateBack引起的返回,不可阻止默认行为。app、H5、支付宝小程序onNavigationBarSearchInputChanged监听原生标题栏搜索输入框输入内容变化事件App、H51.6.0onNavigationBarSearchInputConfirmed监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的“搜索”按钮时触发。App、H51.6.0onNavigationBarSearchInputClicked监听原生标题栏搜索输入框点击事件(pages.json 中的 searchInput 配置 disabled 为 true 时才会触发)App、H51.6.0onShareTimeline监听用户点击右上角转发到朋友圈微信小程序2.8.1+onAddToFavorites监听用户点击右上角收藏微信小程序2.8.1+ 仅百度小程序基础库 3.260 以上支持 onInit 生命周期 其他版本或平台可以同时使用 onLoad 生命周期进行兼容,注意避免重复执行相同逻辑 不依赖页面传参的逻辑可以直接使用 created 生命周期替代 onLoad(获取参数,一次) – onShow(每次切换tabbar/回退都会触发)— created (也是一次,不能获取参数)– onReady(也是一次,,可以操作dom对象) - mounted(也是执行一次,只不过数据变更会再次触发) 二、uniapp路由内置 vue-router 这个组件,已经内置,不需要自己手动集成 1:在pages目录下新建对应页面模板即可 2:它会自动创建好的页面模板注册到pages.json中。 3:然后我们可以在页面中或者tabbar去进行调整和转发 4:一种是标签的方式,一种是js的方式 <navigator url="../detail/detail"> open-type 默认是:navigate 保留当前页面,跳转到应用内的某个页面 特点是:在头部左上角有一个回退按钮 open-type 是:redirect 关闭当前页面,跳转到应用内的某个页面。 特点是:没有回退按钮。也没有tabbar。如果要离开就代表退出 一般用来:跳转登录,跳转注册。

两步快速查询电脑GPU的方法

两步快速查询电脑GPU的方法 ①打开任务管理器 ②点击任务管理器的性能选项即可查看是否有GPU 参考文章: https://blog.csdn.net/weixin_42008966/article/details/103508896.

网络通信协议的发展及socket/netty理解

一:网络通信诞生 诞生于冷战期间,起源于美国军方,发展行对成熟后,交予大学及商业机构,开发出民用网络。 二:核心协议发展 ARPANET(ARPA网) 最初的军事研究使用的网络,网络交换的核心是使用专门的小型计算机执行消息交换,专门的计算机被称为接口信息处理器(IMP)。 IMP间使用电话线连接,同时期还有英国、法国等国家发展不同类型的计算机网络。 NPC(网络控制协议) 随着网络的发展,互联的趋势增强。基于互联的需求,发展出了“数据包交换”的数学理论,使用数据包交换成为计算机之间通过网络通信的基本方式,如果进行具体的通信则涉及网络协议。最初的网络协议,称为网络控制协议,即NCP。 MAC 当多个用户同时发送信息的时候,会发生“碰撞”,好比教室里几个人同事大声说话,没人能听清楚说了什么。此时需要一个算法规范来约束,因此产生了MAC--介质访问控制。 以太网、CSMA/CD 基于MAC改进,使用电缆线把局部的计算机连接起来,构成一个局域网,称为以太网。以太网(Ether)描述这个系统的本质特征:物理介质(如网线)传播数字电信号。 改进MAC,减少碰撞的算法--如果碰撞了,同时闭口n秒再说话,而这个n是随机数。例如,你和小明同时发,碰撞了,两个人同时退1s,再发送,还是碰撞,但是,如果你选了一个随机数1,退1秒,他选一个随机数3,退3秒,这样就避开了。改进后的介质访问控制协议称为CSMA/CD。 TCP/IP 在之前的网络通信,都是在一个局域网中通信。互联网的不断发展,推进产生了不同子网的相互连接通信--开放架构网络概念:互联网对每一个子网没有特别的要求,现有的网络不做任何改变就可以连入互联网;网络必须能够处理数据包传输丢失的情况,一个数据包丢失之后应该随即重发;子网之间通过网关和路由器连接;此外,网络中不存在全局的控制。 由此 IMP进化为TIP(更强大的中断接口处理器) NCP+数据包丢失重发,进化出TCP 不同子网间连接,产生IP 三:网络硬件如何连接 国际互联网-->NAP(网络接入节点)-->NSP(网络服务商)-->ISP(本地网络服务商)-->用户网络 中国的互联网通过海底电缆和美国的互联网连接。接入的网络由国家的网络服务商的通信基础设置构建国内的骨干网,再通过地方的网络服务商构建的网络连接到用户 宏观上分为三个部分:1/和国际互联网连接 2/建立国内的骨干网 3/用户接入网络 四:通讯介质 电缆线-->光纤、无线电波、卫星、星链 光纤:使用光的折射原理 无线电波:电磁波传输原理。常用技术为调幅、调频、调相 卫星:电磁波 五:网络七层模型 物理层 解决问题:实现两台机器互联,机器和机器之间是怎么通信? 1.两台机器互联的物理链路,物理介质。网线(双绞线)光纤、无线电波---基本连接 2.存在形式:01001二进制形式存在,电信号、比特流 数据链路层 解决问题:01010比特流其实是没有什么意思的数据,变成有意义的数据呢?确认这个数据是发给我的呢? 比特流进行处理:分组。8位为一组,一个字节,依次按顺序发送数据。 数据格式:帧 定义发送地址,MAC地址---网卡--身份证,唯一的。寄件人地址(源MAC地址)----收件人地址(目的MAC地址) 网络层 解决问题:主机A-B-C-D-E--主机F??路径很多条,怎么选择最优路?要怎么知道对方的MAC地址? 怎么知道对方的MAC地址? ---ARP协议(address resolution Protocol),通过IP地址知晓MAC地址 判断是否在同一个子网,怎么判断?---IP协议 路径很多,怎么选择最优路径?---一组协议 路由协议,动态路由协议(RIP,OSPF,BGP)。 数据格式:数据包 传输层 解决问题:发送数据多,数据包很大需要很长时间??中间网络中断,重传??数据包是否完整的,正确的? 对发送的数据进行封装---TCP协议,UDP协议,使数据包一个一个按顺序依次发送 两个应用通信(qq--qq),怎么判断是用qq来回应的呢,而不是其他应用程序呢,-----定义端口的概念,通过端口寻找对应的程序,对应的进行数据处理。 会话层 解决问题:断点续传功能 可以从校验点继续恢复数据进行重传,适用大文件 自动收发,自动寻址的功能 表示层 解决问题:操作系统win mac linux 语法不一样,不同系统之间进行通信 翻译工作,提供一种公共语言,通信。 应用层 解决问题:字节流格式,不好识别,不好操作。 定义了各种应用协议,规范数据格式: HTTP协议,HTTPs协议,FTP协议,DNS协议,TFTP,SMTP协议等等 六:HTTP和TCP/IP协议的关系 我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有很多,比如HTTP、FTP、TELNET等,也可以自己定义应用层协议。WEB使用HTTP协议作应用层协议,以封装HTTP文本信息,然后使用TCP/IP做传输层协议将它发到网络上

Vue3+ts 配置i18n国际化,解决i18n警告

Vue3全局配置国际化i18n,封装hook,解决i18n警告 1. 安装包 yarn add vue-i18n@next 2. 基础步骤 导入创建i18n方法 // locale/index.ts import { createI18n } from "vue-i18n"; 创建i18n实例对象,导出 // locale/index.ts // 导入全局中英文配置对象 import en from './en-US' import zh from './zh-CN' // 默认读取本地存储语言设置 const defaultLocale = localStorage.getItem('locale') || 'en-US' const i18n = createI18n({ locale: defaultLocale,// 默认语言 fallbackLocale: 'en-US',// 不存在默认则为英文 allowComposition: true,// 允许组合式api messages: { 'en-US': en, // 标识:配置对象 'zh-CN': zh }, }) export default i18n 在main.ts中导入并挂载 // main.ts import { createApp } from 'vue' // 导入创建App实例 import App from '.

path.join() 、path.basename() 和 path.extname()

简要介绍 path.join() 方法,用来将多个路径片段拼接成一个完整的路径字符串 path.basename() 方法,用来从路径字符串中,将文件名解析出来 path.extname() 方法,可以获取路径中的扩展名部分 代码详情 // 导入path模块 const path = require('path') // path.join 拼接路径链接 // __dirname 自动定位到当前目录 const pathUrl = path.join(__dirname,'/files/1.txt') console.log('===================path.join start==============='); console.log(pathUrl); //E:\MYDownload\前端\学习内容\我的前端代码\11-nodeJs\day2\files\1.txt console.log('===================path.join end================='); // path.basename() 获取文件名 const fpath = '/a/b/c/index.html' const bname = path.basename(fpath) console.log('=================path.basename start============='); console.log(bname); // index.html console.log('=================path.basename end==============='); // path.extname() 获取文件拓展名 const ename = path.extname(fpath) console.log('=================path.extname start============='); console.log(ename); // .html console.log('=================path.extname end==============='); 运行结果 安装配置NodeJs环境 想用这三种方法,首先需要安装配置NodeJs环境,我把链接放在这里,请前往菜鸟教程去看具体的教程,这里我就不多做赘述了。 Node.js 安装配置 | 菜鸟教程 (runoob.

距离度量 —— 闵可夫斯基距离(Minkowski Distance)

Python学习系列文章:👉 目录 👈 文章目录 一、概述二、计算公式1. 闵氏距离公式2. 闵氏距离的参数 p3. 闵氏距离的缺点 一、概述 闵可夫斯基距离 (Minkowski Distance),也被称为 闵氏距离。它不仅仅是一种距离,而是将多个距离公式(曼哈顿距离、欧式距离、切比雪夫距离)总结成为的一个公式。 二、计算公式 1. 闵氏距离公式 首先假设两个 n 维变量 A ( x 11 , x 12 , . . . , x 1 n ) A(x_{11},x_{12},...,x_{1n}) A(x11​,x12​,...,x1n​) 与 B ( x 21 , x 22 , . . . , x 2 n ) B(x_{21},x_{22},...,x_{2n}) B(x21​,x22​,...,x2n​)。 对于这两个 n 维变量,则有闵氏距离公式为: d 12 = ∑ k = 1 n ∣ x 1 k − x 2 k ∣ p p d_{12}=\sqrt[p]{\sum_{k=1}^n|x_{1k}-x_{2k}|^p} d12​=pk=1∑n​∣x1k​−x2k​∣p ​

借助于OpenCV将多帧图像合并为视频及OpenCV录制视频并保存

目录 一、写在前面二、视频录制保存三、多帧图片合成为视频三、小总结 Author:qyan.li Date:2022.6.19 Topic:借助于OpenCV将多帧图像合并为视频及OpenCV录制视频并保存 一、写在前面 ​ ~~~~~~~~ 最近一直在网络上检索借助于OpenCV如何将多帧图像合并为视频,了解到可以借助于VideoWrite()函数实现,顺便学习一下VideoWriter函数使用,以及借助于此函数实现摄像头视频录制并保存以及将多帧图片合成为视频。 二、视频录制保存 ​ 老样子,先上代码,方便大家参考借鉴: def VideoWrite_Function(): cap = cv2.VideoCapture(0) # ## 输出摄像屏幕的大小尺寸 # width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # print("width:", width, "height:", height) ## width = 640,height = 480 fourcc = cv2.VideoWriter.fourcc('m', 'p', '4', 'v') # 指定输出视频的格式 ## VideoWriter(fileName,fourcc,fps,frameSize[:,iscolor])创建VideoWriter对象 ## 调用摄像头录制视频并保存时,文件后缀名为mp4无法正常播放,改为mp4v后可以正常进行播放 ## 参考文献:https://blog.csdn.net/bgmcat/article/details/120751531 out = cv2.VideoWriter('./output.mp4v', fourcc, 20, (640,480)) while (cap.isOpened()): ## 添加判断,相机是否成功打开 ret, frame = cap.read() if ret: ## 调用Canny进行图像的边缘检测 # frame = cv2.

MeterSphere教程:使用脚本更新“配置环境->通用配置下的环境级的全局变量”

首先看一下metersphere(以下简称ms)的设计:在调试和运行用例的时候,需要选择一个环境去运行,再进行接口测试的时候,接口的url和路径是分开的。这样做的一个好处就是相同的case,可以直接指定不同的环境去执行,一套脚本可以同时去校验不同的环境有没有问题。 接下来看一下在ms里面配置环境的时候,是怎么去配置环境变量的: 在这个地方定义的环境变量的话,就有点类似于在postman里面自己定义的环境分组,然后在里面添加的变量。需要在运行的时候,选择对应的这个环境,然后就可以获取到对应的数据。 接下来讲一下在代码中怎么去定义变量,使得变量出现在上图的通用配置下面: 通过脚本编辑右边的那个项目环境下面,可以快速的调出设置环境变量的demo案例: vars.put(${__metersphere_env_id}+"key","value"); # 会体现在环境配置的通用配置下面,会持久化 vars.put("key","value") #在用例运行的过程中才会去设置,运行完,估计变量就获取不到了 上面讲了2种设置方式的区别,今天主要来讲一下第一种可以在哪些场景下去使用,以我目前在公司使用的举例: 1、将登录的token存进去。 因为考虑到后期用例可能会并行执行,如果是在用例的脚本中去调用登录接口,并行的时候可能会出问题 ,账号单点登录的话,每个场景都去调用会造成干扰,貌似平台现在不支持测试计划级别的脚本,也就是执行测试计划前只跑一次的那种,现在貌似只有每个场景前执行一次的脚本。 2、在针对微服务做接口自动化的时候,由于每次在rancher上重新部署服务后,服务的ip地址和端口会变化,可以写一个脚本将动态ip存储到环境级别的变量中,这样的话,就不用每个接口都去调用获取ip的脚本,可以缩短脚本运行的时间。 如果你在使用metersphere平台做接口自动化的过程中有遇到问题, 欢迎一起探讨。 往期精彩回顾 MeterSphere教程:windows下ubuntu子系统安装metersphere环境用于本地练习 MeterSphere教程:接口返回结果为空时如何进行断言 MeterSphere教程:操作redis集群

企业级WEB应用服务器TOMCAT

文章目录 1web技术1.1 HTTP协议和B/S 结构1.2 前端三大核心技术1.2.1 HTML1.2.2 CSS(Cascading Style Sheets)层叠样式表1.2.3 JavaScript 2Java基础2.1 WEB架构2.1.1 web资源和访问2.1.2 后台应用架构 2.2 Java2.2.2 java 组成2.2.4 JDK 3tomcat基础功能3.1 Tomcat历史和介绍3.1.1 WEB应用服务器3.1.2 Tomcat 介绍3.1.3 Tomcat 各版本区别 3.2 安装 Tomcat3.2.1 基于包安装 Tomcat3.2.2 二进制安装 Tomcat 3.3 tomcat的文件结构和组成3.3.1 目录结构3.3.3 组件3.4.4 应用部署实现 4结合反向代理部署tomcat服务4.1 常见部署方式介绍4.2 利用 nginx 反向代理实现全部转发置指定同一个虚拟主机4.3 利用nginx实现动静分离代理4.5 实现 tomcat 负载均衡4.5.1 HTTP的无状态,有连接和短连接4.5.2 会话保持方式4.5.3实现 https 的负载均衡 5tomcat session负载集群5.1 配置说明5.2 实战案例: 实现 Tomcat Session 集群 6memcached6.4 Memcached 工作机制6.4.1 内存分配机制6.4.2 懒过期 Lazy Expiration6.4.4 集群 6.5 安装和启动6.5.1 yum安装 **6.

设计模式——抽象工厂

抽象工厂 目的 抽象工厂是一种创建型的设计模式,它允许您生成一系列相关的对象而无需指定它们的具体类。 问题 假设您正在创建一个家具商店模拟器。你的代码由以下类组成: 系列相关产品,如:Chair + Sofa + CoffeeTable。 这个家族的几个派生。例如Chair + Sofa + CoffeeTable产品有Modern、Victorian、ArtDeco等多种版本。 您需要一种方法来创建单独的家具对象以便它们与同类的其他对象相匹配。顾客收到不匹配的家具时会很生气。 此外在向程序添加新产品或产品族时,您不希望更改现有代码。家具供应商经常更新他们的目录,您不会希望每次都更改核心代码。 解决方案 抽象工厂模式建议的第一件事是为产品家族的每个不同产品(例如,椅子、沙发或茶几)显式地声明接口。然后您可以让所有具体产品遵循这些接口。例如所有椅子变体都可以实现chair接口;所有的咖啡桌变体都可以实现CoffeeTable接口。 下一步是声明抽象工厂——一个包含所有产品的创建方法列表的接口(例如createChair,createSofa,createCoffeeTable)。这些方法必须返回由我们前面提取的接口表示的抽象产品类型:Chair、Sofa、CoffeeTable等等。 现在具体产品呢?对于产品系列的具体产品,我们基于AbstractFactory接口创建一个单独的工厂类。工厂是返回特定类型产品的类。例如ModernFurnitureFactory只能创建ModernChair, ModernSofa和ModernCoffeeTable物件。 客户端代码必须通过各自的抽象接口与工厂和产品一起工作。这允许您更改传递给客户端代码的工厂类型以及客户端代码接收的产品变体而不会破坏实际的客户端代码。 结构 抽象产品为组成产品族的一组相关的产品统一声明接口。 具体产品是抽象产品的各种实现,按类型分组。具体产品(Victorian/Modern)必须实现抽象产品的接口。 抽象工厂接口声明了一组创建抽象产品的方法。 具体工厂实现了抽象工厂的创建方法。每个具体工厂对应于一组具体产品并且只创建这些具体产品。 虽然具体的工厂实例化具体的产品,但是它们的创建方法的签名必须返回相应的抽象产品。这样,使用工厂的客户机代码就不会与它从工厂获得的产品的特定变体耦合。客户端可以使用任何具体的工厂/产品变体,只要它通过抽象接口与它们的对象通信。 伪码 这个例子说明了如何使用抽象工厂模式来创建跨平台的UI元素而不用将客户端代码耦合到具体的UI类,同时保持所有创建的元素与所选的操作系统一致。 在跨平台应用程序中相同的UI元素的行为应该是相似的,但在不同的操作系统下看起来会有些不同。此外确保UI元素与当前操作系统的风格匹配是您的工作。您不希望您的程序在Windows中执行时呈现macOS控件。 抽象工厂接口声明了一组创建方法,客户端代码可以使用这些方法来生成不同类型的UI元素。具体的工厂对应于特定的操作系统并创建与特定操作系统相匹配的UI元素。 它是这样工作的:当一个应用程序启动时,它检查当前操作系统的类型。应用程序使用这个信息从一个匹配操作系统的类中创建一个工厂对象。剩下的代码使用这个工厂来创建UI元素。这可以防止创建错误的元素。 使用这种方法,客户端代码不依赖于工厂和UI元素的具体类只要它通过抽象接口处理这些对象即可。这也允许客户端代码支持将来可能添加的其他工厂或UI元素。 因此你不需要每次在你的应用程序中添加一个新的UI元素变体时修改客户端代码。你只需要创建一个新的工厂类来产生这些元素并稍微修改应用程序的初始化代码,以便它在适当的时候选择那个类。 // The abstract factory interface declares a set of methods that // return different abstract products. These products are called // a family and are related by a high-level theme or concept. // Products of one family are usually able to collaborate among // themselves.

Nginx location(正则)

Nginx location(正则) 1、nginx location2、匹配标识说明3、不同uri及特殊字符组合匹配的顺序说明4、示例 1、nginx location location 指令的作用是根据用户请求的URI来执行不同的应用。 location使用的语法为: location [=|~|~*|^~] uri { ······ } 解释 location[=||*|^~]uri{…}指令匹配标识匹配的网站地址匹配URI后要执行的配置段 2、匹配标识说明 1.~ 匹配内容区分大小写 2.~* 匹配内容不区分的小写 3.!~ 取反 4.^~ 但多个匹配同时存在,优先匹配 ^~匹配的内容;不做正则表达式的检查 (优先处理) 3、不同uri及特殊字符组合匹配的顺序说明 顺序不用URI及特殊字符组合匹配匹配说明1location = / {}精确匹配 /2location ^~ /image/{匹配常规字符串,不做正则表达式匹配检查3location ~* \.(gif|jpg|jpeg)$ {正则匹配4location /documents/ {匹配常规字符串,如果有正则,则优先匹配正则5location / {所有location 都不能匹配后的默认匹配 4、示例 测试代码 #location / { # root html; # autoindex on; # index index.html index.htm; #} location / { return 401; } location = / { return 402; } location /documents/ { return 403; } location ^~ /images/ { return 404; } location ~* \.

KVM批量删除虚拟机脚本

virsh list |awk 'NR>2{print $2}' > 2.txt for line in `cat 2.txt` do virsh snapshot-list $line |awk 'NR>2{print $1}' > 1.txt for time in `cat 1.txt` do virsh snapshot-delete --snapshotname $time $line echo "$line" sleep 0.2 done done

【Spring注解驱动开发】01-Import 注册组件

笔记来源:✨尚硅谷Spring注解驱动教程(雷丰阳源码级讲解) 文章目录 Import 注册组件1、@ImportImport 注解源码解析ImportSelector 接口源码解析ImportBeanDefinitionRegistrar 接口源码解析 2、测试 Import 注册组件 1、@Import 1)包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)【局限于自己编写的组件】2)@Bean【导入的第三方包中的组件】3)@Import【快速给容器中导入一个组件】 1)@Import(要导入到容器中的组件):容器中会自动注册这个组件,id 默认是全类名2)ImportSelector:返回需要导入的组件的全类名数组3)ImportBeanDefinitionRegistrar:手动注册 Bean 到容器中 Import 注解源码解析 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Import { /** * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar} * or regular component classes to import. */ Class<?>[] value(); } @Import 只能作用于类上,可以传入“一组” Class 类 可以是需要导入到容器中的组件 Bean可以是 ImportSelector 实现类可以是 ImportBeanDefinitionRegistrar 实现类 ImportSelector 接口源码解析 public interface ImportSelector { String[] selectImports(AnnotationMetadata importingClassMetadata); } 其中定义一个 selectImports 方法,提供了一个入参 AnnotationMetadata:可以获取当前类的注解信息 getAnnotationTypes:获取注解类型集合getMetaAnnotationTypes:获取元注解类型集合hasAnnotation:是否有某个注解hasMetaAnnotation:是否有某个元注解hasAnnotatedMethods:是否有注解方法getAnnotatedMethods:获取注解方法集合 public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata { Set<String> getAnnotationTypes(); Set<String> getMetaAnnotationTypes(String annotationName); boolean hasAnnotation(String annotationName); boolean hasMetaAnnotation(String metaAnnotationName); boolean hasAnnotatedMethods(String annotationName); Set<MethodMetadata> getAnnotatedMethods(String annotationName); } ImportBeanDefinitionRegistrar 接口源码解析 public interface ImportBeanDefinitionRegistrar { public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry); } 其中定义一个 registerBeanDefinitions 方法,提供了两个入参

django+vue3+el-tree树形组件菜单

前言 在一些消费的app,eg京东,淘宝。我们经常在pc端上面会出现点击电视 ,就会有小米、海尔、等各种品牌的电视。这也就是咱们说的树形组件 --也就是一级标签,二级标签,三级标签。(以上是小编举的例子,如有不对请多指教包容) 这个篇文章主要的效果图 既然说了是Django+vue3+el-tree就了一列大纲他的步骤分那些 1.分析django 中所需要的表 2.django 中主要实现的业务逻辑 2.1django 重写后台管理 3.vue3中使用elementUI配置 4.vue3使用el-tree的布局 5.el-tree上附加的功能 那小编带着来第一步 1.分析django 中所需要的表 1.菜单表:id,name(菜单名),pid(父类),status(1显示0不显示) class Menu(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=38, verbose_name='菜单名称') pid = models.IntegerField(default=0, verbose_name='父id') status = models.IntegerField(default=1, verbose_name='显示1不显示0') def __str__(self): return self.name class Meta: db_table = 'meum_menu' 2.django 中主要实现的业务逻辑 增加菜单 查看菜单 修改菜单 删除菜单 添加菜单接口 请求:postApi:http://127.0.0.1:8000/meum/add_menu/描述:添加菜单名,父类,状态(显示不显示)添加条件 获取前端传来的数据, 判断 菜单名字是空的? 判断 改子类的父类是否存在 id=pid 参数名称 参数类型 参数描述 实例 name string 菜单名称 冰箱 Pid int

iOS解决UITableView 滑动卡顿问题

1.最常用的就是cell的重用, 注册重用标识符 如果不重用cell时,每当一个cell显示到屏幕上时,就会重新创建一个新的cell如果有很多数据或者滚动cell的时候,就会堆积很多cell。如果重用cell,为cell创建一个ID每当需要显示cell 的时候,都会先去缓冲池中寻找可循环利用的cell,如果没有再重新创建cell 2.避免cell的重新布局 cell的布局填充等操作 比较耗时,一般创建时就布局好如可以将cell单独放到一个自定义类,初始化时就布局好 3.提前计算并缓存cell的属性及内容 当我们创建cell的数据源方法时,编译器并不是先创建cell 再定cell的高度 而是先根据内容一次确定每一个cell的高度,高度确定后,再创建要显示的cell,滚动时,每当cell进入凭虚都会计算高度,提前估算高度告诉编译器,编译器知道高度后,紧接着就会创建cell,这时再调用高度的具体计算方法,这样可以方式浪费时间去计算显示以外的cell 4.减少cell中控件的数量 尽量使cell得布局大致相同,不同风格的cell可以使用不用的重用标识符,初始化时添加控件,不适用的可以先隐藏我们在cell上添加系统控件的时候,实际上系统都会调用底层的接口进行绘制,大量添加控件时,会消耗很大的资源并且也会影响渲染的性能。当使用默认的UITableViewCell并且在它的ContentView上面添加控件时会相当消耗性能。所以目前最佳的方法还是继承UITableViewCell,并重写drawRect方法。在实现drawRect方法的时候,它的参数rect就是我们需要绘制的区域,在rect范围之外的区域我们不需要进行绘制,否则会消耗相当大的资源。 5.离屏渲染的问题 渲染耗时比较长 为图层设置遮罩(layer.mask)将图层的layer.masksToBounds / view.clipsToBounds属性设置为true将图层layer.allowsGroupOpacity属性设置为YES和layer.opacity小于1.0为图层设置阴影(layer.shadow *)。为图层设置layer.shouldRasterize=true具有layer.cornerRadius,layer.edgeAntialiasingMask,layer.allowsEdgeAntialiasing的图层文本(任何种类,包括UILabel,CATextLayer,Core Text等)。使用CGContext在drawRect :方法中绘制大部分情况下会导致离屏渲染,甚至仅仅是一个空的实现不要使用ClearColor,无背景色,透明度也不要设置为0 6.使用局部更新 如果只是更新某组的话,使用reloadSection进行局部更新 7.加载网络数据,下载图片,使用异步加载,并缓存 我们时常会看到这样一个现象,就是加载时整个页面卡住不动,怎么点都没用,仿佛死机了一般。原因是主线程被阻塞了。所以对于网路数据的请求或者图片的加载,我们可以开启多线程,将耗时操作放到子线程中进行,异步化操作。这个或许每个iOS开发者都知道的知识,不必多讲。 8.少使用addView 给cell动态添加view 在初始化cell的时候就将所有需要展示的添加完毕,然后根据需要来设置hide属性显示和隐藏。 9.按需加载cell,cell滚动很快时,只加载范围内的cell 滑动很快时,只加载目标范围内的cell,这样按需加载(配合SDWebImage),极大提高流畅度。 10.不要实现无用的代理方法,tableView只遵守两个协议 11.缓存行高: 如果cell高度不动态变化,可设置预估行高来减少计算量,cell行高的计算比较消耗性能如果cell高度动态变化,提高cell高度的计算效率之外,对于已经计算出的高度,我们需要进行缓存,对于已经计算过的高度,没有必要进行计算第二次。estimatedHeightForRow不能和HeightForRow里面的layoutIfNeed同时存在,这两者同时存在才会出现“窜动”的bug。所以我的建议是:只要是固定行高就写预估行高来减少行高调用次数提升性能。如果是动态行高就不要写预估方法了,用一个行高的缓存字典来减少代码的调用次数即可 值得注意的是,设置了预估行高和没设置预估行高,tableview代理的执行顺序不一样 12.其他方案: 当我们需要圆角效果时,可以使用一张中间透明图片蒙上去使用ShadowPath指定layer阴影效果路径使用异步进行layer渲染(Facebook开源的异步绘制框架AsyncDisplayKit)设置layer的opaque值为YES,减少复杂图层合成尽量使用不包含透明(alpha)通道的图片资源尽量设置layer的大小值为整形值直接让美工把图片切成圆角进行显示,这是效率最高的一种方案很多情况下用户上传图片进行显示,可以让服务端处理圆角使用代码手动生成圆角Image设置到要显示的View上,利用UIBezierPath(CoreGraphics框架)画出来圆角图片 在iOS应用中,UITableView应该是使用率最高的视图之一了。几乎所有自带的应用中都能看到它的身影,一些常见的应用(QQ/微信/天猫)也离不开他的身影。 然而在使用第三方应用时,却经常遇到性能上的问题,普遍表现在滚动时比较卡,特别是table cell中包含图片的情况时。 以上方案可解决大部分tableView卡顿问题,在优化tableView的时候,针对性的优化一下,这种问题就不会存在 如有其他问题可联系:qq - 1640165742 手机:188****7754

集群、微服务与分布式

集群: 同一个业务,部署在多个服务器上(不同的服务器运行同样的代码,干同一件事) 集群是指将多台服务器集中在一起,每台服务器都实现相同的业务,做相同的事情。如果一台死机,另一台可以起作用。 但是每台服务器并不是缺一不可,存在的作用主要是缓解并发压力和单点故障转移问题。我们可以利用一些廉价的符合工业标准的硬件构造高扩展、高性能、低成本、高可用的系统。 什么是分布式? 分布式:一个业务分拆多个子业务,部署在不同的服务器上(不同的服务器,运行不同的代码,为了同一个目的。而集群指的是将几台服务器集中在一起,实现同一业务。) 好处: 模块之间独立,各做各的事,便于扩展,复用性高 高吞吐量 简单说,分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。 什么是微服务? 维基上对其定义为:一种软件开发技术- 面向服务的体系结构(SOA)架构样式的一种变体,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够独立地部署到生产环境、类生产环境等。另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据上下文,选择合适的语言、工具对其进行构建。 每个模块可以采用不同的语言编写,数据库也可以不一样。 1.分布式与微服务的关系 分布式和微服务的架构很相似,只是部署的方式不一样而已。 生产环境下的微服务肯定是分布式部署的,分布式部署的应用不一定是微服务架构的。比如集群部署,它是把相同应用复制到不同服务器上,但是逻辑功能上还是单体应用。 2.集群和分布式的区别 集群模式是不同服务器部署同一套服务对外访问,实现服务的负载均衡。区别集群的方式是根据部署多台服务器业务是否相同,分布式中的每一个节点,都可以做集群。而集群并不一定就是分布式的。而分布式,从窄意上理解也跟集群差不多。但是它的组织比较松散,不像集群有一个组织性,一台服务器垮了,其它的服务器可以顶上来。分布式的每一个节点都完成不同的业务,一个节点垮了那这个业务就不可访问了。 简单说 集群就是一台主机接收请求然后分发请求到不同的服务器(每台服务器业务相同),单纯的提高访问量的承载,做好负载均衡就好。 分布式是不同的服务器放不同的业务,松耦合,实现小的模块升级的时候不会让每个模块都停止。 3.在开发中我们可以将分布式和集群分开吗? 针对这个问题,我们可以根据分布式的介绍看出,其主要的功能是用来将我们的系统模块化,将系统进行解耦的,方便我们以后的维护和开发的。但是其并不能解决我们的并发问题,也无法保证我们的系统在服务器宕机后的正常运转。 而集群恰好弥补了分布式的缺陷,集群就是多个服务器处理相同的业务。这在一方面可以解决或者说改善我们系统的并发问题,一方面可以解决我们服务器如果出现一定数量的宕机后,系统仍然可以正常运转。 好的设计应该是分布式和集群相结合,先分布式再集群。具体实现就是业务拆分成很多子业务,然后针对每个子业务进行集群部署。这样每个子业务如果出了问题,整个系统完全不会受影响。 简单实现微服务。(后面加入注册中心后代码会有改动,就不会直接访问接口) 注入ResrfulAPI /** * @author : LeeGaki * @date : 2022/6/18 8:03 * 面向面试编程 --> 李佳琪 */ @Configuration public class RestBean { @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } } 利用RestfulAPI做到调用接口,模块之间用http通信。 /** * @author : LeeGaki * @date : 2022/6/18 8:02 * 面向面试编程 --> 李佳琪 */ @RestController @RequestMapping("

分支限界法求0-1背包问题

使用分支限界法求解01背包问题,3个物品,重量和价值,背包容量 (1)画出解空间树 (2)Say如何剪枝 (3)求出最优解 假设物品的个数n=3,背包容量W = 30, 重量w =(16,15,15),价值v =(45,25,25) (1)队列式(FIFO)分支限界法:按照队列先进先出(FIFO)原则选取下一个结点为扩展结点。 (2)优先队列式分支限界法:按照优先队列中规定的优先级选取优先级最高的结点成为当前扩展结点。 (1)画出解空间树 迷惑点:解空间树书上给的是一个排列树,把超重的情况也画出来了,其实是无用功,那么如果考虑超重的话,就在D的时候就已经超重了,就不需要画出来,但是书上却把它称之为搜索空间树,所以我们画解空间树应该画哪种呢? a.队列分支限界法 b.优先队列分支限界法:当前价值高的节点优先 (2)Say如何剪枝 限界函数代码: void bound(NodeType &e) //计算分支结点e的上界 { int i=e.i+1; int sumw=e.w; double sumv=e.v; while((sumw+w[i]<=W)&&i<=n) { sumw+=w[i]; sumv+=v[i]; i++; } if(i<=n) //余下物品只能部分装入 e.ub=sumv+(W-sumw)*v[i]/w[i]; else //余下物品全部可以装入 e.ub=sumv; } 剪枝:如果超重需要剪枝,如果这个结点对应的上界不比当前最优值更大,则说明相应的子树不含问题的最优解,因此该节点也需要剪枝。 (3)求出最优解 由图可知最优解为50,装第二个和第三个物品。

使用CubeMX快速搭建FREERTOS

如何使用STM32快速搭建FREERTOS 小编之前一直使用正点原子家的产品, 最近准备学习学习TOUCHGFX,要用到HAL+RTOS,原子家的使用起来不方便。于是琢磨着使用STM32CUBEMX直接生成FREERTOS+HAL工程。非常方便,在这里分享给大家 CUBEMX安装 安装CUBEMX前, 需要安装JAVA,注意一定要下载64位JAVA才可,大家可参考这个教程https://jingyan.baidu.com/article/3aed632ede2a2f7010809114.html进行下载安装 2022.6.18更新:Win11,cubemx6.5版本,已经不需要自己安装java环境了。 CUBEMX软件可以直接从官网下载最新版,链接在此https://www.st.com/en/development-tools/stm32cubemx.html。软件直接选择最新版安装。 装好后(首次打开可能需要更新, 耐心等待),点击下图位置安装相应的支持包。我这里使用的是正点原子F407最小系统板 创建第一个工程 1,选择MCU型号 2,配置SYS 点击左边的SYS选项卡,选择Debug模式为SW。注意这里将时钟源换成了Timer1。这个时钟源是给HAL库提供时钟的。HAL在运行一些超时监测的代码时, 需要一个时钟源提供时钟,一般用systick。但是本例中systick被RTOS占用。所以修改HAL时钟源为Timer1. 3,配置RCC 这里使用的是外部晶振 4,配置一个LED引脚 5,配置RTOS V1, V2 的区别我也不大清楚。网上也没搜索到,这里暂且V1。 大家有知道的请在下方留言。FREERTOS内部的配置不在这里介绍了,这里不改动任何配置 6,配置时钟树 我用的是外部8M晶振, 参数如下。这里仅做参考,大家根据自己的情况配置,只要不报错应该都没啥问题。 7,配置工程选项 注意:Application structure 建议选择Advanced, 小编之前用Basic, 在代码重新生成时会把usercode覆盖掉(代码书写位置正确的情况下也会这样)。 8,生成代码 小编比较习惯用单独的.c.h 文件,大家按习惯来 9,测试 至此, 我们的RTOS已经完成了, 为了验证一下,我们可以写一个小程序验证一下 生成的freertos里, cubemx已经为我们创建好了一个任务defaultTask, 我们直接将我们的代码塞到这个线程里即可。 在freertos.c里添加如下代码: void StartDefaultTask(void const * argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ for(;;) { HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);//翻转电平 osDelay(500); //延时+调度 } /* USER CODE END StartDefaultTask */ } 。

MATLAB系统辨识

MATLAB系统辨识 最终效果:自动调出PID三项对应的参数,控制效果很不错。 目的:通过matlab,辨识出系统的传递函数,找到最理想的PID参数。 优点:1.节省“盲调PID”的时间。2.在辨识出传递函数后,还可以设计专门的控制器,达到经验调参不能做到的效果,逼近完美。 用到的工具:1.matlab的system identification 和PID tunner app2.simulink。 在使用系统辨识工具箱之前,我们先使用simulink模块生成我们需要的仿真模型以及输入输出数据。 搭建完整个仿真模型后,点击simulink模块的绿色开始按钮,即可开始进行仿真。 点击图3中灰色齿轮,打开参数配置界面,点击“Solver”选项,将“Type”选项设置为Fixed-step,同时,将Fixed-step size与输入信号周期一致,这里选取0.02。 我们将输入信号的周期设定为0.02秒,这里也可以设定为其他值,该周期需要与系统辨识工具箱中的周期匹配,否则会导致系统辨识结果错误。 搭建完简单的仿真模型之后,我们就可以开始使用Matlab系统辨识工具箱了。 在Matlab命令窗口输入“ident”命令,即可打开系统辨识工具箱。或则点击APP中的system identifaication Matlab系统辨识工具箱组成说明。 首先,我们需要导入需要辨识的输入数据,点击“Import data”按钮,工具箱出现下拉选项,这里我们选择“Time domain data”。 这里的Input与Output输入框中的名称即为上文中通过Simulink模型仿真生成的输入-输出信号对应的工作区中的变量名称。Samping interval即为采样间隔,该值需与上文Simulink仿真模型中的信号仿真步长一致,否则,会导致辨识结果出现偏差。将参数配置完成后,点击“Import”按钮,结束输入信号的导入。 输入信号预处理选项,其中包括滤波器、数据转换等功能。 模型辨识设置,这里选择过程模型。 过程模型参数配置,这里选择无零点、无时延无积分环节的一阶系统模型作为待辨识模型,配置完参数后,勾选“Display Progress”按钮,点击“Estimate”按钮开始进行辨识。 过程模型辨识结果,左边对话框显示了模型辨识精度及相对误差。 双击右边对话框中的辨识模型结果P1,弹出如下对话框,由图可知,Kp = 1,Tp1 = 1,与上文中Simulink仿真模型中的传递函数参数吻合,至此,完成了整个简单的系统辨识工具箱的使用流程。

AutoSar软件文档阅读

AutoSar软件文档阅读 1 名词及术语说明2 阅读整体架构解释文档3 阅读感兴趣的文档(SWS)3.1 介绍及功能概述3.2 相关标准文档3.3 与其他模块关系3.4 模块功能详细介绍(子模块标准及相互关系)3.5 API生成及调用3.6 配置详细介绍 4 相关文档下载说明 1 名词及术语说明 Autosar文档数量及内容特别多,Autosar对于不同人员的规范也是不同,文档名称也做了类似区分。 Autosar文档命名:AUTOSAR+类型+模块名称 类型简写类型中文解释类型英文全称EXP解释ExplainationRS需求规范Requirement SpecificationSRS软件需求规范Softeware Requirement SpecificationSWS软件规范Softeware SpecificationTPS模板规范Template SpecificationMOD建模ModelMMOD元模型MMOD Meta Model 2 阅读整体架构解释文档 对于软件开发人员或者是OEM开发人员,直接查看模块的需求规范或是开发规范理解会比较困难。因此从Autosar的整体架构解释文档阅读,对于架构有个比较清楚的认知后进行模块文档学习会比较容易理解。 文档推介(软件开发及设计人员):AUTOSAR_EXP_LayeredSoftwareArchitecture.pdf 3 阅读感兴趣的文档(SWS) 对于软件开发规范文档,结构比较固定主要包括10个章节,内容和目录高度关联。个人认为比较重要的模块为:1、3、5、7、8、10。下面以DCM模块为例介绍文档包含的内容。 3.1 介绍及功能概述 1 Introduction and functional overview内容包括: 1、该模块在开发、生产及售后的作用 2、该模块在软件架构中的具体作用 3.2 相关标准文档 3 Related documentation主要介绍遵循的规范文档(和Autosar的版本相关),某些标准文档的下载地址等 3.3 与其他模块关系 5 Dependencies to other modules主要介绍该模块与其他模块的相互关系以及生成的代码的文件结构等 3.4 模块功能详细介绍(子模块标准及相互关系) 7 Functional specification介绍模块错误处理记录(可以通过DET模块将这些错误上报给Rte)、各个子模块之间的功能及相互关系 3.5 API生成及调用 8 API specification该部分介绍API函数的定义类型及函数接口等 3.6 配置详细介绍 10 Configuration specification这部分主要介绍的是如何配置,配置工具中的配置项基本与该部分介绍的配置项对应 4 相关文档下载说明 Autosar文档下载步骤:

Winform:dataGridView中让某一单元格不可以编辑、修改背景颜色

单元格禁止编辑 private void dataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) { e.Cancel = true; } private void dataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e) { if(e == null) { return; } DataGridViewRow dgr = dataGridView1.Rows[e.RowIndex]; if ((bool)dgr.Cells[columnUsed].Value) { dgr.Cells[columnFilterIndex].Style.BackColor = Color.Lavender; } else { dgr.Cells[columnFilterIndex].Style.BackColor = Color.White; } }

屏蔽百度热搜及首页热榜

背景 Edge浏览器 使用Adblock Plus插件 步骤 Edge浏览器下载地址 (其他浏览器找对应插件的应用市场)https://microsoftedge.microsoft.com/addons/search/adblock%20plus?hl=zh-CN 插件安装完成后,点击图标 直接鼠标选择要屏蔽的元素就行

win10+vs2015+CPU-only caffe环境搭建

记一下过程以防下回重置 本机环境:win10+vs2015+anaconda3 流程 安装vs2015、anaconda3、cmake vs2015 vs2015要下update3(毕竟已经2202年了vs2015太早了老是出问题) 可以直接到这里下:D 安装时记得一定一定选自定义安装(划重点),勾选c++(及web)工具项以及windows SDK 具体勾选情况可以参照这里 记得,万一出情况需要卸载vs,一定一定要删干净!(找找教程)anaconda3 正常安装就好了,具体看这cmake cmake官网直接下就行 python3.5虚拟环境 caffe只支持python3.5和2.7(貌似),所以先用anaconda搭建一个基于python3.5的虚拟环境 开cmd键入 conda create -n caffe-python35 python=3.5 caffe-python35可以替换成你自己想设的虚拟环境名字 进入刚刚创建的虚拟环境 activate caffe-python35 可以用conda也可以直接pip conda install --yes numpy scipy protobuf==3.1.0 six scikit-image pyyaml pydotplus graphviz or pip install numpy scipy protobuf==3.1.0 six scikit-image pyyaml pydotplus graphviz ↑上两段是安完之后copy的这里的,本机配置如下: 此时把你创建的虚拟环境路径放到系统环境变量,也可以直接为图省事挪到第一个,这样一来系统默认就是python3.5了 查看你的虚拟环境位置↓ conda env list caffe配置 跟着官网走↓ git clone https://github.com/BVLC/caffe.git cd caffe git checkout windows 然后进入\scripts找到build_win.cmd,右键编辑 首先是把你刚才添加入环境变量的那个python位置拷贝过来(就是conda env list查看到的位置) 然后

Vue2.x 二次封装双向绑定Selector

目录 项目需求 组件设计 项目需求 1.数据双向绑定 2.支持单选和多选 组件设计 <template> <div class="container placeholder_class"> <el-select v-model="selectedOptions" placeholder="请选择类型" :multiple="multiple" collapse-tags @change="handleChange"> <el-option v-for="(o, i) in options" :key="i" :value="o.value" :label="o.label"></el-option> </el-select> </div> </template> <script> export default { model: { prop: 'value', event: 'change' }, props: { value: { type: Array, default() { return [] } }, multiple: { type: Boolean, default: false } }, data() { return { options: [], //使用v-model无法绑定prop,所以重新创建一个data selectedOptions: this.value } }, watch: { value(newVal) { this.

买了两年CSDN年VIP,用着实在太爽

买2年CSDN的年VIP有多爽及使用攻略! 一、前言 这段时间,一旦打开CSDN就不断的弹出618活动,手机APP打开是这样的 然后在电脑网上打开,一股白嫖之的气息吹来,让人直接忍不住剁手 最后经过近5天的挣扎,我还是受不了CSDN的蛊惑,618不买衣服不买裤子,不买键盘,却花了200元大洋买了CSDN的两年年VIP会员,竟然买都买了,那必须把钱用在刀刃上面,自己假装不后悔的🤣。 二、购买CSDN会员的体验 当我下单购买CSDN的vip之后我整个人都升华了,直接发消息让我抽奖,运气不是很好抽中了8.8元红包 抽奖之后,直接免费领取一件128元的程序员专属CSDN短袖,我直接填写地址白嫖 然后最重要的就是扑面而来的粉丝关注自己的CSDN!但是我们购买CSDN的会员肯定不是为了能得一件衣服抽个奖之类的嘛,当你领取了CSDN的VIP之后,一大波特权来袭! 三、VIP特权 1、下载特权 VIP 购买成功后,在会员有效期内,VIP 可以免费享受以下权益:超级年卡 **400 **次下载立即发放到账,含 VIP 专享资源下载特权和积分资源下载特权,每日下载上限为 20 个资源。 本次618活动期间购买年卡的用户,可额外获赠** 618 次**下载权益,自购买年卡之日起 31 天内有效,即前 31 天使用的下载次数会优先消耗额外获赠的 618 次下载次数,如618 次下载次数消耗完毕,则再正常消耗年卡权益中的下载次数。 我母亲还剩下400次下载机会,做软件开发的我们经常需要下载别人的内容,很多人都去淘宝买,其实下载一次差不多一元,但是这次直接400次,618再送618次,那不就是1018次,做开发的来说稳赚不赔呀! 2、课程及专栏权益 仅限超级会员年卡享受以下权益: 5000+门精品视频课、1000+精选专栏,VIP可以免费学习,权益于2022年4月13日新增; 购单门课程9折,不包含组合课程/套餐课程。戳此查看 >> VIP课程、 VIP专栏,选择心仪内容! 做开发同学都知道,需要不断的学习,虽然哔哩哔哩等平台有很多免费资源,但是CSDN我也看到很多优秀的视频专栏,这便宜简直就是白捡的!全是免费 3、电子书 1000+本电子书免费读,打开CSDNAPP-学习-电子书立即开始阅读(暂不支持其他端口阅读)。 很多同学说,现在出来工作,很多时间没时间看视频,都看书为主,那CSDN就更好了,1207本电子书免费读! 4、VIP身份标识及专享皮肤 VIP身份标识这简直就是装逼利器,比如当某位粉丝打开你的CSDN,一大个CSDN的VIP的大黄色,土豪气息扑面而来,最主要的这个也和QQ空间的会员差不多吧,这里面也可以获得官方更多的推荐,你写的文章阅读的人多了,关注度高了,更容易上热榜了,感觉和专家博主一个段位的! 最好的是七款VIP皮肤直接免费使用,直接给大家看看效果 这是我没买VIP之前的CSDN主页皮肤 买了之后的皮肤,大家看看是不是直接上了一大个档次 5、博客自定义域名 我没买CSDN会员的时候,我的csdn文章链接没域名的,什么都是人家的,虽然写的是自己的博客,但是总感觉不是自己的 这是我申请之后的域名,相当于你在百度上搜索,也能出现我的文章了! 点击我的CSDN地址知道我的CSDN首页:wanghj.blog.csdn.net 点开文章也是自己的域名 6、博文原创保护 大家在CSDN写文章原创还是很重要的,保护自己的博客,虽然没开通vip,也有但是感觉花钱了自己心安! 7、博文内进行个人号推广等特权 可以在写文章的时候推广自己的微信公众号,QQ,QQ群,这简直就是写·博客最好的礼物了,谁都想证明自己推广自己,这个=功能给了我们所有的幻想! 自己添加微信等,然后在文章底部直接展示 直接点一下粉丝就能加自己微信 8、可以自定义模板 自定义模板是我最喜欢的一个界面 这是我没自定义模板之前的一个首页界面 自定义之后,可以直接加微信公众号和我想账户,进行推荐 三、总结 因为一直使用CSDN嘛,也经常在上面写博客,所以我开SDN的会员我还是不后悔的,对自己用处很大,如果你也经常使用CSDN,我感觉开一个会员也是可以的!我办理了我人生中的第一个CSDN年卡,怀着无比激动的心情,我打开了高贵的CSDN会员中心,当我的个人信息栏显示了一个小皇冠时,我知道我已经不是之前的我了,此时此刻我已然是一名高贵的CSDN贵族了! 毫不夸张的的说,成为CSDN会员的那一刻,已经是我此生的巅峰时刻,我想今后再也没有什么可以激起我内心的丝毫微波。 但是随着身体的一阵颤抖一切都变得索然无味了,CSDN年卡除了给了我一顶闪亮的皇冠外就啥也没有留下,徒增的就是我那该死的气质了。

go集成nacos测试grpc负载均衡

简介 nacos官方文档 nacos-sdk-go 本文代码地址 代码 proto syntax = "proto3"; import "google/protobuf/empty.proto"; option go_package = ".;proto"; service Test{ rpc Test(google.protobuf.Empty) returns(TestResponse); } message TestResponse{ string msg = 1; } 输入代码生成对应的go代码 protoc -I . proto.proto --go_out=plugins=grpc:. server package service import ( "context" "go-nacos-demo/load_balance_nacos/server/proto" "google.golang.org/protobuf/types/known/emptypb" "log" ) type Service struct{} func (s Service) Test(ctx context.Context, empty *emptypb.Empty) (*proto.TestResponse, error) { log.Println("收到一个请求") return &proto.TestResponse{Msg: "test"}, nil } package main import ( "fmt" "github.com/nacos-group/nacos-sdk-go/clients" "

Better to Follow, Follow to Be Better: Towards Precise Supervision of Feature Super-Resolution

参考 Towards Precise Supervision of Feature Super-Resolution - 云+社区 - 腾讯云 摘要 虽然最近基于区域建议的CNN模型在目标检测方面取得了成功,但是由于小兴趣区域(small Region of Interest, RoI)所包含的信息有限且失真,小目标的检测仍然比较困难。解决这一问题的一种方法是使用超分辨率(SR)技术来增强小型RoI的特性。我们研究如何提高级的超分辨率特别是对小目标检测,并发现它的性能可以显著提高通过: (1)、利用适当的高分辨率目标特性作为SR的训练监督信号模型。 (2)、匹配输入的相对接受训练领域对低分辨率的特性和目标高分辨率特性。 我们提出了一种新的特征级超分辨率方法,它不仅能正确地解决这两个问题,而且可以与任何基于特征池的检测器集成。在我们的实验中,我们的方法显著提高了Faster R-CNN在清华-腾讯100K、PASCAL VOC和MS COCO三个基准上的性能。对于小目标的改进是非常大的,令人鼓舞的是,对于中、大目标的改进也不是微不足道的。因此,我们在Tsinghua-Tencent 100K上取得了最新的技术水平,在PASCAL VOC和MS COCO上取得了极具竞争力的成绩。 1、简介 自深度卷积神经网络(CNN)出现以来,目标检测方法的性能迅速提高。目前主要有两种方法:基于两阶段建议的模型具有准确性优势,而基于单阶段建议的模型具有速度优势。尽管近年来在目标检测方面取得了巨大的进展,但在某些特定条件下,如小、闭塞或截断,仍然很难检测到目标。在这项工作中,我们的重点是改进小目标检测在基于建议的检测框架,如Faster R-CNN。 基于建议的检测器从根本上存在小目标区域建议太小无法识别的问题。例如,Huang等人表明,小目标的平均精度(mAP)分数大约比大目标低10倍。对于小的建议,感兴趣区域(RoI)池层通常提取复制的特征向量作为box预测器的输入,而box预测器最终在对小目标没有足够详细信息的情况下进行预测。此外,很可能RoI池池化的位置和它在图像中的实际位置是不匹配的。通过RoI align和和PrRoI pooling等先进的池化技术,可以部分缓解这种RoI池的失真。但是,它们没有提供框预测器可以用来更好地检测小目标的附加信息。 为了使得小建议的信息丰富,超分超分辨率是一个很好的方法。由于超分辨整个图像的效率很低,Bai等人提出将小建议的图像像素超分辨为类似于大建议的像素。但是,它的RoI超分辨率无法考虑上下文信息,因为它只关注RoI。该方法利用上下文信息作为建议的特征,通过大范围的连续卷积操作来提取建议的特征。特别是,Perceptual GAN利用生成对抗网络(GAN)对建议特征进行超分辨,提高了对小目标的检测精度。 然而,现有的用于小目标检测的特征级超分辨率模型存在一个明显的局限性:缺乏直接的监督。也就是说,它们的超分辨率模型训练没有明确的目标特征,导致训练不稳定,限制了超分辨率特征的质量。在图像检索任务中,Tan等人表明,低分辨率和高分辨率特征对之间的特征-内容丢失导致了更好的超分辨率特征,具有更快的收敛速度。 对更好的训练不仅是重要构造适当的高分辨率特性为目标,我们的分析还表明,这至关重要的比赛之间的相对接受字段对,尤其是对小RoI(图1)。也就是说,在的图像检索任务只考虑整体图像的特点,相对接受字段不多对高、低分辨率之间的不同特征。另一方面,对于目标检测任务中常见的小RoI,差异非常大,导致小建议的超分辨率质量较差。 在这方面,这项工作的贡献有三个方面: (1)、我们深入研究了现有的特征级超分辨率小目标检测方法,发现:(i)、利用高分辨率目标特征作为监督信号。(ii)、匹配输入与目标特征的相对接受域,显著提高了性能。 (2)、我们提出了一种新的特征级超分辨方法,该方法可以垂直地应用于任何基于特征池的检测器。它充分利用了新目标提取器创建的高分辨率目标特征的直接监督,利用不需要额外参数的卷积,因为它与基础检测器的CNN主干共享参数。此外,我们提出了一种迭代细化生成器作为超分辨特征的新方法。 (3)、利用ResNet-50、ResNet-101、MobileNet等多种CNN骨干,在Tsinghua-Tencent 100K、PASCAL VOC、MS COCO三个基准数据集上,显著提高了Fast R-CNN小目标检测性能。对于小目标的改进是非常大的,令人鼓舞的是,对于中、大目标的改进也不是微不足道的。因此,我们在清华-腾讯100K上取得了最新的技术水平,在PASCAL VOC和MS COCO上取得了极具竞争力的成绩。 2、相关工作 综述了小目标检测的三个主要研究方向。 高分辨率图像:小目标检测的一种直接方法是生成高分辨率图像作为检测模型的输入。Hu等人使用双线性插值获得两次上采样的输入图像,Fookes等人使用传统的超分辨率技术来更好地识别人脸。然而,像级超分辨率还存在两个潜在的问题。首先,超分辨率和检测模型通常是独立训练的;超分辨率模型被训练成生成高分辨率的图像,即使是对于那些由于其独立性而对检测不重要的部分。其次,整体架构可能过于沉重,因为它采用放大的超分辨率图像作为输入,这可能会大大增加推断时间。虽然Haris等人提出了一种端到端联合训练超分辨率和检测模型的模型,但是对与检测任务无关的大量图像执行超分辨率仍然是低效的。SOD-MTGAN不是对整个图像进行超分辨,而是先将RoI池化,然后使用这些池化的RoI训练超分辨模型。虽然他们的工作通过只关注RoI来解决这两个问题,但仍然没有考虑RoI的上下文信息。 高分辨率特征:感知GAN是一种显著的特征级超分辨率小目标检测方法。由于它只关注RoI的特性,所以不存在图像级超分辨率的两个问题。此外,由于这些特征是通过与较大的接收域卷积来提取的,所以SOD-MTGAN的问题也得到了缓解。然而,由于缺乏直接监督,其超分辨率训练可能不稳定;没有训练低分辨率RoI特征对及其对应的高分辨率特征对。相反,它隐含地利用了分类、本地化和对抗性损失。对于图像检索任务,Tan等人在训练特征级超分辨率模型时加入了特征级损失。他们报告说,增加这种更强的约束有助于生成网络产生更快收敛的更好的特征。然而,我们观察到在[34]中这样的直接监督对目标检测是不够的,因为它可能会由于高分辨率和低分辨率特征之间的相对接受域不匹配而误导超分辨率过程。在第3节中,我们将进一步阐述这个问题。 纹理信息:许多研究已经经验证明,上下文信息也有助于检测小目标。如[27]所示,CNNs中来自顶层的特征足够捕获大目标,但太粗糙,无法检测小目标;而来自底层的特征包含的局部信息太具体,对检测大目标没有帮助,但对检测小目标有帮助。因此,许多方法使用额外的层来从多个层构建上下文特性。使用上下文的另一个简单方法是在RoI集中时也考虑附近的区域。Hu等人利用提取周围区域和ROI来检测人脸,因为知道附近区域存在人体是有帮助的。还研究了目标之间的关系信息,以增强检测模型。最后,一些研究建议使用卷积和非卷积层的混合来更好地分割小目标,因为非卷积层覆盖了更大的接收域,而不会丢失分辨率。由于这一特性,我们也使用了卷积层来匹配高分辨率和低分辨率特征之间的相对接受域。第3节提供了更详细的解释。 3、相对感受野不匹配 在这一节中,我们将讨论为什么匹配相对接受域对于获得足够的低分辨率输入特征和高分辨率目标特征非常重要。在此基础上,我们提出了一种新的超分辨率目标提取器。 一种直接的方法是从原始图像中获取较大的ROI,从下采样图像特征超分中获取较小的ROI。不幸的是,就相对接受域而言,这些配对的特征并不完全匹配。为了清楚地了解为什么会出现这种差异,我们在图2中给出了一个带有符号的直观示例。为便于讨论,仅考虑一个水平轴,宽度为w的RoI特征的绝对感受野(ARF)为: 相对感受野(RRF)定义为相对于图像大小的ARF: 让我们讨论输入尺寸如何影响输入尺寸。在0.5倍的下采样输入图像中,图像的宽度为/2,而特征图上的ROI宽度为w/2。我们将ROI在原始图像和下采样图像之间的差异定义为: 其中为常数。式(3)很容易从式(2)推导出来。 根据式(3),当趋近于0时,DRRF收敛于2,当增大时,DRRF收敛于1。也就是说,对于小的RoI,相同RoI的相对接受域(RRF)可以是原始图像和下采样图像的差值的2倍。另一方面,如果建议的规模足够大,那么RRFs也会变得相似。 例如,对于输入图像的ROI ,,如果我们使用Faster R-CNN和ResNet-50主干网,其中= 291, = 16,那么接近1.8。也就是说,下采样图像的RoI的RRF大约是原始图像的1.8倍。Tan等人使用超分特征处理整个图像特征被超分辨的图像检索任务,因此RRF中的差异不显著。相反,对于我们工作中检测的小ROI的超分辨率,RRF的差异非常大,会严重误导超分辨率模型。 4、本文的方法 提出了一种基于两个关键思想的小目标检测特征超分辨方法: (1)、直接监督超分辨发生器; (2)、通过卷积进行感受野匹配。 在基本检测模型的基础上,我们引入了四个附加组件:SR特征发生器和鉴别器、SR目标提取器和小预测器。SR特征发生器作为一种基于GAN的模型,利用SR目标提取器的特征作为目标,在SR特征鉴别器的引导下产生高分辨率的特征。此外,小的预测器是基本检测器中预测器的复制,我们称之为大预测器。大预测器对大建议进行分类和定位的置信度的计算与普通检测器相同,而小预测器对小建议执行相同的任务,这些小建议首先由SR特征生成器进行增强。我们为小型建议设定的门槛为:清华-腾讯(Tsinghua-Tencent)为32×32,VOC和COCO数据集为96×96。图3显示了我们模型的整体架构。我们解释了基于Faster R-CNN的模型,尽管我们的方法可以与任何基于特征池的提议检测器集成。