1 特征检测与匹配(FAST,SIFT,FlannBased)
opencv2.4特征检测程序:
initModule_nonfree(); //if use SIFT or SURF
//定义特征检测所需的变量和类
vector<KeyPoint> keypointsL, keypointsR; //vector模板类存放任意类型动态数组,增加和压缩数据
Ptr<FeatureDetector> detector = FeatureDetector::create("FAST"); // 特征检测器
Mat descriptorsL, descriptorsR;
Ptr<DescriptorExtractor> des = DescriptorExtractor::create("SIFT");//描述子
double t1 = (double)getTickCount();
//调用detect函数检测出FAST特征关键点,保存在vector容器中
detector->detect(imgL, keypointsL);
detector->detect(imgR, keypointsR);
t1 = ((double)getTickCount() - t1) / getTickFrequency();
printf_s("检测FAST关键点运行时间:%5f\n", t1);
double t2 = (double)getTickCount();
//调用compute函数计算FAST关键点的SIFT描述子,保存在vector容器中
des->compute(imgL, keypointsL, descriptorsL);
des->compute(imgR, keypointsR, descriptorsR);
t2 = ((double)getTickCount() - t2) / getTickFrequency();
printf_s("计算SIFT描述子运行时间:%5f\n", t2);
//定义匹配变量和类
vector<vector<DMatch>> matches; //定义vector<DMatch>中装入两个匹配--最近邻匹配和次近邻匹配,再作为一个整体装入容器中
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
matcher->knnMatch(descriptorsL, descriptorsR, matches, 2);
std::cout << "matches数目"<< matches.size()<<endl;
2 画关键点和匹配线函数
//画关键点drawKeypoints()
Mat imgl_keypoints;
drawKeypoints(imgL, keypointsL, imgl_keypoints, Scalar::all(-1), DrawMatchesFlags::DEFAULT);//显示imgl图关键点
//画出匹配线drawMatches()
Mat img_matches;
drawMatches(imgL, keypointsL, imgR, keypointsR, matches, img_matches);
imshow("matches", img_matches); //左图像为查询图像,故左图像的每个特征点都有两个匹配(最近邻匹配和次近邻匹配)
imwrite("./特征检测/FlannBased匹配初始图.jpg", img_matches);
3 打印关键点坐标
//关键点类型转换----KeyPoint类型通过iterator转化为Point2f类型
vector<Point2f> pointL, pointR;
vector<KeyPoint>::iterator L = keypointsL.begin(); //然后定义了一个具有KeyPoint元素的迭代器类型。L的类型就是vector<KeyPoint>::iterator。keypointsL.begin()就是首元素keypointsL[0]的地址
for ( ; L != keypointsL.end(); L++) //for循环有3个表达式,分别是初始化区、循环条件判断区、循环变量改变区。可以全写,也可以不写,表示死循环,for( ;; )
pointL.push_back(L->pt);
std::cout << "左图vector<Point2f>类型关键点数目:"<<pointL.size()<<endl;
//定义变量
float xl, xr, yl, yr, ylr;
char str[100];
Mat imgShow = imgL.clone();
vector<Point2f>::iterator iterL = pointL.begin();
int cnt1 = 0;
//图上打印关键点坐标
for (; iterL != pointL.end(); iterL++)
{
xl = iterL->x;
yl = iterL->y;
if ((cnt1++) % 20 == 0) //为了不显示太多的点,20次显示一个
{
Scalar color = CV_RGB(255, 255, 255);//获取颜色
sprintf_s(str, 100, "%.0f,%.0f", xl, yl);//格式化
circle(imgShow, *iterL, 1, color, 3);
putText(imgShow, str, Point(xl, yl), FONT_HERSHEY_SIMPLEX, .3, color);//在图像上打印出点的信息
}
}
imshow("关键点坐标图", imgShow);