SVO(SVO: fast semi-direct monocular visual odometry)
SVO(SVO: fast semi-direct monocular visual odometry)翻译
文章目录
- SVO(SVO: fast semi-direct monocular visual odometry)翻译
- 1、介绍
- 2、系统概述
- 3、符号
- 4、运动估计
- 4.1、 基于稀疏模型的图像对齐
- 4.2、 通过特征对齐松弛
- 4.3、 姿态和结构优化
- 4.4、 讨论
- 5、建图
- 6、 实施细节
- 7、实验结果
- 8、结论
1、介绍
摘要——半直接法消除了运动估计中昂贵的特征提取和匹配技术的需要,直接在像素级上操作,做到了在高帧率下的亚像素精度(subpixel precision),采用概率建图(probabilistic mapping)方法对异常测量值进行显式建模,从而得到较少的异常值和更可靠的点。精确的高帧率运动估计在纹理较少、重复性和高频的场景中具有更强的鲁棒性。该算法应用于GPS无效环境下的无人机状态估计,在嵌入式计算机上以每秒55帧的速度运行,在消费型笔记本电脑上以每秒300帧以上的速度运行。我们将我们的方法称为SVO(半直接视觉里程计)。它将基于特征的方法(跟踪多个特征、并行跟踪和建图、关键帧选择)的成功因素与直接方法的精度和速度相结合。无人机的高帧率VO有望提高鲁棒性和更快的飞行操纵
A、 视觉运动估计方法的分类
同时从视频中恢复摄像机姿势和场景结构的方法可以分为两类:
a) 基于特征的方法:标准的方法是在每个图像中提取一组稀疏的显著的图像特征(例如点、线);使用不变的特征描述子在连续的帧中进行匹配;使用对极几何鲁棒地恢复相机的运动和结构;最后,通过最小化重投影误差来优化位姿和结构。
基于特征的方法的缺点是依赖于检测和匹配阈值,必须使用鲁棒估计技术来处理错误的特征匹配关系,而且大多数特征检测都是针对速度而不是精度进行优化的,因此,运动估计中的漂移必须通过对多个特征测量进行平均来补偿。
b) 直接法:直接从图像中的强度值(单通道图像像素值的大小)估计结构和运动。利用图像中的所有信息的直接方法,即使是来自梯度很小的区域,在纹理很少的场景中,或者在相机无法聚焦和运动模糊[15]的情况下,在鲁棒性方面优于基于特征的方法[14]。光度误差的计算比重投影误差更为密集,因为它涉及到大图像区域的图像扭曲和积分(warping and integrating)。然而,由于直接方法直接对图像的强度值进行操作,因此可以节省特征检测和不变描述子计算的时间。
B、 相关工作
大多数用于无人机[1]、[2]、[7]的单目VO算法都依赖于PTAM[16]。PTAM是一种基于特征的SLAM算法,它通过跟踪和建图许多(数百)个特征来实现鲁棒性。同时,它通过并行化运动估计和建图任务并依靠高效的基于关键帧的光束平差(BA)[17]来实时运行。然而,PTAM是为小型桌面场景中的增强现实应用而设计的,需要进行多次修改(例如,限制关键帧的数量)以允许在大型室外环境中操作[2]。
早期的直接单目SLAM方法跟踪和建图少部分,有时需要手动选择平面片[18]–[21]。第一个方法[18],[19]是使用滤波算法来估计结构和运动的,之后的方法[20] –[22]采用非线性最小二乘法优化。所有这些方法都可以估计面片的法线,从而可以在很大的视点范围内跟踪一个面片,从而大大减少了估计中的漂移。然而,[19]-[21]的作者报告了实时性能,只能做到少数选定的平面区域和小数据集。文献[22]提出了一种适用于车载全向摄像机的VO算法。在文献[8]中,放宽了局部平面性假设,提出了基于立体摄像机计算任意三维结构的直接跟踪方法。在[9]-[11]中,同样的方法也适用于RGB-D传感器。在DTAM[15]中,引入了一种新的直接方法,该方法通过最小化全局空间正则化能量泛函来计算每个关键帧的密集深度建图。通过摄像机的直接定位,找到了整个深度图。这种方法计算量非常大,而且只有通过大量的GPU并行处理才能实现。为了减少计算需求,在本文回顾过程中发表的文献[23]中描述的方法只使用具有强梯度特征的像素。
C、 稿件及提纲
为了减少计算需求,只使用具有强烈梯度特征的像素。
提出的半直接视觉里程计(SVO)算法进行特征匹配,但是特征匹配是直接运动估计的隐式结果,而不是显式特征提取和匹配的结果。因此,只有当选择一个关键帧来初始化新的3D点时,才需要特征提取(见图1)。
与以前的直接方法不同,我们使用了许多(数百)个小面片,而不是几个(几十个)大的平面片[18]–[21]。使用许多小面片可以提高鲁棒性,并允许忽略面片法线。
本文提出的基于稀疏模型的运动估计图像对齐算法与基于模型的稠密图像对齐相关[8]–[10]。我们证明了稀疏的深度信息足以得到运动的粗略估计和特征匹配。一旦建立了特征匹配和摄像机姿态的初始估计,该算法将继续只使用点特征;因此,命名为“半直接”。这种转换使我们可以依赖于快速和成熟的框架来进行光束平差(例如,[25])。
用一个贝叶斯滤波器显式地建模异常测量值,来估计特征位置的深度值。只有当相应的深度过滤器已收敛时,才会在地图中插入三维点,这需要多次测量。可以可靠地跟踪一些异常点的结果。
本文的主要贡献是:(1)一种比现有的无人机系统更快、更精确的半直接VO管道;(2)集成了一种对异常测量具有鲁棒性的概率建图方法。
2、系统概述
运动估计线程
第一步是通过基于稀疏模型的图像对齐来初始化位姿:通过最小化相同3D点的投影位置相匹配的像素之间的光度误差来找到相对于前一帧的相机姿势(见图2)。
图2:改变当前帧和前一帧之间的相对姿势Tk,k−1隐式地移动新图像u′i中重投影点的位置。稀疏图像对齐找到Tk,k−1,将匹配于同一3D点(蓝色方块)的图像面片之间的光度差减到最小。注意,在所有图中,要优化的参数用红色表示,优化成本用蓝色显示。
在下一步中,通过对齐相应的特征面片(参见图3),可以细化与重投影点相匹配的二维坐标。运动估计是通过优化位姿和结构来完成的,即通过最小化前一个特征对齐步骤中引入的重投影误差来完成的。
图3:由于3D点和相机姿势估计的不精确性,通过单独优化每个面片的2D位置,可以进一步最小化当前帧中的相应面片(蓝色方块)与先前关键帧ri之间的光度误差。
建图线程
为每个2D特征初始化一个概率深度滤波器,其匹配的3D点将被估计。每当新的关键帧从图像区域中挑选出来,只要有很少的3D到2D匹配关系被找到,新的深度滤波器就会被初始化。始化时深度有很大的不确定性。在随后的每一帧,深度估计都会以贝叶斯方式更新(见图5)。当深度滤波器的不确定性变得足够小时,一个新的3D点被插入地图,并立即用于运动估计。
图5:参考帧r中特征i的概率深度估计ˆdi。真实深度处的点投影到两个图像中相似的图像区域(蓝色方块)。因此,根据与参考面片相关度最高的点u′i计算的三角化深度~dk i更新深度估计值。在新图像中,相关性最高的点总是位于极线上。
3、符号
4、运动估计
4.1、 基于稀疏模型的图像对齐
SVO使用直接法,通过计算相机运动和特征匹配的初步猜测,并以基于特征的非线性重投影误差优化为结论。
以下各节详细说明了每个步骤,并在图2至图4中进行了说明。
4.2、 通过特征对齐松弛
4.3、 姿态和结构优化
4.4、 讨论
算法的第一个(第四-A节)和最后一个(第四-C节)优化似乎是多余的,因为这两个都优化了相机的6自由度位姿。实际上,我们可以直接从第二步开始,通过Lucas Kanade跟踪所有特征面片[27]来建立特征匹配关系,然后进行非线性位姿优化(第四-C节)。虽然这样可以工作,但处理时间会更长。在大距离(例如,30像素)上跟踪所有特征需要更大的面片和金字塔实现。此外,有些特征可能会被错误地跟踪,这就需要异常值检测。然而,在SVO中,在稀疏图像对齐步骤中,只需优化摄像机姿态的六个参数即可有效地初始化特征对齐。在稀疏图像对齐步骤隐式地满足了对极约束,并确保没有异常值。
也有人认为第一步(稀疏图像对齐)足以估计摄像机运动。在事实上,这就是最近为RGB-D相机开发的算法所做的[10],然而,通过对齐全部深度地图而不是稀疏的面片。我们从经验上发现,与同时使用所有三个步骤相比,使用第一步只会导致更多的漂移。改进的精度是由于新图像相对于关键帧和地图进行对齐,而稀疏图像对齐仅将新帧与前一帧对齐。
5、建图
[28]中详细描述了该模型的递归贝叶斯更新步骤。与[28]相比,我们使用逆深度坐标来处理大场景深度。
当只搜索极线上当前深度估计值周围的小范围时,所提出的深度估计值是非常有效的;在我们的情况下,该范围相当于当前深度估计值标准差的两倍。图6展示了如何减少深度的不确定性所需的运动量。与标准的两视图三角测量方法相比,本文提出的方法的主要优点是,每个滤波器经过多次测量直到收敛,这样观察到的异常值要少得多。此外,错误的测量被显式地建模,这使得深度即使在高度相似的环境中也能收敛。在[29]中,我们演示了如何将相同的方法用于稠密建图。
图6:为了使深度滤波器(如红线所示)的不确定性收敛,无人机(从顶部看)只需要很少的运动。
6、 实施细节
该算法通过引导(bootstrapped)得到前两个关键帧的位姿和初始地图。和[16]一样,我们假设一个局部平面场景并估计一个单应矩阵。初始地图是从前两个视图三角化的。
为了处理更大的运动,我们采用了由粗到细的稀疏图像对齐算法。对图像进行半采样以创建五个级别的图像金字塔。然后在最粗级别上优化强度残差,直到收敛。随后,在下一个更精细的级别初始化优化。为了节省处理时间,我们在第三级收敛后停止,此时估计值足够精确,可以初始化特征对齐。
为了提高效率,该算法在地图中保持固定数量的关键帧,这些关键帧被用作特征对齐和结构细化的参考。如果新帧相对于所有关键帧的欧式距离超过平均场景深度的12%,就被选为关键帧。在地图中插入新的关键帧时,将移除距离相机当前位置最远的关键帧。
在建图线程中,我们将图像分成固定大小的单元(30×30像素)。除非已经存在二维到三维的匹配关系,否则就在单元中具有最高Shi-Tomasi分数的快速角点[30]处初始化一个新的深度滤波器。这将导致图像中的特征均匀分布。相同的网格也用于在特征对齐之前重投影地图。请注意,我们在图像金字塔的每个级别提取快速角点,以找到与比例无关的最佳角点。
7、实验结果
实验是在一个向下看的相机上记录的数据集和一个手持相机的序列上进行的。视频在笔记本和安装在无人机上的嵌入式平台上处理(参见图17)。注意,算法最多使用2个CPU内核。在消费者笔记本电脑上进行的实验有两个不同的参数设置,一个优化速度,一个优化精度(表一)。在嵌入式平台上,只用到了速度参数。
图17:KMel机器人公司的“Nano+”,定制嵌入式处理器和向下看的摄像头。SVO在平台上以每秒55帧的速度运行,用于稳定和控制。
表一:SVO的两种不同参数设置。
比较了SVO算法与文献[2]中改进的PTAM算法的性能。我们没有与原始版本的PTAM[16]进行比较的原因是它不能处理大环境,并且在高频纹理的场景中不够健壮[2]。文献[2]的版本解决了这些问题,并就我们所知构成了无人机中性能最好的单目SLAM算法。
A、精确度
我们对同样在[2]中使用过的数据集进行精度评估,如图7所示。真实地面(ground-truth)来源于一个运动捕捉系统。飞行轨迹长84米,无人机飞行平均离地高度1.2米。
图7:快速参数设置的SVO(见表一)与PTAM和真实地面对比。放大显示,该算法生成的轨迹比PTAM平滑。
图8和图9说明了随时间变化的位置和姿态误差。为了生成平面图,我们使用[31]将前10帧与实际情况对齐。PTAM的结果与文献[2]中报告的范围相似。由于平面图高度依赖于前10帧的对准精度,我们还报告了以米每秒为单位的偏移表II。
表二:图7中轨迹的相对位姿和旋转误差
图8:SVO的位置漂移,用快速和精确参数设置,并与PTAM进行比较。
图9:SVO的Attitutde漂移,用快速和精确参数设置,并与PTAM进行比较。
总的来说,两个版本的SVO都比PTAM更精确。我们怀疑这一结果的主要原因是[2]的PTAM版本没有在最高分辨率的金字塔级别上提取特征,并且没有对PTAM中的所有特征进行亚像素细化。忽略最高分辨率的图像不可避免地会导致精度降低,这在图7中清晰可见。在文献[2]中,低分辨率图像的使用是因为图像中的高频自相似纹理会产生太多的异常3D点。SVO有效地解决了这一问题,通过使用深度滤波器可以得到很少的异常值。
由于相机只是一个角度传感器,所以不可能通过运动管道(pipeline)从结构中获取地图的比例。因此,在上述评估中,我们还将前10次测量的比例与地面真实情况相一致。建议的管道传播比例,但是有一些漂移,如图10所示。尺度漂移是通过比较相对平移的欧几里德范数与实际情况来计算的。未知的尺度和尺度漂移促使人们需要一个用于无人机控制的相机IMU状态估计系统,如[33]所述。
图10:图7所示轨迹随时间的漂移
图11显示了平均重投影误差。稀疏图像对齐步骤使帧非常接近最终位姿,因为细化步骤仅略微减少了误差。重投影误差是在特征对齐步骤中“生成”的;因此,该图还显示在该步骤中,面片仅移动一小部分的像素。
图11:图7所示轨迹随时间的平均重投影误差。初始误差是在稀疏图像对齐(第四-A节)之后,最终误差是在位姿优化之后(第四-C节)。
快速和精确参数设置之间的精度差异不显著。在每次迭代(快速参数设置)中分别优化位姿和观察到的3D点,对于无人机运动估计而言足够精确。
B、运行时间评估
图13和图14显示了在快速参数设置下,分别在指定的笔记本电脑和嵌入式平台上计算相机运动所需的时间。笔记本电脑能够以每秒300帧(fps)的速度处理,嵌入式平台的处理速度为每秒55帧。PTAM对应的时间分别为91 fps和27 fps。主要的区别是SVO不需要在运动估计过程中提取特征,而是PTAM的主要耗时(笔记本电脑为7ms,嵌入式计算机为16ms)。此外,PTAM跟踪160到220个特征,而在快速参数设置中,该值被限制为120。我们能用较少的特征可靠地跟踪相机的原因是使用了深度滤波器,从而确保跟踪到的特征是有效的。在笔记本电脑上,精确参数设置的运动估计平均需要6毫秒。时间的增加主要是由于局部BA,它在每个关键帧处运行,耗时14ms,建图线程用新帧更新所有深度滤波器所需的时间高度依赖于滤波器的数量。在选定关键帧后,滤波器的数量很高,并且随着滤波器的收敛(converge)而迅速减少。平均而言,建图线程比运动估计线程快,因此它不是限制因素。
C、稳健性
SVO的速度和精度部分归功于深度滤波器,它只产生最少数量的异常点。另外,健壮性也是由于深度滤波器:精确、高帧率跟踪允许滤波器即使在重复和高频纹理的场景(如沥青、草地)中也能收敛,这在本文随附的视频中得到了最好的演示。视频的屏幕截图如图15所示。图16显示了在同一场景中使用PTAM和SVO生成的建图的比较。虽然PTAM生成异常3D点,相比之下,SVO几乎没有异常点,这要归功于深度滤波器的使用。
8、结论
在本文中,我们提出了半直接VO管道(pipeline)“SVO”,它比现有的VO更加精确和快速。速度的提高是由于运动估计不需要特征提取和匹配。取而代之的是一种直接的方法,它直接基于图像的强度。该算法在当前的嵌入式计算机上以每秒50帧以上的速度运行,特别适用于无人机的状态估计。高帧速率运动估计结合抗异常点的概率建图方法,在纹理较少、重复和高频的场景中提高了鲁棒性。
相关文章:

