文章目录
立体匹配算法分类
1、OpenCV实现的立体匹配算法:可以分为2类:全局匹配算法与局部匹配算法。全局匹配算法精度高,缺点是计算速度慢,实时性差;局部匹配算法分为基于区域的匹配,基于特征的匹配;局部匹配计算速度快,可以满足实时性要求,但是精度较全局匹配差;基于特征的匹配只能得到稀疏的视差,需要靠插值完成视差图的重建;
2、全局匹配算法:OpenCV实现了SGBM(半全局块匹配算法),GC算法(OpenCV3.0以后版本没有实现);
3、基于区域的局部匹配算法:OpenCV实现了BM(块匹配算法);
4、基于特征的局部匹配算法:OpenCV实现了10种特征检测匹配方法:
1. FAST --FastFeatureDetector;
2. STAR --StarFeatureDetector;
3. SIFT --尺度不变特征变换;
4. SURF --加速鲁棒特征;
5. ORB
6. MSER
7. GFTT
8. HARRIS
9. Dense
10.SimpleBlob
SURF特征点检测原理
1、SURF : SpeededUp Robust Features , 直译“加速版的具有鲁棒性的特征算法” , SURF是尺度不变特征变换算法(SIFT)的加速版,计算速度更快,在多幅图片下具有更好的稳定性;SURF最大的特征在于采用了Harr特征以及积分图像的概念,大大加快了程序的运行时间;
2、SURF算法原理:
①构建Hessian矩阵,构建高斯金字塔尺度空间;
②利用非极大值抑制初步确定特征点;
③精确定位极值点(采用三维线性插值法得到亚像素级的特征点);
④选取特征点的主方向:
Sift选取特征点主方向是采用在特征点领域内统计其梯度直方图,取直方图bin值最大的以及超过bin值80%的哪些方向作为特征点的主方向;
Surf则是不统计其梯度直方图,而是统计特征点领域内的harr小波特征,取最大值那个扇形的方向作为特征点的主方向;
⑤构造surf特征点描述子(Descriptor):
Sift算法是在特征点周围取1616的领域,将该领域化为44个小区域,每个小区域统计8个方向梯度,最后得到448 = 128维的向量,作为该点的Sift描述子;
Surf算法中,在特征点周围取20s(s是所检测到该特征点所在的尺度),然后将该框分为16个子区域,每个区域计算harr小波特征的4个值,所以每个特征点就是16*4=64维的向量,相比Sift,特征点描述子少了一半,特征匹配速度大大加快;
3、OpenCV3.0以后版本中,SURF、SurfFeatureDetector、SurfDescriptorExtractor代表相同含义(typedef定义的别名);(类继承关系)


4、SurfFeatureDetector类常用的方法:detect()(寻找特征点)、compute()(计算特征点的描述子);
绘制关键点与KeyPoint类
1、drawKeyPoints()函数:第5个参数flag : 绘制关键点的特征标识符(注意不同参数效果)

(Google翻译:)

2、KeyPoint关键点:(使用描述符描述其特征信息)
关键点是角点概念的扩展,对来自图像的小的局部像斑的信息进行编码,使关键点具有高度可辨别性,关键点的描述性信息被概括成描述符的形式,其描述符的维度通常比形成关键点的像素像斑低得多。(摘自Learning OpenCV3)


_size : 特征点领域直径
_angle : 特征点方向(0-360),(-1表示不使用)
_response : 关键点强度;
_octave : 关键点所在的图像金字塔的组;
_class_id : 用于聚类的id;
3、Surf、Sift是OpenCV的nofree模块,需要安装opencv_contrib附加库;(CMake编译时需要选择编译平台为x64!)

