canvas状态的保存(save)和恢复(restore)

canvas的状态如何保存和恢复 save():保存当前的绘图状态。restore():恢复之前保存的绘图状态。 调用save方法将当前绘图状态保存到绘图堆栈中,每次调用restore方法从栈顶取出保存的状态。 由于出栈的次数不能多于入栈的次数,故程序中restore方法调用的次数不应该比save方法多。 save都可以保存什么? 当前的坐标变换信息(比如旋转rotate()或平移setTransform())当前剪贴区域图形上下文对象(CanvasRenderingContext2D)的当前属性值 其中CanvasRenderingContext2D的主要属性值如下,完整请查看MDN文档: 属性描述canvas取得画布<canvas>元素fillStyle填充路径的当前的颜色、模式或渐变globalCompositeOperation指定颜色如何与画布上已有颜色组合(合成)lineCap指定线段端点的绘制方式lineJoin指定线段连接的绘制方式lineWidth绘制线段的宽度miterLimit当lineJoin为miter时,这个属性指定斜连接长度和二分之一线宽的最大比率shadowBlur指定阴影模糊度shadowColor指定阴影颜色shadowOffsetX指定阴影水平偏移值shadowOffsetY指定阴影垂直偏移值strokeStyle指定线段颜色 实例 在线查看 const c = document.getElementById("myCanvas"); const ctx = c.getContext("2d"); ctx.fillStyle = "#999"; ctx.fillRect(0, 0, 400, 30); ctx.save(); // 保存当前状态 01 ctx.fillStyle = "#09F"; ctx.fillRect(0, 30, 400, 30); ctx.save(); // 保存当前状态 02 ctx.fillStyle = "#333"; ctx.fillRect(0, 60, 400, 30); ctx.restore(); // 取出保存的状态 02 恢复 ctx.fillRect(0, 90, 400, 30); ctx.restore(); // 取出保存的状态 01 恢复 ctx.fillRect(0, 120, 400, 30);

ACL和NAT介绍及EASY-IP原理实验

目录 一、ACL 1、什么是ACL 2、ACL的两种应用及匹配机制 3、ACL基本种类 4、ACL配置命令 二、ACL实战配置 1、实验目的 2、实验工具及机器 3、实验拓扑 4、实验步骤 二、NAT 1、NAT原理及作用 2、NAT分类 3、NAT配置 3、EASY-ip实验(重要!!!) ①实验目的 ②实验工具及机器 ③实验拓扑 ④实验步骤 一、ACL 1、什么是ACL ACL(访问控制列表):用于过滤流量。例如:在同一个vlan 中要允许PC1可以访问服务器A,但是PC2不能访问服务器A,这种情况就需要使用ACL。原理是在数据包经过路由器时,由于路由器开启了ACL所以会对报文进行检查做出相应的处理。 2、ACL的两种应用及匹配机制 ①应用在端口的ACL,用于过滤数据包。 ②应用在路由协议,匹配对应的路由协议。 匹配机制:规则自上而下依次匹配,一旦匹配不再向下,例如第一条是允许所有1.1.1.0/24 段ip通过,那么第二条拒绝1.1.1.2/32 访问的规则就不会再生效 3、ACL基本种类 2000-2999:基本ACL,只能根据数据包中的源IP,对数据包进行处理 3000-3999:高级ACL,可以根据数据包中的五元组(源IP地址,目的IP地址,源Mac地址,目的Mac地址,协议端口号)对数据包进行处理。 4000-4999:二层ACL,Mac、VLAN-id、根据这些条件对数据包进行处理 4、ACL配置命令 ①ACL 2000 ## 创建基础ACL ②rule permit(deny) source 1.1.1.1 ##添加规则允许、拒绝 源IP为1.1.1.1的地址 ③int g/0/0/1 ##进入要配置的端口 ④traffic-filter oubound(inbound) ACL 2000 ## 在入口或出口调用ACL 2000 的规则 二、ACL实战配置 1、实验目的 同一个局域网中,要求PC1不能访问server而PC2可以访问server。 2、实验工具及机器 工具:eNSP V100R003C00SPC100虚拟器 设备:华为AR220路由器一台、华为HUB一台、华为计算机二台、华为服务器一台。 3、实验拓扑 4、实验步骤 ①首先配置PC1和PC2的IP、掩码以及网关,如下图 ②配置路由器接口地址并检测PC1、PC2是否都可以访问server。如下图 <huawei> undo terminal monitor #关闭用户视图提示 <huawei> system-view #进入系统视图 [huawei] undo infor-center enable #关闭系统视图提示 [huawei] int g0/0/0 #进入接口g/0/0/0 [huawei-g0/0/0] ip address 192.

内存分析工具mat的安装和使用(full GC 排查方法)

1、安装 下载地址:Eclipse Memory Analyzer Open Source Project | The Eclipse Foundationhttps://www.eclipse.org/mat/downloads.php 下载后解压,点击MemoryAnalyzer.exe进行启动 mat启动是需要jdk11或者更高的版本,我本地jdk版本是1.8,所以会报jdk版本不适合 解决方法:在MemoryAnalyzer.ini 中加入指定jdk的地址, (jdk不用安装直接下载 解压指定bin/javaw.exe就可) -vm D:/software/jdk-11.0.18_windows-x64_bin/jdk-11.0.18/bin/javaw.exe 2、导出dump文件 先进入服务器,使用jps命令查询运行中的java进程和进程id 生成dump文件 jmap -dump:format=b,file=testFile.dump 16868 // 16868 是java的进程id 将生成好的testFile.dump文件导出到桌面 sz testFile.dump mat界面 导入dump文件 查看内存占用过大的指标 可以看到bytes占用内存的22.17% 点击mat的 Histogram进行查询 Objects 对象个数 Shallow Heap 浅堆内存(对象实际占用的内存数量) Retained Heap 深堆内存(可释放内存,目前没有被回收占用的内存) 查看占用内存多大的对象被谁引用了,点击mat的Dominator tree,用来分析对象的调用链 点击mat的thread_overview,线程简介图,这个里面有方法的调用链 分3个步骤分析即可 1、观察name、shallow heap 、retained heap指标,一般也是倒序排序 2、 查看占比最大两个即可,java.lang.Thread @0xd9d01a20,可看到具体代码出现问题的行数以及对象引用链 3、查看线程详情,选中线程点击详情Thread Details查看具体发生的异常信息 结语 业务代码导致频繁full gc ,优化业务代码即可。发生full gc有很多种原因,结合自己程序问题解决即可

docker离线安装部署详细步骤

docker离线安装部署 一、准备工作1、服务器相关2、官方下载地址 二、安装部署 一、准备工作 1、服务器相关 IP地址服务器作用系统其他192.168.80.80dockerAnolis OS release 7.9centos 步骤一致 2、官方下载地址 https://download.docker.com/linux/static/stable/x86_64/ 二、安装部署 1、上传解压到/data目录下 tar xf docker-20.10.23.tgz -C /data/ ##加压到/data下,替换为自己的数据盘目录 2、创建软链接并后台启动docker ln -s /data/docker/* /usr/bin/ ##将/data/docker/目录下的所有文件链接到/usr/bin/下 dockerd & ##后台启动docker 3、检查进程和版本 ps -ef | grep docker ##查看进程 docker -v ##查看版本 4、配置systemctl启动 注意事项: 1)软链接地址为:/usr/bin/ 2)which kill 的路径为:/usr/bin/kill vim /etc/systemd/system/docker.service 添加内容如下: [Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target firewalld.service Wants=network-online.target [Service] Type=notify # the default is not to use systemd for cgroups because the delegate issues still # exists and systemd currently does not support the cgroup feature set required # for containers run by docker ExecStart=/usr/bin/dockerd ExecReload=/usr/bin/kill -s HUP $MAINPID # Having non-zero Limit*s causes performance problems due to accounting overhead # in the kernel.

基于Spark的电影推荐系统 协同过滤

一、基本情况介绍 电影推荐系统 Spring Boot+Vue 前后端分离 基于Spark协同过滤算法的大数据 电影推荐系统&订电影票网站 二、网站系统: Spring Boot + VUE3 前后端分离 数据库 : MongoDB 推荐:Scala, Spark,协同过滤,ALS算法 后台管理系统:Element UI, Echarts 三、推荐模块: 离线推荐:Spark ALS 协同过滤算法统计推荐:基于统计指标的推荐,例如热门歌单统计…实时推荐:根据用户的听歌行为,利用Spark Streaming,Flume,Kafka等大数据组件实时计算,并即时作出新的推荐数据来源:MovieLens数据集 + 爬虫9472部电影的海报 本项目是“网站系统”与“推荐系统”与“大数据技术”的结合体,工作量足够,涉及的技术栈较广泛。 四、系统展示

Fio 命令生产环境测试

请不要测试 / 目录 Linux生产环境测试fio命令 安装 fio yum install libaio libaio-devel fio -y 磁盘挂载 mkfs.xfs -n ftype=1 /dev/vdc -f mkdir -p /data1 echo “blkid | grep /dev/vdc | awk '{print $2}' /data1 xfs defaults,noatime,nodiratime,prjquota 0 0” >> /etc/fstab mount -a 确认挂载 df -h 测试说明 5分钟、1小时随机读写,主要衡量磁盘IOPS性能; avg反馈平均性能,越大性能约e好; stdev反馈稳定性,越小越好; min反馈最差的性能,通常跟stdev一起,主要反馈性能波动; 不同场景的测试公式基本一致,只有 rw 模式、runtime 运行时间 两个参数的区别。runtime 1 小时,可以更好的反馈磁盘的稳定性情况;runtime 5 分钟,可以快速的评估磁盘的当前平均性能。 测试结果 5分钟随机读,iodepth 128,主要衡量磁盘IOPS性能 fio --name=/data1/fio --size=10g --bs=4k --iodepth=128 --ioengine=libaio --rw=randread --time_based --runtime=300s --direct=1

ORB-SLAM学习总结

一、ORB-SLAM简介 ORB-SLAM是一种基于ORB特征的三维定位与地图构建算法(SLAM)[1]。该算法由Raul Mur-Artal,J. M. M. Montiel和Juan D. Tardos于2015年发表在IEEE Transactions on Robotics。ORB-SLAM基于PTAM架构,增加了地图初始化和闭环检测的功能,优化了关键帧选取和地图构建的方法,在处理速度、追踪效果和地图精度上都取得了不错的效果。要注意ORB-SLAM构建的地图是稀疏的。 ORB-SLAM一开始基于monocular camera,后来扩展到Stereo和RGB-D sensor上。作者好像还会做Semi-dense mapping的扩展。作者的开源代码都在GIT上[2]。 ORB-SLAM算法的一大特点是在所有步骤统一使用图像的ORB特征。ORB特征是一种非常快速的特征提取方法,具有旋转不变性,并可以利用金字塔构建出尺度不变性。使用统一的ORB特征有助于SLAM算法在特征提取与追踪、关键帧选取、三维重建、闭环检测等步骤具有内生的一致性。 ORB-SLAM架构如下: ORB-SLAM利用三个线程分别进行追踪、地图构建和闭环检测。 一、追踪 ORB特征提取初始姿态估计(速度估计)姿态优化(Track local map,利用邻近的地图点寻找更多的特征匹配,优化姿态)选取关键帧 二、地图构建 加入关键帧(更新各种图)验证最近加入的地图点(去除Outlier)生成新的地图点(三角法)局部Bundle adjustment(该关键帧和邻近关键帧,去除Outlier)验证关键帧(去除重复帧) 三、闭环检测 选取相似帧(bag of words)检测闭环(计算相似变换(3D<->3D,存在尺度漂移,因此是相似变换),RANSAC计算内点数)融合三维点,更新各种图图优化(传导变换矩阵),更新地图所有点 作者提供了ORB-SLAM在New College Data[3]上的时间统计,如下图。 1. 追踪部分,平均每帧约30毫秒,基本达到了30fps。特征提取速度是非常快的,平均11毫秒左右,非常适合于实时SLAM。姿态估计稍微耗时一些,平均需要20毫秒,特别是姿态优化需要耗费16毫秒的时间。 2. 地图构建部分,平均每关键帧约385毫秒。其中生成新的点约70毫秒,Local BA约300毫秒,相对还是比较耗时的。不知道这两部分还有没有优化的空间。 二、ORB-SLAM性能 ORB-SLAM程序提供了运行Monocular、Stereo和RGBD数据的程序。编译成功后,可以通过运行TUM的标准数据来验证程序是否成功。如果想自己测试一些数据,可以通过OpenCV提供的接口调起电脑的摄像头。 个人认为,ORB-SLAM是一个完整的单目SLAM实现,集合了当前流行的SLAM特性。作者的程序非常工程化,其中有诸多精度与运算量的权衡。具体总结如下。 ORB-SLAM的优点: Tracking的平均时间约为20ms每帧,基本可以达到实时追踪(i5-5200,2.2GHz)。丢帧以后回到原来的场景,很容易就可以找回来。定位的稳定性较好,姿态流畅,没有跳变。在简单背景下,可以有效地追踪目标物体。 ORB-SLAM的缺点: 旋转时比较容易丢帧,特别是pure rotation。地图中的点云很稀疏,完全不能看出任何结构。加载地图需要一定时间(10秒左右,通过二进制词典可以加速,DBoW2的作者似乎是为了兼容性放弃了二进制)。初始化时最好保持低速运动,对准特征和几何纹理丰富的物体。作者为了增强系统的鲁棒性,在很多地方采用了多重判断,引入了N多参数。不同场景下的应用可能需要花一些时间理解和调整这些参数。 简言之,对于地图密度要求不高的定位和追踪问题,ORB-SLAM是个不错的选择。 三、ORB-SLAM 初始化 单目SLAM地图初始化的目标是构建初始的三维点云。由于不能仅仅从单帧得到深度信息,因此需要从图像序列中选取两帧以上的图像,估计摄像机姿态并重建出初始的三维点云。 ORB-SLAM中提到,地图初始化常见的方法有三种。 方法一 追踪一个已知物体。单帧图像的每一个点都对应于空间的一条射线。通过不同角度不同位置扫描同一个物体,期望能够将三维点的不确定性缩小到可接受的范围。 方法二 基于假设空间存在一个平面物体,选取两帧不同位置的图像,通过计算Homography来估计位姿。这类方法在视差较小或者平面上的点靠近某个主点时效果不好。 参考文献Faugeras et al, Motion and structure from motion in a piecewise planar environment. International Journal of Pattern Recognition and Artificial Intelligence, 1988.

