最近在学习vue框架,想在vue中使用sass写样式,但在vue中安装的node-sass 和 sass-loader后 ,在style中写样式总是报错。
下面是我对这个问题的一点记录
在vue中使用sass写css代码,我们需要在vue的style样式上添加一些样式
<style scoped lang="scss"> // 添加一个属性 lang="scss" .main{ background-color: #00FFFF; /* height: 100%; */ span{ font-size: 30px; } } </style> 这是运行会发现报错
Failed to resolve loader: sass-loader
说是没有sass-loader
那我们安装呗 cnpm install sass-loader -D
这是会报错
Module build failed (from ./node_modules/_sass-loader@8.0.0@sass-loader/dist/cjs.js):
Error: Cannot find module ‘node-sass’
那我们也安装一个 cnpm install node-sass -D
如果这是用 最新版的vue搭建脚手架 @vue/cli 这时你的sass样式应该可以用了,
但是。如果你用你不是最新的脚手架搭建工具
也可能还是会报错
Module build failed: TypeError: this.getResolve is not a function
at Object.
1. 中断向量 中断向量把中断/异常与相应的处理方法联系起来
每种中断都会对应一个中断向量号,而这个向量号通过IDT(中断向量表)就与相应的中断处理程序对应起来了。
2. 中断类型码 我们把每个中断服务程序进行编号,这个号就代表一个中断服务程序,就是中断类型码。这个中断类型码是计算机用来查找中断向量用的。
3. 中断向量表 起始地址:0
每个中断向量包含4Bytes
低地址2个Byte放偏移
高地址两个Byte放段描述符
最多256个中断向量
4. 实模式下中断程序地址如何得到 中断类型号×4=存放中断向量的首地址
按照实模式的寻址方式找到对应的中断处理的入口
5. 保护模式下中断程序地址如何得到 在保护模式下,为每一个中断和异常定义了一个中断描述符,来说明中断和异常服务程序的入口地址的属性
由中断描述符表取代实地址模式下的中断向量表
中断描述符含有中断处理程序地址信息
6. 中断向量的地址如何得到 中断类型号 $\times$ 4
7. 实模式下如何根据中断向量的地址得到中断程序地址 根据中断号获取中断向量值,即对应中断服务程序的入口地址值
8. 解释中断描述符 低地址的0和1两个字节是中断代码的偏移量A15~A0; 高地址的6和7两个字节是中断代码的偏移量A31~A162和3两个字节是段选择符,段选择符和偏移量用来形成中断服务子程序的入口地址4和5两个字节称为访问权限字节,它标识该中断描述符是否有效、服务程序的特权级和描述符的类型等信息 9. 保护模式下中断描述符表如何得到 CPU切换到保护模式之前,运行于实模式下的初始化程序必须使用LIDT指令装载中断描述符表IDT,将IDT基地址与段界值装入IDTR。
10. 保护模式下中断门如何得到 查中断描述符表以IDTR指定的中断描述符表的基地址为起始地址,用调用号N×8算出偏移量,即为N号中断门描述符的首地址,由此处取出中断门的8个字节
11. 保护模式下如何根据中断门得到中断处理程序 查全局或局部描述符表根据中断门中的选择子(段选择符)和偏移量得到中断处理程序入口
12. 中断的分类,举例不同类型的中断 由CPU以外的事件引起的中断,如I/O中断、时钟中断、控制台中断来自CPU的内部事件或程序执行中的事件引起的中断,如由于CPU本身故障、程序故障、请求系统服务的指令引起的中断。 13. 中断与异常的区别 中断是CPU具备的功能,异常是软件运行过程中的一种开发过程中没有考虑到的程序错误中断是CPU暂停当前工作,有计划地去处理其他事情,一般可以预知,也有事先制定的处理过程,处理中断时,程序正常运行;异常是CPU遇到了无法响应的工作,而后进入一种非正常状态,异常的出现表明程序有缺陷。中断是异步的,异常是同步的中断和异常的返回点 良性的如中断和trap,处理完后会返回原来的指令流中的下一条指令恶性的如fault和abort,若修复fault,重新执行;不可修复的fault和abort不再返回 中断是由于当前程序无关的中断信号触发的,CPU对中断的响应是被动的,且与CPU模式无关;异常是由CPU控制单元产生的,大部分异常发生在用户态 14. 实模式和保护模式下的中断处理差别 保护模式下的中断处理与实模式下的中断处理最大区别在于寻找中断处理代码入口的方式
实模式直接根据中断号查中断向量表获取
保护模式要先从IDTR中获得中断描述符表的首地址,再根据调用号×8得到中断描述符,再根据其中的选择子和偏移量获取
15. 如何识别键盘组合键 为第一个键设定一个变量,按下就置为1,释放置为0
16. IDT是什么,有什么作用 中断描述符表,存中断描述符
17. IDT中有几种描述符 最多256种
18. 异常的分类 Fault:是一种可被更正的异常,一旦被更正,程序继续运行Trap:一种在发生Trap的指令执行后立即被报告的异常,允许程序正常执行Abort:不总是报告精确异常发生位置的异常,不允许程序继续执行 19.
文章目录 1.python 删除list中元素三种方式(一般)1. pop()2.del3.remove 2.嵌套数组删除存在的问题坑**Solution**: 1.python 删除list中元素三种方式(一般) 1. pop() 1.默认删除最后一个元素.pop()中也可以传入参数,为list的索引
2.pop() 接收的是索引,无参的情况下删除的是最后一个元素(典型的栈的特性)
3.pop() 存在返回值,返回的是删除的元素值
list=[11,12,13,14,15] list=[11,12,13,14,15] list.pop() print(list.pop()) print(list) #output 14 [11, 12, 13] 2.del list=[11,12,13,14,15] del(list[1]) print(list) #output [11, 13, 14, 15] 3.remove remove() 的参数是具体的元素值,而不是索引,
list=[11,12,13,14,15] list.remove(11) print(list) #output [12, 13, 14, 15] 2.嵌套数组删除存在的问题 坑 存在于嵌套list中, 如果list1中的一个元素发生改变,list0也会变化.
目的:list0生成后不随list1的改变而改变
if(len(first_images)==12): #获取到了1分钟内的12个图像 grey_images.append(to_grey(first_images)) first_images.clear() if(len(grey_images)==5): #获得了5分钟的图片 images.append(grey_images) print("image1前的shape:") arr1 = np.array(images) print(arr1.shape) del(grey_images[0]) print("image1之后的shape:") arr1 = np.array(images) print(arr1.shape) 结果:image1前的shape和image1之后的shape并不一样.删除元素后比之前的少了一个元素.因为list存放的是索引,并不是实际的值
Solution: 思路:将索引改为实际的值,然后再删除
最近在学vue框架, 在写单独一个页面组件(login) 的时候,遇到了页面的高度不能自适应浏览器的高度。
下面是我对这个问题的一些个人见解。
举个列子来说:
对应vue项目来说,App.vue是项目的根组件,其他的组件都是它的子组件或是子孙组件,我就以一个最简单的例子来阐述我遇到的问题,
问题:就如vue项目初始化后的结构
在app.vue(父组件)中包含了HelloWorld.vue(子组件)
<template> <div id="app"> <HelloWorld/> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'app', components: { HelloWorld } } </script> 而我想让HelloWorld.vue 占满全屏。
当时我无论是在app.vue 还是在 HelloWorld.vue上怎么设样式,都不能得到满意的结果。
最终还是借用jquery来解决这个问题(后话,之后找到了更方便的方式,在本文的最下面)
在vue中安装jquery
cnpm install jquery -S 在HelloWorld.vue上引入jquery
使用代码如下
<template> <div class="main"> <span>hello</span> </div> </template> <script> import $ from 'jquery' export default { name: 'HelloWorld', props: { msg: String }, mounted(){ // 实现APP的高度占满全屏 $('.main').height($(window).height()) } } </script> <!
段落缩进是文本中都有的一个概念。在一个段落中,会有一个至多个句子组成的。为了让段落结构更加分明,段落的第一句会向右空一定的距离。由于LaTeX的段落默认是有缩进的(一般首先有2个字符的缩进),所以无论一个段落有多长,或者无论有多少个段落,每个段落都会缩进它们的第1行。
在一般的段落中,在水平标尺方向,有四个段落缩进的概念:首行缩进、悬挂缩进、左缩进以及右缩进。其中:
首行缩进
将某个段落的第一行向右进行段落缩进,其余行不进行段落缩进。其形状为倒三角形。悬挂缩进
将某个段落首行不缩进,其余各行缩进。其形状为正立三角形。左缩进
将某个段落整体向右进行缩进。其形状为矩形。右缩进
将某个段落整体向左进行缩进,在水平标尺的右侧留白,形状为正立三角形。 一个段落分行的问题
但是需要注意的是,由于在源代码中,连续的行会被当成同一个段落来处理,所以即便会有换行,也是按同一行处理的。如果内容短很容易理解,但是当内容多时,就会给人带来困扰。
现在让我们看以下的示例。
\documentclass{article} \usepackage{indentfirst} \begin{document} \title{This an example.} \author{Wei HAO} \date{December 12, 2019} \maketitle In this section we ara going to discuss the distribution of probability. There are many distributions that are commonly used in real life, such as: $$ F(x) = \int_{-\infty}^{\infty}f(x)dx = \int_{-\infty}^{\infty}\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(x-\mu)^2}{2\sigma^2}}dx $$ This is the most common one ... \end{document} 可以看到,根据连续行按同一段落处理:In this section we ara going to discuss the distribution of probability.
希腊字母 序号大写,小写大写,小写1 α \alpha α, A \Alpha A\Alpha,\alpha2 β \beta β, B \Beta B\Beta,\beta3 γ \gamma γ, Γ \Gamma Γ\Gamma,\gamma4 δ \delta δ, Δ \Delta Δ\Delta,\delta5 ϵ \epsilon ϵ, E \Epsilon E\Epsilon,\epsilon6 ζ \zeta ζ, Z \Zeta Z\Zeta,\zeta7 η \eta η, H \Eta H\Eta,\eta8 θ \theta θ, Θ \Theta Θ\Theta,\theta9 ι \iota ι, I \Iota I\Iota,\iota10 κ \kappa κ, K \Kappa K\Kappa,\kappa11 λ \lambda λ, Λ \Lambda Λ\Lambda,\lambda12 μ \mu μ, M \Mu M\Mu,\mu13 ν \nu ν, N \Nu N\Nu,\nu14 ξ \xi ξ, Ξ \Xi Ξ\Xi,\xi15 ο \omicron ο, O \Omicron O\Omicron,\omicron16 π \pi π, Π \Pi Π\Pi,\pi17 ρ \rho ρ, P \Rho P\Rho,\rho18 σ \sigma σ, Σ \Sigma Σ\Sigma,\sigma19 τ \tau τ, T \Tau T\Tau,\tau20 υ \upsilon υ, Υ \Upsilon Υ\Upsilon,\upsilon21 ϕ \phi ϕ, Φ \Phi Φ\Phi,\phi22 χ \chi χ, X \Chi X\Chi,\chi23 ψ \psi ψ, Ψ \Psi Ψ\Psi,\psi24 ω \omega ω, Ω \Omega Ω\Omega,\omega 注:需要添加引用 \usepackage{amsmath}。
我在执行network.cuda()的时候报错:
RuntimeError: cuda runtime error (38) : no CUDA-capable device is detected at /pytorch/aten/src/THC/THCGeneral.cpp:50 查询了一下解决方案,很多时候这个错误是Nvidia的驱动版本和CUDA不匹配导致的,比如:https://blog.csdn.net/flowrush/article/details/80254301
但是我的问题其实不是这样,而是我开始时候将显卡设置的显卡号CUDA_VISIBLE_DEVICES设置错误了。。我的设置是:
os.environ["CUDA_VISIBLE_DEVICES"] = "6" 然而我的机器只有4张卡。。。。
记录一下,可能可以帮大家快一点排错。
翻币问题 问题描述 有N个硬币(6<=N<=20000)全部正面朝上排成一排,每次将其中5个硬币翻过来放在原位置,直到最后全部硬币翻成反面朝上为止。试编程找出步数最少的翻法,输出最少步数及翻法。
input 从键盘输入一个正整数N(6<=N<=20000),表示硬币的数量。
output 第1行:一个整数,表示最少步数
第2行至最后一行:先是一个整数,表示步骤序号(从0开始编号),后接一个":",再接当前硬币的状态(用一个整数表示正面朝上的硬币的个数)
样例 输入
6
输出
6
样例解释
0:6 (第0步结果:6个硬币正面朝上)
1:1 (第1步结果:1个硬币正面朝上)
2:4 (第2步结果:4个硬币正面朝上)
3:3 (第3步结果:3个硬币正面朝上)
4:2 (第4步结果:2个硬币正面朝上)
5:5 (第5步结果:5个硬币正面朝上)
6:0 (第6步结果:0个硬币正面朝上)
6 (最少用6步实现全部反面朝上)
问题分析 由题可得知有6种翻法:
原正个数原负个数翻后正个数翻后负个数50-5+541-3+332-1+123+1-114+3-305+5-5 判断当前状态是否满足翻的条件,并且翻后状态没有出现过
是就 tail++,放入队尾,将翻后状态=1
如果当前状态正数个数=0,输出步数
别的就套模板啦,我只是个蒟蒻
代码 #include<iostream> #include<cstdio> using namespace std; int a[20100],h,t,n; int fz[7]={0,5,4,3,2,1,0},ff[7]={0,0,1,2,3,4,5}; struct c{ int s,b,f; }s[20100]; int main() { scanf("%d",&n); s [1] .s=n; s[1].b=0; s[1].f=0; // 付初值,s 是正数个数,b 是步数,f 是父节点 h=0; t=1; a[n]=1; // 状态出现,设为1 do{ h++; for (int i=1;i<=6;i++) if (s[h].
Dart汇总请点击这里
库和可见性 import 和 library 指令可以用来创建一个模块化的,可共享的代码库。 库不仅提供了 API ,而且对代码起到了封装的作用: 以下划线 (_) 开头的标识符仅在库内可见。 每个 Dart 应用程序都是一个库 ,虽然没有使用 library 指令。
库可以通过包来分发。有关 pub(集成在SDK中的包管理器)的信息,请参考 在pub上发布自己的库。
使用库 通过import指定一个库命名空间中的内如如何在另一个库中使用。 例如,Dart Web应用程序通常使用dart:html 库,它们可以像这样导入:
import 'dart:html'; import参数只需要一个指向库的 URI。 对于内置库,URI 拥有自己特殊的dart:方案。 对于其他的库,使用系统文件路径或者 package:方案 。 package:方案指定由包管理器(如 pub 工具)提供的库。例如:
import 'package:test/test.dart'; 提示: URI 代表统一资源标识符。 URL(统一资源定位符)是一种常见的URI。
指定库前缀 如果导入两个存在冲突标识符的库, 则可以为这两个库,或者其中一个指定前缀。 例如,如果 library1 和 library2 都有一个 Element 类, 那么可以通过下面的方式处理:
import 'package:lib1/lib1.dart'; import 'package:lib2/lib2.dart' as lib2; // 使用 lib1 中的 Element。 Element element1 = Element(); // 使用 lib2 中的 Element。 lib2.
参考:https://blog.csdn.net/orichisonic/article/details/79951460 (https实现)
https://www.cnblogs.com/boycelee/p/6425325.html (https详解)
(SSH详解)
https://mp.weixin.qq.com/s?src=11×tamp=1575620980&ver=2017&signature=l0JMOHdKnIaY5myynb4qCAVgGNrsw-rsRz1fTvLa4lQjUhV9YBM6Ht0*guHi385w0TAXsvwAarfSr967oj3GsS4Z-8itxgQb2u37JG4VwksKTtg-*SPtyAIgxrvPd*J0&new=1
HTTPS:与SSL(安全套接层)组合使用的HTTP被称为HTTPS(超文本传输安全协议)
加密处理防止窃听:通信加密。HTTP协议与SSL组合使用,加密HTTP的通信内容。用SSL建立安全通信线路之后,就可以在这条线路通信了。
HTTP+加密+认证+完整性保护 = HTTPS
在使用http协议时,HTTP直接与TCP通信,当使用SSL时,则需要先与SSL通信,然后再有SSL和TCP通信
SSL是对计算机之间整个会话进行加密的协议。在SSL中,采用了公开密钥和私有密钥两种加密方法。
下面开始讲解https的小例子:
https其实是安全套接层SSL和http组合的,需要SSL证书,SSL证书可以通过CA机构申请得到,也可以本地自己生成(不安全),本次就自己在本地生成SSL证书,以访问https://www.alipay.com/为例子
1、浏览器(以chrome为例)访问https://www.alipay.com/,点击域名左侧的小锁,可以查看支付宝的证书信息,将支付包的证书信息导出,证书格式有很多中,der、cer等。随便选择即可。
2、命令行或者shell执行 keytool -import -alias "my alipay cert" -file www.alipay.com.cert -keystore my.store,
如果keytool命令不识别,去检查一下jdk的环境变量是否设置正确。”my alipay cert”是个别名,随便取。“www.alipay.com.cert”这个文件就是从浏览器中导出的支付宝的证书。“my.store”是生成的自己 的证书库文件。回车执行,效果如下:
接下来就是代码了,代码如下:
trustStore.load(instream, "123456".toCharArray()); 这个“123456”是秘钥库口令,你生成my.store自己设的口令。
用到的jar包有:commons-logging.jar fastjson-1.2.58.jar JSONObject等用到
httpclient-4.5.9.jar org.apache.http.impl.client.*用到
httpcore-4.4.11.jar org.apache.http.client.* 用到
public class HttpsClient { public final static void main(String[] args) throws Exception { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); //加载证书文件 FileInputStream instream = new FileInputStream(new File("F:\\ideaWork\\HttpUtil\\src\\my.store")); try { // trustStore.
项目地址:https://gitee.com/lwj/flowable.git 分支flowable-base
视频讲解地址
https://space.bilibili.com/485524575/channel/detail?cid=94579
1、演示 2、代码分享 public ReturnVo<String> stopProcessInstanceById(EndVo endVo) { ReturnVo<String> returnVo = null; ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(endVo.getProcessInstanceId()).singleResult(); if (processInstance != null) { //1、添加审批记录 this.addComment(endVo.getUserCode(), endVo.getProcessInstanceId(), CommentTypeEnum.LCZZ.toString(), endVo.getMessage()); List<EndEvent> endNodes = flowableBpmnModelService.findEndFlowElement(processInstance.getProcessDefinitionId()); String endId = endNodes.get(0).getId(); String processInstanceId = endVo.getProcessInstanceId(); //2、执行终止 List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list(); List<String> executionIds = new ArrayList<>(); executions.forEach(execution -> executionIds.add(execution.getId())); this.moveExecutionsToSingleActivityId(executionIds, endId); returnVo = new ReturnVo<>(ReturnCode.SUCCESS, "终止成功"); }else { returnVo = new ReturnVo<>(ReturnCode.FAIL, "不存在运行的流程实例,请确认!"); } return returnVo; }
公众号后台回复“学习”,免费获取精品学习资料
扫描下方海报 试听
本文来源:Java知音
前言 上一篇发了手动搭建Redis集群和MySQL主从同步(非Docker)之后,很多同学对文中主从结构提到的读写分离感兴趣,本打算在双十一期间直接把读写分离分享给大家,奈何工作一直没停下,所以这周抽空把这些分享出来。
关于MySQL的读写分离的实现,有两种方式,第一种方式即我们手动在代码层实现逻辑,来解析读请求或者写请求,分别分发到不同的数据库中,实现读写分离;第二种方式就是基于MyCat中间件来实现读写分离的效果;这两种方式我都会在这篇博客中进行详细地介绍、搭建,并且分析其中的优劣。
原理初探 从MySQL的主从同步开始谈起,最开始我们的数据库架构是这样的。
主库负责了所有的读写操作,而从库只对主库进行了备份,就像我在上一篇文章中说的那样,我认为如果只实现了一个备份,不能读写分离和故障转移,不能降低Master节点的IO压力,这样的主从架构看起来性价比似乎不是很高。
我们所希望的主从架构是,当我们在写数据时,请求全部发到Master节点上,当我们需要读数据时,请求全部发到Slave节点上。并且多个Slave节点最好可以存在负载均衡,让集群的效率最大化。
那么这样的架构就不够我们使用了,我们需要找寻某种方式,来实现读写分离。那么实际上有两种方式。
方法1:代码层实现读写分离 这种方法的优势就是比较灵活,我们可以按照自己的逻辑来决定读写分离的规则。如果使用了这样的方法,我们整个数据库的架构就可以用下面这张图进行概括:
方法2:使用中间层(虚拟节点)进行请求的转发 这种方式最主要的特点就是我们在除了数据库以外地方,新构建了一个虚拟节点,而我们所有的请求都发到这个虚拟节点上,由这个虚拟节点来转发读写请求该相应的数据库。
这种方式的特点就是,其构建了一个独立的节点来接收所有的请求,而不用在我们的程序中配置多数据源,我们的项目只需要将url指向这个虚拟节点,然后由这个虚拟节点来处理读写请求。不是有这么一句话吗,专业的事交给专业的人来做,大概是这么个意思吧。而现在存在的MyCat等中间件,就是这样的一个”专业的人“。
那么下面我就会动手实现上述两个读写分离的解决方案,代码层实现读写分离和使用中间件实现读写分离
手动实现读写分离 实现读写分离的方法有很多,我这里会说到两种,第一种是使用MyBatis和Spring,手写MyBatis拦截器来判断SQL是读或者写,从而选择数据源,最后交给Spring注入数据源,来实现读写分离;第二种是使用MyCat中间件,配置化地实现读写分离,每种方式都有其可取之处,可以自己视情况选用。
环境说明 这里用到了我的上篇博客手动搭建Redis集群和MySQL主从同步(非Docker)中所搭建的MySQL主从同步,如果手上没有这套环境的,可以先比着这篇博客进行搭建。但是需要注意的是,要将8.0版本的MySQL改为5.7。
192.168.43.201:3306 Master
192.168.43.202:3306 Slave
开发环境:
IDE:Eclipse
Spring boot 2.1.7
MySQL 5.7
CentOS 7.3
新建Maven项目 为了演示方便,这里使用SpringBoot作为测试的基础框架,省去了很多Spring需要的xml配置。没有用过SpringBoot的同学也没关系,我会一步一步地进行演示操作。
导入依赖 <parent>
<groupId>org.springframework.boot<groupId>
<artifactId>spring-boot-starter-parent<artifactId>
<version>2.1.7.RELEASE<version>
<relativePath /> <parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot<groupId>
<artifactId>spring-boot-starter-web<artifactId>
<dependency>
<dependency>
<groupId>com.oracle<groupId>
<artifactId>ojdbc7<artifactId>
<version>12.1.0<version>
<dependency>
<dependency>
<groupId>org.mybatis.spring.boot<groupId>
<artifactId>mybatis-spring-boot-starter<artifactId>
<version>2.0.0<version>
<dependency>
<dependency>
<groupId>mysql<groupId>
<artifactId>mysql-connector-java<artifactId>
<dependency>
<dependency>
<groupId>org.springframework.boot<groupId>
<artifactId>spring-boot-starter-test<artifactId>
<dependency>
<dependency>
我们在使用photoshop的时候,有时候把项目快要做完了,这个时候电脑突然弹出了一个提示“你的photoshop已经停止工作”,这个时候是不是让你很抓狂。相信对photoshop有一定使用经历的人应该都有过这样的经历,这个时候可以说是欲哭无泪啊。花了这么长时间做出的成果,就这样一下子化为泡沫!真的是太可惜了,那么这个时候真的就没救了吗?其实遇到这种情况的时候可以使用以下方法尝试找回已经丢失的文件。
当我们遇到photoshop停止工作的时候,先不要着急,先不要强制关闭photoshop,如果你使用的是windows电脑,使用快捷键ctrl+alt+dellate调出任务管理器,我们可以看到下面的窗口。
我们在应用程序里找到正在运行的photoshop程序,然后对其进行右击,选择创建转存文件,这个时候我们需要耐心等待几分钟,不要着急,所有的等待都是值得的。
在这个过程中,我们可以在弹出的窗口上看到下面的内容,上面会有我们转存的路径,我们可以通过这个路径找到转存的文件,我们可以根据这个路径找到一个dmp文件,这个文件非常关键,我们回复我们的项目就要靠这个了。
这个时候我们已经可以把正在运行的photoshop关闭了,然后重新打开photoshop软件,然后我们把刚才转存的dmp文件拖到photoshop软件中,这个时候我们发现我们的项目又打开了,是不是很神奇。这个技能虽然不是很难,但是关键的时候可以帮助我们很大的忙。
但是我希望我们每个人读用不到这个技能,因为当我们用到这个技能的时候,通常都是我们没有办法的时候了,其实在我们使用photoshop的时候,我们注意养成良好的习惯,就可以避免我们文件的丢失。
比如在我们使用Photoshop的时候,在作图的时候,做过一定时间后主要按ctrl+S保存一次,这个即使我们的软件崩溃了,我可以也可以重新打开保存的文件继续处理。这个习惯不仅在使用Photoshop的时候需要注意,我们在使用其他软件,比如使用office软件的时候也应该注意,我们对文档处理过一段时间之后就按一下Ctrl+S进行保存一次,避免软件的崩溃造成的不必要的损失!
另外,我们也可以通过优化一下软件的设置来避免这种情况的发生,首先我们打开photoshop。找到编辑,然后找到首选项。
我们把后台存储打开
然后把自动储存恢复信息时间间隔打开调整一下。我们把自动保存时间改成五分钟。
当当我们设置好之后,我们在使用photoshop作图的时候,会每隔5分钟自动保存一次,这样就算是软件崩溃也可以找回到五分钟之前的状态,避免整个项目完全丢失。
对于很多设计师来说,photoshop是自己挣钱的重要工具,如果photoshop经常出现问题,对于设计师来说,损失的不仅仅是时间,更是金钱。
我们使用的photoshop如果经常崩溃的话,除了养成良好的保存习惯,还要考虑是不是自己的软件有问题,因为网上下载的“非正规”软件,很多是被人修改过的,有时候会出现不稳定的情况,如果电脑配置没有问题的话,那么需要考虑下是不是软件有问题,更换更稳定的photoshop版本。
另外,电脑的硬件配置也是非常重要的,如果电脑的配置不高的话,也会经常出现软件的崩溃的情况。这个时候建议升级一下自己的电脑配置,因为好的配置不仅可以有效的避免软件出现崩溃,让软件运行的更加的稳定。而且还可以有效的节省我们的大量时间,配置低的电脑时不时出现的卡顿真的会浪费我们大量的时间。
Undeclared variable 原因:
mysql 不支持该语句 :
SELECT * INTO mew_table FROM old_table 不支持向还未建立的表中插入数据
解决:
CREATE TABLE new_table ( SELECT * FROM old__table ) modify和alter区别 alter放在语句前面,表示插入或者修改表,对象是表;而modify修改属性,对象是表属性
数据库中下标从零开始,而且闭区间 选择字符串前 三个字符
SELECT MID(City,1,3) as SmallCity FROM Persons
继承 模型继承 Odoo提供了两种模型继承机制
第一种继承允许在其他包(module)中继承修改当前包(module)的相关内容(inherit): 1. 在已存在的model中继承新增字段 2. 重写已存在model的字段定义 3. 增加model约束 4. 增加model方法 5. 重写model中已存在的方法 第二种继承允许连接到每一个继承的父级model,并且提供直接访问父级model 字段属性的方式。(inherits) 继承写法分为三种
1. 有_inherit无_name: 对当前model属性进行扩展. 2. 有_inherit有_name: 创建出一个新的model拥有父级的所有字段,会在当前model表中初始化继 承的字段列. 3. _inherits: 隐含式继承,能够直接使用父级的所有字段,调用时就和使用自己model的 字段一样,但不需要出现在当前的表记录列中. 视图继承 简介
替换已有视图的内容,Odoo提供了多子视图继承一个父视图,并且对父视图中的 元素进行增加删除或修改。 视图的继承需要在XML视图定义的时候使用inherit_id字段,在继承的子视图中, arch标签块内能够定义任意数量的xpath标签元素,用来修改当前的父视图内容。 <!--在父级视图description字段后添加一个idea_ids字段--> <!-- improved idea categories list --> <record id="idea_category_list2" model="ir.ui.view"> <field name="name">id.category.list2</field> <field name="model">idea.category</field> <field name="inherit_id" ref="id_category_list"/> <field name="arch" type="xml"> <!-- find field description and add the field idea_ids after it --> <xpath expr="//field[@name='description']" position="after"> <field name="
用原生Java实现http请求是有些问题的,一般会涉及到汉字编码问题,如果请求的接口代码是自己写的,那没什么问题,只需要编码(请求方传的参数编码)和解码(响应方对参数进行解码)就行了
编码和解码方式有:URLEncoder.encode(name,"UTF-8"); 编码
URLEncoder.decode(name, "UTF-8"); 解码
或者。。。其他方式
(new InputStreamReader(name, "UTF-8"); 解码)
在工作中,请求的接口一般是第三方的接口,第三方可能收到你的请求参数是乱码的,你又没办法修改到第三方接口的代码,所以说用原生Java实现http请求有点艰难,建议用封装后工具,比如:httpClient等
package com.powerX.httpClient; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class HttpClient { public static String doGet(String httpurl) { HttpURLConnection connection = null; InputStream is = null; BufferedReader br = null; String result = null;// 返回结果字符串 try { // 创建远程url连接对象 URL url = new URL(httpurl); // 通过远程url连接对象打开一个连接,强转成httpURLConnection类 connection = (HttpURLConnection) url.
很多人之所以从事Python,是因为很不爽PHP的语法,虽然PHP被称为世界上最好的编程语言。于是为了这个原因,付出了沉重的代价,失业了好几回。
身边有些人时不时总是会问我一些Python的技术问题,但是大多数情况下都是比较基础的。要不是近几年Python火了起来,说不定我真的转行送外卖了。
对于Python这么语言,可以当作一门兴趣或爱好来学习,但是若是想找到份好的工作还是谨慎为主,这也是为什么不建议你搞Python的原因。
Python学习热 VS Python就业市场广阔 Python流行起来实话说是意料之中的事情,只是没有想到它是那么的快。在14年的时候,实在无法忍受PHP那美元符号和分号的结尾,于是开始入坑Python。那时的Python,市面上只有寥寥几本的书籍可以参考。至于廖雪峰的Python入门教程,:看了2篇就放弃了,写的实在太浅显。当然,后来他也写了些高级的教程,有兴趣的可以看看。
然而,Python仍然是门小众的语言。有多么小众呢?你可以上拉钩或BOSS直聘上搜索下,基本上一线城市除了北京、上海外,其他区域来来去去就那么10-20家公司,而且这些公司中80%都是创业公司。
曾经,我在1年中入职了2家Python的公司,前1家公司我才进去3个月就倒闭了。为什么呢?没人用它搞业务啊。
当前Python比较适合的业务主要有:
数据分析信息安全系统运维应用测试 运维就不用说了,现在基本都是自动化时代了。而数据分析中,说的最多的就是爬虫。实际上,它跟分析没有太多的关系。常见的反倒是一些报表的导出功能。再高级一些的就是什么大数据了。
对于信息安全,完全可以说是石器往青铜时代过渡。虽然有metasploit这样的大杀器,然而很多事情还待人为实现。
对于如下的一些业务还是谨慎使用:
GUI开发嵌入式开发 首先GUI开发,现在不是热门业务。即使有这业务,也只会是Windows的GUI,人家有MFC,跟你Python没有半毛钱关系。如果你要用PyQt5写个界面,还不如用Electron,人家内存管理方面做得反倒更好些。
至于嵌入式开发,还是老老实实学习C语言和汇编吧,不要指望Python能在里面帮上什么忙。当然,做做应用级别的业务,什么语言都是可以的。
对于Web开发,可以选择的余地就更多了。前有Java深耕市场多年,后有nodejs来势汹汹,下有Golang虎视眈眈。而Python在这个市场中能分到的梗真心不多,而且很大一部分都是Django带来的。
这几年Flask的流行,让不少人体会到了Python的简洁。然而,真的好用的还是Pyramid这个名不见经传的框架(仅本人自身观点,可以挖掘很多有意思的东西)。
理性的回归 2018年是个疯狂的一年,资本的市场风起浪涌。相比2019年,反倒平静了许多。理性的回归,资本也逐渐回归到正常。
有位哥们说他公司现在前端最火,他的Java都要退居二线了。随便随便1个3年的前端,动不动就要求薪资最低16K。如果放在16-17年完全是有可能的事情,而放在19年只能说是痴人说梦。
因此19年还是要多从自身的学习做起,多沉淀自身的技术。当然随便学习下技术之外的东西,一些赚钱的方式总是在你认知之外的地方。
你完全可以把学习Python当作一门投资,至于有没有回报就不要太看重了。
错入一行误半生 之所以不建议从事Python的问题在于,你以为从事Python是门轻松的事情,然而却选择了条艰难的不归之路。
不得不说,在从事Python的这几年中,每天都在朝九晚六中度过,还时不时要找点事情做做。虽然薪水没有Java大佬们那么高,然而生活还是过得有滋有味。为什么呢?Python效率高的。效率有多高,直接pip装个包就好了。
每次看到Java的大佬在用maven或grade安装依赖时,就默念还是pip好用,至少还有个进度条知道还需要多久能完成。至于npm就不谈论了,再说下去就会沦为语言之争了。
如果你觉得从事Python是件轻松的事情,那么混吃等死的日子就会到达尽头。有时你拍着胸脯跟BOSS说,这个东西我半天就能完成,结果现实狠狠的闪了你一个耳光。举个简单的例子,比如报表导出word是个很常见的业务输出,如果要在word中输出对应的目录,那真的是件可怕的事情。因为python常用的docx库根本不支持,而Java的POI及PHP的phpword是支持的,结果为了你的无知不得不加班。
然而,闲着无事又会激发自身的瞎折腾,不然没法对上级交待。这里也要庆幸总是遇到些好的领导,鼓励你多学习一点。于是,逐渐的就变成了1个打酱油的人物,救火版的存在。别人搞不定的东西,你花个半个小时完美解决。
什么Win32 API编程,GUI编程,数据报表、分析,打补丁甚至开发外挂样样都过了一遍。结果,2-3个人做了1个团队5-6个人的活,钱还是那么多。
当你从事Python久了,就会发现自己的知识是多么的零少。结果,又不得不推动着你系统的学习一遍,从而每天都在信息量巨大的日子中度过漫漫长夜。
举个最简单的例子,在股票技术面的分析中,什么K线分析是常用的方法。此时你用Python来折腾,是个很不错的主意。结果,你不得不学习点金融的知识来扩充。于是事情就开始变得不可控制和确定了。当然,结果会是有意思的。
曾经在某个夜里,自己通过Python分析的几只股票的组合的收益率达到了20%,我几近失眠了。我从来没有想到,事情是那么的简单且来的不容易。作为1个发了工资就还花呗的人来说,余额宝的收益率才3%而已。即使我1年存了1W,1年后利息也才300。而我用1-2个月的时间,却达到了20%的收益,那种欣喜有点佩服自己,只是后悔当初投入太少。
于是,后来慢慢了解到Python在量化分析中大有用途,虽然没有什么大公司用它进行实时交易。但是,不得不说Python是门很不错的分析语言。
Python作为1门学院派语言,只有在重点高校才会存在的语言,有其独到的先天优势。相比其他分析的工具,如R、Matlab,Python使用起来更人性化些。特别是开发外挂的时候,当然这涉及到黑产的部分内容,就不展开说明了。你会发现Python写起来的效果只是比易语言稍微复杂一些。
抛开信息安全的领域,虽然数据分析动不动就是7位数的收入。但是,要成为1位数据科学家也不是件容易的事情。之所以能给你这个价位的薪资,是因为你自身能提供对应的数据观点,换句话你能挖掘出大数据后的商机。这必定是个缓慢的过程。
很多人没有坚持到那么一步就放弃了,还不如早点找些收入稳定的渠道,避免错过机遇与财富的积累。如果能理性对待,清楚认知自己的当前情况,才知道该岗位是否适合自己。
结语 对于Python,建议可以学习下,但是如果想靠他找到份工作就要谨慎些。毕竟,决定你工资的是你的稀缺程度,如果没有业务的支撑,即使你再精通也是瞎扯。
如果期望高薪资的话,还是建议从事Java或C、C++的岗位。如果想快速找到工作,还是建议从事前端或PHP的岗位。而对于想多方面发展,想折腾自己的人,建议来混混Python的岗位,每天"混吃等死"。
用到的jar包有:commons-logging.jar fastjson-1.2.58.jar JSONObject等用到
httpclient-4.5.9.jar org.apache.http.impl.client.*用到
httpcore-4.4.11.jar org.apache.http.client.* 用到
package com.httpUtil.cn; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.*; /** * DefaultHttpClient clients = new DefaultHttpClient(); HttpClient client = HttpClientBuilder.create().build();//获取DefaultHttpClient请求 */ /** * @author wangwei * @version v1.
spring mvc绑定对象String转Date 问题 1.问题 有时前台页面传递的参数 是时间字符串形式,而后台接受的实体属性类型是java.util.Date类型。springmvc 就无法将值set到该属性上
2.原因 后台的json 反序列化分 fastJson 和 jackson
fastjson默认使用的序列化格式:
public static String DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; jackson默认支持的日期反序列格式:
("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd")) jackson默认的日期反序列化不支持yyyy-MM-dd HH:mm:ss 这种格式,所以在属性上加注解后台依然报错 有可能是注解的时间字符串格式不正确导致反序列化失败
3.解决办法 1.重写jackson反序列化 import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * @version 1.0.0 * @description 重写反序列化 **/ public class CustomJsonDateDeserializer extends JsonDeserializer<Date> { @Override public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { SimpleDateFormat format = new SimpleDateFormat("
'<img class="goodsImg" alt="" src="/sort/'+content.cakePicture+'">'
执行如下命令:
rosdep install --from-paths src --ignore-src --rosdistro=kinetic -y
遇到报错:
executing command [sudo -H apt-get install -y ros-kinetic-map-server] 正在读取软件包列表... 完成 正在分析软件包的依赖关系树 正在读取状态信息... 完成 有一些软件包无法被安装。如果您用的是 unstable 发行版,这也许是 因为系统无法达到您要求的状态造成的。该版本中可能会有一些您需要的软件 包尚未被创建或是它们已被从新到(Incoming)目录移出。 下列信息可能会对解决问题有所帮助: 下列软件包有未满足的依赖关系: ros-kinetic-map-server : 依赖: libsdl-image1.2-dev 但是它将不会被安装 依赖: libsdl1.2-dev 但是它将不会被安装 E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。 ERROR: the following rosdeps failed to install apt: command [sudo -H apt-get install -y ros-kinetic-map-server] failed 网上寻找解决方案:
1.切换源 清华源 阿里源 均未解决
2.sudo apt-get update 然后upgrade,再执行rosdep install --from-paths src -iy 未果`
接下来,我们将学习如何使用jieba模块来实现古典名著《西游记》的分词,并且会将书中重点人物出场次数以图形化的方式显示出来,并进一步创建一个词云图。
17.4.1 读取文件 因为小说《西游记》的内容非常长,我们不太可能会把它放到一个字符串中来操作,所以我们需要它保存在一个文件中。那么我们就需要操作整个文件,把文件中的内容读取出来。我们操作文件的流程是:
1.打开文件,得到文件句柄并赋值给一个变量;
2.通过句柄对文件进行操作;
3.关闭文件。
打开文件就要用到open()函数。其实,我们在第11章中详细介绍了打开文件的方法,读者如果忘了的话,可以再次查阅11.1节回顾一下。
17.4.2 《西游记》的分词 在前面,我们已经介绍了如何使用jieba库分词,以及如何打开一个文本文件。接下来,我们要对经典小说《西游记》进行分词,并且把出现频率最高的词语展示出来。首先,把《西游记》保存到一个文本文件中,要注意的是,保存文件的时候,要将编码格式选择为UTF-8,否则读取文件的时候会报错。此外,我们要把这个文本文件放到和程序代码所在位置相同的文件夹中,这样就不需要指定路径了。
读者可以从本书配套源代码和文件中获取整个文本文件,如图17-5所示。
图17-5
我们先来看一下用于分词的程序代码,代码参见ch17\17.2.py。
import jieba def takeSecond(elem): return elem[1] def main(): path = "西游记.txt" file = open(path,"r",encoding="utf-8") text=file.read() file.close() words = jieba.lcut(text) counts = {} for word in words: counts[word] = counts.get(word,0) + 1 items = list(counts.items()) items.sort(key = takeSecond,reverse=True) for i in range(20): item=items[i] keyWord =item[0] count=item[1] print("{0:<10}{1:>5}".format(keyWord,count)) main() 因为要使用jieba的函数,所以这里首先需要导入jieba模块。
import jieba 接下来,我们定义了两个函数:main(主体函数)和takeSecond(用于获取列表的第2个元素)。然后,定义了变量path来保存相对路径。使用open()函数以只读方式打开文本文件“西游记.txt”,指定的编码方式是UTF-8,并且将文件句柄赋值给变量file。随后调用read()方法读取文件中的内容并保存到变量text中。调用close()方法关闭文件。
然后我们使用jieba.lcut()方法对变量text中的内容进行分词,并且把分词的结果列表保存到变量words中。我们新建一个叫作counts的字典。然后,通过一个循环语句,遍历列表words中的每个元素,用变量word来表示每个元素。在循环中,把word作为字典counts的键,把get()方法返回的值加上1,作为这个键所对应的值。这表示每次遇到同样的键,都会让它的值加上1(以统计相同的键的数目)。需要注意,如果在字典中没有找到键所对应的值,那么get()方法会返回默认值0。当循环结束后,字典counts就包含了西游记中拆分出来的全部词语以及对应的该词语出现的次数。
接下来,我们想要按照词的出现次数排序。第4章介绍字典的时候曾经提到,字典是没有办法排序的,我们需要把字典转换为列表,然后利用列表的sort()方法来排序。因为我们是使用人物的出现次数来排序的,所以要给sort()方法传递一个key参数,以指定用来进行比较的元素,该元素就是取自于可迭代对象中。这里调用了自定义的takeSecond()函数。这个函数接收的参数是一个列表,返回的是这个列表的第2个元素。这样,我们就可以指定第2个元素进行逆序排序,并且把结果赋值给items。
然后,借助range()函数生成一个等差数组,展示items中前20个元素。在每次循环中,我们先把获取的元素赋值给变量item。然后把item的第1个列表元素赋值给变量keyWord,第2个元素赋值给变量count。然后使用print()方法把格式化后的两个变量输出到屏幕上。这里我们用到了format()方法,它可以按照需求来格式化字符串。代码的含义是把keyWord的值左对齐,宽度是10;把count的值右对齐,宽度是5。
提示 字符串的format()方法可以用来格式化字符串。format()方法通过字符串中的花括号 {} 来识别要替换的内容,而format()中的参数是要填入的内容,按照顺序进行匹配。花括号中冒号后面的<符号表示左对齐,>符号表示右对齐,数字表示宽度。 然后调用main()函数。最终得到的词频统计结果如图17-6所示。
Davinci是一个开源的图表可视化编辑项目,包括前端跟后台工程。启动项目后可以导入数据源、配置数据视图、配置小组件、设计显示面板和大屏等,并可将设计好的页面生成链接进行发布。
github地址:https://github.com/edp963/davinci
操作文档地址:https://edp963.github.io/davinci/docs/zh/1.1-deployment
davince版本:davinci-0.3.0-beta.8 release
以下是在开发过程中碰到的一些坑:
运行项目前要准备的东西
JDK 1.8(或更高版本)
MySql5.5(或更高版本)
Mail Server
phantomjs 或 chrome(需同时安装chromedriver,清注意版本)
Redis(可选)
这里做下说明:
Mail Server 指的是准备好一个免费的邮箱,并开通SMTP服务且在邮箱设置开启客户端授权码(有的邮箱叫客户端独立密码)
phantomjs或chrome(需同时安装chromedriver,清注意版本)指的是需要安装一个特殊浏览器,用于爬取指定页面并截图的,在项目里的定时发送截图邮件会用到,推荐phantomjs,下载和安装可参考:https://blog.csdn.net/qq_37245397/article/details/81543450?tdsourcetag=s_pctim_aiomsg
配置启动的时候,一定要下载release版本,github上放的是源码,不是部署安装的版本
如何下载release版本: 进入本文开头引用的github链接后,将页面拖到最后
点击release进行下载。
初始化数据库之前的注意事项
比如如下初始化数据库命令:
mysql -P 3306 -h localhost -u root -p123456 davinci3 < $DAVINCI3_HOME/bin/davinci.sql 1,事先在localhost的mysql中建好名称为“davinci3”的数据库,否则运行的时候会提示找不到数据库
2,数据库名在操作文档中给的是davinci0.3,但是在mysql(版本5.6)建库的时候报错了,改为davince3后建库成功,如果这步用davince0.3建库出错可以这样改库名称试试。(如果这里数据库名称改了,后面的yml配置文件中的数据库连接串也要做对应的修改)
3,命令中的“123456”为连接数据库的密码和“-p”之间无空格
yml配置文件,每个配置项的冒号和值之间至少要有一个空格
这个官方操作文档明确说明了,但还是容易不小心踩坑,这里再强调一下
yml中邮箱配置中的password项
邮箱配置是十分必要的,再注册账号和定时发送邮件功能中,都会使用这个地方配置的邮箱来发送相应的邮件
这里需要注意的是常见免费邮箱(如 163 邮箱、QQ 邮箱、gmail 等)这里应填客户端授权码(也叫客户端独立密码,各邮箱提供商叫法不同),这是各大邮箱为了在用户开通SMTP服务后可能导致密码泄露而设置的,可前往对应邮箱账号设置页面开启 SMTP 服务,并申请客户端授权码(或客户端独立密码)
yml截图配置中的浏览器路径配置
此处建议使用官方操作文档中的“ PHANTOMJS ”,phantomjs的下载和安装可以参考:
https://blog.csdn.net/qq_37245397/article/details/81543450?tdsourcetag=s_pctim_aiomsg
注意该配置中的“phantomjs_path”或者“chromedriver_path”配置项,填的是浏览器可执行文件在本机的绝对路径,比如以下完整配置:
screenshot: default_browser: PHANTOMJS # PHANTOMJS or CHROME timeout_second: 600 phantomjs_path: D:\phantomjs-2.
对于integer、bool等values类型的资源还好,对于比较大的资源比如Drawable等,如果我们每次去获取,都要从resources.arsc中查寻资源相关的信息(对于Drawable来说就是资源路径),然后再根据资源信息(路径)去加载图片,那么这个过程将会非常耗时。所以,为了加快资源的获取速度,同时减少不必要的加载次数,android在资源管理过程中存在着大量的缓存机制,并且还会在Zygote进程起来后就会preload许多系统资源。本文我们挑选一些典型的代码来做分析。
ResourcesManager中对Resources的缓存 ResourcesManager是Android用来统一管理同一个进程中的所有资源,也就是Resources对象的,应用进程中每一个Resources对象的创建和获取都应该经过ResourcesManager之手。它会对它自己创建的每一个Resources对象做缓存,我们在获取Resources对象的时候,如果缓存中已经存在并且没有过时,那么ResourcesManager就会直接返回缓存中的Resources;如果不存在则会创建对应的Resources,然后把它加入缓存并返回:
//frameworks/base/core/java/android/app/ResourcesManager.java public class ResourcesManager { private static ResourcesManager sResourcesManager; //... /** * 缓存在mActiveResources里面,注意这里使用了若引用, * 也是为了当进程中没有地方使用这个Resources对象的时候能够 * 在gc的同时释放掉资源,节省内存 */ final ArrayMap<ResourcesKey, WeakReference<Resources> > mActiveResources = new ArrayMap<ResourcesKey, WeakReference<Resources> >(); //非常典型的一个单例模式 public static ResourcesManager getInstance() { synchronized (ResourcesManager.class) { if (sResourcesManager == null) { sResourcesManager = new ResourcesManager(); } return sResourcesManager; } } public Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs, String[] libDirs, int displayId, Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) { //根据这些参数构造key ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale, token); Resources r; /** * 根据key去缓存中查找 */ WeakReference<Resources> wr = mActiveResources.
1 二叉树复原(10分) 题目内容:
给定一种序列化二叉树的方式:从根节点起始按层次遍历二叉树所有“可能”存在节点的位置:若该位置存在节点,则输出节点值,并在下一层相应增加两个可用位置;否则输出None,且不增加下一层的可用位置。
例如"[5, 4, 7, 3, None, 2, None, -1, None, 9]"是下图所示的二叉树序列化的结果:
其中红色箭头对所有的None进行了标记。
现给出一个二叉树以这种形式序列化的结果,请复原该二叉树并给出它的中序遍历。
输入格式:
一行合法的Python表达式,可解析为包含整数与None的列表
输出格式:
二叉树中序遍历的整数序列,以空格分隔
输入样例:
[5, 4, 7, 3, None, 2, None, -1, None, 9]
输出样例:
-1 3 4 5 9 2 7
输入样例2:
[5,1,4,None,None,3,6]
输出样例2:
1 5 3 4 6
注:树结构如图(红色箭头对None的对应位置进行了标记):
参考代码模板:
def seq2tree(seq): # 将列表反序列化为树 pass def inorderTree(root): # 中序遍历树 pass lst = eval(input())tree = seq2tree(lst)inorder = inorderTree(tree)print(inorder) # 请自行确定打印方式 程序代码: class BinTree: def __init__(self, data): self.
以前写MFC的DLL的时候,总会在自动生成的代码框架里看到提示,需要在每一个输出的函数开始添加上AFX_MANAGE_STATE(AfxGetStaticModuleState())。一直不明白这样做的含义,也一直没有这样做,而且代码也工作得好好的,所以感觉这好像一句废话。
最近的项目中,需要在DLL里使用MFC生成界面,这才发现一旦资源放在不同的动态库里,而且还和多线程搅和在一起的时候,事情就变得异常的复杂,以前对MFC的一知半解已经不足与应付了。程序莫名的崩溃,莫名的ASSERT,资源怎样也装载不起来,为什么呢?每次,总是尝试着,在每一个线程的开始,把AFX_MANAGE_STATE(AfxGetStaticModuleState())添加上去,或者在某些地方用AfxSetResourceHandler()一把,然后问题就解决了,但是不是很明白到底是怎么回事,总感觉这种解决办法让人很不安心,仿佛在下一秒问题又会突然冒出来。
前天,这个问题终于发挥到了极致,任我花费了好几个小时,怎样的尝试都不能成功,在项目的关键时候发生这种事情,让我暗暗发誓以后再也不用MFC了。正像很多的电影情节一样,事情最后还是得到了解决,这次我决定不能再这么算了,一定要把这个事情理解得明明白白。
在这里,我遇到的问题就是,如何让DLL里的界面代码使用该DLL的资源(Resource),如何在工作线程里加载有IE控件的对话框?
我问同事,他们是如何实现DLL资源切换的?AFX_MANAGE_STATE(AfxGetStaticModuleState())这就是他们的答案,一如微软的推荐,原来就是这么简单啊!让我们来看看,这句代码到底做了什么?
#define AFX_MANAGE_STATE§ AFX_MAINTAIN_STATE2 _ctlState§;
AFX_MAINTAIN_STATE2::AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pNewState)
{
m_pThreadState = _afxThreadState;
m_pPrevModuleState = m_pThreadState->m_pModuleState;
m_pThreadState->m_pModuleState = pNewState;
}
_AFXWIN_INLINE AFX_MAINTAIN_STATE2::~AFX_MAINTAIN_STATE2()
{ m_pThreadState->m_pModuleState = m_pPrevModuleState; }
原来,就是定义一个局部的对象,利用其构造和析构函数在函数的入口和函数的出口进行State状态的切换,我猜AfxGetStaticModuleState()一定是获取当前代码所在DLL的State。
果然,请看
static _AFX_DLL_MODULE_STATE afxModuleState;
AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()
{
AFX_MODULE_STATE* pModuleState = &afxModuleState;
return pModuleState;
}
class _AFX_DLL_MODULE_STATE : public AFX_MODULE_STATE
// AFX_MODULE_STATE (global data for a module)
class AFX_MODULE_STATE : public CNoTrackObject
{
…
CWinApp* m_pCurrentWinApp;
HINSTANCE m_hCurrentInstanceHandle;
HINSTANCE m_hCurrentResourceHandle;
效果如下 2个表 spr_course
sys_user
表中我们可以发现一个科目会有多个老师教,如果我们直接进行表连接的话就会出现问题,这就牵扯到我们的一对多的sql语句,从而让我们写一条sql语句就带到一对多的效果
sql语句一对多(spr_course和sys_user表) SELECT spr_course.*,GROUP_CONCAT(sys_user.`username`) AS createrName FROM spr_course JOIN sys_user ON FIND_IN_SET(sys_user.`user_id`,spr_course.`cou_teach`) GROUP BY spr_course.`cou_couid` 我们在前端界面显示课程对应的老师的时候,只需要在entity层加一个createName字段,我们就可以查询到课程所对应的老师,
总结:sql语句1对多, 本帖课程为1,老师为多
最近在写一个项目,程序偶现一个“double free” 问题,经过排查发现在实际运行情况中会有多个线程调用一个loadString操作,而原本loadString只是一个读操作,而多线程共同读同一个资源信息按理说应该是不会有同步问题出现的,但是通过GDB调试发现程序的崩溃处在switchLanguage的一个赋值操作。
然后我走进switchLanguage中发现那个崩溃的赋值操作发生在两个map进行赋值的时候。
而容器在进行赋值操作时,会先清理掉原先的内存然后再对新的内存进行赋值,而STL中的容器大多不是线程安全的。所以很有可能内部的销毁操作执行多次,这也就是为什么会发生double free的原因了。而且多线程的运行情况无法保证每次都重现、程序都崩溃。所以自然是个偶现的BUG。
因此解决办法就是在外部执行switchLanguage操作时加锁,以防止多个进程同时进入。
总结: 由于之前的多线程编程经验较为贫乏,想当然地认为读操作多线程访问肯定是没有问题的,事实证明多线程的水还很深。
需要下载几个jar包,下载链接:https://mvnrepository.com/
原文如下:
maven依赖
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch --> <dependency> <groupId>com.jcraft </groupId> <artifactId>jsch </artifactId> <version>0.1.54 </version> </dependency> 代码如下
package com; import java.io.BufferedInputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; public class Ftp { //打印log日志 private static final Log logger = LogFactory.getLog(Ftp.class); private static Date last_push_date = null; private Session sshSession; private ChannelSftp channel; private static ThreadLocal<Ftp> sftpLocal = new ThreadLocal<Ftp>(); private Ftp(String host, int port, String username, String password) throws Exception { JSch jsch = new JSch(); jsch.
爬取数据的方式有很多种,正则表达式,scrapy,从接口中爬取动态网页的数据…今天我们讲的是用正则表达式来爬取京东一个大米商品的具体信息。
正则表达式的优点:可以精准的爬取我们想要的数据信息
缺点:爬取的速度会很慢,时间就会变得很长,就容易被反爬虫,封ip
若想爬取大量数据的信息,就需要分为三部分进行
1:爬取一个大米商品的具体信息(也就是下图中的蓝色部分)
2:爬取一整个页面上的所有的商品的信息(也就是这个页面上所有的商品)
3:分页爬取(也就是下图中的蓝色部分,一共一百页)
这次主要针对第一个爬取一个大米商品的具体信息进行讲解,剩下的两个爬取所有和分页爬取将到下一次进行讲解。
爬虫步骤:1:发送请求(request),获取响应内容。
2:解析内容
3:运行函数
下面我们就开始吧
我们爬取的网址是
https://item.jd.com/56986006225.html 一:导入相应的库
import re from urllib import request re库用来进行正则表达式匹配
request用来发送请求
库的安装都可以用以下指令来进行安装
pip install re pip install urllib 二:建立一个spider类(因为我们的爬虫是在类里进行的),在类下写正则表达式
class Spider(): inform = '<div class="p-parameter">([\s\S]*?)</div>' dianming = 'target=\'_blank\'>([\s\S]*?)</a>' name ='商品名称:([\s\S]*?)</li>\n' bianhao = '商品编号:([\s\S]*?)</li>\n' maozhong = '商品毛重:([\s\S]*?)</li>\n' chaidi = '商品产地:([\s\S]*?)</li>\n' jinghanliang = '净含量:([\s\S]*?)</li>\n' fenlei = '分类:([\s\S]*?)</li>\n' baozhuang = '包装:([\s\S]*?)</li>\n' jiage = '<div class="dd">([\s\S]*?)</div>' pinjia = '<div class="tab-con">([\s\S]*?)</div>' 正则表达式的匹配要学习的内容有很多,但是要说有没有一种正则表达式可以匹配数字或者文字。
背景:
新手,第一次尝试使用微信小程序访问WebService接口。
使用Microsoft Visual Studio新建了一个WebService项目,发布后,按照常规流程部署到IIS,使用浏览器访问接口,测试正常,使用外部域名访问接口,测试正常,使用接口测试工具.NET WebService Studio测试正常。 但是写入微信小程序(勾选“不校验合法域名……”选项),使用wx.request方法访问接口,返回500错误。
微信小程序js代码:
//调用接口返回数据
getDataset:function(){
wx.request({
url: 'http://www.shwhhk.cn:12345/WebService1.asmx/HelloWorld',
/*域名是通过腾讯云申请的,绑定了公司当前的IP外网地址,在路由器中配置了12345端口跳转到本机的12345端口,接口网站绑定的也是12345端口。端口根据自己的配置修改,域名也可以使用本机的局域网地址*/
data:{},
header:{
'content-type':'application/json'//默认值
},
method:'POST',
success(res){
console.log(res)
}
})
},
console中返回内容:
解决过程:(中间对解决问题无用的过程省略)
因为是新手,只能看懂上面的“500(Internal Server Error)”,根据这个错误提示找到了一堆解决办法,但是都没有真正解决问题。
实际的错误原因在下面的{data……}里面,但是由于界面太小原因,看不到全部的内容,就表面上能看到的内容也无法判断错误原因是什么。解决办法如下:
1.单击{data……}前面的三角箭头“▷”,使内容展开
2.右键单击cookies下面的data行,点击弹出菜单上的Store as global variable,会在下方显示data的所有内容
3.将data的具体内容复制到txt文件中(不包含头尾的双引号),另存为1.html文件。
4.使用浏览器打开1.html文件,这个时候就可以清楚的看到返回的报错信息。
5.根据报错信息,百度到解决办法:将接口文件中的这行代码注释取消。
6.重新发布接口,结果还是500错误,但是这回具体的错误内容改变了
按照错误提示,在接口项目的Web.config文件中添加了如下的节点配置。
7.重新发布接口后,微信小程序测试通过。
后记:
对于老手来说,这些可能都是不可能犯的低级错误,但是对于我这种第一次尝试的新手来说,每一个小错误都是拦路虎。所以记录下来,希望能帮助到和我一样第一次的新手。
最近在写项目遇到一个之前忽略的有关const 成员函数的特性:
class sample { public: sample(int* p) : _p (p) {} private: int* _p; }; class Test { public: void getA() const { sample s(&a); } private: int a; int b; }; 实例代码如上,乍一看好像没啥问题。但实际编译时编译器给出这个错误
明明有一个参数是int*的构造函数,而且传递的也是int*,为什么会说没有找到参数类型为const int*的构造函数呢?后来回想了一下,首先这是一个const成员函数,它的this指针应该包含顶层const和底层const。也就是它除了最基本的不能改变对象的指向外,还不能对对象的值或属性进行修改。那么对象的属性我们可以理解为一个类的成员变量。而且成员函数中的变量我们可以理解为实际引用方式为 this->变量,如果换成图中的代码的话则应该是this->a。而this可以认为是const Test* const 类型。作为一个Test类型的整体既然它无法修改其值或内部属性,那么通过this指针引用变量a时,自然也需要为其加上一层const属性,否则就不能保证其内部属性无法修改。所以在这个const函数中 a的类型变成了const int*,而const int* 不能向int*类型进行赋值。所以编译报错。
解决方法: 1. 将变量声明为mutable 这样可以使得其即使在const成员函数中依然可以修改其值。
2. 执行强制类型转换 const_cast<int*>(&a)
[root@localhost 桌面]# yum install glibc.i686
已加载插件:fastestmirror, langpacks
/var/run/yum.pid 已被锁定,PID 为 49901 的另一个程序正在运行。
Another app is currently holding the yum lock; waiting for it to exit…
另一个应用程序是:PackageKit
内存:103 M RSS (432 MB VSZ)
已启动: Mon Jan 11 10:43:58 2016 - 02:36之前
状态 :睡眠中,进程ID:49901
Another app is currently holding the yum lock; waiting for it to exit…
另一个应用程序是:PackageKit
内存:103 M RSS (432 MB VSZ)
已启动: Mon Jan 11 10:43:58 2016 - 02:38之前
Linux虚拟网络:
NAT:虚机连接vnet8连接路由器连接物理网卡;
桥接:虚机连接vnet0连接物理网卡;
仅主机:虚机连接vnet1,不连接真实的物理网卡;
仅主机模式:真实环境和虚拟环境是隔离开的;在这种模式下,所有的虚拟系统是可以相互通信的,但虚拟系统和真实的网络是被隔离开。(虚拟系统和宿主机器系统是可以相互通信的,相当于这两台机器通过双绞线互连。)和nat唯一的不同的是,此种方式下,没有地址转换服务,因此,默认情况下,虚拟机只能到主机访问。-------与宿主主机可以ping通,无法上网;
桥接模式:在桥接模式下,VMWare虚拟出来的操作系统就像是局域网中的一台独立的主机(主机和虚拟机处于对等地位),它可以访问网内任何一台机器。我们往往需要为虚拟主机配置IP地址、子网掩码等(注意虚拟主机的ip地址要和主机ip地址在同一网段)。这样,虚拟机就可以和主机之间独立的通信(当然,只要在同一个局域网中都可和虚拟机通信),同时,配置好网关和DNS的地址后,以实现通过局域网的网关或路由器访问互联网。。------与宿主主机可以ping通,可以上网;
NAT模式:就是让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网。使用NAT模式可以实现在虚拟系统里访问互联网。简单讲就是宿主机器再构建一个局域网,然后,局域网内只有一台机器,就是虚拟机。NAT模式下的虚拟系统的TCP/IP配置信息是由VMnet8(NAT)虚拟网络的DHCP服务器提供的,无法进行手工修改,因此虚拟系统也就无法和本局域网中的其他真实主机进行通讯。采用NAT模式最大的优势是虚拟系统接入互联网非常简单,只需要宿主机器能访问互联网,你不需要配置IP地址,子网掩码,网关,但是DNS地址还是要根据实际情况填的。--------与宿主主机不可以ping通,可以上网;
nat模式可以上网但是不能和宿主计算机通信,理论上是更安全的,无论虚拟的系统做任何破坏,都不会影响宿主计算机。桥接模式相当于是交换机上又接了个独立主机,一般是作为子网中提供服务用的。
总结:如果自己希望虚拟机访问外网则可以使用Nat模式,如果是想和主机进行通讯则使用桥接模式,前提是要自己设置你在局域网中的独立ip,主机ping不通虚拟机,很可能是虚拟机的防火墙没有关闭 。
语义分割中的损失 loss list: CEBCEWCEFocal lossDice lossIOU lossTversky loss敏感性–特异性 lossGeneralized Dice lossBCE + Dice lossDice + Focal lossExponential Logarithmic loss
以上部分有一篇博客讲得比较清楚:
原文博客链接: (https://blog.csdn.net/m0_37477175/article/details/83004746) Lov´asz-Softmaxloss
请看我的另一篇博客:(https://blog.csdn.net/weixin_41134246/article/details/103280203) Boundary loss 提出generalized Dice loss,对Dice loss在计算中加上权重,主要是为了解决样本不平衡问题。
根据这一个权重函数可以看出来, r l n r_{ln} rln代表这一个类的label map之和,当这一个类别像素值少的时候权重会变大,像素值大的时候权重会变小。
主要还是应用权重来解决不平衡的问题。
还有一个部分是边界损失
想法比较简单,用groundtruth计算出边界部分,然后在预测值对这一部分进行损失计算,对各像素损失求和。
代码链接:(https://github.com/LIVIAETS/surface-loss) ConservativeLoss 核心思想是为了在不同领域的适应能力中,有较强的泛化性。对表现极度好的结果进行惩罚,从而鼓励中等表现得结果。
如图所示,根据置信度来计算CL loss,相应得进行惩罚。 λ \lambda λ为5, a a a为 e e e。
combo loss
代码地址:https://github.com/asgsaeid/ComboLoss/blob/master/combo_loss.py
dice loss + weighted ce
β \beta β控制 假阳性和假阴性的权重,大于0.5惩罚假阳性,小于0.5惩罚假阴性。
a a a控制dice loss 和weighted ce loss的权重。 边界部分有权重的loss Active Contour Loss
anaconda
anaconda------>lib------>site-packages
python
python------>lib------->site-packages
Yolov3DetectionOutput 125 3 1 104 114 124 125 0=4 1=3 2=0.300000 3=0.450000 -23304=18,15.000000,15.000000,30.000000,30.000000,60.000000,60.000000,60.000000,60.000000,90.000000,90.000000,120.000000,120.000000,120.000000,120.000000,150.000000,150.000000,180.000000,180.000000 -23305=9,6.000000,7.000000,8.000000,3.000000,4.000000,5.000000,0,1.000000,2.000000 -23306=3,32.000000,16.000000,8.000000 按顺序来
125:层输出标号
3:有3个输入
1:1个输出
104 114 124 125:3个输入与1个输出对应层输出编号
0=4:检测任务有4个class
1=3:???
2=0.300000:置信度
3=0.450000 :nms
-23304=18:anchor有18/2=9组
15.000000,15.000000,30.000000,30.000000,60.000000,60.000000,60.000000,60.000000,90.000000,90.000000,120.000000,120.000000,120.000000,120.000000,150.000000,150.000000,180.000000,180.000000:9组anchor的宽高
-23305=9:anchor有9组
6.000000,7.000000,8.000000,3.000000,4.000000,5.000000,0,1.000000,2.000000:9组anchor分配的顺序为678345012
-23306=3:yolo层共有3个头
32.000000,16.000000,8.000000:3个头对应的anchor_scale,对应anchor标号678,345,012
注:本文内容大多数来源于“计算机视觉life”微信公众号,因文章较多,笔者记忆又不强,所以整理成博客形式,感兴趣的伙伴可以移步微信公众号浏览更多精彩内容哦!
一.为什么要学SLAM? 计算机视觉主要分为两大方向:基于学习的方法(代表:深度学习)和基于几何的方法(代表:视觉SLAM)
1.深度学习在检测、识别领域具有强大能力,但涉及多视角几何相关的SLAM领域,深度学习作用非常有限,SLAM需要清晰的理论基础保证,而深度学习[黑盒子]模型目前还不奏效。
2.SLAM技术门槛高。需要具备三维空间刚体变换、相机成像模型、特征点提取与匹配、多视角几何、捆集调整等内容。
3.消费级RGB-D相机快速发展催生了以三维视觉为基础的商业化应用。
4.目前据算计视觉领域主要还是通过二维图片来感知世界,而三维视觉才是人类感知理解世界的正确方式,因此以三维视觉为基础的SLAM技术是机器人、无人驾驶、AR等人工智能细分领域的核心技术。
5.SLAM需求公司:互联网公司如百度、腾讯、阿里、京东等,计算机视觉算法公司如旷世、虹软、商汤等,自动驾驶创业公司如图森、momenta、景驰、驭势、滴滴及各大汽车厂商等,无人机/机器人公司如大疆、思岚、高仙等,AR移动终端应用相关公司如三星、华为、悉见等。
二.SLAM到底做什么? SLAM是指当某种移动设备(如机器人、无人机、手机等)从一个未知环境里的未知地点出发,在运动过程中通过传感器(如激光雷达、摄像头等)观测定位自身位置、姿态、运动轨迹,再根据自身位置进行增量式的地图构建,从而达到同时定位和地图构建的目的。定位和建图是两个相辅相成的过程,地图可以提供更好的定位,而定位也可以进一步扩建地图。定位和建图是SLAM的基本要求,而路径规划是在此基础上的高级功能,不属于SLAM的讨论范畴。
三.SLAM使用的传感器 SLAM使用的传感器主要分为激光雷达和视觉两大类。
1.早期SLAM研究几乎全使用激光雷达,优势精度高,解决方案相对成熟,但价格贵,体积大,信息少不直观。
2.视觉SLAM就是用摄像头做主传感器,用拍摄的视频流作为输入来实现同时定位于建图。广泛应用于AR,自动驾驶,机器 人(京东,阿里等大型电商已经配备了仓储机器人,根据任务需求进行路径规划),无人机等前沿领域。
四. 手机地图APP即可定位,为什么还要SLAM? 地图类APP的定位主要应用GPS,民用GPS定位精度为米,导航时并不知道当前车在哪个车道上。且GPS只能在室外使 用,而在建筑物内,洞穴,海底等很多地方GPS失效,对于这些地方定位需求更强烈,目前最有效的就是SLAM技术。
五.建图相关应用有哪些? 根据相机扫描图片进行三维重建,包括室内及室外。利用室内场景的三维重建可以玩增强现实游戏;室内机器人可以判断障碍物 距离,识别理解环境,进行导航等;还可以将二维图片和重建结果进行融合实现三维漫游等。
六.SLAM需要学哪些? SLAM里涉及很多图像处理、计算机视觉知识,总结一下主要有:
相机相关:单目、双目、RGB-D等相机的物理参数意义、相机成像模型、相机的标定、去畸变等。双目的话还涉及到视差计算,RGB-D的话涉及到RGB和depth图像的对齐等。
图像处理相关。比如和特征点相关的有:特征点描述子、特征点提取、特征点匹配。图像梯度计算、边缘检测、直线检测等。
多视角几何相关。比如对极约束、本质矩阵、单应矩阵、光流估计、三角化等。
开源代码:
虽然SLAM比较难,但是令人欣慰的是,SLAM领域有很多优秀的开源代码可以学习。列举几个主流的如下:
稀疏法:
ORB-SLAM2:支持单目,双目,RGB-D相机 https://github.com/raulmur/ORB_SLAM2
半稠密法:
LSD-SLAM:支持单目,双目,RGB-D相机 https://vision.in.tum.de/research/vslam/lsdslam
DSO:单目https://vision.in.tum.de/research/vslam/dso
稠密法:
Elastic Fusion:RGB-D相机 https://github.com/mp3guy/ElasticFusion
BundleFusion:RGB-D相机 https://github.com/niessner/BundleFusion
RGB-D SLAM V2:RGB-D相机 https://github.com/felixendres/rgbdslam_v2
多传感器融合:
VINS:单目 + IMU(惯性测量单元)https://github.com/HKUST-Aerial-Robotics/VINS-Mono
OKVIS:(单目、双目、四目)+ IMU https://wp.doc.ic.ac.uk/sleutene/2016/02/04/release-of-okvis-open-keyframe-based-visual-inertial-slam/
数据集:
1、TUM RGB-D SLAM Dataset and Benchmark
德国慕尼黑理工大学计算机视觉组制作的数据集,使用Kinect相机采集的数据集,包括IMU数据,并且用高精度运动采集系统提供了groundtruth(真值)。提供测试脚本,可以方便的实现量化评估。https://vision.in.tum.de/data/datasets/rgbd-dataset。
2、KITTI Vision Benchmark Suite
德国卡尔斯鲁厄理工学院和丰田工业大学芝加哥分校一起合作制作的用于自动驾驶的数据集。使用一辆改装的汽车采集,该车配备了两台高分辨率彩色和灰度摄像机,还有Velodyne激光扫描仪和GPS定位系统,用来提供精确的groundtruth。主要采集区域是卡尔斯鲁厄市区、农村地区和高速公路。提供测试脚本可以方便的实现量化评估。http://www.cvlibs.net/datasets/kitti/
3、EuRoC MAV Dataset
目前JAVA实现HTTP请求的方法用的最多的有两种:一种是通过HTTPClient这种第三方的开源框架去实现。HTTPClient对HTTP的封装性比较不错,通过它基本上能够满足我们大部分的需求,HttpClient3.1 是 org.apache.commons.httpclient下操作远程 url的工具包,虽然已不再更新,但实现工作中使用httpClient3.1的代码还是很多,HttpClient4.5是org.apache.http.client下操作远程 url的工具包,最新的;另一种则是通过HttpURLConnection去实现,HttpURLConnection是JAVA的标准类,是JAVA比较原生的一种实现方式。
第一种方式:java原生HttpURLConnection
package com.mobile.utils; import com.alibaba.fastjson.JSONObject; import org.apache.log4j.Logger; import java.io.*; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.*; public class HttpUtil { static Logger log = Logger.getLogger(HttpUtil.class); /** * 向指定URL发送GET方法的请求 * * @param httpurl * 请求参数用?拼接在url后边,请求参数应该是 name1=value1&name2=value2 的形式。 * @return result 所代表远程资源的响应结果 */ public static String doGet(String httpurl) { HttpURLConnection connection = null; InputStream is = null; BufferedReader br = null; String result = null;// 返回结果字符串 try { // 创建远程url连接对象 URL url = new URL(httpurl); // 通过远程url连接对象打开一个连接,强转成httpURLConnection类 connection = (HttpURLConnection) url.
基于python版的PSNR和ssim值计算 总所周知,图像质量评价的常用指标有PSNR和SSIM等,本博文是基于python版的图像numpy的float64格式和uint8格式计算两种指标值(附代码),代码经多方测试和对比,是可用的噢~如有问题请在下面评论留言!
psnr峰值信噪比 psnr是用来评价两幅图像相比质量的好坏,即失真情况。这两幅图像分别为原图像和经图像重建或者压缩后等图像处理方法的图像。PSNR越高,图像失真越小,具体细节就不展开说了。首先简单介绍一下psnr的公式计算。对于大小为m*n的两幅图像I和K(一幅是原图,一幅一般是图像重建后的图像),其均方差MSE定义为:
而PSNR的计算公式则为:
其中,MAX为最大像素,即255。这个计算公式主要是针对的是灰度图,也就是单通道的。那么多通道的彩色图像应该怎么计算呢?这里给出两种计算方式:
分别计算RGB三个通道的PSNR,然后取平均值计算RGB三通道的MSE,然后再除以3 这里给出三通道图像计算PSNR值的方法二,附上代码:
def psnr(target, ref): #将图像格式转为float64 target_data = np.array(target, dtype=np.float64) ref_data = np.array(ref,dtype=np.float64) # 直接相减,求差值 diff = ref_data - target_data # 按第三个通道顺序把三维矩阵拉平 diff = diff.flatten('C') # 计算MSE值 rmse = math.sqrt(np.mean(diff ** 2.)) # 精度 eps = np.finfo(np.float64).eps if(rmse == 0): rmse = eps return 20*math.log10(255.0/rmse) ssim结构相似性 SSIM公式是从三个方面衡量两个图像x和y之间的结构相似度,分别为:亮度,对比度和结构,他们的公式如下:
其中:L为像素值范围,为255。
ssim的计算一般也是基于单通道(即灰度图)来计算的,而本文采用了两种方式,
分离每个通道,计算ssim,再求平均值直接转换为灰度图,计算ssim 对于结构的计算公式,是求x和y的协方差,关于协方差,我一开始还没搞明白是怎么计算的,后来查了资料,看到了一句非常重要的话 **协方差矩阵计算的是不同维度之间的协方差,而不是不同样本之间的。**那么理解协方差矩阵的关键就在于牢记它计算的是不同维度之间的协方差,而不是不同样本之间。拿到一个矩阵,我们最先要明确的就是一行是一个样本还是一个维度。而对于三通道的图像,拥有三个维度,要计算两个三通道图像的协方差,是要根据计算每一个维度之间的协方差,故要把三通道分离。
在这里,需要注意的一点是,博主并没有计算结构公式。
附上代码:
def ssim(imageA, imageB): # 为确保图像能被转为灰度图 imageA = np.array(imageA, dtype=np.uint8) imageB = np.
因为最近在自学微信小程序,掌握了他的基础的使用,包括小程序的语法、小程序的自有组件、小程序的自有API及小程序的自定义组件。
在学玩以上的各方面的知识体系后,我就想着学了这么就的微信小程序,自己总要写出点什么东西来才对的起自己这段时间来的努力吧,当然在使用的时候就遇到一 "图标"这一问题.我们在写vue也好,react项目也好,都会有自己UI库,也都有好看的图标,当然小程序也有他自己的原生的图标库,可是相当来说不仅数量少,而且样式也是差强人意,所有我就自己搜罗了在小程序中使用图标的一些方法,来对比他们之间的使用区别。
1、在小程序中使用原生是的图标 小程序的官方组件中有提供一些的自己的原生的图标,
这个的使用相对的简单
<icon type="success" size="20"/> 看起来是不是很容易,还想进一步了解的看这里:https://developers.weixin.qq.com/miniprogram/dev/component/icon.html
2、使用小程序的组件库 有关小程序的组件可有很多,我们就拿小程序自己团队开发的组件组WeUI组件库来说,其他的团队开发的组件库也可以自己试着去鼓弄鼓弄。
从https://developers.weixin.qq.com/miniprogram/dev/extended/weui/download.html
这个地址进入小程序官网,下载相应的icon组件
最下面的基础样式也一定要选上
直接下载即可,下载之后得到一个文件
接下来,你只需要在app.wxss文件上引入weui-wxss 文件夹中的样式
@import './weui-miniprogram/weui-wxss/dist/style/weui.wxss';//这里的路径是相对路径,依自己的目录结构而定 上面的的准备就绪,我们就可以在在项目上使用WeUI的图标了,具体的使用这是把他当作一个自定义的组件来使用就可以了。
wxml文件代码
<mp-icon class="container" type="outline" icon="email" size="{{50}}" color="blue"></mp-icon> <mp-icon class="container" type="field" icon="add-friends" size="{{50}}" color="blue"></mp-icon> json文件代码
{ "usingComponents": { "mp-icon":"../../weui-miniprogram/icon/icon" } } 这些就是他的基本用法,当然如果你还要继续探究的话,看这里吧。
https://developers.weixin.qq.com/miniprogram/dev/extended/weui/icon.html
3、如若小程序的组件库的图标还不够你用的,别担心,我们还可以在小程序中用font-Awesome字体图标。 首先说下我们要使用的网站
http://www.fontawesome.com.cn/字体图标网站
https://transfonter.org/ 一个转码的网站
首先从awesome 官网上下载 文件
打开https://transfonter.org/
在font-awesome的文件夹里找到字体文件(后缀名为ttf的)
等待文件上传成功
上传完成后,我们打开这个开关,它的意思是将我们上传的字体文件转码为Base64格式
接着点击convet进行转码
转码成功后我们就可以下载他了,接着把下载好的压缩包解压,
打开里面的stylesheet.css 和原来font-Awesome文件中的css文件
对比这两个文件,咱们可以发现,这两个文件都有@font-face部分,我们接下来用转过码的@font-face(也就是stylesheet.css文件的全部内容)替换掉原来的font-Awesome的@font-face部分,最后将文件保存,并把把后缀名改为wxss(为了不破坏原来的font-awesome.css文件,建议你复制一份出来单独改动它)。
这样我们就得到了一个新的font-awesome.wxss 文件,把他放入我们的微信小程序的目录上,我是这样子方的(新添一个style文件夹用于放样式)
在app.wxss上引入这个font-awesomee.wxss文件
@import "./style/fontawesome.wxss";// 路径是相对路径,自己看着办 做好了上面的这些我们终于可以在小程序中使用font-awesome字体图标了,
<i style="color: #FFFFFF;"
先搭建一个简单的服务器 参阅 simple_server.go 需要引入 "net/http" 包 获取 get 参数 request 是 *http.Request 实例 writer 是 http.ResponseWriter 实例 query := request.URL.Query() // 第一种方法 name := query["name"][0] // 第二种方法 name := query.Get("name") fmt.Printf("GET : id=%s\n", id) fmt.Fprintf(writer, `{"code":0}`) // 往页面返回数据 获取 post 参数 post 请求有两种 application/jsonapplication/x-www-form-urlencodedrequest.Header.Get("Content-Type") 可以通过方法获取头部信息 需要引入包 encoding/json // 根据 body 创建一个 json 解析器实例 decoder := json.NewDecoder(request.Body) // 存放参数 var params map[string]string // 解析参数 存入 map decoder.Decode(¶ms) fmt.Printf("POST json: name=%s , age=%s \n"
参考博客:https://blog.csdn.net/weixin_42159320/article/details/87803532
在学习ros时,当安装ROS-Academy-for-Beginners依赖包时,遇到了WARNING: The following packages cannot be authenticated! ERROR: the following rosdeps failed to install的问题。
在创建一个名为tutorial_ws的工作空间,在它的的src路径下克隆ROS-Academy-for-Beginners软件包:
$ mkdir -p tutorial_ws/src #创建catkin工作空间 $ cd tutorial_ws/src #进入src路径,克隆教学软件包 $ git clone https://github.com/DroidAITech/ROS-Academy-for-Beginners.git 之后安装依赖:
$ cd ~/tutorial_ws $ rosdep install --from-paths src --ignore-src --rosdistro=kinetic -y 当安装依赖是,跳出如下提示:
WARNING: The following packages cannot be authenticated! ros-kinetic-voxel-grid ros-kinetic-costmap-2d ros-kinetic-nav-core ros-kinetic-base-local-planner ros-kinetic-clear-costmap-recovery ros-kinetic-move-base-msgs ros-kinetic-navfn ros-kinetic-rotate-recovery ros-kinetic-move-base E: There were unauthenticated packages and -y was used without --allow-unauthenticated ERROR: the following rosdeps failed to install apt: command [sudo -H apt-get install -y ros-kinetic-move-base] failed 在尝试多种方法之后,发现直接从src文件夹中安装,使用如下指令:
优先队列式分支限界法求解0-1背包问题 #include <iostream> #include <cstdlib> #include <queue> #include <vector> using namespace std; #define n 4 int w[n]= {3,5,2,1},v[n]= {9,10,7,4},x[n]= {0}; int W=7; double cw=0,cp=0,bestp=0,UP=0; class QNode { public: double cw; //当前背包中物品的重量 double cp; //当前背包中物品的价值 bool isLeft; //是否为左子树 int level; //结点所处的层 double up; QNode *parentNode; //QNode父节点 QNode() { cw=0; cp=0; isLeft=true; level=0; up=0; } QNode(double _cw,double _cp,bool _isLeft,int _level,double _up,QNode *_parentNode=NULL) { cw=_cw; cp=_cp; isLeft=_isLeft; level=_level; up=_up; parentNode=_parentNode; } }; QNode *qNode=NULL,*retQNode=NULL; struct Dvalue { int id; double DV; }; int f(const void *a,const void *b)//升序 { int t; if((*(Dvalue *)a).
JSP 内置对象 jsp一共有9个内置对象,这些对象由web容器创造并且适用于所有jsp页面。
九大内置对象如列表所示:
对象类型outJspWriter类的实例requestHttpServletRequest接口的实例responseHttpServletResponse接口的实例configServletConfig类的实例applicationServletContext类的实例sessionHttpSession类的实例pageContextPageContext类的实例pageObject类exceptionThrowable Github项目下载地址
out 对于任意想要写入缓存的数据,都可以使用JSP的内置函数out,它是JspWriter对象。
在servlet中书写格式为 PrintWriter out=response.getWriter();
但在JSP中可以直接使用。
request request是一个类型为HttpServletRequest的隐式对象,即由web容器为每个JSP请求创建。它可以用来获取请求信息,如参数、头信息、远程地址、服务器名称、服务器端口、内容类型、字符编码等。
它还可以用于从jsp请求范围中设置、获取和删除属性。
response response是一个类型为HttpServletResponse的隐式对象。即HttpServletResponse的实例由web容器为每个jsp请求创建。
它可以用来添加或操作响应,例如将响应重定向到另一个资源、发送错误等。
config config是ServletConfig类型的隐式对象。此对象可用于获取特定JSP页面的初始化参数。config对象是由web容器为每个jsp页面创建的。通常用于从web.xml文件获取初始化参数。
application 在JSP中,application是ServletContext类型的隐式对象。
当应用程序或项目部署在服务器上时,web容器只创建一次ServletContext实例。
此对象可用于从configuaration文件(web.xml)获取初始化参数。它还可以用于从应用程序范围中获取、设置或删除属性。
session 在JSP中,session是类型为HttpSession的隐式对象。Java开发人员可以使用这个对象来设置、获取或删除属性或获取会话信息。
pageContext 在JSP中,pageContext是类型为pageContext类的隐式对象。pageContext对象可用于设置、获取或删除下列范围之一的属性:
pagerequestsessionapplication jsp中page范围是页面默认范围
page 在JSP中,page是object类类型的隐式对象。这个对象被分配给自动生成的servlet类的引用。
page是this的同义词,用于调用翻译后的servlet类定义的方法。
它是这样写的:Object page=this;
为了使用这个对象,它必须转换为Servlet类型。例如:<%(HttpServlet)page.log("message"); %>
因为它是Object类型的,所以很少使用它,因为您可以在jsp中直接使用这个对象。例如:<% this.log("message"); %>
exception 在JSP中,exception是java.lang类型的隐式对象。Throwable类。此对象可用于打印异常。但是它只能用于错误页面。
Github: https://github.com/whyicn/JSP_implicit_object/tree/master
参考文献:
https://www.tutorialspoint.com/jsp/jsp_syntax.htm
https://www.runoob.com/jsp/jsp-tutorial.html
这篇文章是社区维基 。 编辑现有答案以改善此职位。 它当前不接受新的答案。 了解更多 。 如何在Python中列出目录的所有文件并将它们添加到list ? #1楼 dircache是“自2.6版起不推荐使用:dircache模块已在Python 3.0中删除。” import dircache list = dircache.listdir(pathname) i = 0 check = len(list[0]) temp = [] count = len(list) while count != 0: if len(list[i]) != check: temp.append(list[i-1]) check = len(list[i]) else: i = i + 1 count = count - 1 print temp #2楼 从目录及其所有子目录获取完整的文件路径 import os def get_filepaths(directory): """ This function will generate the file names in a directory tree by walking the tree either top-down or bottom-up.
BIOS中各个选项的用处 BIOS:basic input and output system
系统启动时:开机自检POST(power on self test)→按BIOS设置的启动顺序搜索设备→引导记录→系统启动
1.information
显示笔记本的一些基本硬件的版本、序列号等信息,喷黑就是序列号,每台机子都不一样的。
这里可以看出本机的品牌是acer,型号是Aspire 4750,CPU是I5 2410M主频2.3GHz,BIOS版本是2.01,还有机器序号等等信息,该页面无可调节选项,除非你修改bios文件再刷进去。
2.main
选项功能日期和时间可以调节日期和时间Total Memory内存6GVideo Memory显存1GGraphic mode显卡调节选项 integrated:独显被屏蔽,只有集显工作; swithable:显卡根据应用自动切换,该选项一般选默认的“swithable”quiet boot安静启动模式,也有两个选项“disabled”和“enabled”是禁用和启用的意思,启用安静启动后开机会显示那个大大的acer的logo,禁用后会在开机界面显示自检的过程,该选项一般选默认的“enabled”network boot网络引导选项:无盘启动项,比如网吧用服务器,也可以选择启用和禁用,一般个人用户难得用到F12 Boot MenuF12启动菜单,选择启用后按F12会进入boot manager,就可以选择不同的设备启动D2D recoveryacer的那个系统还原,启用后开机按ALT+F10可以进行恢复SATA Mode硬盘传输模式选项:有“IDE Mode”普通传输模式和“ACHI Mode”SATA模式两个选项,默认“ACHI Mode”,传输性能更优,建议选用Wake on lan远程唤醒xCHI supportusb3.0标准(开:3.0传输快 关3.0传输慢) ps:在不重装的情况下让win10也可在AHCI模式下进入。修改为ahci的步骤:
a)进入win10系统,打开cmd 输入msconfig,进入启动选项,将安全启动打勾
b)重启电脑 f2进入bios界面,将sata改为ahci,保存退出后会进入win10安全模式
c)再次重启电脑就可进入win10,此时satamode为AHCI d)再次打开cmd输入msconfig,进入启动项,将安全启动取消
参考原文链接:https://blog.csdn.net/moX980/article/details/103331324
远程开机这个功能实在屌爆了,工作中会经常遇到需要远程开机的情景,比如说,晚上在家里,突然接到领导的电话需要改东西,然而家里的电脑又没有工作环境,各种工具软件都没有安装,这时如果往公司跑一趟真是麻烦,或者需求等不及你往公司跑一趟,也许这途中公司会损失更多。或者,晚上在家里工作了,第二天忘记把资料带回公司,这时远程开机也显得尤为重要。总之,如果你有远程办公的需求,就会用到远程开机。这个功能我也试过,可以参考下https://blog.csdn.net/wang740209668/article/details/78664067?utm_source=copy
3.security
选项功能supervisor password超级管理员密码user password用户密码HDD password硬盘密码password on boot启动密码 ps:最上面三行显示密码状态:set说明已设置密码,clear为未设置密码,supervisor password拥有最高权限,在其他密码忘记的情况下可以用supervisor password进行解锁,建议大家根据需要设置密码,简单应用可以设置Windows密码,bios密码忘了会死的很难看的;某些品牌电脑需设置完密码后才能设置secure boot 选项
4.boot
选项功能boot modelUEFI是新式的BIOS,legacy是传统BIOS。你在UEFI模式下安装的系统,只能用UEFI模式引导;同理,如果你是在Legacy模式下安装的系统,也只能在legacy模式下进系统。UEFI只支持64为系统且磁盘分区必须为GPT模式,传统BIOS使用INT13中断读取磁盘,每次只能读64KB,非常低效,而UEFI每次可以读1MB,载入更快Legacy模式对于MBR,UEFI对应GPT,否则电脑启动就黑屏啦。Secure bootu盘启动时i(装系统时)将其改为disable,否则Ufei模式下U盘启动盘可能失效 ps:硬盘模式的修改,GPT模式/MBR用分区助手diskgenius改为guid/mrb即可,注意磁盘需要格式化,具体操作见https://jingyan.baidu.com/article/7082dc1c3c7e42e40b89bd40.html
5.exit
总共有5个选项分别为“退出并保存更改”、“退出且不保存更改”、“恢复默认设置”、“取消更改”和“保存更改”。大家调节bios相关选项后一般用 “exit saving changes”退出并保存更改才能使更改的设置起作用
1.题目:二叉树的层次遍历 给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
2.解法 /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public List<List<Integer>> levelOrderBottom(TreeNode root) { LinkedList<List<Integer>> result=new LinkedList<>(); Queue<TreeNode> queue=new LinkedList<>(); if(root==null) return result; queue.add(root); int count=0; while(!queue.isEmpty()){ List<Integer> list =new ArrayList<>(); count=queue.size();; for(int i=0;i<count;i++){ TreeNode node=queue.poll(); list.add(node.val); if(node.left!=null){ queue.
一、k8s收集日志方案简介
本文主要介绍在k8s中收集应用的日志方案,应用运行中日志,一般情况下都需要收集存储到一个集中的日志管理系统中,可以方便对日志进行分析统计,监控,甚至用于机器学习,智能分析应用系统问题,及时修复应用所存在的问题。
在k8s集群中应用一般有如下日志输出方式
直接遵循docker官方建议把日志输出到标准输出或者标准错误输出
输出日志到容器内指定目录中
应用直接发送日志给日志收集系统
本文会综合部署上述日志收集方案。
日志收集组件说明
elastisearch 存储收集到的日志
kibana 可视化收集到的日志
logstash 汇总处理日志发送给elastisearch 存储
filebeat 读取容器或者应用日志文件处理发送给elastisearch或者logstash,也可用于汇总日志
fluentd 读取容器或者应用日志文件处理发送给elastisearch,也可用于汇总日志
fluent-bit 读取容器或者应用日志文件处理发送给elastisearch或者fluentd
二、部署
本次实验使用了3台虚拟机做k8s集群,每台虚拟机8C16G内存
1、部署前准备工作
# 拉取文件 yum -y install git #服务器没有git命令直接安装即可,有请忽略 git clone https://github.com/mgxian/k8s-log.git cd k8s-log git checkout v1 # 创建 logging namespace kubectl apply -f logging-namespace.yaml 2、部署elastisearch
注意: # 本次部署虽然使用 StatefulSet 但是没有使用pv进行持久化数据存储 # pod重启之后,数据会丢失,生产环境一定要使用pv持久化存储数据 # 部署 kubectl apply -f elasticsearch.yaml # 查看状态 kubectl get pods,svc -n logging -o wide [root@k8s-node1 k8s-log]# kubectl get pods,svc -n logging -o wide NAME READY STATUS RESTARTS AGE IP NODE pod/elasticsearch-logging-0 1/1 Running 0 20h 10.
多尺度训练这个问题应该是可以分为两个方面:一个是图像金字塔,一个是特征金字塔吧。
1、人脸检测的MTCNN就是图像金字塔,使用多种分辨率的图像送到网络中识别,时间复杂度自然就很高,毕竟每幅图都要用多种scale去检测。
2、像FPN特征金字塔网络,是在多个feature map上面识别的话,但是是一次图像输入完成的,所以只是识别时间会稍微长一些,时间复杂度并不会增加吧。
3、faster rcnn多个anchor带来的多种尺寸的roi这种是不是也可以算muti scale?
4、faster rcnn训练的时候,RPN和ROI Head网络的训练数据都不是简单的随机选取的啊,是通过计算IOU来根据正负样本数量和比例来选取的哇。先经过RPN粗略选取之后再使用ROI Head网络做矫正,效果一般是要好于yolo v1和ssd啊
来源:知乎 作者:不知道叫什么