package main import ( "time" "fmt" ) func main() { limitTime(funcA, 6*time.Second) } func limitTime(f func(),timer time.Duration) { ok := make(chan struct{}) go func() { f() ok<- struct{}{} }() select { case <- time.After(timer): fmt.Println("time out") case <-ok: } } func funcA() { time.Sleep(time.Second*10) fmt.Println("there is a function") }
vue2使用animate css
安装
安装的方式有很多种
1.在html文件中直接引用从github上下载的资源
<link rel="stylesheet" href="vue2-animate.min.css"> 2.如果使用webpack并且用对了css-loader可以使用npm 安装
npm安装包依赖
npm install --save vue2-animate
3.在main.js中引用
require('vue2-animate/dist/vue2-animate.min.css') 或者
import 'vue2-animate/dist/vue2-animate.min.css'; 使用less
@import "<PATH_TO_SOURCE>/src/vue2-animate.less"; 4.使用构建器编译
git clone https://github.com/asika32764/vue2-animate.git
cd vue2-animate
npm install
npm run build #Compiled .css files go to the dist folder
正式使用
1.基本的使用就是在过度元素上使用对应的name属性
<transition-group name="fadeLeft" tag="ul"> <li v-for="item in items" v-bind:key="item"> {{ item }} </li> </transition-group> 2.使用不同的载入载出动画
第一种:使用custom-classes-transition,需要在不同的载入载出动画上加-enter和-leave后缀
<transition name="custom-classes-transition" enter-active-class="bounceLeft-enter" leave-active-class="bounceRight-leave" > <p v-if="show">hello</p> </transition> 第二种:使用in/out类名在动画名后面加上In或者Out
<transition name="
需求:点击表格列为问题的单元格,弹出问题详情。展示为:
在element-ui表格组件中嵌套popover组件,会用到slot(插槽),将自定义的模板(el-popover)插入到表格的某一列中。
HTML代码如下:
<el-table :data="tableData" border :cell-style="cellStyle"> <el-table-column prop="fgsCode" label="机构"></el-table-column> <el-table-column :width="250" prop="content" label="问题"> <template slot-scope="scope"> <!-- popover弹出框显示时可通过contentDetail()调接口获取questionForm数据 --> <!-- 触发方式为click,将popover的箭头显示或隐藏通过设置visible-arrow实现 --> <el-popover @show="contentDetail(scope.row.id)" trigger="click" visible-arrow="false"> <div slot="reference" > <!-- 问题列显示文本 即触发Popover显示的HTML元素 --> <p class="text">{{scope.row.content}}</p> </div> <!-- popover弹出框开始 --> <div class="questionDetail"> <h4 class="questionList title"> <span class="left">问题:</span> <span>{{scope.row.content}}</span> </h4> <!-- questionForm可以调接口获取,这里把数据写死了 --> <!-- 循环遍历questionForm中的数据并显示在popover弹出框中 --> <div :data="questionForm" v-for="(item,index) in questionForm" :key="index" class="questionList"> <div class="left"><span class="right">日期:</span>{{item.handleDate}}</div> <div class="left">{{item.handlePeople}}:<span style="font-size:14px; color:#dcdfe6">回复</span></div> <div class="
string a = "dfdfdd"; s.Substring(expression,start,length); expression:字符串、文本、列或包含列的表达式 start:指定字符串的开始位置 length:指定字符串的长度
报错
参数计数不匹配 原因
报的错
集合已修改,可能无法执行枚举操作 原因
不要在枚举集合的操作,比如Foreach中去执行修改集合的操作,如果需要修改,应先使用ToArray()方法 例如: foreach(var x in MyList.ToArray()) { 执行可能修改MyList的操作 }
var curTable = dataSet.Tables[0]; RemoveEmpty(curTable);//调用方法 //清除datatable上的所有数据 protected void RemoveEmpty(DataTable dt) { List<DataRow> removelist = new List<DataRow>(); for (int i = 0; i < dt.Rows.Count; i++) { bool IsNull = true; for (int j = 0; j < dt.Columns.Count; j++) { if (!string.IsNullOrEmpty(dt.Rows[i][j].ToString().Trim())) { IsNull = false; } } if (IsNull) { removelist.Add(dt.Rows[i]); } } for (int i = 0; i < removelist.Count; i++) { dt.Rows.Remove(removelist[i]); } }
报的错:
CS0649 C# Field is never assigned to, and will always have its default value null 解决方案:
private IEnumerable<Machinetaskhistory> _lstTasks = null;
欢迎您能进来,如果你也和我一样,对接下来的工作行情充满了太多的不确定性,那不妨停下您冲忙前进的脚步,和我一起重新刷新一下你自己的看法和规划吧!
我的提问 2019年Android真的还可以养活你自己?2019年我的工作重心在哪一块?2019年是继续留在原地做技术积累还是考虑跳槽?对过去2018年的总结是否满意? 我能做什么 管理方向(天赋欠缺,暂不做讨论)技术方向 从Android的技术类别来看,工作中主要还是应用层开发为主,可在应用层开发中自己又达到什么一个水平?以下是参考别人的android知识分类所对应的开发水平等级(本内容更新于过去,但依然存在参考价值)。
知识分类图1 知识分类图2 知识点掌握所对应的开发级别 通过以上图对知识点的分类,除了基本知识点特别熟悉和系统核心机制特别不熟悉之外,其他的工作中基本天天遇到,一旦关掉所有参考资料,又似乎只跟他们似曾相识。综上看,对自己2018年的开发等级顶多达一个中级水平,但薪资已远远不足行业等级平均值。
到这里也基本明白了自己2019年我的眼前最棘手的问题就是对各个知识点进行加强巩固,当然我们的目标并不是等级划分,而跟多是薪资待遇的有所提升。
诚然工作中并不是你专修什么专业你就只做什么工作,那么对于我们这个行业来说,我能做的就是快速将工作中所需求的东西学会,并将其运用到项目中、平台中来。
我正在做什么 针对于2018,我虽然主要做负责的是开发,但是平台运维和公司打杂也一概包揽。因为我对自己的规划,前两年还是一个积累过程,并不对工作范围和质量有所要求。只要是公司需求,我只要以最快的速度、最低的成本把这件事情在领导接受的时间内完成下来即可。下面是我过去所涉及到的工作内容,希望在计划的结尾时间应该是用来总结和深入,以达到真正的学为己用。
电视桌面系统app开发电视桌面系统java后台维护开发电视端安防监控app开发手机端智能家居产品控制app开发IPTV系统运维工作公司产品和网站推广工作项目方案文档工作IPTV新建用户出差 我涉及哪些领域 开发方向来说,主要就是android、java、H5以及C、C++等等运维方向主要有IPTV系统维护、服务器搭建和管理、网络管理、网站推广以及产品推广等等打杂角色来说负责各种大小项目方案书等等 总结 通过对过去一年中的工作总结来看,从技术角度来说自己的薪资待遇可以在接收范围之内,但从工作量上来说,还有待提升。但我相信大家都和我一样,作为一枚程序员最不希望的事情就是我们的薪资是根据工作量来含量,希望在新的一年里我们都能用自己的实力来为自己提升工资。
对自己过去的工作重心总结就是,希望在技术为主,运维为辅,推广工作能有个帮手,多一些时间去加强android相关知识以及工作所设计的相关知识(如java后台、ffmpeg、c以及c++等等)。
至于能不能养活自己,对过去的工作是否满意就不做讨论了,眼前的工作就是快速提升自己的基础知识,实在养不活自己的时候再考虑跳槽吧!
应用退居后台,如何在低功耗的情况下保证任务正常运行?本文华为软件功耗专家黄文将分享议题——应用后台功耗经验。
本文将从安卓绿色联盟功耗标准2.0、谷歌后台功耗方案、华为后台功耗方案以及开发者资源使用建议和检测工具五大方面进行全面讲解。
安卓绿色联盟功耗标准2.0 《安卓绿色联盟应用体验标准2.0---功耗标准》详细介绍了应用后台软资源和硬资源的使用标准,查看详情请访问安卓绿色联盟官网。
谷歌后台功耗方案 谷歌从Android M开始着力改善终端的续航表现。Android版本在演进中主要提供如下几个方案。
1.后台位置限制:
对后台应用获取用户当前位置的频率进行限制。
相关链接:https://developer.android.goo...
2.后台服务限制:
限制应用在后台运行服务,并禁止应用通过隐藏/不可见方式调用 CPU 或网络资源。
相关链接:https://developer.android.goo...
3.后台限制:
当系统检测到应用出现不良行为时,系统会向用户询问是否要限制该应用在后台访问设备资源。
相关链接:https://developer.android.goo...
4.谷歌后台功耗方案-Doze(低耗电模式和应用待机模式)
谷歌在Android M版本引入了Doze方案,此方案主要针对后台应用在没有活动的情况下做某些限制。设备未充电且屏幕关闭处于空闲状态一段时间后,系统会进入低耗电或者应用待机模式,对应用行为施加相应限制。
相关链接:https://developer.android.goo...
如图所示,以下是Doze模式各状态说明:
ACTIVE: 设备活动态
INACTIVE:设备不活跃(灭屏、不运动) 等待进入idle.
IDLE_PENDING: 设备准备进入下一阶段
SENSING: 传感器检测设备是否运动
LOCATING: 设备位置变化.
IDLE: 设备进入idle,并尽量长时间保持该状态
IDLE_MAINTENANCE: 退出idle进入“维护期”
谷歌还引入了Light-Doze(Android N)和Deep-Doze(Android M)的概念,具体内容如下:
5.应用待机群组
应用待机群组对应用进行分组管理,不同的分组享有不同的权限设置,杜绝了对应用一刀切的现象。
相关链接:https://developer.android.goo...
应用待机分组:
1)活跃 (Active): 应用正在被使用
2)工作 (Working set): 应用使用频率很高
3)常用 (Frequent): 应用经常但不是每天被使用
4)极少 (Rare): 应用偶尔被使用
5)从不(Never):安装后一次都未被使用过的应用
分组策略:
调试:
通过adb命令将应用手动划分至某一待机群组。输入以下命令,更改群组:
$ adb shell am set-standby-bucket packagename active/working_set/frequent/rare
输入以下命令,查看应用所处群组:
现象:录制脚本是events事件有内容,但是录制的脚本为空
解决方法一:
IE浏览器不要使用代理, IE选项->连接->局域网设置:自动检测不要勾选 解决方法二
录制设置时, Recording Options->Network->PortMapping->Capture level:将默认的Socket level data更改为WinlNet level data。这种情况尤其适用于录制https协议的脚本时。 解决方法三
把IE浏览器设置为默认浏览器就: 工具->Internet 选项->程序->设置默认值 解决方法四
测试脚本的地址改用IP地址
6
解决方法五
把电脑上的杀毒软件关掉。在此,强调一下,Loadrunner在录制web脚本时,有很多兼容性问题,所以推荐比较干净的电脑环境安装软件进行录制
参考地址:https://jingyan.baidu.com/album/d2b1d102c7fb835c7e37d4a4.html?picindex=2
大于小于是可以像整数那样直接判断的,但是不可以判断两个double是相等的。
因为
double类型的表示往往是不精确的(近似表示). 有精度范围的那种. 如果是运算结果,即使都是0.0,也不保证相等!一般用一个容差e(很小的值)
那么a和b相等就可以表示为
if ( fabs(a-b) < e ) return true; 注意:double类型虽然可以通过>和<直接比较,但是大于等于,小于等于是不能直接>=和<=比较的。
错误比较方式:now >= mid*n
正确比较方式:now - mid * n > -0.000001
问题情形 解决方法 点选Cydia Impactor 选单「Impactor」,将「Insecure SSL」打勾。
搞定!
安装 百度云盘下载提取码为:vhyq
特别注意!!!此时不要双击点击
破解 打开终端CD到下载文件内 cd Downloads/win-mac\ scrt\&sfx 看到破解文件,输入命令CRTde sudo perl securecrt_linux_crack.pl /Applications/SecureCRT.app/Contents/MacOS/SecureCRT FX sudo perl securefx_linux_crack.pl /Applications/SecureFX.app/Contents/MacOS/SecureFX 然后开启,并打开文件夹中txt文件
使用 创建连接后关于内部的一些设置
创建仿真模式
修改字体
添加窗口
全局窗口调整
每次登陆都需要密码改为不需要密码
type interfaceA interface { Num() int } type structA struct { num int } func (s *structA) Num() int { return s.num } func getData(ia interfaceA) { if ia == nil { fmt.Println("true") } else { fmt.Println("false") } } // 打印结果:true func TestInitStructIsNil2(t *testing.T) { var initStruct *structA if initStruct == nil { fmt.Println("true") } else { fmt.Println("false") } } // 打印结果:false func TestInitStructIsNil(t *testing.T) { var initStruct *structA getData(initStruct) } // 打印结果:true func TestInitInterfaceIsNil(t *testing.
前言 通过前面几篇《最简单的DRM应用程序》系列文章,我们学习了如何编写一个最基本的DRM应用程序。但是,这些程序所使用的接口,在如今的DRM架构中其实早已经被标记为 Legacy(过时的) 接口了,而目前DRM主要推荐使用的是 Atomic(原子的) 接口。Atomic接口我会在下篇文章中重点介绍,本篇主要介绍Atomic操作必须依赖的基本元素,Property(属性)。
Property 所谓Property,其实就是把前几篇的legacy接口传入的参数单独抽出来,做成一个个独立的全局属性。通过设置这些属性参数,即可完成对显示参数的设置。
Property的结构简单概括主要由3部分组成:name、id 和 value。其中id为该property在DRM框架中全局唯一的标识符。
采用property机制的好处是:
减少上层应用接口的维护工作量。当开发者有新的功能需要添加时,无需增加新的函数名和IOCTL,只需在底层驱动中新增一个property,然后在自己的应用程序中获取/操作该property的值即可。增强了参数设置的灵活性。一次IOCTL可以同时设置多个property,减少了user space与kernel space切换的次数,同时最大限度的满足了不同硬件对于参数设置的要求,提高了软件效率。 DRM中的property大多以功能进行划分,并且还定义了一组 Standard Properties,这些标准properties在任何平台上都会被创建。
下表列出了应用程序开发中,常用的property:
CRTC namedesctriptionACTIVECRTC当前的使能状态,一般用于控制CRTC上下电MODE_IDCRTC当前所使用的display mode ID,通过该ID可以找到具体的display mode配置参数OUT_FENCE_PTR输出fence指针,指向当前正在显示的buffer所对应的fence fd,该fence由DRM驱动创建,供上层应用程序使用,用来表示当前buffer CRTC是否还在占用 (optional)
namedesctriptionDEGAMMA_LUTde-gamma查找表参数DEGAMMA_LUT_SIZEde-gamma查找表参数长度CTMColor Transformation Matrix,颜色矩阵转换参数,3x3的矩阵GAMMA_LUTgamma查找表参数GAMMA_LUT_SIZEgamma查找表参数长度 PLANE namedesctriptiontypeplane的类型,CURSOR、PRIMARY或者OVERLAYFB_ID与当前plane绑定的framebuffer object IDIN_FENCE_FD与当前plane相关联的input fence fd,由buffer的生产者创建,供DRM底层驱动使用,用来标识当前传下来的buffer是否可以开始访问CRTC_ID当前plane所关联的CRTC object ID,与CONNECTOR中的CRTC_ID属性是同一个propertySRC_X当前framebuffer crop区域的起始偏移x坐标SRC_Y当前framebuffer crop区域的起始偏移y坐标SRC_W当前framebuffer crop区域的宽度SRC_H当前framebuffer crop区域的高度CRTC_X屏幕显示区域的起始偏移x坐标CRTC_Y屏幕显示区域的起始偏移y坐标CRTC_W屏幕显示区域的宽度CRTC_H屏幕显示区域的高度 (optional)
namedesctriptionIN_FORMATS用于标识特殊的颜色存储格式,如AFBC、IFBC存储格式,该属性为只读rotation当前图层的旋转角度zposition当前图层在所有图层中的Z轴顺序alpha当前图层的global alpha(非pixel alpha),用于多层合成pixel blend mode当前图层的合成方式,如Pre-multiplied/Coverage等 CONNECTOR namedesctriptionEDIDExtended Display Identification Data,标识显示器的参数信息,是一种VESA标准数据格式DPMSDisplay Power Management Signaling,用于控制显示器的电源状态,如休眠唤醒。也是一种VESA标准link-status用于标识当前connector的连接状态,如Good/BadCRTC_ID当前connector所连接的CRTC object ID,与PLANE中CRTC_ID属性是同一个property (optional)
namedesctriptionPATHDisplayPort专用的属性,主要用于Multi-Stream Transport (MST) 功能,即多路显示应用场景TILE用于标识当前connector是否应用于多屏拼接场景,如平时随处可见的多屏拼接显示的广告大屏幕 Property Type Property的类型分为如下几种:
enumbitmaskrangesigned rangeobjectblob 以上类型中需要着重介绍的是object和blob类型,其它类型看名字就知道什么意思,所以就不做介绍了。
.NET Reactor是一款功能强大的代码保护以及许可授权管理系统,主要用于开发人员对其.NET软件的保护,其支持所有支持.NET编译的程序开发语言。
上一篇文章给大家带来了.NET Reactor针对De4Dot脱壳工具的应对,本次给大家分享一下.NET Reactor中的工具。
一、Hardware ID Tool Generator(硬件ID工具生成器) 要将许可证链接到特定计算机,你必须将我们的HID.exe工具与你的可分发程序捆绑在一起。你的客户端运行HID.exe以生成硬件标识文件(* .hid),并使用其许可证申请提交该文件。使用.NET Reactor License Manager处理此.hid文件, 可在几秒钟内为已标识的计算机生成许可证。
硬件ID工具生成器生成自定义的HID.exe是可分发的。你必须配置硬件ID工具生成器以匹配你为受保护的程序集规定的HID设置。要将自定义HID.exe工具输出到受保护程序集的目标目录,请单击“Generate”。
二、License Reactivation Tool(许可证重新激活工具) 许可证无效后,你可以使用此工具重新激活无效的许可证。如果要部署硬件标识锁,则可以使用许可证失效工具和许可证重新激活工具在一台计算机上强制执行许可证失效,以允许被许可方将安装移动到另一台计算机。
要重新激活许可证,请加载.NET Reactor项目,打开许可证重新激活工具,输入相应计算机的硬件ID,然后单击“Generate Reactivation Code”。每次单击“Generate Reactivation Code”时,都会生成新的激活代码。请注意,每个新的激活代码仅对一次重新激活有效。要重新激活许可证,请使用library License.dll(库许可证)的Status.ReactivateLicense(字符串代码)方法 。
三、Stack Trace Deobfuscator(堆栈跟踪反混淆器) 要设置堆栈跟踪,请加载相应的映射文件(由受保护的输出设置生成),复制并粘贴障碍堆栈跟踪,然后单击“Deobfuscate”。
四、ShareIt Module Generator(ShareIt模块生成器) .NET Reactor可以轻松跳过生成ShareIt模块的环节。ShareIt模块生成器使用你的.NET Reactor项目文件创建ShareIt许可证文件生成器,可减轻你要生成ShareIt许可证文件的开销。
点击下载.NET Reactor最新试用版
top.layer.open() is not defined 问题。
首先怀疑的依赖包是否导入进去了。top是window的对象,使用该方法需要导入layer.js。其次要想成功调用该方法,还需要在在外层的页面中引用layer.js才可以。
iframe和父页,window.open打开页面和被打开页面之间的关系可以通过下面的对象获取到
1)通过iframe加载的,在iframe中用parent对象得到父页window作用域,如果iframe中又加载了iframe,在最里层的iframe中需要重复调用parent直到得到需要的父页作用域(如parent.parent)。如果是直接引用最顶级的父页作用域,可以使用top对象。
2)父页使用document.getElementById("iframe的id").contentWindow得到iframe的window作用域,如果iframe还继续嵌套了iframe,则还需要继续执行.getElementById("iframe的id").contentWindow操作才能得到内层iframe的作用域。如
-收缩JavaScript代码
var ifrWin=document.getElementById("iframe的id").contentWindow.getElementById("再次被嵌套的iframe的id").contentWindow;
3)aaa.html中使用 var win=window.open("xxx.html"),win就是xxx.html的window作用域,xxx.html中使用opener对象得到打开这个页面的window作用域。如果xxx.html又打开了bbb.html,那么bbb.html中使用opener.opener得到aaa.html作用域,aaa.html要想得到bbb.html作用域,那么xxx.html需要保存打开bbb.html的作用域如var win=window.open("bbb.html"),那么aaa.html通过win.win就得到bbb.html的作用域了
通过上面的介绍知道了关系之后,就很容易从一个页面更新到其他通过window.open或者iframe嵌套的子页面或者父页面了。
在博文https://blog.csdn.net/fengbingchun/article/details/87007598 中对R-CNN进行了简单介绍,这里在R-CNN的基础上简单介绍下Fast R-CNN。
在R-CNN网络结构模型中,由于卷积神经网络的全连接层对于输入的图像尺寸有限制,所以所有候选区域的图像都必须经过变形转换后才能交由卷积神经网络模型进行特征提取,但是无论采用剪切(crop)还是采用变形(warp)的方式,都无法完整保留原始图像信息,何凯明等人提出的空间金字塔池化层(Spatial Pyramid Pooling Layer)有效地解决了传统卷积神经网络对输入图像的尺寸的限制。
SPP-net:R-CNN候选区域缩放后的畸变问题和提取特征时的重复计算导致了模型性能和速度的瓶颈。为了解决这些问题,2015年,何凯明等人提出了SPP-net,在保证性能的同时,检测速度也有了较大的提升,论文名字为” Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition”, 可从https://arxiv.org/pdf/1406.4729.pdf 直接下载。
R-CNN需要对候选区域进行缩放的原因是全连接层的输入维度必须固定。整个网络包含底部的卷积层和顶部的全连接层,卷积层能够适应任意尺寸的输入图像,产生相应维度的特征图,但是全连接层不同,全连接层的参数是神经元对于所有输入的连接权重,即如果输入维度不固定,全连接层的参数数量也无法确定,网络将无法训练。为了既能固定全连接层的输入维度又不让候选区域产生畸变,很自然的想法就是在卷积层和全连接层的衔接处加入一个新的网络层,使得通过该层后特征的维度可以固定,在SPP-net中引入的空间金字塔池化层(Spatial Pyramid Pooling Layer, SPP Layer)就是这样一种网络层,SPP-net也因此得名。
此外,SPP-net也解决了R-CNN重复计算的问题。SPP-net的思路是由于原图与经过卷积层后得到的特征图在空间位置上存在一定的对应关系,所以只需对整张图像进行一次卷积层特征提取,然后将候选区域在原图的位置映射到卷积层的特征图上得到该候选区域的特征,最后将得到每个候选区域的卷积层特征输入到全连接层进行后续操作。
SPP-net网络结构如下图所示,输入一副任意尺度的待测图像,用CNN可以提取得到卷积层特征(例如VGG16最后的卷积层为Conv5_3,得到512幅特征图)。然后将不同大小候选区域的坐标投影到特征图上得到对应的窗口(window),将每个window均匀划分为4*4, 2*2, 1*1的块,然后对每个块使用Max-Pooling下采样,这样无论window大小如何,经过SPP层之后都得到了一个固定长度为(4*4+2*2+1)*512维的特征向量,将这个特征向量作为全连接层的输入进行后续操作。这样就能保证只对图像提取一次卷积层特征,同时全连接层的输入维度固定。
空间金字塔池化层与传统的池化层的不同在于空间金字塔池化层由不同尺度的池化层构成,并且池化层的大小是与输入的特征图矩阵的大小成正比。设输入特征图矩阵的尺寸为 a*a,输入特征图矩阵的数目为k,池化层的分割尺度为n*n,则该池化层的窗口大小为「a/n],移动步长为[a/n」,输出的池化后的特征向量长度为n*n*k维,n可以取多个值,构成多个尺度上的池化层,这样空间金字塔池化层的输出特征向量的维度只与输入特征图矩阵的数目与池化层的分割尺度有关,因此不再对网络模型的输入图像有尺寸限制。
SPP-net的目标检测整体流程:
(1). 输入一幅待检测图像;
(2). 提取候选区域:利用Selective Search算法在输入图像中提取出约2000个最有可能包含目标实例的候选框;
(3). 候选区域尺度缩放:候选区域长宽中的较短边长度进行统一,即min(w, h)=s, s∈{480, 576, 688, 864, 1200},s取值标准是使得统一后的候选区域尺寸与224*224最接近;
(4). 特征提取:利用SPP-net网络结构提取特征;
(5). 分类与回归:根据所提特征,利用SVM进行分类,用边框回归器微调候选框的位置。
空间金字塔池化操作有许多明显的优点:一是实现了任意尺寸输入,固定大小输出。层多可对任意尺度提取的特征进行池化。二是大大降低了计算时间。将某一大小的图片输入到卷积神经网络中,结果特征值提取处理得到了特征图(feature maps),然后利用空间金字塔池化对所有的候选框进行处理可以得到长度固定的特征向量。相比之下,R-CNN是将所有的候选框一一输入之后再进入CNN来处理,在R-CNN中,一般使用Selective Search方法将一种图片生成多个(2000左右)候选区,再对于每个候选框内图像块提取特征,使用分类器判别对候选框中提取出的这些特征是否属于一个特定类。对于属于某一特征的候选框,用回归器进一步调整其位置。使用过分割的方法将数据分割成小区域,然后不断地重复合并可能性最高的两个区域直到整张图像上合并成一个区域为止。因为空间金字塔池化操作对整张图片的特征提取过程是操作了一次。R-CNN遍历一个CNN 2000次,而SPP-net只遍历了1次,而两者最后都是采用SVM算法进行特征向量分类识别,所以整体计算速度提高了很多倍。
SPP layer一般跟在卷积层后面,此时网络的输入可以是任意尺度的,在SPP layer中每一个pooling的filter会根据输入调整大小,而SPP的输出则是固定维数的向量,然后给到全连接FC层。
SPP-net解决了R-CNN重复提取候选区域特征的问题,同时允许各种尺寸图像作为输入,解决了图像畸变的问题,但R-CNN的其它问题,如训练步骤繁琐、磁盘空间开销大等依然有待解决。
为了解决R-CNN训练速度慢、训练所需空间大的问题,R-CNN的原作者Ross Girshick对R-CNN做出了改进,提出了Fast R-CNN,该网络吸收了SPP-net的特点,使得目标检测的速度大幅提升,论文名字为”Fast R-CNN”,可以从https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/Girshick_Fast_R-CNN_ICCV_2015_paper.pdf 直接下载。
Fast R-CNN的网络结构如下图所示:Fast R-CNN的输入由两部分组成:一是待处理的整张图像;二是候选区域(region proposal)。Fast R-CNN处理的第一步是对图像进行多次卷积核池化处理来获取卷积特征图。由于存在多个候选区域,系统会有一个甄别,判断出感兴趣区域,也就是Region of Interest, RoI。RoI池化层是SSP(Spatial Pyramid Pooling)层的特殊情况,它可以从特征图中提取一个固定长度的特征向量。每个特征向量,都会被输送到全连接(FC)层序列中,这个FC分支成两个同级输出层。其中一层的功能是进行分类,对目标关于K个对象类(包括全部”背景background”类)输出每一个RoI的概率分布,也就是产生softmax概率估计;另一层是为了输出K个对象中每一个类的四个实数值(bbox regression)。每4个值编码K个类中的每个类的精确边界框(bounding-box)位置。整个结构是使用多任务损失的端到端训练(trained end-to-end with a multi-task loss)(除去Region Proposal提取阶段)。
什么是递归函数? 官方的解释就是:函数直接或间接调用函数的本身,则该函数叫做递归函数。
使用原理:自己调用自己,从后面往前推。
特点:
有参数有return自己调用自己 案例:计算1+2+3+4+...+100的和
function sum(n){ var res = 0; for(var i = 1; i <= 100; i++){ res += i; } return res; } alert(sum(100));//输出5050 以上的案例就是一个函数自己调用自己的递归函数。先去寻找规律,sum(100) = sum(99) + 100,sum(99) = sum(98) + 99依次类推得出sum(n) = sum(n - 1) + n;
递归函数使用技巧 首先寻找临界值,即不需要计算,就能得出结果。找这一次和上一次的关系。假设当前函数可以使用,调用自身计算上一次和这一次的关系 【注】使用递归函数的时候一定要注意,处理不好就会进入死循环当中。
创建测试表
使用phoenix在HBase中创建测试表,字段使用VARBINARY类型
CREATE TABLE IF NOT EXISTS test_binary (
date VARCHAR NOT NULL,
dist_mem VARBINARY
CONSTRAINT test_binary_pk PRIMARY KEY (date)
) SALT_BUCKETS=6;
创建完成后使用RoaringBitmap序列化数据存入数据库:
实现自定义聚合函数bitmap
import org.apache.spark.sql.Row;
import org.apache.spark.sql.expressions.MutableAggregationBuffer;
import org.apache.spark.sql.expressions.UserDefinedAggregateFunction;
import org.apache.spark.sql.types.DataType;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;
import org.roaringbitmap.RoaringBitmap;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* 实现自定义聚合函数Bitmap
*/
public class UdafBitMap extends UserDefinedAggregateFunction {
@Override
public StructType inputSchema() {
List<StructField> structFields = new ArrayList<>();
structFields.add(DataTypes.createStructField("field", DataTypes.BinaryType, true));
求任意三个整数的最小公倍数。
过程:每一次操作都把当前最小的那个数加上他的初始值。
所以,首先,我们要判断三个数是否相等,如果不相等则求出三个值里面的最小值并得到它的索引,加上对应的初始值,如此循环,直到三个数相同。
import java.util.Scanner; /* 求三个整数的最小公倍数 */ public class _6_2 { public static void main(String[] args) { Scanner scanner=new Scanner(System.in); int[] num=new int[3]; for(int i=0;i<3;i++){ int m=scanner.nextInt(); num[i]=m; } int reslut=fun(num); System.out.println("最小公倍数为:"+reslut); } //判断三个数是否相同 public static boolean isSame(int[] arr){ boolean flag=false; int count=0; for(int i=0;i<2;i++){ if(arr[i]==arr[i+1]){ count++; } } if(count==2){ flag=true; } return flag; } //求数组里最小数的索引 public static int minIndex(int[] arr){ int min=arr[0]; int index=0; for(int i=1;i<3;i++){ if(arr[i]<min){ min=arr[i]; index=i; } } return index; } //求最小公倍数 public static int fun(int[] arr){ int a=arr[0]; int b=arr[1]; int c=arr[2]; int index; while (!
转载来源:
https://www.cnblogs.com/nzbbody/p/3553222.html
https://blog.csdn.net/jack_20/article/details/78913202
一、‘\0’的添加 存在的C语言方法,如strlen(s),计算字符串的长度,其中s指针。
strlen要计算字符串长度,必须知道哪里是结尾,因此使用\0表示结尾。
只有字符数组才有\0的概念,其它类型(int)的数组没有这个概念。
二、内存分配 数组可以在栈上分配,也可以在堆上分配,但必须指定大小。
char a1[100]; //在栈上分配 char* pa = new char[100]; // 在堆上分配,返回首元素的地址 三、初始化 char str[10] = "Hello"; char str[10] = {'H','e','l','l','o','\0'}; char str[10] = {'H'}; char str[10] = {0}; char str[10] = "Hello, world.\n"; char str[] = "Hello, world.\n"; 第一种情况:初始化数据小于数组长度
如前面两个初始化的例子,这两个例子的效果一样,前五个字符为Hello,剩余的用’\0’填充
第三行与第四行,都只指定了第一个字符,剩余的全部用’\0’填充。第四个例子相当将整个数组初始化为’\0’
第二种情况:初始化数据等于或超过数据长度
这种情况下,超出的部分将被丢弃,所以最五个例子的最后一个字符为’l’.
此时使用一些字符串函数时要特别注意,因为该数组不含有’\0’,会造成不可预期的结果
第三种情况:不指定数组长度
这种情况下,数组部分如果不含有明确指定的’\0’,那么编译时会被自动添加一个’\0’;
在数组不含有明确的’\0’时,sizeof=strlen+1
四、结果输出 char a1[] = “abc”; 下面的结果分别是什么?
输出相同,都是数组元素的第一个地址。
cout << &a1[0] << endl; cout << a1 << endl; char* pa = “abc”; 下面的结果分别是什么?
问题描述 任何一个正整数都可以用2进制表示,例如:137的2进制表示为10001001。
将这种2进制表示写成2的次幂的和的形式,令次幂高的排在前面,可得到如下表达式:137=27+23+2^0
现在约定幂次用括号来表示,即a^b表示为a(b)
此时,137可表示为:2(7)+2(3)+2(0)
进一步:7=22+2+20 (2^1用2表示)
3=2+2^0
所以最后137可表示为:2(2(2)+2+2(0))+2(2+2(0))+2(0)
又如:1315=210+28+2^5+2+1
所以1315最后可表示为:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
输入格式 正整数(1<=n<=20000)
输出格式 符合约定的n的0,2表示(在表示中不能有空格)
样例输入 137
样例输出 2(2(2)+2+2(0))+2(2+2(0))+2(0)
样例输入 1315
样例输出 2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
提示 用递归实现会比较简单,可以一边递归一边输出
思路
这道题采用递归嵌套的方法解决,首先将输入的正整数转换成二进制数,进而将高次幂通过递归方式降为0,1,2次幂。
重点注意输出格式问题,代码原理比较简单,但是需要循环判断末尾二进制数是否为0,末尾为0则不输出“+”号。 import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); Digui(n); } private static void Digui(int n) { String temp =Integer.toBinaryString(n); int j = temp.length()-1; boolean flag = true;//用于判断是否到末尾 for (int i = 0; i <temp.
在linux中, 有些命令是大家通用的, 比如ls, rm, mv, cp等等, 这些我觉得没有必要再细说了。 而有些命令, 只有开发人员才会用到的, 这类命令, 作为程序员的我们, 是有必要了解的, 有的甚至需要熟练使用。
有的人总说, 这些命令不重要, 用的时候去查就行了, 这么多么扯淡的说法啊。 具体用法细节是可以可查, 但至少得知道有ldd这个东西吧。连ldd都不知道, 怎么知道ldd是干啥的呢?
在本文中, 我们来介绍一下ldd命令, 尽管它非常简单。 哦, 我突然想起来, 我有个朋友, 她的名字的是三个字, 首写字母刚好是l, d, d, 有点意思。 在linux中, ldd是list, dynamic, dependencies的缩写, 意思是, 列出动态库依赖关系。 当然, 你也可以用ldd --help或者man ldd来看其用法。 下面, 我们也来看看:
test.h的内容为:
void print(); test.c的内容为:
#include <stdio.h> #include "test.h" void print() { printf("rainy days\n"); } main.c的内容为:
#include "test.h" int main() { print(); return 0; } 进行一系列的编译, 并用ldd命令, 得到:
设三角形三点为A(x1,y1),B(x2,y2),C(x3,y3),三边长为a,b,c,高为h,面积为s,p=(a+b+c)/2
计算三角形面积
公式:
①s=(a * h)/2=(b * h)/2=(c * h)/2;
double area(double h,double x){ return 0.5*x*h; } ②s=(p * (p-a) * (p-b) * (p-c))^0.5;
double area(double x1,double y1,double x2,double y2,double x3,double y3){ double a,b,c,p,s; a=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); b=sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3)); c=aqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3)); p=(a+b+c)/2; s=sqrt(p*(p-a)*(p-b)*(p-c)); return s; } 三点顺序
给三个点A,B,C的坐标,判断能否组成一个三角形;若能,判断A,B,C是顺时针给出的还是逆时针给出的?
利用矢量叉积判断是逆时针还是顺时针。
三角形两边的矢量分别是:AB=(x2-x1,y2-y1), AC=(x3-x1,y3-y1)
则AB * AC=(x2-x1) * (y3-y1) - (y2-y1) * (x3-x1)
利用右手法则进行判断:
如果AB * AC>0,则三角形ABC是逆时针的;
如果AB * AC<0,则三角形ABC是顺时针的;
如果AB * AC=0,则说明三点共线(不能构成三角形)。
int orderPoints(double x1,double y1,double x2,double y2,double x3,double y3){ double abx,aby,acx,acy,k; abx=x2-x1; aby=y2-y1; acx=x3-x1; acy=y3-y1; k=abx*acy-aby*acx; if(k>0) return 1;//三角形逆时针给出 else if(k==0) return 0;//不能构成三角形 return -1;//三角形顺时针给出 }
引自:https://blog.csdn.net/m0_37777649/article/details/74937242
什么是T检验?
T检验是假设检验的一种,又叫student t检验(Student’s t test),主要用于样本含量较小(例如n<30),总体标准差σ未知的正态分布资料。 T检验用于检验两个总体的均值差异是否显著。
一个例子
例1: “超级引擎”工厂是一家专门生产汽车引擎的工厂,根据政府发布的新排放要求,引擎排放平均值应低于20ppm,如何证明生产的引擎是否达标呢?(排放量的均值小于20ppm)
思路1
一个直接的想法就是,把这个工厂所有的引擎都测试一下,然后求一下排放平均值就好了。比如工厂生产了10个引擎,排放水平如下: 15.6 16.2 22.5 20.5 16.4 19.4 16.6 17.9 12.7 13.9 排放平均值为 (15.6+16.2+22.5+20.5+16.4+19.4+16.6+17.9+12.7+13.9)/10=17.17(15.6+16.2+22.5+20.5+16.4+19.4+16.6+17.9+12.7+13.9)/10=17.17 小于政府规定的20ppm,合格!
这也太简单了!
然而,随着“超级引擎”工厂规模逐渐增大,每天可以生产出10万个引擎,如果把每个引擎都测试一遍,估计要累死人了…… 有没有更好的方法?
思路2
由于引擎数量太多,把所有引擎测试一遍太麻烦了,“智多星”有一个好想法: 可不可以采用“反证法”?先假设所有引擎排放量的均值为μμ,然后随机抽取10个引擎,看看这10个引擎的排放量均值与假设是否相符,如果相符,则认为假设是正确的,反之认为假设是错误的。这样,就可以通过一小部分数据推测数据的总体,真是太棒了!
具体怎么操作呢?
先建立两个假设,分别为: H0:μ⩾20H0:μ⩾20 (原假设) H1:μ<20H1:μ<20 (备择假设) 【μμ代表总体(所有引擎的排放量)均值】
在原假设成立的基础上,求出”取得样本均值或者更极端的均值”的概率,如果概率很大,就倾向于认为原假设H0H0是正确的,如果概率很小,就倾向于认为原假设H0H0是错误的,从而接受备择假设H1H1。
那么如何求这个概率p呢? 这就需要引入一个概念——统计量 简单的讲,统计量就类似于用样本已知的信息(如样本均值,样本标准差)构建的一个“标准得分”,这个“标准得分”可以让我们求出概率p
由于样本服从正态分布,且样本数量较小(10),所以这里要用到的统计量为t统计量,公式如下: t=x¯−μS/n−−√∼t(n−1)
t=x¯−μS/n∼t(n−1)
x¯:样本均值x¯:样本均值 μ:总体均值μ:总体均值 S:样本标准差S:样本标准差 n:样本容量n:样本容量 该tt统计量服从自由度为n−1n−1的t分布
让我们试验一下! 现在抽取出10台引擎供测试使用,每一台的排放水平如下: 15.6 16.2 22.5 20.5 16.4 19.4 16.6 17.9 12.7 13.9 样本均值
x¯=∑nk=1xkn=(15.6+16.2+22.5+20.5+16.4+19.4+16.6+17.9+12.7+13.9)10=17.17
x¯=∑k=1nxkn=(15.6+16.2+22.5+20.5+16.4+19.4+16.6+17.9+12.7+13.9)10=17.17
样本方差
S2=∑nk=1(xk−x¯)n−1
S2=∑k=1n(xk−x¯)n−1
样本标准差
引自:https://blog.csdn.net/ludan_xia/article/details/81737669
卡方检验是一种用途很广的计数资料的假设检验方法。属于非参数检验,主要是比较两个及两个以上样本率(构成比)以及两个分类变量的关联性分析。根本思想在于比较理论频数和实际频数的吻合程度或者拟合优度问题。
应用:两个率或两个构成比比较的卡方检验;多个率或多个构成比比较的卡方检验以及分类资料的相关分析。
举例一:想知道喝牛奶对感冒发病率有没有影响。
喝牛奶组和不喝牛奶组的感冒率为30.94%和25.00%,两者的差别可能是抽样误差导致,,也可能是 牛奶对感冒率真的有 影响。
下面就就行假设了:假设喝牛奶对感冒发病率没有影响,即喝牛奶与感冒无关
所以感冒的发病率实际是(43+28)/(43+28+96+84)=28.29%
所以可以得到理论的表格
如果说真的没有影响的话 表格中理论值和实际值差别应该会很小。
卡方检验的计算公式
其中:A是实际值,T为理论值
X^2值的意义:衡量理论与实际的差异程度。
经过计算可以计算得到
X^2=1.077
下面就是我们如何根据卡方值来判断是否有差异了。
我们需要查询卡纸分布的临界值,将计算的值与临界值比较。
查询临界值就需要知道自由度
自由度V=(行数-1)*(列数-1);
对于该问题V=1,查询可得 临界值为3.84
如果x^2 <临界值 则假设不成立。。
参考博客
http://blog.sina.com.cn/s/blog_7054a1960102wizu.html
https://blog.csdn.net/qq_15111861/article/details/80723754
元学习论文总结||小样本学习论文总结
2017-2019年计算机视觉顶会文章收录 AAAI2017-2019 CVPR2017-2019 ECCV2018 ICCV2017-2019 ICLR2017-2019 NIPS2017-2019
摘要 同时定位与映射(SLAM)包括同时构造环境表示(MAP)和估计机器人在环境中运动的状态。在过去的30年中,SLAM社区取得了惊人的进步,实现了大规模的现实世界应用,并见证了这项技术向工业的稳步过渡。我们调查了SLAM的现状。我们首先介绍的是SLAM的实际标准。然后我们回顾了相关的工作,涵盖了一系列广泛的主题,包括长期映射的健壮性和可伸缩性、映射的度量和语义表示、理论性能保证、主动SLAM和探索以及其他新的领域。这篇论文是供非专家读者参考的.这也是一份立场文件:用批判性的眼光看待已发表的研究,我们勾勒出公开的挑战和新的研究问题,这些问题仍然值得认真的科学研究。这篇论文还包含了作者对机器人会议中经常引发讨论的两个问题的看法:机器人需要SLAM吗?SLAM解决了吗?
介绍 SLAM包括同时估计机器人的状态和环境的地图。在简单的例子中,机器人的状态被描述为它的姿态(位置和方向),虽然在状态中还可以包含其他的量,例如机器人的速度,传感器的偏差,和校准参数。另一方面,地图是对机器人工作环境的感兴趣方面(例如,地标位置、障碍物)的表示。
需要建立一个环境地图是双重的。首先,地图通常需要支持其他任务;例如,地图可以为路径规划提供信息,或者为人工操作人员提供直观的可视化。第二,地图允许限制在估计机器人状态时所犯的错误。在没有地图的情况下,推算数据很快就会随着时间的推移而漂移;另一方面,给定地图,机器人可以通过重新访问已知区域(所谓的循环闭合)来“重置”其定位误差。 因此,SLAM在所有场景中找到应用程序,其中先前的映射不可用并且需要构建。
在一些机器人应用中,环境的地图是先验的。例如,在工厂地板上操作的机器人可以被提供一张人工建造的环境信标地图。另一个例子是机器人能够获得全球定位系统的测量数据(可将全球定位系统卫星视为已知位置上的移动信标)。SLAM问题的流行与移动机器人在室内应用的出现有关。室内操作排除了使用gps来限制定位误差的可能性;此外,SLAM提供了一种有吸引力的替代用户构建地图的方法,表明在没有临时定位基础设施的情况下,机器人操作是可能的。
达兰特-怀特和贝利在[13,86]中对SLAM问题的前20年进行了彻底的历史回顾。调查[13,86]主要涵盖我们所称的经典年龄(1986-2004);经典时代引入了SLAM的主要概率公式,包括基于扩展卡尔曼滤波、粗糙粒子滤波和最大似然估计的方法;此外,它还描述了与效率和稳健的数据关联有关的第一个挑战。随后的时期是我们所称的算法分析时代(2004-2015年),部分时间由Dissanayake等人负责。在[84]中。算法分析阶段研究了SLAM的基本性质,包括可观测性、收敛性和一致性。在这一时期,对于高效的SLAM求解者,SLAM的关键作用也得到了理解,并且开发了主要的开源SLAM库。
我们回顾了表一中迄今为止的主要SLAM调查,注意到最近的调查只涉及SLAM的具体方面或子领域。SLAM在过去30年中的流行是不足为奇的,如果你想到SLAM涉及的多个方面。在较低层次(在第二节中称为前端),SLAM自然地与计算机视觉和信号处理等其他研究领域交叉;在更高层次(我们后来称之为后端),SLAM是几何、图论、优化和概率估计的一个很吸引人的组合。最后,SLAM专家必须处理从传感器建模到系统集成的实际问题。
本文对SLAM的现状进行了较为全面的综述,并对SLAM研究中存在的问题和未来的发展方向提出了自己的看法。本文总结了在机器人:科学与系统(RSS)会议期间(罗马,2015年7月)举办的研讨会“移动传感器问题:设定未来目标和SLAM进展指标”[35]的结果。虽然我们经常提到拓扑映射,但我们的重点是度量和语义SLAM,我们向读者介绍了Lowry等人最近的调查。[177]更全面地覆盖基于视觉的拓扑SLAM和位置识别。在深入研究论文之前,我们将讨论两个经常在机器人会议上进行讨论的问题。
自主机器人真的需要SLAM吗?回答这个问题需要了解SLAM的独特之处。SLAM旨在建立一个全球一致的环境代表,利用自我运动测量和循环关闭。这里的关键字是“循环闭包”:如果我们牺牲循环闭包,SLAM就会减少到节理。在早期的应用中,通过对车轮编码器的集成来实现测点。车轮测距仪得到的姿态估计值很快漂移,使估计值在几米后无法使用;这是SLAM发展背后的主要推力之一:观测外部地标有助于减少轨道漂移,并可能对其进行修正。然而,现代的测向算法都是基于视觉和惯性信息的,漂移很小(小于轨迹长度的0.5%)。因此,这个问题就变得合理了:我们真的需要SLAM吗?我们的答案是从三点论述。
首先,我们观察到,过去十年所做的SLAM研究是一项产生视觉惯性校正算法的研究,该算法目前代表着最先进的技术;从这个意义上说,视觉-惯性导航(Vin)是SLAM:Vin可以被认为是一个简化的SLAM系统,在该系统中,环路闭合(或位置识别)模块被禁用。总的来说,SLAM提供了一个借口,在更具挑战性的装置(即没有GPS、低质量传感器)下研究传感器融合,而其他文献(例如,航空航天工程中的惯性导航)则是这样做的。
第二个答案涉及循环闭包。机器人执行节理和忽略闭路,将世界解释为“无限走廊”(图5)。(1A)机器人一直在无限期地探索新的领域。循环关闭事件通知机器人,这条“走廊”不断地与自己相交(图中所示)。1B)。循环闭包的优点现在变得清晰:通过找到循环闭包,机器人了解环境的真实拓扑,并且能够找到位置之间的快捷方式(例如,地图中的点B和C)。因此,如果获得正确的环境拓扑是SLAM的优点之一,那么为什么不简单地删除度量信息,只进行位置识别呢?答案很简单:度量信息使位置识别变得更简单、更健壮;度量重构通知机器人关于环路关闭的机会,并允许丢弃虚假的环路闭包。因此,虽然大满贯原则上可能是冗余的(OraclePlace识别模块将足以用于拓扑映射),但是Sock提供了针对错误的数据关联和感知别名的自然防御,其中类似地查找对应于环境中的不同位置的场景将欺骗地方识别。在这一意义上,满贯图提供了一种预测和验证未来测量的方法:我们认为该机制是鲁棒操作的关键。
第三个答案是,SLAM是必要的,因为许多应用程序隐式或显式地需要一个全局一致的映射。例如,在许多军事和民用应用中,机器人的目标是探索环境并向人类操作者报告地图。另一个例子是机器人必须(对建筑物、桥梁等)进行结构检查;在这种情况下,一个全球一致的三维重建是成功操作的必要条件。
我们可以找出不同口味的SLAM配方比其他配方更适合的任务。因此,当一个机器人专家不得不设计一个SLAM系统时,他/她面临着多种设计选择。例如,拓扑映射可以用来分析给定位置的可达性,但不适用于运动规划和低级控制;局部一致的度量映射非常适合于避障和与环境的局部交互,但可能会牺牲精度;一个全局一致的度量图允许机器人执行全局路径规划,但它可能需要计算和维护。选择最合适的SLAM系统的一种更普遍的方法是将SLAM作为一种机制来计算一个足够的统计数据来总结机器人过去的所有观察,在这个意义上,在这种压缩表示中保留哪些信息是非常依赖于任务的。
最近在使用RecyclerViewAdapter的时候遇到这个问题,这里总结记录一下,先看一下报错日志:
原因是我在Adapter中的item放了一个CheckBox, 并给CheckBox设置了监听,当选中状态改变的时候,在监听回调中直接调用notifyItemChanged就会出现这个问题。代码如下:
@Override protected void convert(final BaseViewHolder helper, ContactDataSection item) { final ContactMobileManage mobileContact = item.getEntity(); if (mobileContact != null) { .... CheckBox checkBox = helper.getView(R.id.ckb_check); checkBox.setChecked(mobileContact.isChecked()); checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, final boolean isChecked) { mobileContact.setChecked(isChecked); notifyItemChanged(helper.getAdapterPosition()); } }); } } 我们在RecyclerView源码中找到错误日志中提到的assertNotInLayoutOrScroll方法看一下:
/** * Checks if RecyclerView is in the middle of a layout or scroll and throws an * {@link IllegalStateException} if it <b>is</b>.
(转载:https://www.cnblogs.com/pinard/p/5992719.html)
交叉验证是在机器学习建立模型和验证模型参数时常用的办法。交叉验证,顾名思义,就是重复的使用数据,把得到的样本数据进行切分,组合为不同的训练集和测试集,用训练集来训练模型,用测试集来评估模型预测的好坏。在此基础上可以得到多组不同的训练集和测试集,某次训练集中的某样本在下次可能成为测试集中的样本,即所谓“交叉”。 那么什么时候才需要交叉验证呢?交叉验证用在数据不是很充足的时候。比如在我日常项目里面,对于普通适中问题,如果数据样本量小于一万条,我们就会采用交叉验证来训练优化选择模型。如果样本大于一万条的话,我们一般随机的把数据分成三份,一份为训练集(Training Set),一份为验证集(Validation Set),最后一份为测试集(Test Set)。用训练集来训练模型,用验证集来评估模型预测的好坏和选择模型及其对应的参数。把最终得到的模型再用于测试集,最终决定使用哪个模型以及对应参数。
回到交叉验证,根据切分的方法不同,交叉验证分为下面三种: 第一种是简单交叉验证,所谓的简单,是和其他交叉验证方法相对而言的。首先,我们随机的将样本数据分为两部分(比如: 70%的训练集,30%的测试集),然后用训练集来训练模型,在测试集上验证模型及参数。接着,我们再把样本打乱,重新选择训练集和测试集,继续训练数据和检验模型。最后我们选择损失函数评估最优的模型和参数。 第二种是S折交叉验证(S-Folder Cross Validation)。和第一种方法不同,S折交叉验证会把样本数据随机的分成S份,每次随机的选择S-1份作为训练集,剩下的1份做测试集。当这一轮完成后,重新随机选择S-1份来训练数据。若干轮(小于S)之后,选择损失函数评估最优的模型和参数。
第三种是留一交叉验证(Leave-one-out Cross Validation),它是第二种情况的特例,此时S等于样本数N,这样对于N个样本,每次选择N-1个样本来训练数据,留一个样本来验证模型预测的好坏。此方法主要用于样本量非常少的情况,比如对于普通适中问题,N小于50时,我一般采用留一交叉验证。
通过反复的交叉验证,用损失函数来度量得到的模型的好坏,最终我们可以得到一个较好的模型。那这三种情况,到底我们应该选择哪一种方法呢?一句话总结,如果我们只是对数据做一个初步的模型建立,不是要做深入分析的话,简单交叉验证就可以了。否则就用S折交叉验证。在样本量少的时候,使用S折交叉验证的特例留一交叉验证。
此外还有一种比较特殊的交叉验证方式,也是用于样本量少的时候。叫做自助法(bootstrapping)。比如我们有m个样本(m较小),每次在这m个样本中随机采集一个样本,放入训练集,采样完后把样本放回。这样重复采集m次,我们得到m个样本组成的训练集。当然,这m个样本中很有可能有重复的样本数据。同时,用没有被采样到的样本做测试集。这样接着进行交叉验证。由于我们的训练集有重复数据,这会改变数据的分布,因而训练结果会有估计偏差,因此,此种方法不是很常用,除非数据量真的很少,比如小于20个。
转载:https://blog.csdn.net/qq_15746879/article/details/80340671 1.引言 上一节我们解决了数据来源问题,成功将ECG数据读入了Matlab中.而我们现在还不能马上使用高大上的机器/深度学习算法,原因在于一个问题:在这个问题中,对于我们的机器/深度学习来说,直接处理的对象是什么?
是我们在上一节说的一条"记录"吗?对于大多数研究/论文来说,并不是所谓的记录,而是ECG的基本单位:心拍,就是在最开始的时候介绍的,包含了P波,QRS波,T波的信号段。那为什么不是“记录”呢?我猜测的原因可能如下:
1)一条充分长的记录中包含的信息太多,可能包含了很多种类型的心拍,直接全局处理不利于精细的识别。
2)一条充分长的记录数据量偏大,若一次性全局投入后端机器/深度学习算法,不利于复杂而又大量的迭代。
3)目前可用的开源数据库数据量偏少,若直接以一条记录为一个算法处理单位,则总体样本量大大下降,不利用机器学习,尤其是深度学习的应用。以MIT-BIH数据库为例,若以记录为单位处理,则只有48个样本;若以心拍为单位处理,样本量可达10W+。
暂时看不懂也没关系,总之记住,我们在这里直接处理的是心拍,而非一整条记录。
那么问题就来了,我们读到Matlab中的ECG数据都是以记录形式存在的,包含了形态各异,数量不等的心拍,例如下图给出了100,114,119信号的一部分,我们怎么样才能定位提取这些心拍呢?
这就引出了ECG算法领域的经典问题:QRS波定位检测问题。通过检测QRS波的位置,可以大体定位心拍所在的位置。
2.基本思想 1)为什么是QRS波?
直观来看,各类型心拍的各波段中,QRS波往往是最大、最明显的、最尖锐的,本身就利于检测;而在数学上,称为QRS波的“奇异性”,表现为斜率的突变,存在不可导的点,即波峰(或波谷)点。利用该性质可配合多种处理手法,如差分法,小波变换法等等进行有效检测。
2)基本步骤
预处理+自适应阈值。预处理的目的在于两点:
(1) 消除噪声和其他的杂波(P波,T波)等。 (2) 同时使波形模式变得更为单一,QRS波的变化更为突出。
预处理完成后,配合自适应阈值完成QRS波的定位。自适应的意思是能够适应不同类型的记录。自适应机制越好的算法,能够在各种类型的记录下良好地区分目标与非目标,从而达到很高的准确率和可用度。自适应阈值的设计原则,个人总结如下:
(1) 自适应阈值变换机制中的经验参数需固定。在自适应阈值的变化机制中,有些参数可能需要我们根据经验提前设定好。这没有问题。但是一旦确定好之后检测性能时,对于不同的记录,这些经验参数不可以再重新设定。
(2) 自适应阈值要跟随波形实时地,稳健地变化。自适应阈值,并不是至给一整条记录计算好一个阈值后就一成不变了,而是要跟随波形实时地变化,例如当检测到的QRS波振幅呈总体上升态势时,自适应阈值也要相应地提高,反之则要相应降低;自适应阈值的变化往往不可过于剧烈,可通过设定上下限的方式使其变化更加稳健。
(3) 自适应阈值要有针对性地防错检、漏检的机制。例如可以回溯之前的波形,再次进行检测防止漏检;利用“不应期”(当一个QRS波出现后,短时间(~0.24s)内不会再出现第二个)的含义,在检测到一个QRS波后短时间内不再检出QRS波,防止错检。当然并不是说有了这些机制就完全可以避免错检漏检,而是有效地减少。
以上几条关键点是本人自己总结的,可能有所疏漏,仅供参考。另外这些所谓目的和原则对于初学者来说都过于抽象,而且往往在阈值的设计中交织在一起。下面一部分我们将结合具体算法来进行讲解。
3.示例:QRS波定位算法设计与评估 在QRS波识别领域,不得不提的就是经典的Pan-Tompkins算法[1]和Cuiwei Li等人发表的小波变换法[2]。已经有大神实现并开源了Pan-Tompkins算法的Matlab代码,已经放到了本人github上:pan_tomkin.m。不过这里不打算以这两个算法为例讲解,因为这两个算法对初学者来说比较复杂。下面是以本人原创的一个QRS波定位算法进行分析。
1)预处理。这一部分的总体步骤图如下:
(1)我们对心电信号进行40阶FIR带通滤波,通带为15~25Hz,大致为QRS波所在频段。关于滤波器的设计可以使用Matlab的Fdatool工具,得到相应的滤波器系数,然后套用filter内建函数完成滤波。以数据库的103号信号为例,滤波前后的波形示意如下:
通过对比可以看到,滤波后P波,T波被明显削弱,体现了上一部分中预处理目的的第(1)点。
(2)对滤波后的波形“双斜率”预处理。所谓“双斜率”处理是参考自另一篇文献[3]。基本思想是分别在一个点的左右两侧的某个区间内寻找最大平均斜率与最小平均斜率,然后分别用左侧最大斜率减去右侧最小斜率,用右侧最大斜率减去左侧最小斜率,再求取两者中的最大者。过程有些复杂,但其实其基本动机就是利用QRS波两侧较陡的性质,只有QRS波这样的尖峰在经过上述处理时才会有很大的响应。在这里,我们设定这个寻找斜率的区间是左右两侧0.015s~0.060s处,此为经验参数。经过处理,可对比前后波形:
可以看到,双斜率处理后,波形模式更为单一,体现了预处理目的的第(2)点。但是,波形出现了双峰现象,一定程度上不利于精准检测。因此,在双斜率处理后继续低通滤波(截止频率5Hz,经验参数),使得波形更光滑:
可以看到,低通滤波后的波形变得非常光滑,杂波基本消失,模式也非常单一,基本上已经达到了进一步阈值处理的要求。
(3)滑动窗口积分。仔细观察前几步,每一步得到的波形由于滤波或是求斜率的因素,其幅度值越来越小,而过小的幅值其实不利于检测。这里我们利用滑动窗口积分,使得绝对振幅增大,并使波形进一步光滑,滑动窗口宽度设为17个采样点,为经验参数:
积分后,波形幅值明显增大(注意纵坐标),体现了预处理目的的第(2)点。至此,预处理阶段完成,经过处理后,原始的心电信号变成了一个个模式单一的波峰组成的信号,每个波峰对应一个QRS波。相比原信号,预处理后的信号更易定位检测,可以说达到了预处理的目的。
2)自适应阈值设计
与上述所说的自适应阈值设计原则相契合,这个算法的思路是:
(1)自适应阈值要跟随信号实时变化。问题是如何决策此时阈值的变化。这里我采用了一种常用的策略:双阈值。一高一低,当某个波峰超过低阈值时,我们认为检测到了一个QRS波,然后通过比较波峰振幅与高低阈值的关系,调整阈值。
(2)为了保证变化的稳健,阈值需要根据前面已经检测到的正确波峰振幅变化,另外设定下限,以确保不会过高或过低。
通过以上两点,我设计自适应机制如下(THR1为高阈值,THR2为低阈值):
其中,peak指检测到的峰值,peak_buffer指存储了当前峰值之前8个峰值,mean(.)则是求均值。THR1_lim与THR2_lim为两个经验常数,代表两个阈值变化的下限,在这里分别取值为0.3和0.23。
具体来说,当当前波峰高于高阈值时,我们倾向于认为此时阈值偏低,阈值变化为之前检测到的8个波峰平均值的0.7倍,0.25倍(均为经验系数),如果相比最近的8个峰值,阈值确实偏低程度很大,则就算乘上了一个小于1的系数(例如0.7,0.25),自适应阈值还是会增大,如果偏低程度不大,则不一定增大。之所以乘上系数还是因为要保持变化的稳健,保证只有阈值明显偏低时才会明显增大;当当前波峰在高低阈值之间,我们倾向于调低高阈值,而低阈值要与高阈值保持距离,因此也倾向于调低一些,不过我们倾向于认为此时的波形较为异常(因为较小,在两阈值之间),不宜根据前面的平均峰值变化,因此此时阈值变化与当前波峰的值相关。具体变化机制可以参考上面的公式,体现实时变化原则。另外重复一下,当波峰低于低阈值时,认为是噪声。
(3)防漏检与错检。其实本身双阈值的设计一定程度上就可以防漏检。因为一高一低的阈值,相比只有一个阈值,可以捕捉到更多层次的波峰。另外在防错检方面,我采用了“不应期”的方式,当两个波峰过于靠近时,只取较大的波峰。这个“过近”指的是距离低于0.24s,即不应期的长度;双阈值的变化存在下限,也防止了一些噪声被错检为QRS波。
另外,双阈值的初始值是被提前设定好的经验系数,与其他经验系数一样,一旦确定就不会因记录的不同而变化。体现了上述自适应阈值设计的第(1)原则。
以上阈值的操作,均在原信号预处理后的特征信号上进行,检测到的波峰都认为对应于原信号中的一个QRS波。另外预处理中的两次滤波都造成了信号的延迟,我们检测到特征信号的波峰后,可减去延迟,即可得到原信号中的QRS波的位置。
说了这么多确实有些抽象,还是看一下直观的图:
上图这是以100号信号为例。由于本身信号比较稳定,因此阈值的变化主要在信号开始。可以看到初始时阈值明显偏低,自适应阈值很快向上变化找到了合适的值。下面再看一条变化比较大的信号119:
可以看出双阈值可以很好地跟随信号变化,从而正确检出QRS波的位置。注意,这里检测的"正确"并非是指精准地落在QRS波的波峰或波谷中,尽管精确的人工标注往往就是在波峰或波谷上.美国EC38标准提供了一个评判标准:与人工标准差距在150ms内,即可认为定位成功.事实上,这个标准相当宽松,以至于现在的QRS波定位算法的准确率普遍在99%以上(以MIT-BIH数据库为测试数据), 而一些出色的算法甚至达到了99.9%以上.
以上原创算法已开源,放在本人的github上: DS_detect.m, 已封装为函数。以上的算法可能理解起来相当抽象,建议结合代码(有注释)体会。
3)算法评估
上一部分中曾说过,目前QRS波定位检测算法的“准确率”已经普遍在99%以上。但这么说其实不准确,因为衡量QRS波检测算法的指标并非我们印象中的准确率,而是有两个常用指标:敏感度(SE)和正预测率(P+),定义如下:
其中TP代表检测正确的心拍个数,FN代表漏检的心拍个数,FP代表错检的心拍个数。我们尝试对整个MIT-BIH数据库跑一遍,统计算法的性能参数。这一部分不是算法的核心,所以在这里不再讲具体的实现步骤,不过已经开源了测试代码:DS_test.m,为Matlab脚本文件。在运行之前注意数据库路径的设置。注意在代码的第164行,调用了上面的算法DS_detect。
DS_detect和DS_test最好在一个文件夹中,或者将这些文件放到Matlab可以检索到的目录中。以上都没有问题后,直接运行DS_test,等待其完成。当然也可以把DS_detect改为其他算法,只要搞清楚其输出哪个是QRS波的索引就可以。DS_test程序完成后,在工作空间中可以找到名为INFO的变量,双击打开:
从左到右,第一列:记录编号,第二列:人工标记心拍数,第三列:算法正确检出心拍数,第四列:算法错检心拍数,第五列:算法漏检心拍数,第六列:Se,第七列:P+。看最后一行:
可以看出算法共错检648个心拍,漏检380个心拍,总体Se达到了99.65%,P+达到了99.41%,汇总如下:
在我的笔记本电脑上,该算法处理一条30min,采样率360Hz的记录需要14s左右。各项指标虽达不到顶尖,但也不算差,算是有一定的可用度了。接下来,我们将使用该算法将我们需要的心拍截取出来。
4.心拍截取 这里其实有一个矛盾。无论我们的QRS波定位算法有多厉害,都很难100%将人工标注过的所有心拍定位准确,必然有错检和漏检。这就导致我们无法100%利用好人工标记的心拍。这里我们采用一个折衷的手段:忽略漏检的心拍,而错检和正确检出的心拍都截取出来。由于QRS定位算法的、性能已经够好了,所以截取出来的心拍绝大多数是正确检出的心拍,只有少部分为错检心拍。而我们接下来所要使用的机器/深度学习算法都具有一定的鲁棒性,较少的错检心拍数不会对结果产生太大影响。至于心拍的类型(标签),我们以距离该心拍最近的人工标记的类型为准。
另外,我们截取心拍其实不是精确截取,即从P波起点到T波终点,而是采取一种较为粗略的手段:以QRS波的位置为基准,分别向前向后包括若干点,然后将这一段数据点截取出来作为心拍。如下图所示为什么不精确截取呢?是因为检测P波和T波及其起始点或终点非常困难,目前也没有一个性能足够好的算法满足应用需求。所以,大部分文献采用的是这种粗略截取的方法,只不过前后包括的点数有区别:
这里我们向左包含100个点,向右包含150个点,即截取的每个心拍长度为250个点(约0.7s)这一部分的实现代码也已开源:SegBeat.m 为脚本文件。同样,数据库路径,代码文件存放位置要正确。该代码与DS_test.m有类似之处,也调用了DS_detect算法进行QRS检测(第164行,同样也可以置换为其他QRS波定位算法)。至于其他实现细节,作为初学者可不必了解,因为确实很绕,并且也并非是我们的主线任务。运行完成后(时间可能会比较长),在工作空间可以找到4个变量,Nb,Lb,Rb,Vb,为我们接下来的目标类型心拍数据集合,分别为“正常(N)”,“左束支阻滞(LBBB)”,“右束支阻滞(RBBB)”,“室性早搏(PVC)”,示例如下(可能横坐标表示有些不准确,请忽略。。。。):
实际上,同一类型的心拍间变化非常大,并非只是示例的四个心拍那么简单,这也就是我们为什么后面要使用高大上的机器/深度学习算法来分辨。我们以.mat的形式将这四个变量保存(N_dat.mat,L_dat.mat,R_dat.mat,V_dat.mat),它们各自包含了一种类型的心拍,是我们接下来使用机器/深度学习算法要进行分类识别的目标。至此,我们所需要的识别对象已经成功准备好了。
5.小结 本节内容很多,也很抽象。实际上,QRS波检测定位算法的设计很大程度都要靠经验,只不过个人认为有了上面说的几条原则的指导下,方向可以更明确。相关代码已经开源,大家可以结合代码来加深理解,多上手,多尝试.
Settings -> Editor -> Code Style -> C/C++ -> Tabs and Indents
随着通信技术的发展,即将到来的 5G 被认为将会带领各行各业完成技术革命。36氪在此前的文章中也曾提出,以 RealTime(即时互动)为主旨的社交时代即将伴随着技术迭代而到来,形式可能涵盖音视频、AR/VR、光场等等。
除了要求程序在某些环节拥有足够的识别、运算和检索能力,即时互动另一个需要解决的问题在于“延迟”。
36氪近期接触到的「清流鼎点」,是一家超低延时音视频互动技术研发与提供商,APP、平台或下游合作伙伴可通过使用清流鼎点 PowerInfo 提供的 SDK,在线上或线下场景完成人类几乎无法感受到延迟的社交互动。
联合创始人兼 CTO 李毅博士告诉36氪,目前清流鼎点的主要业务分两方面,大规模直播分发业务和超低延时音视频互动业务。面向市场推出的超低延迟互动技术分两种规格:
A50:即音视频的端到端传输延迟≤50毫秒。在这种规格之下,普通用户几乎感受不到任何延迟。36氪此前曾报道,腾讯全民K歌投资的线下迷你KTV技术,便使用的 A50 规格 SDK。除此之外,现阶段难以解决的光场数据、点云数据、游戏数据等也可使用这个技术完成高效传输。
A40:即音视频的端到端传输延迟≤40毫秒。李博士介绍,A40 技术正处于内测阶段,更低的延迟能为一些专业场景提供帮助。例如,A40 技术未来可用于乐队线上排练、演出(可达到演出效果),也可用于线上教育、医疗教学、远程会诊等。
清流鼎点作为很多行业的“幕后帮手”,已经拥有数十个、覆盖了各个赛道的合作伙伴。
音乐娱乐方面,清流鼎点在 2018 年 3 月推出了低延迟合唱技术,成功与线下迷你KTV的头部品牌合作,让网友们相隔千里也可以线上合唱;游戏行业,清流鼎点正与合作伙伴将游戏内容以标准的数据化进行传输,从而降低多人联网游戏所带来的延迟,探索更多互动游戏的形式;教育方面,清流鼎点也在尝试与在线教育平台合作,以降低线上授课延迟。
标准化数据传输为何高效
事实上,传输、编码、解码所覆盖的十几个技术环节,都是实现低延迟的关键。把编解码和传输紧耦合,熟悉每个技术环节并不断优化,才能够将音视频传输延迟降低到50ms甚至更低。
李博士介绍,鼎点团队成立于二十多年前,创始成员大部分来自于清华大学,初期主要给电信、网通等大客户做视频点播系统,后来从事视频编码器的研究。
由于同时涉足软硬件,让清流鼎点的团队在研发中看到了超低延迟技术对于“即时互动”的重要性,于是在近几年对此开展研发工作,并先后推出了 A50 与 A40 解决方案。
技术进展方面,李博士表示,“目前的 A50 技术已经能够满足绝大部分的用户体验,我们也在不断优化技术,在保证超低延迟的基础下提升音视频质量、降低丢包率。”
音视频延迟一直以来困扰着许多行业,显卡巨头英伟达曾在多年前推出“流式传输”,意图让用户可以在良好的网络环境下游玩其个人 PC 难以运行的优质游戏(游戏运行由英伟达完成并通过网络传输到用户 PC),但直至今天,流式传输对于带宽、网络稳定性、网速的要求仍然非常严苛(因音视频数据量过大),有条件使用这种技术的用户寥寥无几。
李博士认为,标准化数据传输对于音视频来说是很好的解决方案,此前 Google 曾推出通用协议,使开发者能够将延迟控制在200 - 500 毫秒左右,但现阶段这个延迟量已经难以满足更多需求,所以清流鼎点在推出 A50 后,也希望通过投资入股或合资的方式,通过“技术+资本+流量”的组合方式,帮助更多创业团队解决音视频人才和技术问题,完成产品的体验升级。
清流鼎点拥有多个垂直领域的头部客户,2018 年公司的年利润达到千万元规模,并计划在 2019 年第二季度启动新一轮融资。
详细解决方案地址: https://blog.csdn.net/u010750160/article/details/84070371
问题: 当在开发工具里新建一个工程时,Android Studio会自动添加一个新的依赖库 appcompat_v7 或者 AS中会自动引用,并引用最新的主题样式Theme.AppCompat.Light,这样就会时所有的点击效果都自带 Material Design 的水波纹效果,但我们往往是不需要这个效果的,所以要去除它。我已经尝试过了网上的很多办法,包括设置 style 文件中的主题属性,但都是没有效果的,最终这两段代码解决了问题,亲测有效。
解决方案: 同时设置TabLayout的属性即可
app:tabBackground="@android:color/transparent" app:tabRippleColor="@android:color/transparent"
曼彻斯特编码 曼彻斯特编码(Manchester Encoding),也叫做相位编码( Phase Encode,简写PE),是一个同步时钟编码技术,被物理层使用来编码一个同步位流的时钟和数据。
在曼彻斯特编码中,用电压的跳变的不同来区分1和0。
从低电压到高电压的跳变表示0;
从高电压到低电压的跳变表示1。
如图:
也就是说,若我们已知一个数字信号,就可以通过信号中的每一个时钟信号下电压为0或1得知该数字信号的曼彻斯特编码,如下图所示:
差分曼彻斯特编码 差分曼彻斯特编码是曼彻斯特编码的一种修订格式,是一种使用中位转变来计时的编码方案。数据通过在数据位开始处加一转变来表示。
差分曼彻斯特编码在每个时钟周期的中间都有一次电平跳变,只用于同步时钟信号。
在每个时钟周期的起始处有跳变为0;
无跳变则为1。
或者可以说差分曼彻斯特编码遇到0则在起始位置处跳变,1则不变化。
其0和1的表示与曼彻斯特编码一致,如下图:
也就是说,已知一个数字信号,我们首先根据上图的编码0和1表示画出第一个时钟信号下的编码(下图中第一个信号为1,编码表示为由高变低),若第二个时钟信号为0,则第二个编码发生的初始位跳变(即如果第一个编码的末位为低,那么发生跳变,第二个编码的首位变为高,表示为由高变低,即编码1);若第二个时钟信号不为0,则不发生跳变(即第二个编码的首位继续为低,表示为由低变高,即编码0)。
NRZI编码 NRZ-I编码中是不归零编码(NRZ)的一部分,其中正负电压分别对应于编码0和1,他是基于从一个电压状态向另一个电压状态的跳跃(即从高到低和从低到高状态),而不是采用电压级别对数据进行编码。
在NRZI中,如果不发生跳跃,数据被编码为0;
若发生跳跃,数据被编码为1.
可以理解为:只要时钟信号为0,NRZI编码就不会发生跳跃,只要出现1,就会出现跳跃。
1、AndroidX简介 点击查看Android文档中对androidx的简介
按照官方文档说明 androidx 是对 android.support.xxx 包的整理后产物。由于之前的support包过于混乱,所以,google推出了 androidX。
由于在后续版本中,会逐步放弃对support 的升级和维护,所以,我们必须迁移到 androidX.对此,官方描述如下:
Existing packages, such as the Android Support Library, are being refactored into AndroidX. Although Support Library versions 27 and lower are still available on Google Maven, all new development will be included in only AndroidX versions 1.0.0 and higher. 2、迁移步骤 2.1 修改gradle.properties android.useAndroidX=true android.enableJetifier=true 其中:
android.useAndroidX=true 表示当前项目启用 androidx android.enableJetifier=true 表示将依赖包也迁移到androidx 。如果取值为false,表示不迁移依赖包到androidx,但在使用依赖包中的内容时可能会出现问题,当然了,如果你的项目中没有使用任何三方依赖,那么,此项可以设置为false 2.2 如何迁移(提前做好备份——在点击“Migrate to AndroidX ” 的时候也会提醒你备份) 点击查看官方迁移指南
问题描述:
An exisiting Android SDK was detected
The setup wizard will only download missing or outdated SDK components
检测到现有的Android SDK
安装向导仅下载缺少或过时的SDK组件
解决方案:
以管理员身份运行androidstudio,防止更新失败
如果出现“Installation failed with message Failed to failed to finalize session: ”,那么很遗憾,可能由于某种原因导致你更新失败了,你可以重启Androidstudio (以管理员身份运行androidstudio),然后尝试再次更新。
实体是长方形,属性是椭圆形,关系为菱形。
实体(entity):
即数据模型中的数据对象(即数据表),用长方体来表示,每个实体都有自己的实体成员(entity member)或者说实体对象(entity instance),例如学生实体里包括张三、李四等。
属性(attribute):
即实体所具有的属性,例如学生具有姓名、学号、年级等属性,用椭圆形表示,属性分为唯一属性( unique attribute)和非唯一属性,唯一属性指的是唯一可用来标识该实体实例或者成员的属性,用下划线表示,一般来讲实体都至少有一个唯一属性。
关系(relationship):
用来表现数据对象与数据对象之间的联系,例如学生的实体和成绩表的实体之间有一定的联系,每个学生都有自己的成绩表,这就是一种关系,关系用菱形来表示。
关联关系有三种:
1对1(1:1):
指对于实体集A与实体集B,A中的每一个实体至多与B中一个实体有关系;反之,在实体集B中的每个实体至多与实体集A中一个实体有关系。
1对多(1:N):
1对多关系是指实体集A与实体集B中至少有N(N>0)个实体有关系;并且实体集B中每一个实体至多与实体集A中一个实体有关系。
多对多(M:N):
多对多关系是指实体集A中的每一个实体与实体集B中至少有M(M>0)个实体有关系,并且实体集B中的每一个实体与实体集A中的至少N(N>0)个实体有关系。
举例说明:
ER实体补充讲解:
ER的实体还会细分为弱实体和复合实体:
弱实体:一个实体必须依赖于另一个实体存在,那么前者是弱实体,后者是强实体,弱实体必须依赖强实体存在,例如上图的学生实体和成绩单实体,成绩单依赖于学生实体而存在,因此学生是强实体,而成绩单是弱实体。
弱实体和强实体的联系必然只有1:N或者1:1,这是由于弱实体完全依赖于强实体,强实体不存在,那么弱实体就不存在,所以弱实体是完全参与联系的,因此弱实体与联系之间的联系也是用的双线菱形。
上面实例根据弱实体的情况更改如下图:
复合实体:复合实体也称联合实体或桥接实体,常常用于实现两个或多个实体间的M:N联系,它由每个关联实体的主玛组成,用长方体内加一个菱形来表示。
ER属性补充讲解:
ER图的属性还细分为复合属性、多值属性和派生属性、可选属性,同时还有用来表示联系的属性,称为联系属性;
复合属性(composite attribute):
复合属性是指具有多个属性的组合,例如名字属性,它可以包含姓氏属性和名字属性,如下图:
复合属性也有唯一属性,例如学生的所在班级属性,由于多个年级都有班级,所以单单班级属性是不唯一的,但是和年级组成的复合属性后则可以匹配成唯一属性。
多值属性(multivalued attribute):
一个实体的某个属性可以有多个不同的取值,例如一本书的分类属性,这本书有多个分类,例如科学、医学等,这个分类就是多值属性, 用双线椭圆表示。
派生属性(derivers attribute):
是非永久性存于数据库的属性。派生属性的值可以从别的属性值或其他数据(如当前日期)派生出来,用虚线椭圆表示,如下图。
下面的小组人数就是典型的派生属性,随着学生实例的参加的兴趣小组变化,小组人数属性也会变化,一般来讲派生属性不存在于数据库中,而是通过相应的公式进行计算得到,如果要放到数据库中,那么隔一段时间就要进行更新,否则会出现数据错误。
可选属性(optional attribute):
并不是所有的属性都必须有值,有些属性的可以没有值,这就是可选属性,在椭圆的文字后用(O)来表示,如下图的地址就是一个可选属性。
联系属性:
联系属于用户表示多个实体之间联系所具有的属性,一般来讲M:N的两个实体的联系具有联系属性,在1:1和1:M的实体联系中联系属性并不必要。
实例题目:
假设教学管理规定:
一个学生可选修多门课,一门课有若干学生选修;
一个教师可讲授多门课,一门课只有一个教师讲授;
一个学生选修一门课,仅有一个成绩。
学生的属性有学号、学生姓名;教师的属性有教师编号,教师姓名;课程的属性有课程号、课程名。
要求:根据上述语义画出ER 图,要求在图中画出实体的属性并注明联系的类型;
一、简介 想要使用web3j开发ETH钱包,我们需要把准备工作做好,那么先让我们来了解下什么是web3j:https://web3j.readthedocs.io/en/latest/,我这里是最新版本的地址,随着时间的变化,我们需要使用心得版本来编写我们的程序。
web3j是一个高度模块化,反应灵敏,类型安全的Java和Android库,用于处理智能合约并与以太坊网络上的客户端(节点)集成:这使您可以使用以太坊区块链,而无需为平台编写自己的集成代码的额外开销。
Java和Blockchain对话提供了区块链,以太坊和web3j的概述。
二、准备工作 想要使用web3j,我们只需使用项目构建工具引入就可
Maven Java 8:
<dependency> <groupId>org.web3j</groupId> <artifactId>core</artifactId> <version>3.6.0</version> </dependency> Android:
<dependency> <groupId>org.web3j</groupId> <artifactId>core</artifactId> <version>3.3.1-android</version> </dependency> Gradle Java 8:
compile ('org.web3j:core:3.6.0') Android:
compile ('org.web3j:core:3.3.1-android') 然后开启自己的节点,上一篇是说使用自己的geth客户端开启,但是我们现在使用infura,来创建自己的项目
Infura:https://infura.io/
注册成功后创建自己的项目:
可以看到 我们可以使用不同环境的不同节点。
三、账户创建和充值及部分代码。 我们现在已经把几乎所有的工作都昨做完了,但是还有一个就是我们钱包的eth的获取,我们可以通过挖矿获取,但是这个是测试环境我们还可以通过其他方式获取(在真实环境我们可以通过交易所来购买)。
现在我们先写下我们创建账户和入门web3j的代码:
/* We start by creating a new web3j instance to connect to remote nodes on the network. 实例化web3j,这里HttpService()可不传参,默认 */ Web3j web3j = Web3j.build(new HttpService("https://rinkeby.infura.io/v3/3f0abe3dcf554486a363809349898253")); Admin admin = Admin.build(new HttpService("https://rinkeby.infura.io/v3/3f0abe3dcf554486a363809349898253")); log.info("Connected to Ethereum client version: "
先上个图。。。。
晚点有空写个 安装使用。。。
github 地址 代码
终于完成,记录一下方便以后查看
一:安装准备 安装C语言编译器:gcc
因为源码包为C语言编写,后面操作会对它编译。
[root@localhost ~]# yum -y install gcc下载httpd源码包
http://mirror.bit.edu.cn/apache/httpd/
二:安装注意事项 软件保存位置根据自己习惯,但绝不能随意保存,我为/usr/local/apache如何确定安装过程有报错:安装过程停止后查看后几行是否有
Error,Warning,No等关键字 三:源码包安装 将Windows下载好源码包的用工具传到Linux中。
[root@localhost ~]# tar -zxvf httpd-2.4.38 [root@localhost ~]# tar -zxvf httpd-2.4.38解压后进入解压出的目录中,[root@localhost ~]# cd httpd-2.4.38/(里面的INSTALL文件里面有安装的详细步骤,可以参考)
进入后先进行软件的配置和检查
使用./configure命令
[root@localhost httpd-2.4.38]# ./configure --prefix=/usr/local/apache
-prefix后要跟位置,系统会把文件安装到一个目录中,若无会默认到多个分散,删除等操作不方便
这时候,最头疼的来了,报错了!
报错信息我就不贴了,原因基本一样,没有apr,apr-util,pcre包
下载! apr, apr-util http://apr.apache.org/download.cgi
pcre-http://www.pcre.org/
三个完成下载后:重复步骤
解压:tar -zxvf + 包名
进入目录:cd + 文件名
软件配置与检查:.configure --prefix= + 位置
!注意:在apr-util的命令中还会报错,
它的命令为:.configure --prefix= + 位置 --with-apr=+位置
在pcre过程中也会报错,需c++
只需要:yum install -y gcc gcc-c++即可
在apr,apr-util,pcre包都成功进行.configure后分别进行 make命令进行编译
下载 git clone https://github.com/leggedrobotics/darknet_ros 加入cfg和weights到:/darknet_ros/yolo_network_config/
yolo makefile 修改 修改yolo的makefile使用gpu编译,注意写入tx2的62架构
使用clang++进行catkin_make 检查gcc/g++版本,如果是5以上没有问题,跳到下一个黑体标题
如果对gcc,g++降了级别,且编译时候莫名报错,所以采用clang进行编译catkin_make,需要在CMakeLists.txt中设置使用clang++进行编译,而不是g++
首先安装clang和clang++
sudo apt-get install clang 编译并添加darknet_ros包的环境变量 编译方法参考github:https://github.com/leggedrobotics/darknet_ros
catkin_make -DCMAKE_BUILD_TYPE=Release echo "/darknet_ros/devel/setup.bash" >> ~/.bashrc source ~/.bashrc 查看config文件 进入/darknet_ros/config/
查看ros.yaml如下,修改为自己的摄像头话题。
修改检测的yaml文件 在/darknet_ros/yolo_network_config/中存放了cfg和weights文件
在/darknet_ros/config/存放了不同的yaml,会调用配套的cfg和weights
在/darknet_ros/launch/darknet_ros.launch中修改下面一行就可以调用不同的yaml进行检测,下面采用YOLOV2-tiny网络和权重
<arg name="network_param_file" default="$(find darknet_ros)/config/yolov2-tiny.yaml"/> 启动ros,usb摄像头,yolo检测: roscore roslaunch usb_cam usb_cam-test.launch roslaunch darknet_ros darknet_ros.launch
本电脑配置:一个机械(win10)+2个固态(分别安装两个ubuntu)
其中一个新买的固态硬盘往u盘拷贝文件突然见出现了以下问题:
确认了以下几件事情:
1.u盘是好的
2.该系统盘往其他系统盘互相拷贝文件是可以的
3.在另一个ubuntu系统下,从这个坏的安装ubuntu系统的固态硬盘往出拷贝文件是也可以的
说明是该系统文件出现了错误.
网上百度了很多方法:
1.挂载重新挂载mount /dev/sda1 / -o rw,remount,然后修改sudo gedit /etc/fstab,把挂载 / 的行里的 -error=remount-ro 修改为rw,重启
2.mount -o rw,remount /
以上修改fstab文件和重新挂载的方法都试了好几次,都无法修复!!!
本电脑有两个ubuntu系统,在另一个ubuntu系统下修复固态硬盘,具体过程:
先获取root权限
sudo su sudo fsck.ext4 -p /dev/sdb5 在这里我遇到了以下错误:
这里应该先卸载(即弹出)该硬盘,然后再再重新运行.显示如下:
这里按照提示输入
e2fsck -b 32768 /dev/sdb5 过程中出现的任何情况全部点击y.完成后reboot再进入原来出现错误的ubuntu系统,修复成功!
#include<stdio.h> int main(void){ FILE * flie file = fopen("user.txt","a"); if (! file){ printf("文件打开失败!"); } fputs("\n刘备 abc123",file); system("pause"); fclose(file); printf("文件已经关闭"); system("pause"); return 0; }
KEIL升级至V5.25之后,在打开J-link配置界面及启动调试时,会弹出“The connected J-Link is defective,Proper operation cannot be guaranteed.”的提示框。在DEBUG过程中,STEP执行10秒左右就断开,并且不能STOP。J-Link与设备的连接异常断开。
问题原因:是由于V5.25的KEIL默认安装高版本的J-Link驱动V6.3,市面上的TB盗版J-link OB缺少协议,会被识别。
解决方法:直接使用V490替换掉MDK目录下J-Link文件夹里面对应的文件即可。
具体操作:用V4.90安装目录下(X:\Program Files (x86)\SEGGER\JLink_V490)对MDK目录下Segger文件夹(X:\Keil_v5\ARM\Segger)内相对应的文件进行替换。
该操作必须在MDK及相关调用JLink.exe的应用及进程关闭的情况下进行。
原文链接:https://blog.csdn.net/CHIERYU/article/details/81989920
HNSW算法可类比于skip lists数据结构,对于增和查操作,其与skip lists有很多相同之处,下面讲讲HNSW算法中的2个关键问题,即:如何确定待插入点的层次,如何调参。
一、HSNW算法将样本插入到第几层 每个样本属于哪个层呢?
首先要写一个确定层次的函数,样本点属于每一层的概率是确定好的,且是从底层到高层逐渐递减的。
确定每层概率的函数如下:
//from faiss code //levelMult = 1/log(M) void HNSW::set_default_probas(int M, float levelMult) { int nn = 0; cum_nneighbor_per_level.push_back (0); for (int level = 0; ;level++) { float proba = exp(-level / levelMult) * (1 - exp(-1 / levelMult)); if (proba < 1e-9) break; assign_probas.push_back(proba); nn += level == 0 ? M * 2 : M;//特别地,第0层要求2M个邻居,以提高recall cum_nneighbor_per_level.push_back (nn); } } 上述代码的原理可以参考如下图片内容来辅助理解,层次t越大,那么概率应该越小。
确定样本层次的函数如下: //from faiss code int HNSW::random_level() { double f = rng.
写在前言:如果你装不成功,never give it up,你需要的只是一个纯净的系统而已!很重要!!!
我装了好几遍,最后在纯净的系统上才成功的!因为原来装了很多软件的系统有些依赖或者库可能版本不太对应。
PCL(Point Cloud Library )点云库是一个开源的c++代码库,包含了大量的点云相关的通用算法和数据结构。在SLAM领域有着广泛的应用,官方的安装教程:
sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pcl sudo apt-get update sudo apt-get install libpcl-all 上面那种安装方法会出现无法定位到libpcl-all package的问题,因此最最保守的是要采用源码安装方式。
1.先安装各种依赖
sudo apt-get update sudo apt-get install git build-essential linux-libc-dev sudo apt-get install cmake cmake-gui sudo apt-get install libusb-1.0-0-dev libusb-dev libudev-dev sudo apt-get install mpi-default-dev openmpi-bin openmpi-common sudo apt-get install libflann1.8 libflann-dev sudo apt-get install libeigen3-dev sudo apt-get install libboost-all-dev # 其他依赖
sudo apt-get install libqhull* libgtest-dev sudo apt-get install freeglut3-dev pkg-config sudo apt-get install libxmu-dev libxi-dev sudo apt-get install mono-complete sudo apt-get install libopenni-dev sudo apt-get install libopenni2-dev 2.
解决问题 import HTMLParser
File “/usr/local/lib/python3.5/dist-packages/HTMLParser.py”, line 11, in import markupbase
ImportError: No module named ‘markupbase’
或者:
ModuleNotFoundError: No module named ‘HTMLParser’
解决方法 import HTMLParser更换为from html.parser import HTMLParser
即可!
SimpleNotes 极简风格的专为程序员使用的小清新笔记应用!!!
SimpleNotes 是一个简单的代码片段及长篇markdown管理工具,使用gist作为存储,使用Electron+Vue作为技术栈,初衷是自己想有一款简洁好用的笔记应用,无奈没寻觅到一款好用的,遂自己写了一个,现在分享出来,给有需要的大家
使用截图
附上链接
欢迎使用和建议 Github地址 下载请前往 Github | SimpleNotes官网 (官网小水管如果下载较慢请前往github下载)
现已推出 win平台 & macOs平台 复制代码 觉得好用的话麻烦给个star喔 转载于:https://juejin.im/post/5c45a1f46fb9a049e3086b7d