UDS诊断详解

目录 一、诊断常见的协议: 二、OEM诊断规范 ISO14229 UDS定义的相关服务: SID的格式 ISO-14229常用服务 10服务(诊断会话的控制) 在UDS当中非常常用的表格: CAN总线示例 Recommended Session(s) for Service 三、 安全访问 安全解锁步骤 Supported NRC:基于27服务所支持的NRC 通过DID读数据: 通过DID写数据: 四、DTC DTC的结构 DTC ISO 15031-6: 读取DTC的19服务 02服务 DTC读取: DTC擦写: 五、诊断通讯模式 物理寻址 功能寻址 一、诊断常见的协议: ISO14230针对K线的诊断协议,15765针对CAN线的协议,15031针对排放相关的定义,ISO14229。 二、OEM诊断规范 ISO14229 UDS可以基于不同的总线网络来实现,诊断服务,发送SID给ECU如果ECU认可,就发送SID+40(肯定响应),如果没有认可,会回一个7F,7F是否定响应的标识符。用7F+SID+NRC,NRC就是否定响应的代码。(否定响应),在14229里面NRC有定义(从10到93),这个可以去14229-1里面找到,有全部的定义。 UDS定义的相关服务: 在UDS里面定义的服务有26种,每一个服务发出请求的格式是不一样的。但是每一个服务都带有格式标识符(SID)。 SID的格式 SID主要有四种不同的格式: SID,只发出一个服务的请求,ECU就可以认可, SID+SF,服务后面加上子服务Subfunction,这样ECU才会认可, SID+DID,由我们的服务再加上我们的数据标识符Data Identifier, SID+SF+DID,既要加上子服务,又要加上我们的DID ISO-14229常用服务 在14229的26种服务中,有几个常用服务: 首先是10服务,10服务是诊断会话的控制,是诊断最基本的服务,所对应的是27的服务,是诊断的管理控制的服务,27是安全访问的服务。22和2E,是通过我们的DID来读写我们数据的服务。还有就是跟DTC相关的两个服务,19和14,19是读DTC,14是清除DTC。 10服务(诊断会话的控制) 当ECU上电的时候,进入的是默认会话Default Session(10 01),如果想跳转到非默认会话,也就是02或者03,就需要用10+子服务(SF),里面有一个S3计时器,如果在S3的时间没有任何请求发出来的话,我们会自动的回到默认会话,相当于保护机制。还有一个重要的服务,3E服务,就是保持在当前会话的服务,因为我们在非默认会话的时候,不可能一直发出请求。当我们停下来做数据分析或者其它动作的时候ECU没有发出有效命令的时候,我们可以用到3E,3E就是在S3计时时间到之前,我们发出一个3E服务,这样就会一直保持在非默认会话的情况。 在UDS当中非常常用的表格: 在Cvt列,M代表强制,强制使用10和子服务。在UDS SF当中定义了00到03,其中00是不会被使用的。01到03代表不同的含义。Response对应的相应,对应的肯定响应是在SID上加上40,10+40=50,S也代表强制使用,在这里面代表如果我们的肯定相应没有被抑制的话,这个字节就是要被强制使用的。后面我们的服务也是被强制使用的。后面C是有条件使用的。由客户决定。 不同的NRC,对于10来说主要用到的就是12 13还有22三种否定响应。 CAN总线示例 在CAN总线当中每一个帧的报文每一条请求都只支持8个字节。第一个02代表TP层的一个单帧,2代表后面有两个有效字节。在Request里面,后面5个字节对我们来说是没有意义的。肯定响应也一样,三个字节加5个填充位。最后否定响应,有四个字节7F+SID+否定响应的代码NRC。22表示当前的状态。 Recommended Session(s) for Service 在默认会话服务当中,有一些不支持,但是在非默认会话当中,这些都是支持的。 三、 安全访问 平常读写只需要用到22服务+DID,有一些数据需要加密,在ECU上电以后,是一个锁定的状态,我们通过27+子服务+密钥,通过这样的服务请求来进行一个解锁状态。解锁之后ECU状态就变成了Unlocked状态,Unlocked状态整车厂可以设置不同的级别。各个级别之间没有制约关系。是可以互相转换的。

汇总一些嵌入式相关的公司

来源:https://zhuanlan.zhihu.com/p/585079427 1.芯片行业 目前嵌入式薪资上涨的原因,我觉得很大一部分是芯片公司带起来的。特别是一些初创的GPU、AI、自动驾驶芯片公司,给得都比较高,当然老牌的一线大厂薪资也很可观。 芯片行业是招嵌入式的大户,因为芯片从生产出来,需要写配套的固件、驱动等程序,这样才能形成软硬件生态,下游厂商才能够拿去就能够用或者进行二次开发。芯片行业薪资水平整体比较高,并且玩家多,跳槽也方便。 代表性公司: (1)中国企业:海思、中兴微电子、联发科、紫光系列、兆易创新、长江存储、芯原微电子、哲库、平头哥、汇顶、地平线机器人、黑芝麻智能,寒武纪、摩尔线程、海光、兆芯、龙芯中科、安路、比特大陆等 (2)外企:AMD、英伟达、ARM、NXP、MPS、Intel等 2.人工智能相关行业 (1)自动驾驶方向 也算是目前嵌入式软件薪资给得比较高的行业之一,因为这个行业在国内发展时间不久,非常需要人才,需要高薪去吸引人才进入这个行业,并且自动驾驶企业融资一般也比较多,给得起钱。 自动驾驶公司招嵌入式软件主要集中在中间件、操作系统开发和优化、车辆底层控制等方面。自动驾驶车辆本质上来说就是一个跑着各种算法的机械电子系统,所以它肯定需要嵌入式工程师。 代表性的企业: 小马智行、魔门塔、元戎启行、图森未来、文远知行等自动驾驶公司,百度,美团,京东等互联网公司,蔚来,理想,小鹏等新能源车企,比亚迪,吉利、长安等智能化比较好的传统车企,还有的话就是像华为、大疆这些公司也是在搞无人驾驶。 (2)机器人方向 机器人这个其实和自动驾驶也是有重叠的,比如自动驾驶车本身就是一个移动机器人,像视觉、雷达、控制、地图等自动驾驶和很多机器人方向都要招。 机器人国内主要就是扫地机器人、搬运机器人、物流机器人、工业制造机器人、飞行机器人等,机器人行业嵌入式软件需求也比较多,比如Linux、ROS、RTOS、驱动开发等需求量都是挺大的。 代表企业: 大疆、高仙、科沃斯、普渡、星猿哲、美的、汇川、石头科技、海康机器人等 3.消费电子行业 消费电子比如手机,机顶盒,路由器,无人机、运动相机、安防设备等都是。这个行业必然是嵌入式招聘的大户,因为这些产品本质上就是个嵌入式系统,比如手机,跑的是系统是安卓,各种外设都需要写驱动,还要写相关应用程序。 一般来说,这些企业招嵌入式软件基本是搞linux,rtos,裸机开发,各种协议开发这些方向。 薪资主要看企业规模和产品的利润率,一般大公司,像华为、oppo、vivo、大疆等这些老牌一线厂商工资都还是比较可观的,其他的一些呢比上不足比下有余。 代表性企业: 华为,oppo,小米,vivo,荣耀等手机厂,大疆、影石、海康威视、大华、海信、TCL、联想等 4.传统汽车行业 传统汽车行业不像新能源汽车行业那么注重智能化,很多时候智能化靠其他厂商提供,并不自研,大多也是智能座舱和车机系统这种开发。 当然嵌入式软件工程师还是要招的,比如车辆的整个电控系统、汽车电子、车机系统开发、智能座舱这些都是需要嵌入式的。传统车企一般来说给钱比较少一点,不如现在的蔚小理给钱多。(哔哔一句,我觉得汽车最重要的还是机械素质,智能化只能是锦上添花的东西)。 代表性企业:吉利、长城、长安、奇瑞、广汽、东风、一汽等 5.国企和军工 国企军工呢主要就是一些研究所,比如像研究军用通信、雷达、飞机、兵器等,做这些东西必然是需要嵌入式开发的,不管是裸机开发还是操作系统需求量都比较大。薪资呢不算多,但优点是稳定,基本不会有啥裁员的情况。 代表性企业: 中国电子科技集团系列、航天科工系列、航天工业系列、中国兵器系列等,还有其他各种研究院、研究所都是这一类,还有像中兴、京东方、大唐、烽火等也都是国有企业。 6.传统电子电器类 这一类主要是家电、各种小电器、电子产品等。比如电视、冰箱、空调、洗衣机都是这一类产品。 这些产品虽然可以用纯电路加机械就能实现,但是在现在智能化浪潮下,空调、冰箱这种越来越智能,所以对嵌入式软件工程师的需求也很大,而且现在的智能家具在蓬勃发展,相关的人才需求也越来越大。传统的这种电子电器行业薪资一般不高,但是需求量大。 代表企业: 美的、海尔、格力、TCL、海信等 7.网络及通信设备 主要是做网络以及通信设备,比如企业级的交换机、路由器、网络管理中心、小基站设备等等。这些产品很明显的也是一个嵌入式设备,比如一个路由器或者基站里面都会跑相关算法和控制程序等。 代表企业: 华为、新华三、锐捷、TP-link、腾达、迈普、思科、海格、爱瑞无线等 大家好,欢迎大家关注我的视频号 后续会有更多的优秀内容在视频号上分享

中间件之Pulsar的概念与特性

