关于opencv中的特征提取与匹配(ORB特征为例)

目录
  • 特征点检测
  • 描述子计算
  • 特征点匹配
  • 绘图
  • 各类函数的一些从属关系
特征点检测

  特征点检测是指利用detecter去检测图像中感兴趣的点,一般指角点边缘点等等,其中各类特征点的也有不同的定义方式,譬如角点有harris角点,FAST角点等等。以FAST角点为例(FAST角点属于ORB特征)。
  步骤1:定义KeyPoint容器;
  KeyPoint是C++中的一个模板类。可以理解为一种特殊的数据结构,检测出来的角点通常要存储起来,形成一个KeyPoint类型的容器(vector)。
  步骤2:定义检测器(detector);
  **detector可以看作是一个工具(函数),其功能是用于检测特征点,一般定义opencv中的Ptr智能指针指向一个detector,然后初始化为相应的特征。
  步骤3:进行检测;
  检测的过程很简单,调用相应的detect函数即可。代码如下:

std::vector<KeyPoint> keypoints;
//定义KeyPoint容器
Ptr<FeatureDetector> detector = ORB::create();
//定义检测器,初始化为相应的特征,
detector->detect(image, keypoints);
//进行检测,image为图像,是一个mat矩阵,检测点存于keypoints中

注释:
KeyPoint类下的属性以及访问方式
KeyPoint.pt;KeyPoint.pt.x;KeyPoint.pt.y;分别返回point2d类;x坐标,y坐标;**
KeyPoint.size;特征点领域大小;
KeyPoint.angle;特征点的角度;
KeyPoint.response;特征点的强度;
KeyPoint.octave;特征点所属金字塔的层数;
detect函数:
detector->detect(图像mat,容器keypoint);注意参数的类型

描述子计算

  描述子是指对特征点周围的信息进行描述,常常以向量的形式进行表达,常见的描述子有 BRIEF,SIFT等等,像BRIEF描述子的基本原理是随机选取特征点附近的一对点,然后进行τ测试,将结果表达为向量。以BRIEF描述子为例,opencv中计算描述子的步骤如下:
  步骤1:定义Mat矩阵;
  以向量的形式存储描述子。
  步骤2:定义描述器(descriptor);
  同特征点的检测一样,定义一个Ptr智能指针,然后访问相应的描述子计算函数。
  步骤3:计算描述子;
代码如下:

Mat descriptors;
	//存放描述子
Ptr<DescriptorExtractor> descriptor = ORB::create();
    //建立描述器
descriptor->compute(image, keypoints, descriptors);
    //计算描述子   

注释:
descriptor->comput(图像mat,容器keypoint,描述子矩阵mat);注意参数的类型

特征匹配

  特征匹配是指对多张图像中相同的特征点一一对应起来,通俗地讲就是找相同点。通常匹配时是求解描述子的距离,各种距离的定义也不一样,在ORB特征匹配过程中采用的是汉明距离。特征匹配的意义不言而喻,在CV中的应用也非常广泛。特征匹配的步骤如下:
  步骤1:定义Dmatch容器;
匹配时,需要把两种图像匹配点的信息,如坐标等等进行存储,一般是定义Dmatch容器。
  步骤2:定义匹配器(matcher);
  步骤3:开始匹配;
代码如下:

vector<DMatch> match;
//定义容器
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
//定义匹配器,选择匹配方式
matcher->match(descriptors_1, descriptors_2, match);
//进行匹配

注释:
DMatch类的属性以及访问方法:
①match.distance;距离
②match.queryIdx;特征点1在keypoints_1的下标(索引),注意keypoints_1是一个vector;
③match.queryIdx;特征点1’ 在keypoints_2的下标(索引),注意keypoints_2也是一个vector;
举例:
在这里插入图片描述
**在第0个match中,我们可以看见,keypoints_1的第4个特征点与keypoints_2的第157个特征点是匹配的,并且汉明距离是22。
④参数:matcher->match(descriptors_1(描述子mat), descriptors_2(描述子mat), match(Dmatch类,存放结果));

特征筛选

  特征筛选指把不合理的特征去除掉,通常是考察描述子之间的距离,当举例过大或者过小(每种距离不一样)时,则证明该匹配是错误匹配。
代码如下:

//找出所有匹配之间的最小距离和最大距离, 
即是最相似的和最不相似的两组点之间的距离
	double min_dist = 10000, max_dist = 0;
for (int i = 0; i < descriptors_1.rows; i++) {
	double dist = match[i].distance;
	if (dist < min_dist) min_dist = dist;
	if (dist > max_dist) max_dist = dist;
	
}

printf("-- Max dist : %f \n", max_dist);
printf("-- Min dist : %f \n", min_dist);

//当描述子之间的距离大于两倍的最小距离时,
即认为匹配有误.但有时候最小距离会非常小,设置一个经验值30作为下限.
for (int i = 0; i < descriptors_1.rows; i++) {
	if (match[i].distance <= max(2 * min_dist, 30.0)) {
		matches.push_back(match[i]);
	}
}
绘图

为了可视化,筛选好的匹配点可以绘制出来,基本的语句如下:
画特征点

Mat outimg1;
drawKeypoints(img_1, keypoints_1, outimg1, Scalar::all(-1), DrawMatchesFlags::DEFAULT);

drawKeypoints()函数有5个参数,前三个参数依次为:原图像mat,keypoint容器输出图像mat

画匹配图

  Mat img_match;
  drawMatches(img_1, keypoints_1, img_2, keypoints_2, good_matches, img_goodmatch);

drawMatches()函数一共有6个参数,分别为:原图像1mat,keypoints_1容器,原图像2mat,keypoints_2容器,输出匹配图mat

效果如下:
在这里插入图片描述
在这里插入图片描述

各类函数的一些从属关系

  学这一块的时候,我发现编程的时候特别乱,所以特地看了看opencv中的doucument,对各类函数以及类之间的关系有了一定的轮廓,也方便后面的学习。
在这里插入图片描述

继续学习中,先会掉包再说…

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值