MSER 候选车牌区域检测
#include "opencv2/highgui/highgui.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> // Mser车牌目标检测 std::vector<cv::Rect> mserGetPlate(cv::Mat srcImage…

从HelloWorld看Knative Serving代码实现
为什么80%的码农都做不了架构师?>>> 摘要: Knative Serving以Kubernetes和Istio为基础,支持无服务器应用程序和函数的部署并提供服务。我们从部署一个HelloWorld示例入手来分析Knative Serving的代码细节。 概念先知 官方给出的这…

svo_note
SVO论文笔记1.frame overviews2. Motion Estimate Thread2.1 Sparse Model-based Image Alignment 基于稀疏点亮度的位姿预估2.2 Relaxation Through Feature Alignment 基于图块的特征点匹配2.3 Pose and Structure Refinement3 Mapping Thread3.1 depth-filter3.2 初始化参考…

Druid 配置 wallfilter
这个文档提供基于Spring的各种配置方式 使用缺省配置的WallFilter <bean id"dataSource" class"com.alibaba.druid.pool.DruidDataSource" init-method"init" destroy-method"close">...<property name"filters" v…

vue下的bootstrap table + jquery treegrid, treegrid无法渲染的问题
在mian.js导入的包如下:该bootstrap-table-treegrid.js需要去下载,在复制到jquery-treegrid/js/ 1 import $ from jquery 2 import bootstrap/dist/css/bootstrap.min.css 3 import bootstrap/dist/js/bootstrap.min 4 import bootstrap-table/dist/boot…

