FAST角点的主要优势就是速度快,比SIFT快了几乎一个数量级,从而可以满足SLAM实时性的要求。
Shi-Tomas角点是vins-mono中使用的角点。
下面我对这两种角点在检测上的速度和能够检测到的最大角点数量进行了对比。
使用两种角点对KITTI数据集中的29帧图片进行检测,检测结果如下:
下图显示了ShiTomas角点检测到的角点数量及其花费的时间
下图显示了FAST角点检测到的角点数量及其花费的时间
可以看出,提取相同的29帧图片,FAST角点检测方法提取到了更多的角点,且花费的时间要小于ShiTomas。
FAST的快果然名不虚传。
下面附上这两种提取算法的代码:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <chrono>
using namespace std;
using namespace cv;
int main(int argc , char* argv[])
{
int thread_value = 30;
vector<String> files; //存放文件路径
vector<Mat> images; //存放文件数据
//读取文件夹下所有符合要求的文件路径
glob("/home/wang/code/jiaodian/testingpicture/*.png", files, true);
size_t num = files.size(); //读取的符合条件的文件个数
chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
for (int i = 0; i < num; i++)
{
//Mat after_fast_image;
Mat img = imread(files[i], IMREAD_GRAYSCALE); //读取灰度图像
if (img.empty())
{
cerr << files[i] << " can't be loaded!" << endl;
continue;
}
//images.push_back(img); //将图像数据存入images中
std::vector<cv::KeyPoint> keypoints;
//chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
cv::FAST(img, keypoints,thread_value);
//chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
//chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>( t2-t1 );
//cout<<"fast 角点 solve time cost = "<<time_used.count()<<" seconds. "<<endl;
cout << "fast picture " << i << "角点 数目 " << keypoints.size() << endl;
//cv::drawKeypoints(img, keypoints, after_fast_image, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);
//cv::imshow("after_fast_corner", after_fast_image);
}
chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>( t2-t1 );
cout<<"fast 角点 solve time total cost = "<<time_used.count()<<" seconds. "<<endl;
//waitKey();
return 0;
}
接下来是ShiTomas的检测代码
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <chrono>
using namespace cv;
using namespace std;
//描述:定义一些辅助宏
#define WINDOW_NAME "【Shi-Tomasi角点检测】"
int main(int acgc , char* acgv[])
{
vector<String> files; //存放文件路径
vector<Mat> images; //存放文件数据
//读取文件夹下所有符合要求的文件路径
glob("/home/wang/code/jiaodian/testingpicture/*.png", files, true);
size_t num = files.size(); //读取的符合条件的文件个数
chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
for (int i = 0; i < num; i++)
{
//Mat after_fast_image;
Mat img = imread(files[i], IMREAD_GRAYSCALE); //读取灰度图像
//shi-tomasi算法
vector<Point2f> corner;
double qualityLevel = 0.01; //角点检测可接收的最小特征
//double minDistance =10; //角点之间的最小的距离
double minDistance =5;
int blockSize = 3; //计算导数自相关矩阵时指定的邻域范围
double k = 0.04; //权重系数
//Mat copy = g_srcImage.clone();
if (img.empty())
{
cerr << files[i] << " can't be loaded!" << endl;
continue;
}
//images.push_back(img); //将图像数据存入images中
//chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
goodFeaturesToTrack(img, corner, 4000, qualityLevel, minDistance, Mat(), blockSize, false, k);
//chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
//chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>( t2-t1 );
//cout<<"ShiTomas 角点 solve time cost = "<<time_used.count()<<" seconds. "<<endl;
cout << "ShiTomas picture " << i << " 角点 数目 " << corner.size() << endl;
//cv::drawKeypoints(img, corner, after_fast_image, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);
//cv::imshow("after_fast_corner", after_fast_image);
}
chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>( t2-t1 );
cout<<"ShiTomas 角点 solve time cost = "<<time_used.count()<<" seconds. "<<endl;
return 0;
}