1、使用场景:Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。 render 函数的使用,重点:样式、事件、插槽、指令、props、v-model、函数组件的处理。
2、参数说明:
// @returns {VNode} createElement( // {String | Object | Function} // 一个 HTML 标签名、组件选项对象,或者 // resolve 了上述任何一种的一个 async 函数。必填项。 'div', // {Object} // 一个与模板中 attribute 对应的数据对象。可选。 { // 与 `v-bind:class` 的 API 相同, // 接受一个字符串、对象或字符串和对象组成的数组 'class': { foo: true, bar: false }, // 与 `v-bind:style` 的 API 相同, // 接受一个字符串、对象,或对象组成的数组 style: { color: 'red', fontSize: '14px' }, // 普通的 HTML attribute attrs: { id: 'foo' }, // 组件 prop props: { myProp: 'bar' }, // DOM property domProps: { textContent: 'div 文本',// 优先级高于 v-text innerHTML: 'BAR' // 优先级高于 v-html }, // 事件监听器在 `on` 内, // 但不再支持如 `v-on:keyup.
使用场景:当n个子元素都在单行展示,需要超出宽度隐藏文本,显示省略号。子元素设置成行内元素就可以了。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> .external { width: 200px; overflow:hidden; text-overflow: ellipsis; white-space: nowrap; } .inline { display: inline; } </style> </head> <body> <div class="external"> <div class="inline">testtesttesttesttesttest</div> <span>testtesttesttesttesttest</span> </div> </body> </html>
简单说明一下:
rtsp的默认端口是554;rtmp的默认端口是1935rtsp://192.168.125.128 # 前面的rtsp就决定用:554端口,后面加不加:554都无所谓rtmp://192.168.125.128 # 前面的rtmp就决定用:1935端口,后面加不加:1935都无所谓然后推流的不是只能是视频文件,也可以推流rtsp摄像头地址这些 安装 安装使用的两种方式:
直接使用官方提供的docker镜像,直接一键开启,方便快捷:
docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080 registry.cn-hangzhou.aliyuncs.com/ossrs/srs:4 ./objs/srs -c conf/srs.conf
使用源码安装:
如果使用源码安装,直接看它github,非常便捷;
我是安装在centos7上的,放在/opt/,每次开机需要进到里面:
cd /opt/srs/trunk启动服务:./objs/srs -c conf/srs.conf查看状态:./etc/init.d/srs status查看日志:tail -n 30 -f ./objs/srs.log
然后我只是只执行了make,没有执行make install ,intall会将其安装在/usr/loacl/srs这个目录里面。
然后看这官方文档,将其设置为开机自启的方法。
推流 用ffmpeg推流前需要先安装,这是我前面写的关于ffmpeg安装的教程,可以参考一下。
ffmpeg推流(下面命令是针对srs所在服务器的直接推流):
ffmpeg -re -i ./doc/source.flv -c copy -f flv -y rtmp://localhost/live/livestream
如果是其它机子推流,就把localhost换成srs服务器的地址后面的live必须要有,livestream是自己起的名字,可以改,还可以加,比如livestream_123/456/789 OBS推流(这个要推流成功,就一定要先打开1935的rtmp端口),在obs推流界面设置:
服务:自定义服务器:rtmp://192.168.125.128/live/ #应该就是固定写法串流秘钥:123 # 自己起,也可以是 livestream/123/456 这个给的不同,就可以区分推到同一台srs服务器上不同给的流了,拉取也就用这作为区分
拉流 下面是不同的地址,直接使用ffplay或是其他软件,如vlc、PotPlayer播放即可:
RTMP: ffplay rtmp://192.168.125.128/live/livestreamH5(HTTP-FLV):ffplay http://192.168.125.128:8080/live/livestream.flvH5(HLS):ffplay http://192.168.125.128:8080/live/livestream.m3u8 Tips:
推流时,推流地址一般都是rtmp://localhost/live/my_name localhost看自己情况设置成srs服务器地址live是一定要的,固定写法,后面的就自己随意起了 一般都是开启了防火墙的,所以当外机访问:8080窗口时,肯定会失败,所以服务器上要使用firewall-cmd开启8080端口;因为防火墙,rtmp地址还是不能使用,rtmp的默认端口是1935/tcp,可以用nmap localhost在服务器上看到,所以还需要使用firewall-cmd把1935端口打开(如果是vscode远程的,然后用vscode的terminal执行的运行srs服务的命令,它就会自动转发1935端口,然后就可以直接在windows上直接使用rtmp://localhost/live/123这样的路径就好了,就不需要服务器开启1935端口)。 python使用opencv推流 python里面的一个推流,记录一下吧,也都是调用ffmpeg:
有如下两个json数组: a和b;
let a =[{ "id": 1, "name": "姓名", "code": "name" "value":"zs" //注意,b数组中id=1的元素没有该字段 }, { "id": 2, "name": "年龄", "code": "age" }, { "id": 3, "name": "地址", "code": "addr" }, { "id": 4, "name": "搜索", "code": "as" }] let b= [{ "id": 1, "name": "姓名", "code": "name" }] 需要比较两个数组中是否有重复的元素(数组元素的id值是唯一的,根据两个数组中元素id是否相等来判断是否重复),如果有则从a中删除,获得去重后的新数组;
//a和b中都具有id为1的元素,所以理想的结果是将a中id=1的元素删除掉, //将b数据中的id取出赋给数组c let c = b.map( i => i.id ) //如果c中包含a数组某个元素的id,说明b数组中也有改元素,移除 let d = a.filter( i => !c.inclundes(i.id)) 去重后的新数组d数组结果(可以看到id=1的元素已经成功删除):
[{ "
用 BufferedWriter 串接 FileWriter 写文件,程序运行结束后发现文件是空的。
解决方案:调用 write() 方法后未调用 flush() 刷新该流,要写入的字符还在缓冲中,并未真正写入文件,写操作完成后调用一次 flush() 即可。
Spring注解@Autowired 一、@Autowired注解作用 1、@Autowired 注解@Autowired是Spring对组件自动装配的一种方式。常用于在一个组件中引入其他组件。
//引入Person组件 @Autowired Person person; 自动装配:sprng通过依赖注入(DI),完成IOC容器中各个组件依赖的关系赋值
2、@Autowired自动装配详解 (1) @Autowired自动装配,默认优先按照类型取IOC容器中寻找对应的组件 annotationConfigApplicationContext.getBean(Person.class); (2) 如果有多个相同类型的组件,再将属性的名称作为组件的id去容器中查找 annotationConfigApplicationContext.getBean("person"); (3) @Autowired配合@Primary使用,当使用@Autowired自动装配时,默认优先选择被注解@Primary标注的组件 @Primary @Bean public Person person(){ return new Person("张三"); } (4) @Autowired配合@Qualifier使用,使用注解@Qualifier可以指定需要装配组件的id @Qualifier("person") @Autowired Person person;
(5) 使用@Autowired自动装配,如果在容器中找不到对应的组件,则会报错 Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.dashu.bean.Person' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} (6) @Autowired属性required,默认为true,如果在容器中找不到对应的组件,则会报错;如果为false,如果在容器中找不到对应的组件,则不装配,不会报错; @Autowired(required = false) Person person; @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 示例 2:
输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 示例 3: 输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 示例 4:
输入: s = "" 输出: 0 提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
解题思路: 一开始想到循环遍历然后通过indexOf来判断是否有重复的数组,有之后将之前的放入一个新的数组里面,然后继续遍历判断重复如此直至遍历完所有字符,再判断最长的一个。
代码实现:
var lengthOfLongestSubstring = function(s) { let arr = [], max = 0 for(let i = 0; i < s.
ES6---箭头函数 一、基本用法二、箭头函数的写法1. 没有返回值(1)不带参数(2)带参数 2. 有返回值3. 对象上的函数es6缩写 三、箭头函数可以与变量解构结合使用四、箭头函数简化回调函数五、rest 参数与箭头函数六、计时器里面的箭头函数的使用七、箭头函数使用注意点八、箭头函数不适用场景九、箭头函数嵌套问题 一、基本用法 特点:保证上下文this指针一致ES6 允许使用“箭头”(=>)定义函数。如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。 var f=()=>5; console.log(f());//5 //等同于 var f=function(){return 5;} console.log(f());//5 var sum=(num1,num2)=>num1+num2; console.log(sum(1, 2));//3 //等同于 var sum=function(num1,num2){ return num1+num2; } console.log(sum(1, 2));//3 如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。 let obj=()=>({a:1,b:2}); console.log(obj());//{a: 1, b: 2} let obj=()=>{a:1,b:2}; console.log(obj());//报错SyntaxError: Unexpected token : 二、箭头函数的写法 箭头函数可以分为有返回值和无返回值 1. 没有返回值 (1)不带参数 //不带参 let data = () => { } (2)带参数 //1个参 //es5写法 let data1 = function(a){ } //es6写法 let data2 = a => { } //2个参 //es5写法 let data3 = function(a,b){ } //es6写法 let data2 = (a,b) => { } 2.
文章目录 前言一、题目分类二、最易懂的贪心算法2.1 算法解释2.2 分配问题455. 分发饼干135. 分发糖果 2.3 区间问题435. 无重叠区间55. 跳跃游戏121. 买卖股票的最佳时机122. 买卖股票的最佳时机 II3. 无重复字符的最长子串11. 盛最多水的容器 前言 打开LeetCode网站,如果我们按照题目类型数量分类,最多的几个题型有数组、动态规划、数学、字符串、树、哈希表、深度优先搜索、二分查找、贪心算法、广度优先搜索、双指针等待。
一、题目分类 第一大分类是算法。本文先从最简单的贪心算法讲起,然后逐渐进阶到二分查找、排序算法和搜索算法,最后是难度比较高的动态规划和分治算法。
第二大分类是数学,包括偏向纯数学的数学问题,和偏向计算机知识的位运算问题。这类问题通常来测试是否敏锐,在实际工作中并不常用,可以优先把精力放在其他大类上。
第三大分类是数据结构,包括C++STL内包含的常见数据结构、字符串处理、链表、树和图。其中,链表、树、和图都是用指针表示的数据结构,且前者是后者的子集。最后我们也将介绍一些更复杂的数据结构,比如经典的并查集和LRU。
二、最易懂的贪心算法 内容提要:本小节包括算法解释 、区间问题、分配问题和练习。
2.1 算法解释 顾名思义,贪心算法和贪心思想采用贪心的策略,保证每次操作都是局部最优的,从而使最后得到的结果是全局最优的。
举一个最简单的例子:小明和小王喜欢吃苹果,小明可以吃五个,小王可以吃三个。已知苹果园里有吃不完的苹果,求小明和小王一共最多吃多少个苹果。在这个例子中,我们可以选用的贪心策略为,每个人吃自己能吃的最多数量的苹果,这在每个人身上都是局部最优的。又因为全局结果是局部结果的简单求和,且局部结果互不相干,因此局部最优的策略也同样是全局最优的策略。
2.2 分配问题 455. 分发饼干 【题目描述】有一群孩子和一堆饼干,每个孩子有一个饥饿度,每个饼干都有一个大小。每个孩子只能吃最多一个饼干,且只有饼干的大小大于孩子的饥饿度时,这个孩子才能吃饱。求解最多有多少孩子可以吃饱。
【题解】因为饥饿度最小的孩子最容易吃饱,所以我们先考虑这个孩子。为了尽量使得剩下的饼干可以满足饥饿度更大的孩子,所以我们应该把大于等于这个孩子饥饿度的、且大小最小的饼干给这个孩子。满足了这个孩子之后,我们采取同样的策略 ,考虑剩下孩子里饥饿度最下的孩子,直到没有满足条件的存在。
简言之,这里的贪心策略是,给剩余孩子里最小饥饿度的孩子分配最小的能饱腹的饼干。
至于具体实现,因为我们需要获得大小关系,一个便捷的方法就是把孩子和饼干分别排序。这样我们就可以从饥饿度最小的孩子和大小最小的饼干出发,计算有多少个对子可以满足条件。
注意 对数组或字符串排序是常见的操作,方便之后的大小比较注意 在之后的讲解中,若我们谈论的是对连续空间的变量进行操作,我们并不会明确区分数组和字符串,因为他们本质上都是连续空间上的有序变量集合。一个字符串“abc”可以被看做一个数组[‘a’,‘b’,‘c’]. class Solution { public: int findContentChildren(vector<int>& g, vector<int>& s) { sort(g.begin(), g.end()); sort(s.begin(), s.end()); int child = 0, cookie = 0; while (child < g.size() && cookie < s.size()) { if (g[child] <= s[cookie]) ++child; ++cookie; } return child; } }; 135.
#include<stdio.h> int Max(int a[10]) { int i, m=0, max = a[0];//定义max的初始值为a[0] for(i=1;i<10;i++)//注意i要等于1 if (max < a[i]) { max = a[i]; m = i;//把最大值的角标赋给m } return m; } int Min(int a[10]) { int i, m=0, min=a[0];//定义min的初始值为a[0] for (i = 1; i < 10; i++) { if (min > a[i]) { min = a[i];//求得最小值的角标 m = i; } } return m; } int main() { int a[10],max,min,i,sum; for (i = 0; i < 10; i++) scanf("
一、概述:最近Android P 平台遇到一个打开车机热点,手机连接后不能上网的 问题,下面是正常的log和异常的log
热点正常能上网的log:
热点异常不能上网的log:
通过log发现Tethering: Found upstream interface(s): null 所以出现不能上网的情况,这里也分析一下打开热点,连接上网的过程。
参考博客:
https://blog.csdn.net/weixin_42093428/article/details/84062557
二、打开热点的流程
调用ConnectivityManager 的 startTethering方法
public void startTethering(int type, boolean showProvisioningUi,
final OnStartTetheringCallback callback, Handler handler) {
Preconditions.checkNotNull(callback, “OnStartTetheringCallback cannot be null.”);
ResultReceiver wrappedCallback = new ResultReceiver(handler) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { if (resultCode == TETHER_ERROR_NO_ERROR) { callback.onTetheringStarted(); } else { callback.onTetheringFailed(); } } }; try { String pkgName = mContext.getOpPackageName(); Log.i(TAG, "
最近在做一个主机资源监控的需求,首先是获取一些最简单的基本参,像一些主机名称、系统类型、ip、cpu、内存和磁盘等等这些数据,看起来虽然很简单,Java的基本库就能完成,但是真的去使用的时候,还是有一些坑的。记录一下,已备后用。
目录
Java获取主机信息
1. 获取基本信息
1.1 获取主机名称和系统
1.2 获取用户信息
1.3 获取主机IP等信息
2. 获取CPU信息
2.1 获取CPU核数
2.2 获取CPU使用率
3. 获取内存信息
3.1 获取主机内存
3.2 获取JVM内存
4. 获取磁盘信息
5. 获取Java环境信息
Java获取主机信息 1. 获取基本信息 1.1 获取主机名称和系统 主机名称可以通过网络类InetAddress来获取,主机系统和用户可以通过System类进行获取。 public static void getLocalHost(){ try{ InetAddress ip = InetAddress.getLocalHost(); String localName = ip.getHostName(); String osName = System.getProperty("os.name"); String userName = System.getProperty("user.name"); String osVersion = System.getProperty("os.version"); String osArch = System.getProperty("os.arch"); System.out.println("当前用户:" + userName); System.out.println("用户的主目录:"+props.getProperty("user.home")); System.out.println("用户的当前工作目录:"+props.getProperty("user.dir")); System.out.println("主机名称:" + localName); System.
硬件:Windows7电脑
工具:Apktools
原文
反编译apk 在终端界面,输入:apktool d test.apk -o test
解释:test.apk为要反编译的文件,test为编译后的文件夹名称,根据需要修改,如果apk不在当前文件夹下,需要在apk前附上位置,如C:\Users\usrs\Downloads\test.apk(注意是双斜杠)。
查看签名信息 ./original/META-INF路径下会有一个CERT.RSA的文件;
切换路径;
执行:keytool -printcert -file C:\Users\找到你自己\Downloads\test\original\META-INF,就可以看到签名信息啦。
遇到的问题:中文乱码 终端中输入:chcp 936
如何进行Go语言的代码检查和优化? 在项目开发中,保证代码质量和性能的手段不只有单元测试和基准测试,还有代码规范检查和性能优化。
1.代码规范检查是对单元测试的一种补充,它可以从非业务的层面检查代码是否还有优化的空间,比如变量是否被使用、是否是死代码等。
2.性能优化是通过基准测试来衡量的,这样我们才知道优化部分是否真的提升了程序的性能。
代码规范检查
什么是代码规范检查?
代码规范检查,顾名思义,是从Go语言层面出发,依赖Go语言的规范,对代码进行的静态扫描检查,这种检查和业务无关。 比如定义了某个常量,未使用,虽然对代码运行没什么影响,但是为了节省内存,这个常量是可以删除的。这种未使用的常量可以通过代码规范检查检测出来。
在比如调用了一个函数,该函数返回了一个error,但是并没有对error做判断,这种情况下, 程序也可以正常编译运行。但是代码写的不严谨,因为返回的error 被忽略了。如果使用代码规范检查,这类潜在的问题也会被检测出来。除了这两种情况,还有拼写问题、死代码、代码简化检测、命名中带下划线、冗余代码等,都可以使用代码规范检查检测出来。
golangci-lint
要想对代码进行检查,则需要对代码进行扫描,静态分析写的代码是否存在规范问题。可用于Go语言飞马分析的工具有很多,比如golint、gofmt、misspell等,如果一一引用配置,就会很繁琐,所以通常不会单独使用,而是使用 golangci-lint。
提示: 静态代码分析是不会运行代码的。
golangci-lint 是一个集成工具,它集成了很多静态代码分析工具,便于使用。通过配置这一工具,我们可以很灵活的启动需要的代码规范检查。 要想使用 golangci-lint ,首先要安装。 因为 golangci-lint 本身就是Go语言编写的,所以我们可以从源代码安装,打开终端,输入如下命令即可安装:
go get github.com/golangci/gilangci-lint/cmd/golangci-lint@v1.32.3
使用命令安装的是v1.32.2版本的 golangci-lint,安装完成后,在终端输入如下命令,检测是否安装成功。
golangci-lint version golangci-lint has version v1.32.2 提示: 在MacOS下也可以使用brew 来安装golangci-lint。
安装成功后,可以使用它进行代码规范检查了。方法如下:
golangci-lint run test/ // 检测目录中test下的代码,运行 golangci-lint配置
golangci-lint配置比较灵活,比如可以自定义要启用哪些 linter。 golangci-lint 默认启用的linter,包括:
deadcode - 死代码检查 errcheck - 返回错误是否使用检查 gosimple - 检查代码是否可以简化 govet - 代码可疑检查,比如格式化字符串和类型不一致 ineffassign - 检查是否有未使用的代码 staticcheck - 静态分析检查 struccheck - 查找未使用的结构体字段 typecheck - 类型检查 unused - 未使用代码检查 varcheck - 未使用的全局变量和常量检查 提示: golangci-lint 支持的更多linter,可以在终端中输入 golangci-lint 命令查看,并且可以看到每个 linter 的说明。
目录 1. 前言2. 正文2.1 广播接收者的动态注册2.1.1 ContextWrapper.registerReceiver() 方法2.1.2 ContextImpl.registerReceiver() 方法2.1.3 ContextImpl.registerReceiverInternal() 方法2.1.3.1 LoadedApk.getReceiverDispatcher() 方法2.1.3.2 new LoadedApk.ReceiverDispatcher() 方法2.1.3.3 ActivityManagerNative.getDefault() 方法 2.1.4 ActivityManagerProxy.registerReceiver() 方法2.1.5 ActivityManagerNative.onTransact() 方法2.1.6 ActivityManagerService.registerReceiver() 方法2.1.6.1 IntentResolver.addFilter()方法 2.2 发送普通广播2.2.1 ContextWrapper.sendBroadcast() 方法2.2.2 ContextImpl.sendBroadcast() 方法2.2.3 ActivityManagerProxy.broadcastIntent() 方法2.2.4 ActivityManagerNative.onTransact() 方法2.2.5 ActivityManagerService.broadcastIntent() 方法2.2.6 ActivityManagerService.broadcastIntentLocked() 方法2.2.6.1 ActivityManagerService.collectReceiverComponents() 方法2.2.6.2 IntentResolver.queryIntent() 方法2.2.6.3 IntentResolver.buildResolveList() 方法2.2.6.4 new BroadcastRecord() 方法2.2.6.5 BroadcastQueue.enqueueParallelBroadcastLocked() 方法 2.3 接收普通广播2.3.1 BroadcastQueue.scheduleBroadcastsLocked() 方法2.3.2 BroadcastHandler.handleMessage() 方法2.3.3 BroadcastQueue.processNextBroadcast() 方法2.3.4 BroadcastQueue.deliverToRegisteredReceiverLocked() 方法2.3.5 BroadcastQueue.performReceiveLocked() 方法2.3.6 ApplicationThreadProxy.scheduleRegisteredReceiver() 方法2.3.7 ApplicationThreadNative.onTransact() 方法2.3.8 ApplicationThread.scheduleRegisteredReceiver() 方法2.3.9 InnerReceiver.
1、jQuery中的ajax
get方法:
$.ajax({ url:"v4/api/film/now-playing?t=1539401039415&page=1&count=5", type:"GET", success:(result)=>{ return result } }) post方法:
$.ajax({ type: "POST", url: "v4/api/film/now-playing", data: { t:"1539401039415", page:"1", count:"5" }, success: function(result){ return result } }); 优缺点:
本身是针对MVC的编程,不符合现在前端MVVM的浪潮
基于原生的XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案
JQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理(采取个性化打包的方案又不能享受CDN服务)
2、axios的方式
get请求方式:
import axios from 'axios' axios({ method:"get" url:"/listall/list" params: { //向后端传的参数 code: '1234', name: 'yyy', }, }) .then(result => { return result.data }) .catch(error => { return error }) post请求方式:
import axios from 'axios' let data = new FormData(); data.
1、请描述下面选择器的含义:
div#idSel
div .classSel
div.classSel
div>.classSel
div+.classSel
div~.classSel
input[type=“button”]
2、请说明CSS优先级的判断法则
3、下图中,说明了每个div(display为block)对象的position值,指出下列所有元素的包含块。并描述你对css中绝对定位,相对定位,固定定位等定位方法的了解。
4、简述一下JavaScript中,apply、call与bind的用法、区别,以及他们与this的关系。
5、请回答如下3端代码的this指向什么?为什么?
<input id="name" type="text" name="name" value="Laruence" onclick="alert(this.value);" /> <input id="name" type="text" name="name" value="Laruence" /> function showValue() { alert(this.value); } document.getElementById('name').onclick = showValue; function showValue() { alert(this.value); } <input id="name" type="text" name="name" value="Laruence" onclick="showValue()"/> 6、写出如下javascript的运行结果
var name = 'laruence'; function echo() { alert(name); var name = 'eve'; alert(name); alert(age); } echo(); 7、请写出下列代码的的执行结果和原因。
var z = 10; function foo() { console.
使用RNN对文本预测 假如输入的文本是:the cat sat on the ma 那么下一个字符什么呢?
这里采用的是many to many模型,如下:
此时模型的输出字符概率为:
如何训练RNN模型? 如上一段英语文字,我们采用分割的方法,这里采用输入的长度为40,滑动距离为3,即从开始到第40个字符用作输入,
第41个字符用作标签数据label,如上:
输入为:Machine learning is a subset of artifici label为:a
上面是第一个训练数据对即pairs
第二个如下:
因为滑动为3,因此在第一个训练对的基础上,向后滑动三个字符在进行分割,分割距为40个字符,后面一个为对应的预测label,因此训练标签对为:
输入为:hine learning is a subset of artificial label为 :I
以此类推,直到把这个段落分割完,做成训练对
制作好的数据集,开始训练,输入数据,通过rnn的最后一个状态查找字符字典,然后和label进行比对,通过交叉熵进行计算loss,在通过优化机制和反向传播更新rnn的参数矩阵,然后迭代多次即可完成训练
制作数据集 下面就开始整个数据集的制作和训练
分割数据 该步骤主要是把一段话或者一篇文章或者一本书进行字符分割,分割时有两个需要设置的参数,分割的长度,滑动长度,这里分割长度是60,滑动长度为3 字典制作 这里是制作字符的字典,英文有26个字符还要加上各种标点和空格总共有57个字符向量,现在按照顺序进行编号,然后给编号进行向量化,这样从字符到向量就完成了
第一步假设分割的段落长度为60,字符字典为57
那么每个段落对应的矩阵就表示为:
假如这里有200278这样的pair,都这样进行矩阵化,这样数据集就制作完成了
下面就是搭建模型训练了:
搭建模型并训练
一、前提 确认已经安装好了mmsegmentation的环境。具体安装方法,请看官方的get_started.md。
二、数据准备 首先是结合官方的customize_datasets.md,如图:
其中img_dir中存放的就是原图,ann_dir中就是放的对应图像的"mask"。
我的数据是用labelme标注的,出来就是一张图对应一个json文件,它是只标注了每个目标物的外轮廓,大概这个样子:
然后接下来就是按照官方的说法,制作每张图对应的ann:
import os import json import glob import shutil import tqdm import cv2 import numpy as np from PIL import Image from sklearn.model_selection import train_test_split np.random.seed(0) w, h = (1280, 1024) # 这是我的图的大小,你看你来改 def labelme2seg(json_files: list, output_path: str): for json_file in tqdm.tqdm(json_files, desc="transforming:"): img_data = np.ones((h, w), dtype=np.uint8) * 27 # 我一共27类,你目标物多少类这里就写多少类, with open(json_file, encoding="utf-8") as f: json_data = json.load(f) labels_data = json_data["shapes"] # 将目标物区域像素填充为对应ID号 for label_data in labels_data: # 下面这行,你的label不是数字的话,是汉字或者其它,自己记得稍微改一下,映射成数字,从0开始 goods_id = int(label_data["
从输入URL到渲染出整个页面的过程包括三个部分:
1、DNS解析URL的过程
2、浏览器发送请求与服务器交互的过程
3、浏览器对接收到的html页面渲染的过程
一、DNS解析URL的过程
DNS解析的过程就是寻找哪个服务器上有请求的资源。因为ip地址不容易记忆,一般会使用URL域名(如www.baidu.com)作为网址。DNS解析就是将域名翻译成IP地址的过程。 具体过程:
1)浏览器缓存:浏览器会按照一定的频率 缓存DNS记录 2)操作系统缓存:如果浏览器缓存中找不到需要的DNS记录,就会取操作系统中找
3)路由缓存:路由器也有DNS缓存
4)ISP的DNS服务器:ISP有专门的DNS服务器应对DNS查询请求
5)根服务器:ISP的DNS服务器找不到之后,就要向根服务器发出请求,进行递归查询
二、浏览器与服务器交互过程
1)首先浏览器利用tcp协议通过三次握手与服务器建立连接
http请求包括header和body。header中包括请求的方式(get和post)、请求的协议 (http、https、ftp)、请求的地址ip、缓存cookie。body中有请求的内容。
2)浏览器根据解析到的IP地址和端口号发起http的get请求.
3)服务器接收到http请求之后,开始搜索html页面,并使用http返回响应报文
4)若状态码为200显示响应成功,浏览器接收到返回的html页面之后,开始进行页面的渲染
三、浏览器页面渲染过程
1)浏览器根据深度遍历的方式把html节点遍历成dom 树
2)将css解析成CSS DOM树
3)将dom树和CSS DOM树构造成render树
4)JS根据得到的render树 计算所有节点在屏幕中的位置,进行布局(回流)
5)遍历render树并调用硬件API绘制所有节点(重绘)
补充: 构造render渲染树的过程 从DOM树的根节点开始遍历每个可见的节点。
对于每个可见的节点,找到CSS树中的对应的规则,并且应用他们。
根据每个可见的节点及其对应的样式,组合生成渲染树。
文章主要参考