内存和缓存的区别
今天看书的时候又看到了内存和缓存,之所以说又,是因为之前遇到过查过资料,但是现在又忘了(图侵删)。 所以又复习一遍,记录一下,有所纰漏的地方,欢迎指正。 同志们,上图并不是内存和缓存中的任何…

【Boost】noncopyable:不可拷贝
【CSDN】:boost::noncopyable解析 【Effective C】:条款06_若不想使用编译器自动生成地函数,就该明确拒绝 1.example boost::noncopyable 为什么要boost::noncopyable 在c中定义一个类的时候,如果不明确定义拷贝构造函数和拷贝赋…

BigData NoSQL —— ApsaraDB HBase数据存储与分析平台概览
一、引言时间到了2019年,数据库也发展到了一个新的拐点,有三个明显的趋势: 越来越多的数据库会做云原生(CloudNative),会不断利用新的硬件及云本身的优势打造CloudNative数据库,国内以阿里云的Cloud HBase、POLARDB为代…

ubuntu clion 创建桌面快捷方式
ubuntu clion 创建桌面快捷方式 首先在终端下输入 cd /usr/share/applications/进入applications目录下,建立一个clion.desktop文件 sudo touch clion.desktop然后在vim命令下编辑该文件 sudo vim clion.desktop进入vim后,按i插入开始编辑该文件&…

