SLAM从入门到放弃:SLAM十四讲第七章习题(1-5)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012348774/article/details/83791736

以下均为简单笔记,如有错误,请多多指教。

  1. 除了本身介绍的ORB特征点外,你还能找到哪些特征点?请说说SIFT或SURF的原理,并对比它们与ORB之间的优劣。
    解:除了ORB之外,我了解或用过的还有SIFT、SURF、AKAZE等,其实感觉在分类时按照特征点检测器和特征点描述器两个角度来描述,因为存在很多组合方法。例如ORB其实就是FAST+BRIEF。
    SIFT的检测器大致原理是首先在检测器阶段通过构建差分金字塔的方式,寻找出与众不同的特征点。而SURF的检测器则是通过修改滤波器的尺寸和模糊程度从而得到不同层级的高斯影像。下图中左图是SIFT的高斯金字塔的创建过程,其中被修改的是影像;右图是SURF的高斯金字塔创建过程,其中被修改的是卷积核。
    在这里插入图片描述
    SIFT的特征点描述子算法的示意图如下,通过梯度方向校正和归一化处理能够得到方向、亮度不变的描述子。
    在这里插入图片描述
    SURF则通过计算小波响应计算方向,然后以此为基础进行特征描述,大致如下图所示。
    在这里插入图片描述在这里插入图片描述

  2. 设计程序调用OpenCV中的其他种类的特征点。统计在提取1000个特征点时在你的机器上所用的时间。
    答:OpenCV有非常多的特征点,而且很多算法并不能控制特征点的数目,因此此处时间比较并没有什么太大的意义。以下是OpenCV中所有支持的特征点:
    在这里插入图片描述
    下边是我的一些demo代码:

	// Mat
	cv::Mat image = cv::imread("demo.jpg", 0);

	// SIFT
	cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create(1000);
	std::vector<cv::KeyPoint> siftKeyPoints;
	clock_t siftBegin = clock();
	sift->detect(image, siftKeyPoints);
	cv::Mat siftKeyPointsMat;
	clock_t siftFinish = clock();
	std::cout << "SIFT Time: " << (siftFinish - siftBegin)*1.0 / CLOCKS_PER_SEC << std::endl;
	cv::drawKeypoints(image, siftKeyPoints, siftKeyPointsMat, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
	cv::imshow("sift", siftKeyPointsMat);

	// ORB
	cv::Ptr<cv::ORB> orb = cv::ORB::create(1000);
	std::vector<cv::KeyPoint> orbKeyPoints;
	clock_t orbBegin = clock();
	orb->detect(image, orbKeyPoints);
	cv::Mat orbKeyPointsMat;
	clock_t orbFinish = clock();
	std::cout << "ORB Time: " << (orbFinish - orbBegin)*1.0 / CLOCKS_PER_SEC << std::endl;
	cv::drawKeypoints(image, orbKeyPoints, orbKeyPointsMat, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
	cv::imshow("orb", orbKeyPointsMat);
  1. 我们发现OpenCV提供的ORB特征点在图像当中分布不够均匀。你是否能够找到或提出让特征点分布更加均匀的方法?
    答:OpenCV的ORB特征点分布十分集中,大量点都会在纹理丰富的区域,以下是一个示意图:
    在这里插入图片描述
    解决方法我知道的有ORB-SLAM2中对ORB的改进,其思路是通过一个四叉树的方式来高效控制每个节点里的特征点数目,从而得到更加均匀的效果,可以参考:http://www.fengbing.net/2016/04/03/一步步实现slam2-orb特征检测/。以下的图片是使用ORB-SLAM2中的ORB算法的提取结果,相比而言更加均衡。
    在这里插入图片描述

  2. 研究FLANN为何能够快速处理匹配问题。除了FLANN之外,还有哪些可以加速匹配的手段?
    答:FLANN是一些列进行最邻近搜索的算法的集中库,其中有一些常用的算法例如classic kd-tree,randomized kd-tree和hierarchical k-means tree,具体的算法可以参考一下论文:Fast Approximate Nearest Neighbors With Automatic Algorithm Configuration,Scalable Nearest Neighbor Algorithms for High Dimensional Data。本身而言,特征匹配可以当做为某一个向量从一个高维向量集中寻找距离最近的向量。最传统和朴素的方法就是直接使用逐个计算距离,并返回最近的距离和向量;然而明显可以发现这种方法的计算量十分大,并且随着数据集增长,计算量也会随之增长。classic kd-tree则是通过建立kd-tree的方式,通过搜索-回溯的方式,尽可能减少不必要的计算过程,极大的提高了匹配的搜索过程;然而kd-tree的问题是随着数据维度的增大,其效率会急剧下降。randomized kd-tree则通过从高维向量中随机选出方差较大的维度,并建立kd-tree,最后同时在多个低维的kd-tree上进行搜索-回溯,从而提高效率。hierarchical k-means tree则是通过k-means的方法对数据进行聚类,然后再建立kd-tree。显而易见,无论是那种方法都是尽可能充分的减少不必要的计算过程,从而增加匹配的速度。除此之外,FLANN中还会自动去设置参数来自适应不同的需求,包括最邻近的精度(不一定要最近的,大概最近),kd-tree树创建效率等等。
    目前优化匹配速度的方法我知道的还有使用GPU优化匹配速度(例如siftGPU),其他的我暂时了解的不多。

  3. 把演示程序使用的EPnP改成其他PnP方法,并研究它们的工作原理。
    答:参考OpenCV3.4.3的solvePnP()函数,其目前稳定的方法有SOLVEPNP_ITERATIVE、SOLVEPNP_P3P、SOLVEPNP_AP3P、SOLVEPNP_EPNP。SOLVEPNP_ITERATIVE方法的思路是DLT+LM,即首先用DLT得到一个粗略值,然后用LM算法进行优化,得到更好的结果。SOLVEPNP_P3P在课本上已经有非常详细的介绍了,此处不再展开。SOLVEPNP_AP3P似乎是对P3P的改进,论文还是非常复杂的,具体的以后再看吧,论文如下:An Efficient Algebraic Solution to the Perspective-Three-Point Problem。SOLVEPNP_EPNP的思路是将空间中任意3D点的坐标可以用4个不共面的3D点坐标的权重表示,然后通过n个3D点在相机平面的投影关系,以及与这四个控制点的权重关系,构建一个12*12方阵,求得其零空间特征向量,可以得到虚拟控制点的相机平面坐标,然后使用POSIT算法即可求出相机位姿。
    PnP算法似乎还是很复杂,后续还需要专门展开学习一下。

猜你喜欢

转载自blog.csdn.net/u012348774/article/details/83791736
今日推荐