title: 中间件之Pulsar的概念与特性 date: 2023-2-2 22:07:19 tags: pulsarkafka categories: 中间件 toc_number: true password: 123456qqq message: 请联系微信:codewj,获取本文密码 篇幅有限 完整内容及源码关注公众号:ReverseCode,发送 冲 为什么要学习 Apache Pulsar 什么是云原生 云原生的概念是2013年Matt Stine提出的,到目前为止, 云原生的概念发生了多次变更, 目前最新对云原生定义为: DevOps+持续交付+微服务+容器而符合云原生架构的应用程序是: 采用开源堆栈(K8S+Docker)进行容器化,基于微服务架构提高灵活性和可维护性,借助敏捷方法、DevOps支持持续迭代和运维自动化,利用云平台设施实现弹性伸缩、动态调度、优化资源利用率。 Apache pulsar基本介绍 Apache Pulsar 是一个云原生企业级的发布订阅(pub-sub)消息系统,最初由Yahoo开发,并于2016年底开源,现在是Apache软件基金会顶级开源项目。Pulsar在Yahoo的生产环境运行了三年多,助力Yahoo的主要应用,如Yahoo Mail、Yahoo Finance、Yahoo Sports、Flickr、Gemini广告平台和Yahoo分布式键值存储系统Sherpa。 Apache Pulsar的功能与特性: 多租户模式 租户和命名空间(namespace)是 Pulsar 支持多租户的两个核心概念。在租户级别,Pulsar 为特定的租户预留合适的存储空间、应用授权与认证机制。在命名空间级别,Pulsar 有一系列的配置策略(policy),包括存储配额、流控、消息过期策略和命名空间之间的隔离策略。 灵活的消息系统 Pulsar 做了队列模型和流模型的统一,在 Topic 级别只需保存一份数据,同一份数据可多次消费。以流式、队列等方式计算不同的订阅模型大大提升了灵活度。同时pulsar通过**事务采用Exactly-Once(精准一次)**在进行消息传输过程中, 可以确保数据不丢不重 云原生架构 Pulsar 使用计算与存储分离的云原生架构,数据从 Broker 搬离,存在共享存储内部。上层是无状态 Broker,复制消息分发和服务;下层是持久化的存储层 Bookie 集群。Pulsar 存储是分片的,这种构架可以避免扩容时受限制,实现数据的独立扩展和快速恢复 segmented Sreams(分片流) Pulsar 将无界的数据看作是分片的流,分片分散存储在分层存储(tiered storage)、BookKeeper 集群分片存储和 Broker 节点缓存上,而对外提供一个统一的、无界数据的视图。其次,不需要用户显式迁移数据,减少存储成本并保持近似无限的存储。 支持跨地域复制 Pulsar 中的跨地域复制是将 Pulsar 中持久化的消息在多个集群间备份。在 Pulsar 2.

IMX6ULL-uboot启动内核流程分析(4)

