在ORB SLAM中,通过四叉树的方式存储关键点,使得图像上特征点分布均匀,便于追踪。此次实验分别用opencv接口和ORB SLAM实现特征点的提取,效果图如下:
#include
//#include
//#include
//#include
#include
#include "ORBextractor.h"
using namespace std;
using namespace cv;
int main ( int argc, char** argv )
{
//-- 读取图像
Mat img_1 = imread ( "1.png" );
Mat mImGray=img_1;
Mat outimg1,outimg2;//输出图像
cvtColor(mImGray,mImGray,CV_RGB2GRAY);//转换为灰度图
//opencv中接口函数
std::vector<KeyPoint> keypoints_1,keypoints_2;
Mat descriptors_1,descriptors_2;
Ptr<FeatureDetector> detector = ORB::create();
Ptr<DescriptorExtractor> descriptor = ORB::create();
detector->detect ( mImGray,keypoints_1 );
descriptor->compute ( mImGray, keypoints_1, descriptors_1 );
drawKeypoints( img_1, keypoints_1, outimg1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
imshow("opencv提取ORB特征点",outimg1);
//调用ORB SLAM中特征提取函数
ORBextractor* mpIniORBextractor;
mpIniORBextractor = new ORBextractor(500,1.2,8,20,10);
(*mpIniORBextractor)(mImGray,cv::Mat(),keypoints_2,descriptors_2 ) ;
drawKeypoints( img_1, keypoints_2, outimg2, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
imshow("ORB SLAM提取ORB特征点",outimg2);
waitKey(0);
return 0;
}
cmake_minimum_required(VERSION 3.13)
project(keypoint111)
set(CMAKE_CXX_STANDARD 11)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
aux_source_directory(. DIR_SRCS)#当有多个源文件时,此命令查找当前目录下的所有源文件
#注意.后面有一个空格,将所有源文件的名称保存到DIR_SRCS中
add_executable(keypoint111 ${DIR_SRCS})
target_link_libraries(keypoint111 ${OpenCV_LIBS})
注意:CMake会将当前源文件的文件名赋值给DIR_SRCS,再指示该变量中的源文件需要编译成一个名为keypoint11的可执行文件。
ORB SLAM中特征提取程序分析:
ORBextractor.h
class ORBextractor
{
public:
enum {HARRIS_SCORE=0, FAST_SCORE=1 };
//nfeatures ORB特征点数量 scaleFactor相邻层的放大倍数 nlevels层数 iniThFAST提取FAST角点时初始阈值 minThFAST提取FAST角点时更小的阈值
//设置两个阈值的原因是在FAST提取角点进行分块后有可能在某个块中在原始阈值情况下提取不到角点,使用更小的阈值在进一步提取
//构造函数
ORBextractor(int nfeatures, float scaleFactor, int nlevels,
int iniThFAST, int minThFAST);
~ORBextractor(){}
// Compute the ORB features and descriptors on an image.
// ORB are dispersed on the image using an octree.
// Mask is ignored in the current implementation.
//重载了()运算符,作为提取器的对外接口
void operator()( cv::InputArray image, cv::InputArray mask,
std::vector<cv::KeyPoint>& keypoints,
cv::OutputArray descriptors);
int inline GetLevels(){
return nlevels;}
float inline GetScaleFactor(){
return scaleFactor;}
std::vector<float> inline GetScaleFactors(){
return mvScaleFactor;
}
std::vector<float> inline GetInverseScaleFactors(){
return mvInvScaleFactor;
}
std::vector<float> inline GetScaleSigmaSquares(){
return mvLevelSigma2;
}
std::vector<float> inline GetInverseScaleSigmaSquares(){
return mvInvLevelSigma2;
}
//图像金字塔 存放各层的图片
std::vector<cv::Mat> mvImagePyramid;
protected:
//计算高斯金字塔
void ComputePyramid(cv::Mat image);
//计算关键点并用四叉树进行存储
void ComputeKeyPointsOctTree(std::vector<std::vector<cv::KeyPoint> >& allKeypoints);
//为关键点分配四叉树
std::vector<cv::KeyPoint> DistributeOctTree(const std::vector<cv::KeyPoint>& vToDistributeKeys, const int &minX,
const int &maxX, const int &minY, const int &maxY, const int &nFeatures, const int &level);
void ComputeKeyPointsOld(std::vector<std::vector<cv::KeyPoint> >& allKeypoints);
//存储关键点附近patch的点对
std::vector<cv::Point> pattern;
//提取特征点的最大数量
int nfeatures;
//每层之间的缩放比例
double scaleFactor;
//高斯金字塔的层数
int nlevels;
//iniThFAST提取FAST角点时初始阈值
int iniThFAST;
//minThFAST提取FAST角点时更小的阈值
int minThFAST;
//每层的特征数量
std::vector<int> mnFeaturesPerLevel;
//Patch圆的最大坐标
std::vector<int> umax;
//每层的相对于原始图像的缩放比例
std::vector<float> mvScaleFactor;
//每层的相对于原始图像的缩放比例的倒数
std::vector<float> mvInvScaleFactor;
std::vector<float> mvLevelSigma2;
std::vector<float> mvInvLevelSigma2;
};