Surf特征点检测demo1
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp> //添加Surf
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d; //添加命名空间
int main(int argc, char** argv)
{
Mat src = imread("00.jpg", IMREAD_COLOR);
imshow("input", src);
int minHessian = 1000;
Ptr<SURF> detector = SURF::create(minHessian);
vector<KeyPoint> keypoint_1;
detector->detect(src, keypoint_1); //检测SURF特征关键点
//绘制KeyPoints
Mat img_keypoint_1;
drawKeypoints(src, keypoint_1, img_keypoint_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
//显示KeyPoints
imshow("detect", img_keypoint_1);
waitKey(0);
return 0;
}


Surf特征描述子计算与特征匹配(暴力匹配BFMatch)
1、Surf算法为每个检测到的特征定义了位置与尺度,尺度值可用于定义围绕特征点的窗口大小,不论物体的尺度在窗口是什么样的,都将包含相同的视觉信息,这些信息用于表示特征点以使得它们与众不同;
2、OpenCV中,使用Surf进行特征点描述与匹配主要是drawMatches()方法与BruteForceMatcher类使用;
3、drawMatcher() : 绘制两幅图像中的匹配点


matchMask : 确定哪些匹配是会绘制出来的掩膜,如果掩膜为空,表示所有匹配都进行绘制;
4、BFMatcher类常用方法:
train() :
训练一个描述符匹配器(例如,flann索引)。在所有要匹配的方法中,方法train()每次在匹配之前都会运行。一些描述符匹配器(例如,BruteForceMatcher)具有此方法的空实现。其他的描述符匹配器真的训练他们的内部结构(例如,FlannBasedMatcher训练flann::Index)。
match() : 查询列表,并与训练好的字典中的描述符进行比较,查询列表上每个关键点与列表中的“最佳匹配”匹配;
knnMatch() : k-最邻近匹配;
radiusMatch() : 半径匹配,返回与查询描述符特定距离内的所有匹配;

5、特征点匹配步骤:
①Surf算子计算特征点;
②Surf算子计算特征点描述子;
③BruteForceMatcher中的函数match()强行匹配两幅图像的特征向量;
Surf特征点暴力匹配demo2
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp> //添加Surf
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d; //添加命名空间
int main(int argc, char** argv)
{
Mat src1 = imread("1.jpg");
Mat src2 = imread("2.jpg");
Ptr<SURF> surfdect = SURF::create(1500);
//计算Surf特征点
vector<KeyPoint> keypoint_src1;
vector<KeyPoint> keypoint_src2;
surfdect->detect(src1, keypoint_src1);
surfdect->detect(src2, keypoint_src2);
//计算描述符(特征向量)
Mat descriptor_src1;
Mat descriptor_src2;
surfdect->compute(src1, keypoint_src1, descriptor_src1);
surfdect->compute(src2, keypoint_src2, descriptor_src2);
//匹配两幅图像中的描述子
vector<DMatch> dMatch;
Ptr<BFMatcher> bfMatch = BFMatcher::create(NORM_L2, false);
bfMatch->match(descriptor_src1,descriptor_src2,dMatch);
//绘制匹配点
Mat imgMatches;
drawMatches(src1, keypoint_src1, src2, keypoint_src2, dMatch, imgMatches);
imshow("BF Match", imgMatches);
waitKey(0);
return 0;
}
暴力匹配结果:(许多误匹配点)

快速近似最近邻逼近搜索函数库(FLANN)
1、FLANN : Fast Library for Approximate Nearest Neighbors;
2、FlannBasedMatcher类继承DescriptorMatcher类;使用match()方法匹配;

3、match()方法:

4、DMatch类的四个主要属性:用来存储描述符匹配结果

FLANN匹配demo3

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp> //添加Surf
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d; //添加命名空间
int main(int argc, char** argv)
{
Mat src1 = imread("1.jpg");
Mat src2 = imread("2.jpg");
//计算Surf特征点
Ptr<SURF> surfdect = SURF::create(1000);
vector<KeyPoint> keypoint_src1;
vector<KeyPoint> keypoint_src2;
surfdect->detect(src1, keypoint_src1);
surfdect->detect(src2, keypoint_src2);
//计算描述符(特征向量)
Mat descriptor_src1;
Mat descriptor_src2;
surfdect->compute(src1, keypoint_src1, descriptor_src1);
surfdect->compute(src2, keypoint_src2, descriptor_src2);
//使用FLANN算法匹配描述符向量
vector<DMatch> dMatch;
Ptr<FlannBasedMatcher> flannMatcher = FlannBasedMatcher::create();
flannMatcher->match(descriptor_src1, descriptor_src2, dMatch);
double max_dist = 0, min_dist = 100;
//快速计算关键点之间的最大和最小距离
for (int i = 0; i < descriptor_src1.rows; i++)
{
double dist = dMatch[i].distance;
if (dist < min_dist) min_dist = dist

本文深入探讨了立体匹配算法的分类,包括全局匹配与局部匹配算法的特点及应用场景,重点介绍了SURF、SIFT等特征检测算法的原理与OpenCV实现。通过多个示例演示了特征点检测、描述子计算及匹配过程,对比了不同算法的性能。
8901

被折叠的 条评论
为什么被折叠?