uboot版本2016.03 bootz命令加载linux内核流程分析 bootz命令在启动内核的过程中会一直伴随一个全局变量images,images是一个bootm_headers_t形式的结构体,结构体的定义在文件/include/image.h中: typedef struct bootm_headers { /* * Legacy os image header, if it is a multi component image * then boot_get_ramdisk() and get_fdt() will attempt to get * data from second and third component accordingly. */ image_header_t *legacy_hdr_os; /* image header pointer */ image_header_t legacy_hdr_os_copy; /* header copy */ ulong legacy_hdr_valid; #if defined(CONFIG_FIT) const char *fit_uname_cfg; /* configuration node unit name */ void *fit_hdr_os; /* os FIT image header */ const char *fit_uname_os; /* os subimage node unit name */ int fit_noffset_os; /* os subimage node offset */ void *fit_hdr_rd; /* init ramdisk FIT image header */ const char *fit_uname_rd; /* init ramdisk subimage node unit name */ int fit_noffset_rd; /* init ramdisk subimage node offset */ void *fit_hdr_fdt; /* FDT blob FIT image header */ const char *fit_uname_fdt; /* FDT blob subimage node unit name */ int fit_noffset_fdt;/* FDT blob subimage node offset */ void *fit_hdr_setup; /* x86 setup FIT image header */ const char *fit_uname_setup; /* x86 setup subimage node name */ int fit_noffset_setup;/* x86 setup subimage node offset */ #endif #ifndef USE_HOSTCC image_info_t os; /* os image info */ ulong ep; /* entry point of OS */ ulong rd_start, rd_end;/* ramdisk start/end */ char *ft_addr; /* flat dev tree address */ ulong ft_len; /* length of flat device tree */ ulong initrd_start; ulong initrd_end; ulong cmdline_start; ulong cmdline_end; bd_t *kbd; #endif int verify; /* getenv("

macOS下使用vscode+xdebug调试php

手动安装xdebug 1、浏览器访问https://xdebug.org/wizard 2、在本地终端输入php -i 命令,将输出的内容复制到指南中的输入框中并提交分析 3、分析完后会给出分析概览,然后根据下面提示步骤进行手动安装即可 第5步中的phpize 命令位置:/usr/local/Cellar/php@7.4/7.4.33_1/bin 按上面步骤安装完成后写个测试文件输出输出phpinfo() 看到xdebug的内容说明安装成功了。 配置vscode的xdebug环境 打开vscode编辑器,打开项目所在的文件夹并安装php debug插件 然后切换到调试窗口进行launch.json的配置 我的配置文件是手动安装xdebug后创建99-xdebug.ini文件,如果是直接通过插件安装的应该是php.ini里面配置。 配置文件地址可以通过phpinfo()输出的内容看: 配置内容: zend_extension = xdebug xdebug.start_with_request=yes xdebug.mode=debug xdebug.client_host = 127.0.0.1 xdebug.client_port = 9003 launch.json的配置内容: { // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "args": [ "--extensionDevelopmentPath=${workspaceFolder}" ], "name": "启动扩展", "outFiles": [ "${workspaceFolder}/out/**/*.js" ], "preLaunchTask": "npm", "request": "launch", "type": "extensionHost" }, { "name": "Listen for Xdebug", "type": "php", "request": "

前端面试题

HTML + CSS Position取值和含义? static:静态定位,是默认值,表⽰⽆论怎么设置 top、bottom、right、left 都不会发⽣改变。fixed:固定定位,相对于浏览器窗⼝进⾏定位,同样使⽤ top、bottom、right、left。relative:相对定位,表⽰⽤ top、bottom、right、left 属性可以设置元素相对与其相对于初始位置的相对位置。absolute:绝对定位,表⽰⽤ top、bottom、right、left 属性可以设置元素相对于其⽗元素(除了设置了static 的⽗元素以外)左上⾓的位置,如果⽗元素设置了static,⼦元素会继续追溯到祖辈元素⼀直到body。 四种取值中,除了 static 之外,其他属性都可通过 z-index 进⾏层次分级sticky:粘性定位 如何清除浮动? clear 清除浮动(添加空div法)在浮动元素下方添加空 div,并给该元素写 CSS 样式 {clear:both; height:0; overflow:hidden;} 给浮动元素父级设置高度 父级同时浮动(需要给父级同级元素添加浮动) 父级设置成 inline-block 给父级添加 overflow: hidden 万能清除法 after 伪类 清浮动(现在主流方法,推荐使用) 什么是BFC? 具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素。 在常规流和 float 里面有效,不能包着脱离常规流的定位元素。 BFC 触发条件 根元素 position: absolute/fixed display: inline-block / table 浮动元素 ovevflow 不为 visible 应用: 子元素浮动父元素高度塌陷,可以把父元素设置成 BFC 元素浮动后发生重叠,把其中一个设置成 BFC 行内元素和块元素有哪些,本质区别 行内元素:span、img、button、input、b、q、i、a、em、label 块元素:div、p、h1-h6、ul、ol、dl、li、header、footer、aside、section、article、form、table 区别:行内元素设置 width,height 属性无效,起边距作用的只 有 margin-left、margin-right、padding-left、padding-right,其它属性不会起边距效果(可以设置 line-height),设置 margin 和 padding 的上下不会对其他元素产生影响。块级元素可以设置 width,height 属性

好想好想她

突然听到那首“不下雨就出太阳来”, 好想她。 曾经那个让我魂牵梦绕的她。 曾经那个一天不见就魂不守舍的她。 曾经那个让我冲破自我去要照片的她。 曾经对我唱歌的她。 她还好吗? 还好吗? 我最初最爱的她!

蓝桥杯备考日记0202特殊数的和

题目如下: 解题过程: #include<iostream> using namespace std; int main() { int n; int sum = 0; cin >> n; for(int i = 1;i <= n;i++) { int temp=i;//定义临时变量,方便后续判断i的各个位上的数是否是特殊的数 while(temp) { if((temp%10)==2||(temp%10)==0||(temp%10)==1||(temp%10)==9) { sum=sum+i; break; } else temp=temp/10; } } cout<<sum<<endl; return 0; }

渗透测试(Penetration Test,Pentest)

网络安全行业里说的渗透测试(penetration test,pentest)是实施安全评估(即审计)的具体手段。 渗透测试可能是单独进行的一项工作,也可能是产品系统在研发生命周期里 IT 安全风险管理的一个组成部分。产品的安全性并不完全取决于 IT 方面的技术因素,还会受到与该产品有关的最佳安全实践的影响。具体而言,增强产品安全性的工作涉及安全需求分析、风险分析、威胁建模、代码审查和运营安全。 通常认为,渗透测试是安全评估最终的也是最具侵犯性的形式,它必须由符合资质的专业人士实施。在进行评估之前,有关人员可能了解也可能不了解目标的具体情况。渗透测试可用于评估所有的IT基础设施,包括应用程序、网络设备、操作系统、通信设备、物理安全和人类心理学。渗透测试的工作成果就是一份渗透测试报告。这种报告分为多个部分阐述在当前的目标系统里找到的安全弱点,并且会讨论可行的对抗措施和其他改进建议。充分应用渗透测试方法论,有助于测试人员在渗透测试的各个阶段深入理解并透彻分析当前存在的防御措施。

Windows10 删除桌面右键菜单项

1. 打开注册表 win + R;输入regedit 2. 找到 计算机\HKEY_CLASSES_ROOT\Directory\Background shell:桌面右键菜单 shellx:为文件夹桌面右键菜单 根据自己的需求删掉自己想要删除的东西即可

使用python,利用OSMnx库,获取国外POI数据

由于百度或者高德的API只能获取国内的POI,谷歌API需要翻墙而且还收费,所以一直为为何白嫖国外POI数据头疼。最近终于找到了方法,使用OSMnx,得到基于OSM地图提供的POI数据。# 后续发现这种POI数据有点粗糙,请辨别使用 在学习的过程中,发现居然没有人写相关的文章介绍,没办法只能摸着石头过河,一点一点学习,这个功能最提出是在github issue中提到的。里面对于最初的功能设计、内容呈现之类的问题都有讨论,还是挺有意思的。同时也感谢这些开源贡献者,非常感谢! 文章目录 基本介绍获取POI的方法实战通过点周围的POI获得城市的POI 基本介绍 OSMnx是由南加大规划系的Geoff Boeing教授编写的OpenStreetMap的python拓展包。 参考官网:https://geoffboeing.com/ OSMnx的基本功能:下载街道网络、下载POI、下载城市路网结构、可视化等。 基本的使用教程网上有很多,但我推荐下面这个链接里作者写的介绍 https://geoffboeing.com/2016/11/osmnx-python-street-networks/ 对于这个文章,我们只需要知道,如何获得行政地点边界就可以,因为获取POI要使用到。 获得行政地点边界:osmnx.geocode_to_gdf(place) 本文例子以(‘Berkeley, California’) 作为place import osmnx as ox place = 'Berkeley, California' city = ox.geocode_to_gdf(place) ax = ox.project_gdf(city).plot() _ = ax.axis('off') # 消除图表框 获取POI的方法 OSMnx提供获取POI的方法,和最初在github issue中的名字已经不一样了,现在的模块叫做osmnx.geometries module。模块非常规整,给出了5种获得数据的方式,分别是: 获取给定地址中心一定范围内数据 osmnx.geometries_from_address(address, tags, dist=1000) 获取一个经纬度矩阵内的数据 geometries.geometries_from_bbox(north, south, east, west, tags) 获取给定地址一定范围内的数据 osmnx.geometries.geometries_from_place(query, tags, which_result=None, buffer_dist=None) 获取给定点周围一定范围内的数据 osmnx.geometries.geometries_from_point(center_point, tags, dist=1000) 获取给定地址的数据 osmnx.geometries.geometries_from_polygon(polygon, tags) 这5种方法,大家可以根据需要自己选择。具体的内容可以看官方文档,下面主要使用4和5方法。 需要对tags强调一下。你想要获得的内容就是通过tags进行定义的,详细内容请查阅相关资料。这里只给出获取所有POI。 tags = {"amenity": True} # 表示所有的POI 实战 在这里为了对比不同的方法,使用4和5方法进行演示。

springboot集成flyway使用多数据源的一种实现方式

项目中使用flyway做数据库的版本管理,近期整理项目需要将原本两个包的代码重构合并成一个包,但各自的数据源保留不整合,所以需要flyway实现多数据源迁移,项目中的数据库操作(jpa)同样也需要实现多数据源切换。 这个实现方式会修改flyway执行的时间节点,各位请按照自己的需求,选择性参考。 实现思路: flyway:读取配置文件里的多个数据源配置,使用这些数据源配置构建Flyway对象,并且在代码里通过调用flyway.migrate()方法通知flyway对象去执行迁移。 jpa:依赖dynamic-datasource-spring-boot-starter之后,在配置文件中配置好数据源,在对应的Repository接口上使用@DC注解即可,其参数为配置文件中数据源的key。该注解可以用在类或方法上,且遵循就近原则,既接口和接口中的方法都使用了该注解,方法调用时以方法上的注解配置为准。 maven依赖: <!-- 多数据源依赖包 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.4.1</version> </dependency> <!-- flyway依赖包 --> <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> <version>5.2.1</version> </dependency> 配置文件: 1.依赖dynamic-datasource-spring-boot-starter之后,数据源要配置在datasource.dynaamic.datasource下。 2.flyway的配置里enabled配置要设置成false,关闭自动执行。本人对flyway并不熟悉,没过多的研究过源码和文档,仅仅是会用的阶段。观察到项目启动时flyway的自动执行和spring ioc的初始化是同步执行的,如果不关掉自动执行的话,flyway的自动执行会先在主数据源下把配置路径下的迁移全部执行一次,等spring ioc把配置类实例化出来之后,触发执行的才是需要的多数据源迁移,并且不保证两次迁移不起冲突。关掉自动执行只保留触发执行就能解决这个问题,具体问题并没有深究,在自动执行中使用ioc容器的对象或者配置,不是本文的讨论范围,故此没有深究这个问题。 spring: datasource: dynamic: datasource: db1: #可以通过这个key获取对应的数据源 driverClassName: com.mysql.cj.jdbc.Driver url: username: password: db2: driverClassName: com.mysql.cj.jdbc.Driver url: username: password: db3: driverClassName: com.mysql.cj.jdbc.Driver url: username: password: primary: db1 #主数据源 strict: true jpa: hibernate: naming: physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl ddl-auto: none cache: use_second_level_cache: true use_query_cache: true region: factory_class: org.

Druid(德鲁伊)数据库连接池

文章目录 一.数据库连接池的必要性(一).传统数据库连接模式的的步骤(二).传统数据库连接模式存在的问题 二.数据库连接池技术(一).数据连接池的思想:(二).数据库连接池的任务:(三).数据库连接池的规模:(四).工作原理:(五).数据库连接池的优点: 三.多种开源的数据库连接池四.学习最主流的数据库连接池Druid(一).创建连接(配置文件方式)简易增删改查 一.数据库连接池的必要性 (一).传统数据库连接模式的的步骤 在主程序中创建连接进行sql操作关闭数据库连接 (二).传统数据库连接模式存在的问题 浪费时间:每次连接时都要验证登录和将connection加载到内存, 不能大规模的访问数据库:当数据库访问人数过多时,占用大量系统资源,会导致服务器崩溃 存在内存泄漏问题:每次连接都需要断开连接,如果不断开,程序运行结束,会有创建的连接对象存在内存中一直无法关闭,就会导致java内存泄漏的问题。 内存泄漏:指创建的对象无法被回收 二.数据库连接池技术 (一).数据连接池的思想: 事先在内存中建立一个缓冲池,用来存放一定数量的连接对象,需要时在里面调用,结束时放回缓冲池。 (二).数据库连接池的任务: 管理和释放数据库连接,允许用户使用池内的连接对象,而不需要创建对象。 (三).数据库连接池的规模: 初始化时的数量:由数据库最小连接数来设定; 最大数量:由最大数据库连接数来确定。 当连接数超过了最大连接数,超过的连接就会停止等待连接对象的释放。 (四).工作原理: (五).数据库连接池的优点: 资源重用: 连接池中的对象需要时取出,不需要被连接池回收 更快的反应速度: 事先在池中储备连接对象,初始化已经完成,直接调用。 数据库共享机制 多个用户访问同一数据库,通过在应用层的配置,可以避免资源独占。 避免内存泄漏: 连接对象统一管理,设置连接对象时间片,超时强制回收。 三.多种开源的数据库连接池 JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource是一个接口,该接口通常由服务器提供。 常见的开源数据库连接池: DBCP:速度比C3P0快但有bug c3p0:速度慢,但相对稳定 Proxool:开源连接池,有监控连接池的功能,但稳定性比C3P0差 BoneCP:速度快,开源 Druid:阿里提供的连接池,速度快(不及BoneCP),稳定性好,有监控连接池的功能。 四.学习最主流的数据库连接池Druid Druid 是阿里提供的数据库连接池,据说是集DBCP 、C3P0 和Proxool 优点于一身的数据库连接池,它是目前国内用到最多的数据库连接池技术。 (一).创建连接(配置文件方式) 依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.31</version> </dependency> <dependency> <!--mysql版本对应--> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version> </dependency> 配置文件 创建配置文件druid.properties,并输入配置信息 driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/test username=root password=12345678 initialSize=10 maxActive=20 详细的配置参数 配置缺省说明name配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 如果没有配置,将会生成一个名字,格式是:”DataSource-” + System.

拉格朗日乘子法原理:等式约束和不等式约束KKT条件

我的小程序: 待办计划:卷起来吧,少年! 我们记账:年薪50w够花么? 拉格朗日乘子法是寻找函数在一组约束下的极值方法。 1、等式约束 形式:(x是d维向量) min f(x) s.t. h(x) = 0. 写成如下形式: min f(x)+lambda*h(x)(lambda为参数) s.t. h(x) = 0. 发现两者是等价的。 记:拉格朗日函数L(x,lambda) = f(x)+lambda*h(x). 发现约束条件h(x)=0,其实就是对拉格朗日函数L(x,lambda)关于lambda求偏导等于0得到,略去该约束,继而原约束优化问题就转化成了对拉格朗日函数L(x,lambda)的无约束优化问题(即令L关于x和lambda的偏导等于0求解)。 几何解释: 原目标函数f(x)取得最小化点x*时,可以得到如下结论: a.约束曲面上的任意点x,该点的梯度正交于约束曲面; b.在最优点x*,目标函数在该点的梯度正交于约束曲面(可以反正:若目标函数梯度与约束曲面不正交,则总可以在约束曲面上移动该点使目标函数进一步减小)。 所以,在最优点x*,梯度▽f(x*)和▽h(x*)的方向相同或相反,即存在lambda!=0,使: ▽f(x*)+lambda*▽h(x*)=0. (1式) 定义拉格朗日函数:L(x,lambda) = f(x)+lambda*h(x). 令L(x,lambda)对x的偏导数等于0,得到1式;令L(x,lambda)对lambda的偏导数等于0,得到约束条件h(x)=0。于是,原约束优化问题转化为无约束优化问题。 2、不等式约束 形式: min f(x) s.t. g(x) <= 0. 同样定义拉格朗日函数L(x,lambda) = f(x)+lambda*g(x). 此时,首先看目标函数f(x)在无约束条件下的最优点,显然要么在g(x)<=0的区域内,要么在g(x)>0的区域内。 若f(x)在无约束条件下的最优点在g(x)<=0区域内,则约束条件g(x)<=0不起作用(即可直接求min f(x),得到的结果必然满足g(x)<=0),相当于lambda=0; 若f(x)在无约束条件下的最优点不在g(x)<=0区域内,则f(x)在约束条件下的最优点必然在g(x)<=0区域边界,即在边界g(x)=0上。此类情形类似于等式约束,但此时梯度▽f(x*)和▽g(x*)的方向相反(梯度方向是函数值增大最快的方向),即存在lambda>0,使▽f(x*)+lambda*▽g(x*)=0。 整合上述两种情形,必有lambda*g(x) = 0。所以原不等式约束问题就转化为: min L(x,lambda) s.t. g(x)<=0, lambda>=0, lambda*g(x)=0. 上面的约束条件即为KKT条件。 待办计划:卷起来吧,少年! 我们记账:年薪50w够花么? 参考资料:周志华《机器学习》 参考博文:拉格朗日乘子法及KKT条件证明

网络类型、路由封装实验

实验 1. 拓扑搭建2. 配置各路由器物理接口IP地址边界路由器到ISP通测试PAP认证CHAP认证R3与R5间使用HDLC封装R1与R4为GRE环境R1、R2、R3为MGRE环境私有网络基于RIP全网可达给PC配置IP地址测试ping通性 环境:华为模拟器 实验要求 1. 拓扑搭建 2. 配置各路由器物理接口IP地址 R1 [R1]int s4/0/0 [R1-Serial4/0/0]ip add 15.1.1.1 24 R2 [R2]int s4/0/0 [R2-Serial4/0/0]ip add 25.1.1.1 24 R3 [R3]int s4/0/0 [R3-Serial4/0/0]ip add 35.1.1.1 24 R4 [R4]int g0/0/0 [R4-GigabitEthernet0/0/0]ip add 45.1.1.1 24 R5 [R5]int s3/0/0 [R5-Serial3/0/0]ip add 15.1.1.2 24 [R5-Serial3/0/0]int s3/0/1 [R5-Serial3/0/1]ip add 25.1.1.2 24 [R5-Serial3/0/1]int s4/0/0 [R5-Serial4/0/0]ip add 35.1.1.2 24 [R5-GigabitEthernet0/0/0]ip add 45.1.1.1 24 [R5-GigabitEthernet0/0/0]int lo1 [R5-LoopBack1]ip add 5.5.5.5 24 边界路由器到ISP通 将R1、R2、R3、R4当做内网的边界路由器,R5当做ISP运营商,所以边界路由器需要配置缺省路由指向自己公网的运营商设备

4G模块连接失败的原因(嵌入式视角)

4G模块连接失败的原因(嵌入式视角) 模块问题SIM卡/物联网卡的问题远端云服务器问题小贴士 模块问题 a.4G模块损坏 解决方法:更换4G模块 b.4G模块未安装物联网卡 解决方法:安装物联网卡 c.4G模块设备信号差--> 天线是否接入/ 所在位置是否有干扰(信号正常的地点可能存在某个位置信号极差,或者周围有特殊设备干扰) 解决方法:安装天线/更换一下位置 d.发起GPRS或CSD无线连接 -->所在位置是否有干扰(信号正常的地点可能存在某个位置信号极差,或者周围有特殊设备干扰) 解决方法:更换一下位置 SIM卡/物联网卡的问题 a.SIM卡/物联网卡欠费(可能是忘记缴费,也可能预存的钱用完了,也可能是运营商整顿将自动缴费变更为手动缴费) 解决方法:找运营商/或换一张确实可用,正在使用的卡 b.SIM卡/物联网卡是否能够全国通用(跨地区) 解决方法:找运营商/或换一张确实可用,正在使用的卡 c.SIM卡/物联网卡是否激活-->通常激活后未使用的物联网卡一段时间后(一到两周),会重新进入未激活的状态。 解决方法:找运营商/或换一张确实可用,正在使用的卡 远端云服务器问题 a.远端云服务器服务端口配置问题 解决方法:自己找一个或者让合作方给一个确实可用,正在使用的可连接的远端服务器端口进行连接,以验证远端云服务器服务端口配置没有问题。 小贴士 使用物联网卡时为什么总要让你设置APN? 首先,这种情况可以肯定是你用在了个人设备上,用在个人设备上出问题在所难免。 在设置里面找到“移动网络”选项,不同的手机位置可能不同,这个要自行查找,点进去之后选择你要选择的SIM卡,点进去之后找到一个叫“接入点名称”的选择,也就是APN,(物联卡设置)如果是非4G手机就改成CMMTM,如果是4G手机就改成CMIOT;(普通的SIM卡设置),APN选择里若有CMNET或CMWAP,则直接点击输入员CMTDS即可。若没有,需要手动设置:点击″新建APN",APN名称:填入"CMTDS"(大小写不限),APN接入点:填入"cmtds"即可。 手机使用属于违规现象,如果被运营商检查出来会有锁卡和封卡的风险,毕竟物联卡不是针对手机用户的。

vue3 视频裁剪功能

1.工具:vue3+vite+ffmpeg 指定版本 // "@ffmpeg/core": "^0.10.0", // "@ffmpeg/ffmpeg": "^0.10.1", npm install @ffmpeg/ffmpeg @ffmpeg/core 2.vite环境配置 vite.config.js 配置 build: { minify: 'terser', }, 3.下载ffmpeg文件到public下面 下载地址: https://ffmpeg-core.oss-cn-hangzhou.aliyuncs.com/ffmpeg-core.js?Expires=1675304451&OSSAccessKeyId=TMP.3KgbPc1QsYMFi1n5DAC4KBmgZ34iKQ6gQipA6KkmWCZZFJDG7wtVQFNq8SRmhqY4sew1dqBNK4R24ZapCUzujetjkQSwcb&Signature=jKLRtYaQJXKICdCrIdHYbKjk9JA%3D https://ffmpeg-core.oss-cn-hangzhou.aliyuncs.com/ffmpeg-core.wasm?Expires=1675304465&OSSAccessKeyId=TMP.3KgbPc1QsYMFi1n5DAC4KBmgZ34iKQ6gQipA6KkmWCZZFJDG7wtVQFNq8SRmhqY4sew1dqBNK4R24ZapCUzujetjkQSwcb&Signature=zaal%2BSpU2npk%2B7kz84YPCCuMrWw%3D https://ffmpeg-core.oss-cn-hangzhou.aliyuncs.com/ffmpeg-core.worker.js?Expires=1675304472&OSSAccessKeyId=TMP.3KgbPc1QsYMFi1n5DAC4KBmgZ34iKQ6gQipA6KkmWCZZFJDG7wtVQFNq8SRmhqY4sew1dqBNK4R24ZapCUzujetjkQSwcb&Signature=%2Fdm6RDYsIXgptdhVrnQMh3Wh3lU%3D 3.项目中引入文件 import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg" const ffmpeg = ref( createFFmpeg({ corePath: "/ffmpeg-core.js", // 刚才移动到的目录 log: true, }) ); 4.裁剪视频 const clipFile = async (file) => { console.log(file); const { name } = file; //timeValue.value 时间段,没有可以写死 const startTime = timeValue.value[0].format("HH:mm:ss"); const endTime = timeValue.

Django计算机毕业设计物流库存管理系统python(源码程序+lw+远程部署)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版+ python3.7.7 + Mysql5.7 + HBuilderX+list pip+Navicat11+Django+nodejs。 项目技术: django + python+ Vue 等等组成,B/S模式 +pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,我们在这个版本上开发的。其他版本理论上也可以。 2.pycharm环境:pycharm都可以。推荐pycharm社区版; 3.mysql环境:建议是用5.7版本均可 4.硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS; 6.Navcat11:这个版本不限10/11/14/15都可以。; Python-Django毕设帮助,指导,本源码(见文末),调试部署 5.1管理员功能模块 管理员登录,通过填写注册时输入的用户名、密码、角色进行登录,如图5-1所示。 图5-1管理员功能界面图 管理员登录进入物流库存管理系统可以查看首页、个人中心、资产管理员管理、仓库管理员管理、员工管理、部门信息管理、管理员管理等信息,如图5-2所示。 图5-2管理员功能界面图 资产管理员管理,在资产管理员管理页面中可以查看索引、工号、密码、姓名、性别、年龄、联系电话、电子邮箱等内容信息,还可以根据需要进行修改或删除等详细操作,如图5-3所示。 图5-3资产管理员管理界面图 仓库管理员管理,在仓库管理员管理页面中可以查看索引、工号、密码、姓名、性别、年龄、联系电话、电子邮箱等信息,并可以根据需要进行修改或删除等详细操作,如图5-4所示。 图5-4仓库管理员管理界面图 员工管理,在员工管理页面中可以查看索引、工号、姓名、密码、部门、性别、联系电话、邮箱、身份证、家庭住址等信息,并可以根据需要进行修改或删除等详细操作,如图5-5所示。 图5-5员工管理界面图 部门信息管理,在部门信息管理页面中可以查看部门等内容,并可以根据需要进行修改或删除等详细操作,如图5-6所示。 图5-6部门信息管理界面图 5.2资产管理员功能模块 资产管理员登录进入物流库存管理系统可以查看首页、个人中心、资产信息管理、借出资金管理、还款信息管理等内容,如图5-7所示。 图5-7资产管理员功能界面图 个人中心,在个人中心页面中通过填写工号、姓名、性别、年龄、联系电话、电子邮箱等信息进行修改,如图5-8所示。 图5-8个人中心界面图 资产信息管理,在资产信息管理页面中可以查看索引、固定资产、流动资产、本月利润、库存现金、银行存款、备用现金、备注等信息,并且根据需要进行修改或删除等详细操作,如图5-9所示。 图5-9资产信息管理界面图 借出资金管理,在借出资金管理页面中可以查看索引、借款编号、借款金额、借款人姓名、联系电话、借款日期等内容,并且根据需要进行修改或删除等详细操作,如图5-10所示。 图5-10借出资金管理界面图 还款信息管理,在还款信息管理页面中可以查看索引、还款编号、还款金额、还款人姓名、联系电话、还款日期等内容,并且根据需要进行修改或删除等详细操作,如图5-11所示。 图5-11还款信息管理界面图 5.3仓库管理员功能模块 仓库管理员登录进入物流库存管理系统可以查看首页、个人中心、产品信息管理、产品分类管理、商家管理、物流信息管理、入库管理、出库管理、订货信息管理、出货信息管理等内容,如图5-12所示。 图5-12仓库管理员功能界面图 个人中心,在个人中心页面中通过填写工号、姓名、性别、年龄、联系电话、电子邮箱等信息进行修改,如图5-13所示。 图5-13个人中心界面图 产品信息管理,在产品信息管理页面中可以查看索引、产品编号、产品名称、产品类型、图片、规格、数量、详情等信息,并且根据需要进行出库、入库修改或删除等详细操作,如图5-14所示。 图5-14产品信息管理界面图 产品分类管理,在产品分类管理页面中可以查看产品分类等内容,并且根据需要进行修改或删除等详细操作,如图5-15所示。 图5-15产品分类管理界面图 Python-Django毕设帮助,指导,源码获取������������������,调试部署

python的items()函数的用法

python的items()函数的用法 2023.2.2,复习时发现之前忽略的一个函数 这个函数用在了遍历字典的位置,使用items会返回一个列表,键值对使用集合来存放 student = {'name':'张三','age':'25','phone':'12580','addr':'成都'} print(student.items()) 返回的结果是: 如果通过遍历的方式打印出字典的值,则需要在遍历时加上values() student = {'name':'张三','age':'25','phone':'12580','addr':'成都'} for i in student.values(): print(i) 如果想要打印出字典的键,则需要在后面加上keys() for i in student.keys(): print(i,end="\t") 注意:默认情况下不加任何函数,输出的是key(键)的值 但是如果想要既打印出键,又打印出值应该怎么写? 这里想到了items()函数,通过遍历会输出一个一个集合 for i in student.items(): print(i) 但是如果不想用集合的方式来输出,单独的将值,键存放在一个变量中去输出呢? 遍历时定义两个变量来存放 for key,vlaue in student.items(): print(f"键是:{key},值是:{vlaue}")

scrapy中间件的使用

scrapy中间件的使用 学习目标: 应用 scrapy中使用间件使用随机UA的方法应用 scrapy中使用代理ip的的方法应用 scrapy与selenium配合使用 1. scrapy中间件的分类和作用 1.1 scrapy中间件的分类 根据scrapy运行流程中所在位置不同分为: 下载中间件爬虫中间件 1.2 scrapy中间的作用:预处理request和response对象 对header以及cookie进行更换和处理使用代理ip等对请求进行定制化操作, 但在scrapy默认的情况下 两种中间件都在middlewares.py一个文件中 爬虫中间件使用方法和下载中间件相同,且功能重复,通常使用下载中间件 2. 下载中间件的使用方法: 接下来我们对腾讯招聘爬虫进行修改完善,通过下载中间件来学习如何使用中间件 编写一个Downloader Middlewares和我们编写一个pipeline一样,定义一个类,然后在setting中开启 Downloader Middlewares默认的方法: process_request(self, request, spider): 当每个request通过下载中间件时,该方法被调用。返回None值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其他权重低的process_request方法返回Response对象:不再请求,把response返回给引擎返回Request对象:把request对象通过引擎交给调度器,此时将不通过其他权重低的process_request方法 process_response(self, request, response, spider): 当下载器完成http请求,传递响应给引擎的时候调用返回Resposne:通过引擎交给爬虫处理或交给权重更低的其他下载中间件的process_response方法返回Request对象:通过引擎交给调取器继续请求,此时将不通过其他权重低的process_request方法 在settings.py中配置开启中间件,权重值越小越优先执行 3. 定义实现随机User-Agent的下载中间件 3.1 在middlewares.py中完善代码 import random from Tencent.settings import USER_AGENTS_LIST # 注意导入路径,请忽视pycharm的错误提示 class UserAgentMiddleware(object): def process_request(self, request, spider): user_agent = random.choice(USER_AGENTS_LIST) request.headers['User-Agent'] = user_agent # 不写return class CheckUA: def process_response(self,request,response,spider): print(request.headers['User-Agent']) return response # 不能少! 3.

CUDA编程笔记(9)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言单指令-多线程执行模式线程束内的线程同步函数使用线程束同步函数进行数组归约线程束的基本函数使用线程束洗牌函数进行数组归约 协作组线程块级别的协作组进一步优化 总结参考 前言 线程数基本函数与协助组 单指令-多线程执行模式 在伏特架构之前,一个线程束中的线程拥有同一个程序计算器,但各自有不同的寄存器状态,从而可以根据程序的逻辑判断选择不同的分支。虽然可以选择分支,但在执行时,各个分支是依次顺序执行的。在同一个时刻,一个线程束中的线程只能执行一个共同的指令或者闲置,这就是单指令-多线程(single instruction multiple thread,SIMT)的执行模式。 分支发散:一个线程束中的线程根据不同的条件,选择执行不同的判断语句。 if(condition) { A; } else { B; } 分支发散是一个线程数的部分满足条件的线程执行计算,其他不满足的直接闲置,会导致一些需要执行判断语句的程序性能无法最大化。 一般来说,在编写核函数时要尽量避免分支发散。但很多情况,一些算法的需求是存在分支发散的情况的,像前面的数组相加的计算。使用判断语句: if (n < N) { z[n] = x[n] + y[n]; } 该语句可能会导致最后一个线程块中的某些线程束发生分支发散的情况,故一般来说不会明显地影响程序地性能。 从伏特架构开始,引入了独立线程调度机制,每个线程有自己的程序计数器。这使得伏特架构有了一些以前的架构所没有的新的线程束内同步与通信的模式。 线程束内的线程同步函数 在前面共享内存中机型数组归约的时候,要在一个线程块中进行线程的同步,我们使用线程块同步函数__syncthreads()。可以将同步函数__syncthreads()进行换成一个更廉价的线程束同步函数 __syncwarp()。此函数原型为 void __syncwarp(unsigned mask=0xffffffff); 该函数的一个可选参数代表一个掩码的无符号整型数,默认全部32个二进制位都为1,代表该线程束中的所有线程都参与同步 使用线程束同步函数进行数组归约 首先,前面的线程块同步操作和以前一样: for (int offset = blockDim.x >> 1; offset >= 32; offset >>= 1) { if (tid < offset) { s_y[tid] += s_y[tid + offset]; } __syncthreads(); } 上面代码里,for循环将剩下的最后一个32个线程(正好对应一个线程束)操作进行线程束同步。

C语言-输出* 图形 ** *** **** *****

C语言-输出* 图形 ** *** **** ***** 外部循环while a循环中的a是用来控制每一行的,变量a等于1时就是第一行,打印一个*;变量a等于2时就是第二行,打印2个*,所以变量a的值恰好就是这行所需要的*个数。 #include<stdio.h> #include<stdlib.h> #include<Windows.h> int main() { int a, b; a = 1; system("color f5"); //f-亮白色 底景 ;5-紫色前景 while (a <= 5) { b = 1; while (b<=a) { printf("*"); b++; } printf("\n"); a++; } return 0; }

python-can库基于PCAN-USB使用方法

一、概述 1.介绍 python-can库为Python提供了控制器局域网的支持,为不同的硬件设备提供了通用的抽象,并提供了一套实用程序,用于在CAN总线上发送和接收消息。 支持硬件接口: Name Documentation "socketcan" SocketCAN "kvaser" Kvaser’s CANLIB "serial" CAN over Serial "slcan" CAN over Serial / SLCAN "ixxat" IXXAT Virtual CAN Interface "pcan" PCAN Basic API "usb2can" USB2CAN Interface "nican" NI-CAN "iscan" isCAN "neovi" neoVI "vector" Vector "virtual" Virtual "canalystii" CANalyst-II "systec" SYSTEC interface 2.环境搭建 Python安装:https://www.python.org/ftp/python/3.7.9/python-3.7.9-amd64.exe PCAN-USB驱动:https://www.peak-system.com/fileadmin/media/files/pcan-basic.zip 库:pip install python-can 3.参考文档 https://python-can.readthedocs.io/en/master/# 二、常用方法 1.接收报文 from can.interfaces.pcan.pcan import PcanBus def bus_recv(): """轮询接收消息""" try: while True: msg = bus.

RabbitMq 消息确认机制详解

目录 1.消息可靠性 1.1.生产者消息确认 1.1.1.修改配置 1.1.2.定义Return回调 1.1.3.定义ConfirmCallback 1.2.消息持久化 1.2.1.交换机持久化 1.2.2.队列持久化 1.2.3.消息持久化 1.3.消费者消息确认 1.3.1.演示none模式 1.3.2.演示auto模式 1.4.消费失败重试机制 1.4.1.本地重试 1.4.2.失败策略 1.5.总结 1.消息可靠性 消息从发送,到消费者接收,会经理多个过程: 其中的每一步都可能导致消息丢失,常见的丢失原因包括: 发送时丢失: 生产者发送的消息未送达exchange消息到达exchange后未到达queue MQ宕机,queue将消息丢失 consumer接收到消息后未消费就宕机 针对这些问题,RabbitMQ分别给出了解决方案: 生产者确认机制mq持久化消费者确认机制失败重试机制 1.1.生产者消息确认 RabbitMQ提供了publisher confirm机制来避免消息发送到MQ过程中丢失。这种机制必须给每个消息指定一个唯一ID。消息发送到MQ以后,会返回一个结果给发送者,表示消息是否处理成功。 返回结果有两种方式: publisher-confirm,发送者确认 消息成功投递到交换机,返回ack消息未投递到交换机,返回nack publisher-return,发送者回执 消息投递到交换机了,但是没有路由到队列。返回ACK,及路由失败原因。 注意: 1.1.1.修改配置 首先,修改publisher服务中的application.yml文件,添加下面的内容: spring: rabbitmq: publisher-confirm-type: correlated publisher-returns: true template: mandatory: true 说明: publish-confirm-type:开启publisher-confirm,这里支持两种类型: simple:同步等待confirm结果,直到超时correlated:异步回调,定义ConfirmCallback,MQ返回结果时会回调这个ConfirmCallback publish-returns:开启publish-return功能,同样是基于callback机制,不过是定义ReturnCallback template.mandatory:定义消息路由失败时的策略。true,则调用ReturnCallback;false:则直接丢弃消息 1.1.2.定义Return回调 每个RabbitTemplate只能配置一个ReturnCallback,因此需要在项目加载时配置: 修改publisher服务,添加一个: package cn.itcast.mq.config; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Configuration; @Slf4j @Configuration public class CommonConfig implements ApplicationContextAware { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // 获取RabbitTemplate RabbitTemplate rabbitTemplate = applicationContext.

LVM管理,扩容和挂载

LVM管理 文章目录 LVM管理1. 基本概念2. LVM基本组成块2.1 物理卷Physical Volume(PV):2.2 卷组Volume Group(VG):2.3 逻辑卷Logical Volume(LV):2.4 物理区域Physical Extent(PE):2.5 逻辑区域Logical Extent(LE): 3. 磁盘挂载3.1 查看磁盘信息3.2 磁盘初始化3.3 创建PV(物理卷):3.4 创建 VG3.5 创建LV(逻辑卷)3.6 格式化LV3.7 挂载3.7.1 自动挂载 4. 磁盘扩容4.1 初始化磁盘创建PV4.2 PV加入VG4.3 扩容LV4.4 格式化 LV 1. 基本概念 LVM: Logical Volume Manager(逻辑卷管理),Linux环境下对磁盘分区进行管理的一种机制。Linux用户安装Linux操作系统时遇到的一个常见的难以决定的问题就是如何正确地评估各分区大小,以分配合适的硬盘空间。普通的磁盘分区管理方式在逻辑分区划分好之后就无法改变其大小,当一个逻辑分区存放不下某个文件时,这个文件因为受上层文件系统的限制,也不能跨越多个分区来存放,所以也不能同时放到别的磁盘上。而遇到出现某个分区空间耗尽时,解决的方法通常是使用符号链接,或者使用调整分区大小的工具,但这只是暂时解决办法,没有从根本上解决问题。随着Linux的逻辑卷管理功能的出现,这些问题都迎刃而解,用户在无需停机的情况下可以方便地调整各个分区大小。 2. LVM基本组成块 2.1 物理卷Physical Volume(PV): 可以在上面建立卷组的媒介,可以是硬盘分区,也可以是硬盘本身或者回环文件 (loopback file)。物理卷包括一个特殊的header,其余部分被切割为一块块物理区域(physical extents) 2.2 卷组Volume Group(VG): 由一个或多个物理卷PV组成。可以在卷组上创建一个或多个LV(逻辑卷) 2.3 逻辑卷Logical Volume(LV): 虚拟分区,由物理区域(physical extents)组成 2.4 物理区域Physical Extent(PE): 硬盘可供指派给逻辑卷的最小单位(通常为4MB) 2.5 逻辑区域Logical Extent(LE): 跟PE一样,只不过站在LV的视角上是叫LE,而在VG的视角上则是叫PE,其本质是一样的 3. 磁盘挂载 使用vcenter给虚拟机增加磁盘,这里以添加200G举例 3.1 查看磁盘信息 # 查看文件系统情况 df -h fdisk -l 图中Disk /dev/sdb 为从Vcenter中添加的磁盘

shell 循环学习练习

目录 一,嵌套循环实现9*9乘法表 二,判定一个成绩: 三,循环创建用户:用户名为user01-user20 一,嵌套循环实现9*9乘法表 (for和while都可以) 选做:格式对齐,以及使用单层循环完成9*9乘法表 tips: -n 不输出尾随换行符 -e 启用反斜杠转义 -t 水平制表符 1,使用命令 vim 99table_script.sh打开脚本文件 [root@wangjingjing ~]# vim 99table_script.sh 2,按照要求编写脚本文件 for ((a=1;a<=9;a++)) do for ((b=1;b<=a;b++)) do echo -ne "$a*$b=$(($a*$b))\t" done echo -e "\n" done 3,使用命令 bash 99table_script.sh 执行脚本文件,结果如下: [root@wangjingjing ~]# bash 99table_script.sh 1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 二,判定一个成绩: 85-100 -》 A

win10取消开机密码、睡眠唤醒密码

1. 取消开机密码 按住win+R运行,输入netplwiz并确定: 取消掉“要使用本计算机,用户必须输入用户名和密码”: 2. 取消睡眠唤醒密码 2.1 方法1:设置 进入“设置-账户-登录选项”,修改“需要登陆”。 但是一旦用户启用了Windows Hello指纹或人脸,系统就会体制“阻止某些选项”,解决方案见方法2。 2.2 方法2:编辑组策略 在控制面板里搜索“编辑组策略”,点击进入: 找到“计算机配置-管理模板-系统-电源管理-睡眠设置”,双击右侧的“唤醒计算机时需要密码(接通电源/使用电池)”: 选择“已禁用”,然后确定并退出: 至此便实现了win10取消开机密码、睡眠唤醒密码,方便使用。

RabbitMQ消息队列实战(2)—— Java调用RabbitMQ的三种方式

本文主要介绍Java中调用RabbitMQ的三种方式。三种方式实际上对应了三种不同的抽象级别: 首先,通过Java原生代码来访问RabbitMQ。在这种方式下,需要手动创建Connection,创建Channel,然后通过Channel对象可以显式的创建Exchange、Queue和Bind等等。这种方式的好处就是使得我们能够很显式地了解到整个RabbitMQ操作的生命周期,建议新手可以通过这种方式学习RabiitMQ的入门。 spring-boot-starter-amqp对RabbitMQ的使用进行了进一步的封装,通过这种方式使用集成到spring boot中的RabbitMQ时,我们不再关心Connect和Channel的创建,spring boot会替我们创建好。我们索要做的,只是通过注解的方式创建Exchange、Queue和Bind对象,并把他们交给spring ioc进行管理,然后spring boot又会自动生成这些对象对应的交换机、队列和绑定。 Java中操作RabbitMQ的最后一种方法是通过EDA(Event Driven Achitecture,事件驱动架构)框架的spring cloud stream。spring cloud stream对RabitMQ(准确的说应该是消息队列)封装的更加彻底,我们甚至不用关心使用的消息队列是RabbitMQ还是Kafka(spring cloud stream可以配置RabbitMQ和Kafak两种消息队列,并进行无缝切换)。在使用时spring cloud stream时,只需一个标签就能自动创建RabitMQ的Connection、Chanel,甚至你都不用关心Exchange、Queue和Bind这些在spring-boot-starter-amqp中还需要手动创建的对象,他们就被创建好了。spring cloud stream的强大之处就在于它的封装,但是不足之处也在于它的封装,封装的太强,必然增加了学习成本和调试难度,而且类似RabbitMQ和Kafka这种中间件的使用,一般在系统创建之处就一定确定,进行无缝切换就显得有些鸡肋了。 下面,我们就以代码的方式演示这三种调用RabbitMQ的方式: 一、Java原生代码调用RabbitMQ 1.1 交换机和队列的创建 ConnectionFactory factory = new ConnectionFactory(); factory.setHost(this.rabbitMqHost); factory.setPort(this.rabbitMqPort); factory.setConnectionTimeout(this.rabbitMqTimeOut); factory.setUsername(this.rabbitMqUsername); factory.setPassword(this.rabbitMqPassword); factory.setVirtualHost("/"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.exchangeDeclare("direct-exchange", "direct", true, false, null); channel.queueDeclare("test-queue", true, false, false, null); com.rabbitmq.client.AMQP.Queue.BindOk ok = channel.queueBind("test-queue", "direct-exchange", "test-queue"); channel.basicPublish("direct-exchange", "test-queue", null, msg.getBytes("UTF-8")); 上述的代码,创建了一个直连交换机、一个队列,并进行绑定,最后向交换机中发送了一个"Hello World"的字符串。 1~7行,创建了一个ConnectionFactory 对象并进行配置,配置的参数包括RabbitMQ的ip地址(host),端口号(port)、超时(connectionTimeout)等等。 第8行,通过ConnectionFactory 对象,创建了一个Connection 对象,此时已经完成了对RabbitMQ服务器的连接。如果我们通过RabitMQ Magement Web查看,可以看到这个链接。

Mysql5.X实现row_number( ) over( )分组排序

mysql8.0里支持row_number() over (partition by XX order XX) AS rank这种窗口函数,但是mysql早期版本不支持,所以要实现分组排序只能自己写逻辑来实现。 这套sql主要利用了mysql两个技术点 1. @XX 设置变量 2. := 给变量赋值 例如这里需要对dt进行分组,然后在每个组内对age进行降序排序,然后计算出排序号 -- 1. 窗口函数处理 select dt, age, row_number() over(partition by dt, stu order by age desc) As rank from routing_test ; -- 2. 变量方式实现 select if(@dt = a.dt and @stu = a.stu, @curRank := @curRank + 1, @curRank := 1) AS row_cnt, -- 注意这个计数项需要放在变量设置之前,这样第一次变量和实际dt、stu值不匹配,第一行的行序号会做成1,第二行开始匹配上了就自增了 @dt := a.dt, @stu := a.stu, -- 这里分组字段挨个设置 age from (select dt, stu, age from routing_test order by dt, stu, age desc) a, (select @dt := null, @stu := null, @curRank := 0) temp ; 这样最终的结果里,age相同的记录其排序号是不重复的,和窗口函数的row_number()排序一致

Pytorch实战笔记(3)——BERT实现情感分析

本文展示的是使用 Pytorch 构建一个 BERT 来实现情感分析。本文的架构是第一章详细介绍 BERT,其中包括 Self-attention,Transformer 的 Encoder,BERT 的输入与输出,以及 BERT 的预训练和微调方式;第二章是核心代码部分。 目录 1 BERT1.1 self-attention1.2 multi-head self-attention1.3 Encoder1.4 BERT 的输入与输出1.4.1 BERT 的输入1.4.2 BERT 的输出 1.5 BERT 预训练1.6 BERT 微调 2 BERT 实现情感分析参考 1 BERT 1.1 self-attention Self-attention 接受一个序列输入,并输出等长的序列。其运行流程如下。 上图是 self-attention 的部分实例,因为仅展示了 b 1 b_1 b1​ 的计算过程。其计算过程如下所述(这里仅说明 b 1 b_1 b1​ 的计算过程, b 2 b_2 b2​ 到 b 4 b_4 b4​ 的计算方式与 b 1 b_1 b1​ 一样): 对于输入序列 { a 1 , a 2 , a 3 , a 4 } \{a_1, a_2, a_3, a_4\} {a1​,a2​,a3​,a4​},当我们计算 a 1 a_1 a1​ 对该输入序列的注意力向量时, a 1 a_1 a1​ 会经过三次不同的线性变换,得到 q 1 q_1 q1​、 k 1 k_1 k1​、 v 1 v_1 v1​ 向量,公式如下。这里的 q (query)、k (key)、v (value) 可以用数据库来理解,q 对应的就是 SQL 语句,来查询某个键,最后返回这个键的值,就比如 q 是 ‘select age from girlfriend’,这里 query 就是这个 sql 语句,key 就是 age,value 就是 18。

Hadoop安全之Kerberos

简介 安全无小事,我们常常要为了预防安全问题而付出大量的代价。虽然小区楼道里面的灭火器、消防栓常年没人用,但是我们还是要准备着。我们之所以愿意为了这些小概率事件而付出巨大的成本,是因为安全问题一旦发生,很多时候我们将无法承担它带来的后果。 在软件行业,安全问题尤其突出,因为无法预料的事情实在太多了。软件的复杂性让我们几乎无法完全扫清安全问题,模块 A 独立运行可能没问题,但是一旦和模块 B 一起工作也许就产生了安全问题。 不可否认为了让软件更安全,我们引入了很多复杂的机制。不少人开发者也抱怨为了进行安全处理而做了太多额外的事情。在一个复杂的分布式软件 Hadoop 中,我们为此付出的成本将更大。比如,我们可能可以比较轻松的搭建一个无安全机制的集群,但是一旦需要支持安全机制的时候,我们可能会付出额外几倍的时间来进行各种复杂的配置和调试。 Hadoop 在开始的几个版本中其实并没有安全机制的支持,后来 Yahoo 在大规模应用 Hadoop 之后,安全问题也就日益明显起来。大家都在一个平台上面进行操作是很容易引起安全问题的,比如一个人把另一个人的数据删除了,一个人把另一个人正在运行的任务给停掉了,等等。在当今的企业应用里面,一旦我们的数据开始上规模之后,安全机制的引入几乎是必然的选择。所以作为大数据领域的开发者,理解 Hadoop 的安全机制就显得非常重要。 Hadoop 的安全机制现在已经比较成熟,网上关于它的介绍也很多,但相对较零散,下面我将尝试更系统的,并结合实例代码,给大家分享一下最近一段时间关于 Hadoop 安全机制的学习所得,抛个砖。 预计将包括这样几个方面: Kerberos 协议介绍及实践Kerberos 协议发展及 Hadoop 相关源码分析Hadoop 安全集群搭建及测试周边工具的安全支持 安全认证协议 Kerberos 做 Web 开发的同学们可能比较熟悉的认证机制是 JWT,近两年 JWT 的流行几乎让其成为了实现单点登录的一个标准。JWT 将认证服务器认证后得到的 token 及一定的用户信息经过 base64 编码之后放到 HTTP 头中发送给服务器端,得益于 token 的加密机制(一般是非对称加密),服务器端可以在不连接认证服务器就进行 token 验证(第一次验证时会向认证服务器请求公钥),从而实现高性能的鉴权。这里的 token 虽然看起来不可读,实际上我们经过简单的解码就能得到 token 的内容。所以 JWT 一般是要结合 HTTPS 一起应用才能带来不错的安全性。 JWT 看起来还不错呀,安全模型比较简单,能不能直接用在 Hadoop 上面呢?可能可以。但是由于 Hadoop 的出现早于 JWT 太多,所以当时的设计者们是不可能考虑使用 JWT 的。实际上 JWT 主要是针对 web 的场景设计的,对于分布式场景中,很多问题它是没有给出答案的。一些典型的场景比如服务间的认证该如何实现,如何支持其他的协议,等等。Hadoop 的安全认证使用的是 Kerberos 机制。相比 JWT,Kerberos 是一个更为完整的认证协议,然而也正是因为其设计可以支持众多的功能,也给其理解和使用带来了困难。

NMOS&PMOS&&ADC/示波器采样率

目录 一. NMOS和PMOS 1. 导通特性: PMOS: NMOS: 2. 超经典MOS管电平转换电路 3. 电源切换电路(略) 4. MOS管体二极管 二. ADC采样原理 三. 示波器基本原理 一. NMOS和PMOS 只需记住一点: NMOS:电流D->S,G电位比S电位高,就会导通。 PMOS:电流S->D,S电位比G电位高,就会导通。 区分PMOS管和NMOS管的巧妙记忆方法_tanguohua_666的博客-CSDN博客_nmos管和pmos管 MOS管的管脚有三个:源极S(source)、栅极G(Gate)和漏极(Drain)。 源极:它就是来源,是源头,因此电流应该是从源头到别的地方,到哪呢?是漏极,肯定不是栅极,因为栅极是控制极。 MOS管有两种:PMOS,NMOS。 PMOS管就是positive管,是积极的管,NMOS管是negative管,是消极的管。 积极的管就是顺应潮流,顺势而为;消极的管就是违背趋势,逆流而上。 很显然,电流从源极(输入端)到漏极(输出端),那就是顺势而为,因为源极就是源头嘛,因此这种管就是PMOS管; 而电流要是从漏极(输入端)到源极(输出端),那就是逆流而上,是NMOS管。 记忆技巧: 1.交叉的线最多的是源极; 2.栅极也就是门(gate),既然是门,就具有控制的职能。 3.无论是PMOS管还是NMOS管,二极管的方向正好与输入输出的方向是相反的。 4.无论是PMOS管还是NMOS管,栅源极箭头的方向正好与二极管的方向相同。 1. 导通特性: NMOS和PMOS电流流向以及导通条件 PMOS: (1)PMOS管的主回路电流方向为S→D,导通条件为Vgs有一定的压差,一般为 -5 ~ -10V(S电位比G电位高)。 (2)Vgs小于一定的值就会导通,适合用于源极(S极)接VCC时的情况(高端驱动)。S极电压固定,只要G极电压比S极低,Vgs小于一定值就会导通。 但是,虽然PMOS可以很方便地用作高端驱动,但由于导通电阻大,价格贵,替换种类少等原因,在高端驱动中,通常还是使用NMOS。 NMOS: (1)NMOS管的主回路电流方向为D→S,导通条件为Vgs有一定的压差,一般为5~10V(G电位比S电位高)。 (2)Vgs大于一定的值就会导通,适合用于源极(S极)接地时的情况(低端驱动),此时S极电压为0,只要G极电压大于一定值就可导通。只要栅极电压达到4V或10V就可以了,虽然4V就导通了,但是为了完全导通电压在其可承受范围应该尽量大一些。 2. 超经典MOS管电平转换电路 SDA1(高3.3V)转换为SDA2(高5V),其中Q1(2N7002是一个NMOS)。 3. 电源切换电路(略) 左边采用外部电源供电(V6): Q3(PMOS)的栅极电压约为外部电压,处于高电位。因而Q3无法导通,处于截止状态。 右边采用内部电源供电(V5): Q3(PMOS)的栅极电压为0V,体二极管导通。漏极电压为12V,源极电压约为12-0.7=11.3V,Vgs符合PMOS导通的条件,Q3导通。 (1)D3、D4:进一步隔离两个电源之间相互的影响; (2)这个电路里,MOS管的体二极管内部电流的方向和电路中电流方向相同,这是为了在上电后,让MOS管的Vgs符合导通条件,从而起到开关的作用。 4. MOS管体二极管 MOS管电流方向能反吗?体二极管能过多大电流? 正常情况下,NMOS电流流向为D->S。然而在实际应用电路中,NMOS会有电流从S->D的情况,比如下面这个防电源反接电路。 (1)正常接入时,电流经后级负载接到体二极管,体二极管导通,此时S极电压约为0.7V左右(体二极管导通电压),同时G极接的Vcc,所以Vgs=Vcc-0.7,NMOS导通。导通后压降基本为0,则Vgs=Vcc,MOS管维持导通。 (2)电源接反时,S极、G极电压都为0,Vgs=0,MOS管不导通。 二. ADC采样原理 如何利用单片机的ADC模块(或者独立的ADC芯片)得到接入ADC管脚上的实际电压值? 在芯片手册上,会给出是几位的ADC,比如TIC12400就有一个10bit的ADC。则芯片读到的ADC值,就是从 0 ~ 2^10-1。当把ADC引脚接GND,读到的就是0 ;当把ADC引脚接VDD,读到的就是 2^10-1。所以,如果是中间的某个值,就是求解数学问题:已知两点坐标值,给出中间任一点的横坐标,求其纵坐标。

Java 实现图片压缩、裁剪

1、引入依赖 <!--hutool 工具--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.11</version> </dependency> 2、文件加工 注意:大部分的IO流是无法重复读取的,只能读取一次,再读取时,会抛出异常,我们这里使用ByteArrayOutputStream将流数据缓存到内存中,达到多次读取的目的 import cn.hutool.core.img.Img; import cn.hutool.core.io.FileUtil; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.nio.file.Files; public class ImageUtil { /** * 图片加工方法 * <p> * 支持的图片格式: BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif * * @param imgUrl 目标文件的地址 * @param outputStream 输出流 * @param width 图片裁剪后的宽度 * @param height 图片裁剪后的高度 * @throws IOException */ public static void imageProcess(String imgUrl, ByteArrayOutputStream outputStream, int width, int height) throws IOException { byte[] imgBytes = getImgBytes(imgUrl); try (InputStream pojoInputStream = new ByteArrayInputStream(imgBytes); InputStream readInputStream = new ByteArrayInputStream(imgBytes)) { // 图片对象 BufferedImage bufferedImage = ImageIO.

机器学习:模型评估与选择-数据集划分(附代码实现)

我的小程序: 待办计划:卷起来吧,少年! 我们记账:年薪50w够花么? 通过学习得到的一个学习器,我们要知道它的泛化性能,即面对新的数据,算法产生的结果好不好。显然,我们不能用使用过的数据进行评估。所以,对于手里有限的数据集,我们要进行划分,划分为训练集和测试集,测试样本尽量不在训练集中出现,训练集用来训练模型,测试集用来评估模型的性能。这里介绍3种划分方法。 1、留出法 数据集D划分为训练集S和测试集T,D=S并T,S交T=空集。如1000个数据集,500个正样本,500个负样本,700个作为训练集(350个正样本,350个负样本),300个作为测试集(150个正样本,150个负样本),注意数据划分时数据分布尽量一致,例如在分类任务中,样本的类别比例相似。不同的划分,模型评估的结果也会有差别,所以一般会进行若干次随机划分,最后取平均值。 2、交叉验证法 如把数据集划分为10个大小相似的互斥子集,每次用9个作为训练集,剩下的1个作为测试集,则可以进行10次训练和测试,最后返回10次测试结果的均值,称为10折交叉验证。为减小样本的不同划分引入的差别,通常随机使用不同划分重复p次,如10次,则可称为“10次10折交叉验证”。 3、自助法(改变了初始数据集的分布,会引入估计偏差) 每次从数据集D中挑选一个样本拷贝进D',然后将该样本放回D中,在下次采样仍然可能被采样到。重复执行m次则得到包含m个样本的数据集D',样本在m次采样中始终不被采样到的概率为(1-1/m)^m,取极值得1/e,约为0.368,即D中约有36.8%的样本未出现在采样集D'中,我们可将D'作为训练集,D-D'作为测试集。 自助法在数据集较小时比较有用,数据集足够时,留出法和交叉验证法更常用 交叉验证法代码(含留一法,即N个样本进行N折交叉验证): %留一法 if k==x1_rows+x2_rows, x = [x1;x2]; y = [y1;y2]; for i=1:k, %留一的放回 if length(x_test)>0&&length(y_test)>0, x = [x;x_test]; y = [y;y_test]; end; %留一 x_test = x(1,:); y_test = y(1); %训练集 x(1,:) = []; y(1) = []; [w L] = logisticFunc(x,y,iters,lambda); p0 = 1/(1+exp(x_test*w)); p(i) = p0; if (y_test==0&&p0<=0.5)||(y_test==1&&p0>=0.5), error_num = error_num+1; end; end; error = error_num/k; else%k折 x1_test = []; x2_test = []; y1_test = []; y2_test = []; x1_num = floor(x1_rows/k);%向下取整,2.

Python中import的用法

我的小程序: 待办计划:卷起来吧,少年! 我们记账:年薪50w够花么? Python用了快两年了吧,其中有些东西一直是稀里糊涂地用,import便是我一直没有明白的东西。曾经有过三次解决它的机会,我都因得过且过、一拖再拖而没能化敌为友。今天下午,它又给了我一次机会,我想我还是从了它的心愿吧。 故事是从这篇台湾同胞的博客(Python 的 Import 陷阱)开始的,然后又跳到了Python社区的PEP 328提案(PEP 328 -- Imports: Multi-Line and Absolute/Relative),再结合过去的经验以及一些测试,我想我大概懂了吧。下面是我的总结,希望内容能够言简意赅、易于理解。 import语句有什么用?import语句用来导入其他python文件(称为模块module),使用该模块里定义的类、方法或者变量,从而达到代码复用的目的。为了方便说明,我们用实例来说明import的用法,读者朋友可以跟着尝试(尝试时建议使用python3,python2和python3在import的表现有差异,之后会提到)。 首先,先建立一个文件夹Tree作为工作目录,并在其内建立两个文件m1.py和m2.py,在m1.py写入代码: import os import m2 m2.printSelf() 在m2.py写入代码: def printSelf(): print('In m2') 打开命令行,进入到Tree目录下,敲下python m1.py运行,发现没有报错,且打印出In m2,说明这样使用import没有问题。由此我们总结出import语句的第一种用法。 import module_name。即import后直接接模块名。在这种情况下,Python会在两个地方寻找这个模块,第一是sys.path(通过运行代码import sys; print(sys.path)查看),os这个模块所在的目录就在列表sys.path中,一般安装的Python库的目录都可以在sys.path中找到(前提是要将Python的安装目录添加到电脑的环境变量),所以对于安装好的库,我们直接import即可。第二个地方就是运行文件(这里是m1.py)所在的目录,因为m2.py和运行文件在同一目录下,所以上述写法没有问题。 用上述方法导入原有的sys.path中的库没有问题。但是,最好不要用上述方法导入同目录下的文件!因为这可能会出错。演示这个错误需要用到import语句的第二种写法,所以先来学一学import的第二种写法。在Tree目录下新建一个目录Branch,在Branch中新建文件m3.py,m3.py的内容如下: def printSelf(): print('In m3') 如何在m1中导入m3.py呢,请看更改后的m1.py: from Branch import m3 m3.printSelf() 总结import语句的第二种用法: from package_name import module_name。一般把模块组成的集合称为包(package)。与第一种写法类似,Python会在sys.path和运行文件目录这两个地方寻找包,然后导入包中名为module_name的模块。 现在我们来说明为什么不要用import的第一种写法来导入同目录下的文件。在Branch目录下新建m4.py文件,m4.py的内容如下: def printSelf(): print('In m4') 然后我们在m3.py中直接导入m4,m3.py变为: import m4 def printSelf(): print('In m3') 这时候运行m1.py就会报错了,说没法导入m4模块。为什么呢?我们来看一下导入流程:m1使用from Branch import m3导入m3,然后在m3.py中用import m4导入m4。看出问题了吗?m4.py和m1.py不在同一目录,怎么能直接使用import m4导入m4呢。(读者可以试试直接在Tree目录下新建另一个m4.py文件,你会发现再运行m1.py就不会出错了,只不过导入的是第二个m4.py了) 面对上面的错误,使用python2运行m1.py就不会报错,因为在python2中,上面提到的import的两种写法都属于相对导入,而在python3中,却属于绝对导入。话说到了这里,就要牵扯到import中最关键的部分了——相对导入和绝对导入。

NR RB转带宽

NR RB转带宽 通常我们在5G中使用RB(Resource Block)资源块数量来表示带宽宽度,我们可以通过查表的方法找到对应的值。需要注意FDD和TDD对应的SCS(sub-carrier space)子载波间隔是不同的。 代码描述 //(BW) 5 10 15 20 25 30 40 50 60 80 90 100 //(fdd)25 52 79 106 133 160 216 270 N/A N/A N/A N/A //(tdd)11 24 38 51 65 78 106 133 162 217 245 273 /// <summary> /// rb转带宽 /// </summary> /// <param name="tdd_fdd">0:fdd;1:tdd</param> /// <param name="rb_num"></param> /// <returns></returns> public static int Rb_To_Bandwidth(int tdd_fdd, int rb_num) { int band = 0; if(tdd_fdd == 0)//fdd { switch (rb_num) { case 25: band = 5; break; case 52: band = 10; break; case 79: band = 15; break; case 106: band = 20; break; case 133: band = 25; break; case 160: band = 30; break; case 216: band = 40; break; case 270: band = 50; break; default: break; } } else if(tdd_fdd == 1)//tdd { switch (rb_num) { case 11: band = 5; break; case 24: band = 10; break; case 38: band = 15; break; case 51: band = 20; break; case 65: band = 25; break; case 78: band = 30; break; case 106: band = 40; break; case 133: band = 50; break; case 162: band = 60; break; case 217: band = 80; break; case 245: band = 90; break; case 273: band = 100; break; default: break; } } return band; }

【插件】vue vue-awesome-swiper 视频与图片混合自动轮播 视频播放完后自动切换下一个

vue-awesome-swiper版本3.1.3 组件代码如下: <template> <div class="awesomeSwiper"> <swiper :options="swiperOption" ref="videoSwiper" v-if="initOrNot" class="swiperBox" > <swiper-slide v-for="(item, index) in mediaNews" :key="index"> <video v-if="item.type === 0" :src="item.link" controls muted autoplay fluid="false" preload="auto" class="multimedia video-js" ></video> <img v-else :src="item.link" class="multimedia"/> </swiper-slide> </swiper> <div class="swiper-button-prev" @click="prev"></div> <div class="swiper-button-next" @click="next"></div> </div> </template> <script> //页面引入swiper import 'swiper/dist/css/swiper.css' import {swiper, swiperSlide} from 'vue-awesome-swiper' export default { name: 'awesomeSwiper', components: {swiper, swiperSlide}, props: ['mediaNews'], data() { return { mediaLastIndex: 0, // 记录上一次页面的activeIndex swiperOption: { speed: 1000, loop: false, observer: true, observeParents: true, autoplayDisableOnInteraction: false, allowTouchMove: false, runCallbacksOnInit: false, pagination: { el: '.

JAVA中抽象类为什么不能被实例化

这里可以简单理解为抽象类没有具体的功能实现,因为我们在实例化对象的时候,实例需要去实现类中定义的各种方法(代码),但是抽象类中的抽象方法只是定义了功能,但是并没有给出具体的实现方法(代码),所以即使实例化了,我们也没法去执行,那么这个对象就是不完整的,或者说是没有意义的。 举例说明: /** 这里定义一个抽象类Student*/ public abstract class Student{ /** 定义一个抽象方法study,即定义一个学习的功能*/ public abstract void study(); } 假设我们对Student进行实例化,并调用study方法,那么是无法实现study功能的,即实例s不知道学习什么,因为study方法中就没有功能代码(代码块)。 Student s = new Student(); s.study();

基于微信小程序的课程学习小程序

基于微信小程序的课程学习小程序 文章目录 基于微信小程序的课程学习小程序前言一、怎样实现基于微信小程序的课程学习软件二、部分界面截图1.系统功能架构图2.老师端截图 总结 前言 随着智能移动终端设备的普及,越来越多的学生利用自己碎片化的时间进行学习。这种学习方式已经被越来越多的学生所喜爱,不仅享受大量的互联网教学资源,丰富自己`的知识面,还可以随时随地进行学习。微信小程序作为微信社交"生态"的重要组成部分,具有原生App所不具有的一些优势。本款微信小程序作为"计算机网络"课程学习应用的载体,以Java作为后台开发语言,IDEA、微信小程序开发者工具、Navicat Premium、PostMan作为开发工具,Spring Boot + MyBatis作为开发框架;数据库采用MySQL。计算机网络课程学习微信小程序分为老师和学生模块,老师和学生通过登录之后,老师可以进行教学任务的发布,学生可以进行对计算机网络课程的学习;学生和老师通过线上的方式,可以大大地节约老师和学生的时间。 一、怎样实现基于微信小程序的课程学习软件 基于微信小程序的课程学习软件使用的是前后端分离的方法,前端使用的是微信小程序开发者工具,是HTML+JS的模式,后端使用Spring Boot+MyBatis的方式,这样使得开发环境更加的简单。项目分为学生和老师两个模块 老师模块的功能: 学生模块的功能: 我自己买了一个服务器,将后台的代码都放在了服务器上,但是前端是个人账号,上线非常的麻烦,需要腾讯老大哥进行审核通过,就没有弄。 二、部分界面截图 1.系统功能架构图 2.老师端截图 总结 前端下载地址 后端下载地址

Android 12读写存储卡权限申请

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

【yolov5系列】yolov5-onnxruntime在Ubuntu和RK芯片上运行

前言 这里yolov5的onnx模型的推理,分别在 x64上 和 移动端上运行,前者在自己本地Ubuntu系统上运行,后者在瑞芯微的rk3566上运行。 要完成如上工作我们需要一下步骤: 1 下载onnxruntime编译好的库2 下载opencv库并安装3 下载交叉编译器4 下载yolov5-onnxruntime的工程并运行 1 下载onnxruntime库 github上搜索 onnxruntime,能看到微软提供的库。链接为 https://github.com/microsoft/onnxruntime 2 opencv的下载 https://opencv.org/releases/ opencv的编译比较容易 【OpenCV之路】ubuntu下的安装C++的opencv4、opencv_contrib、python中opencv的cuda加速、ubuntu下opencv的第一个工程 该链接下,只需要编译到【3.1 c++/opencv 的编译】章节即可。 3 交叉编译器的下载 下载链接为 gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu的下载 一般的,下载后解压到固定路径下,并添加到系统环境变量中即可使用。 这里只针对当前工程测试,暂不进行系统环境变量配置,下载解压即可。 4 下载yolov5的onnxruntime的工程并运行 4.1 工程下载与目录结构构建 使用的yolov5-onnxruntime的工程链接为 https://github.com/itsnine/yolov5-onnxruntime 创建某个路径,这里为【/home/xyy/LL_DATA/LL/YOLOV5】 解压并构建如下目录结构: ├──yolov5-onnxruntime 【工程解压路径】 ├──GCC_COMPILER ├── gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu 【交叉编译器解压文件】 ├──libs ├── onnxruntime ├──onnxruntime-linux-x64-1.11.1 【库解压路径】 ├──onnxruntime-linux-aarch64-1.11.1 【库解压路径,用于移动端的库的编译】 ├── opencv ├──opencv_x64 【编译好opencv的bin/include/lib64文件,拷贝到此】 ├──opencv410_aarch64 【用于移动端库的编译,使用交叉编译器可编译,这里不展开介绍】 4.2 代码的修改 因为要在移动端运行,所以cv::imshow()无法使用,故将main.cpp中最后几行代码修改成如下(pc端运行时可不用修改)。 4.3 CMakeLists.txt 文件修改 修改【CMakeLists.txt】文件内的设置如下: cmake_minimum_required(VERSION 3.0.0) project(yolo_ort) set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_C_FLAGS "

VBA检查指定应用程序是否已经打开

VBA中提供了CreateObject和GetObject两种方法获得对象实例,二者的区别在于GetObject用于获取已经打开的应用程序对象,但是如果该应用程序并没有打开,那么将产生运行时错误,代码中需要加入额外的错误处理代码。 在任务管理器中可以轻松的查看当前已经打开的应用程序,如下图所示。 使用VBA也可以通过进程名称查找应用程序实例,示例代码如下。 Function blnCheckProcess(strProcess As String) As Boolean Dim objWMIService As Object Dim strSql As String Dim objProcessList As Object Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") strSql = Replace("select * from Win32_Process where Name='x' ", "x", strProcess) Set objProcessList = objWMIService.ExecQuery(strSql) blnCheckProcess = (objProcessList.Count > 0) Set objWMIService = Nothing Set objProcessList = Nothing End Function Sub Demo() Dim strProcess As String Dim strMsg As String strProcess = "winword.exe" If blnCheckProcess(strProcess) Then strMsg = strProcess & "