Flex 布局:语法篇
2019独角兽企业重金招聘Python工程师标准>>> 布局的传统解决方案,基于盒状模型,依赖 display 属性 position 属性 float 属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。 2009年,W3C 提…

特征运动点估计
cv::Mat getRansacMat(const std::vector<cv::DMatch>& matches, const std::vector<cv::KeyPoint>& keypoints1, const std::vector<cv::KeyPoint>& keypoints2, std::vector<cv::DMatch>& outMatches) {// 转换特征点格式std::vecto…

Vue+Element-ui+二级联动封装组件
通过父子组件传值 父组件: 1 <template>2 <linkage :citysList"citysList" :holder"holder" saveId"saveId"></linkage>3 </template>4 <script>5 import linkage from ./common/linkage6 export de…

MOG2 成员函数参数设定
pMOG2->setDetectShadows(true); // 背景模型影响帧数 默认为500 pMOG2->setHistory(1000); // 模型匹配阈值 pMOG2->setVarThreshold(50); // 阴影阈值 pMOG2->setShadowThreshold(0.7);前景中模型参数,设置为0表示背景,255为前景ÿ…
webpack 大法好 ---- 基础概念与配置(1)
再一次见面! Light 还是太太太懒了,距离上一篇没啥营养的文章已经过去好多天。今天为大家介绍介绍 webpack 最基本的概念,以及简单的配置,让你能快速得搭建一个可用的 webpack 开发环境。 webpack的安装 webpack 运行于 node 环境…

Zookeeper迁移(扩容/缩容)
zookeeper选举原理在迁移前有必要了解zookeeper的选举原理,以便更科学的迁移。快速选举FastLeaderElectionzookeeper默认使用快速选举,在此重点了解快速选举:向集群中的其他zookeeper建立连接,并且只有myid比对方大的连接才会被接…

SVO Without ROS环境搭建
Installation: Plain CMake (No ROS) 首先,建立工作目录:workspace,然后把下面的需要的都在该目录下进行. mkdir workspace cd workspace Boost - c Librairies (thread and system are needed) sudo apt-get install libboost-all-dev Eige…

BackgroundSubtractorGMG 背景建模
#include <opencv2/bgsegm.hpp> #include <opencv2/video.hpp> #include <opencv2/opencv.hpp> #include <iostream> #include <sstream> using namespace cv; using namespace std; using namespace bgsegm; // GMG目标建模检测 void detectBac…

启动webpack-dev-server只能本机访问的解决办法
修改package.json的dev启动设置,增加--host 0.0.0.0启动后localhost更换为本机IP即可访问

TCP/IP:IP选项处理
引言 IP输入函数要对IP 进行选项处理,。RFC791和1122规定了IP选项和处理规则。一个IP首部可以跟40个字节的选项。 选项格式 选项的格式,分为两种类型,单字节和多字节。 ip_dooptions函数 这个函数用于判断分组转发。用常量位移访问IP选项字段…

【SVO2.0 安装编译】Ubuntu 20.04 + Noetic
ways one 链接: https://pan.baidu.com/s/1ZAkeD64wjFsDHfpCm1CB1w 提取码: kxx2 (downloads and use idirectly) ways two: [SVO2-OPEN: https://github.com/uzh-rpg/rpg_svo_pro_open](https://github.com/DEARsunshine/rpg_svo_pro_open)git挂梯子 如果各位终端无法挂梯…

人眼目标检测初始化
// 初始化摄像头读取视频流cv::VideoCapture cap(0);// 宽高设置为320*256cap.set(CV_CAP_PROP_FRAME_WIDTH, 320);cap.set(CV_CAP_PROP_FRAME_HEIGHT, 256);// 读取级联分类器// 文件存放在opencv\sources\data\haarcascades bool flagGlasses false;if(flagGlasses){face_ca…
Qt之界面换肤
简述 常用的软件基本都有换肤功能,例如:QQ、360、迅雷等。换肤其实很简单,并没有想象中那么难,利用前面分享过的QSS系列文章,沃我们完全可以实现各种样式的定制! 简述实现原理效果新建QSS文件编写QSS代码加…

mongDB的常用操作总结
目录 常用查询:查询一条数据查询子元素集合:image.idgte: 大于等于,lte小于等于...查询字段不存在的数据not查询数量:常用更新更新第一条数据的一个字段:更新一条数据的多个字段:常用删除删除:常用查询: 查询一条数据 精确匹配is Query(Criteria.where("id").is(id))…

【GTSAM】GTSAM学习
1 what GTSAM ? GTSAM 是一个在机器人领域和计算机视觉领域用于平滑(smoothing)和建图(mapping)的C库。它与g2o不同的是,g2o采用稀疏矩阵的方式求解一个非线性优化问题,而GTSAM是采用因子图(f…

人脸、人眼检测与跟踪
#include <opencv2/opencv.hpp> #include <iostream> #include <vector> using namespace cv;CascadeClassifier face_cascade; CascadeClassifier eye_cascade;// 人眼检测 int detectEye(cv::Mat& im, cv::Mat& tpl, cv::Rect& rect) {std::v…

linux下jdk简单配置记录
记录哈,搭建环境的时候,copy使用方便。 vim /etc/profile export JAVA_HOME/usr/java/jdk1.7.0_79export PATH$JAVA_HOME/bin:$PATHexport CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarexport JRE_HOME$JAVA_HOME/jreexport LANGzh_CN.UT…

Ubuntu中Could not get lock /var/lib/dpkg/lock解决方案
关于Ubuntu中Could not get lock /var/lib/dpkg/lock解决方案 转载于:https://www.cnblogs.com/daemonFlY/p/10916812.html

so库方法原理
动态库 So库,又动态名库,是Linux下最常见的文件之一,是一种ELF文件。这种so库是程序运行时,才会将这些需要的代码拷贝到对应的内存中。但程序运行时,这些地址早已经确定,那程序引用so库中的这些代码地址如…

上传图片,多图上传,预览功能,js原生无依赖
最近很好奇前端的文件上传功能,因为公司要求做一个支持图片预览的图片上传插件,所以自己搜了很多相关的插件,虽然功能很多,但有些地方不能根据公司的想法去修改,而且需要依赖jQuery或Bootstrap库,所以我就想…

springboot 简单自定义starter - beetl
使用idea新建springboot项目beetl-spring-boot-starter 首先添加pom依赖 packaging要设置为jar不能设置为pom<packaging>jar</packaging> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web&…