《OpenCV3编程入门》学习笔记11 特征检测与匹配(一) SURF特征点检测

第11章 特征检测与匹配

11.1 SURF特征点检测

11.1.1 SURF算法概览

1.定义:
  SURF,SpeededUp Rebust Features,加速版的具有鲁棒性的特征算法,是尺度不变特征变换算法(SIFT)的加速版
2.特征:
  采用了haar特征以及积分图像的概念,加快了运行时间

11.1.2 SURF算法原理

1.构建Hessian矩阵构造高斯金字塔尺度空间
(1)Hessian matrix:
一个自变量为向量的实值函数的二阶偏导数组成的方框矩阵,假设函数f(z,y),Hessian矩阵H,图像中某个像素点的Hessian矩阵如下:
                  在这里插入图片描述
H矩阵判别式为:
                  在这里插入图片描述
判别式的值是H矩阵的特征值,可以利用判定结果的符号将所有点分类,根据判别式取值正负,来判别该点是或不是极值点。
(2)SURF算法中H矩阵的计算

用图像像素l(x,y)作为函数值f(x,y),选用二阶标准高斯函数作为滤波器,通过特定核间的卷积计算二阶偏导数,计算出H矩阵:
                  在这里插入图片描述
由于特征点需要具备尺度无关性,所以在进行H矩阵构造前需要进行高斯滤波,滤波后在进行H计算:
                    在这里插入图片描述
L(x,t)是一幅图像在不同解析度下的表示,可以利用高斯核G(t)与图像函数I(x)在点x的卷积实现,其中高斯核G(t)计算公式为:
                      在这里插入图片描述
其中,g(x)为高斯函数,t为高斯方差。

Herbert Bay提出用近似值替代L(x,t),为平衡准确值与近似值间的误差引入的权值,权值随尺度变化,H矩阵判别式:
                  在这里插入图片描述

(3)SURF的金字塔
  金字塔图像分很多层,每一层叫做一个octave,每一个octave有几张不同尺度图片。
  Sift算法中,同一个octave层图片尺寸(大小)相同,但尺度(模糊程度)不同,高斯模糊时,sift的高斯模板大小不变,只在不同octave之间改变图片大小
  Surf算法中,图片大小一直不变,同一层octave中不同图片高斯模板尺度不同,不同octave层图片改变高斯模糊尺寸
传统金字塔图片尺寸变化,且反复利用高斯函数对子层进行平滑,而surf算法保持原图像不变只改变滤波器大小,节省了降采样过程,提升了处理速度。

2.利用非极大值抑制初步确定特征点
  将经过hessian矩阵处理过的每个像素点与其三维领域的26个点进行大小比较,如果是26个点中的最大/小值,则保留作为初步特征点。
  检测过程中,使用与该尺度层图像解析度对应大小的滤波器进行检测,以3*3滤波器为例,该尺度层图像9个像素点之一的检测特征点与自身尺度层中其余8个点和其上下尺度层中各9个点进行比较。

3.精确定位极值点
  采用三维线性插值法得到亚像素级特征点,同时去掉值小于一定阈值的点,筛选出特征较强点。

4.选取特征点的主方向
(1)Sift选取特征点主方向是采用在特征点领域内统计其梯度直方图,取直方图bin值最大的及超过最大bin值80%的方向作为特征点主方向。
(2)Surf中,不统计梯度直方图,而是统计特征点领域内的haar小波特征。即在特征点领域内(如,半径为6s的圆,s为该点所在尺度),统计60度扇形内所有点的水平haar小波特征和垂直haar小波特征总和,haar小波尺寸边长为4s,得到扇形值,然后60度扇形以一定间隔进行旋转,最后将最大值那个扇形的方向作为该特征点主方向。

5.构造surf特征点描述算子
(1)Sift中,在特征点周围取16*16领域,并把该领域化为4*4个小区域,每个小区域统计8个方向梯度,最后得到4*4*8=128维向量,该向量作为该点的sift描述子。
(2)Surf中,在特征点周围取一个正方形框,框边长为20s,该框方向即为第四步检测的主方向。然后把框分为16个子区域,每个子区域统计25个像素的水平方向和垂直方向(相对于主方向)的haar小波特征,该小波特征为水平方向值之和,水平方向绝对值之和,垂直方向之和,垂直方向绝对值之和。每个小区域有4个值,所以每个特征点就是16*4=64维向量,相比sift少了一半,会加快匹配速度。

                    在这里插入图片描述
                      构造surf特征点描述算子

6.总结
  Surf采用hessian矩阵获取图像局部最值稳定,但求主方向阶段太过于依赖局部区域像素的梯度方向,可能主方向不准确,从而导致后面特征点提取及匹配误差。同时金字塔层不够紧密会使尺度有误差影响特征向量提取,所以应取适量层后进行插值。

11.1.3 SURF类相关OpenCV源码

SURF相关类关系图示:
              在这里插入图片描述

11.1.4 绘制关键点:drawKeypoints()函数

1.函数原型

void drawKeypoints(const Mat&image, const vector&keypoints, Mat& outImage, constScalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT)

2.参数说明
(1)输入图像
(2)根据原图像得到的特征点
(3)输出图像,内容取决于flags
(4)关键点颜色,默认值Scalar::all(-1)
(5)绘制关键点的特征标识符,默认值DrawMatchesFlags::DEFAULT,可选值:
  DEFAULT=0 //创建输出图像矩阵,使用现存的输出图像绘制匹配对和特征点,且对每一个关键点,只绘制中间点
  DRAW_OVER_OUTIMG=1 //不创建输出图像矩阵,在输出图像上绘制匹配对
  NOT_DRAW_SINGLE_POINTS=2 //单点特征点不被绘制
  DRAW_RICH_KEYPOINTS=4//对每一个关键点,绘制带大小和方向的关键点圆圈

11.1.5 KeyPoint类

1.作用
  KeyPoint类是一个为特征点检测而生的数据结构,用于表示特征点
2.类描述

class KeyPoint
{
	Point2f pt;   //坐标
	float size;    //特征点领域直径
	float angle;  //特征点方向,值为[0,360),负值表示不使用
	float response;
	int octave;   //特征点所在图像金字塔的组
	int class_id;  //用于聚类的id
}

11.1.6 示例程序

/*
 OpenCV版本:
	 OpenCV2(含有surf特征提取算法在OpenCV2.0版本中是放在nonfree头文件中,3.0版本暂时还没有nonfree库,而是放在了xfeatures2d头文件和xfeatures2d库中,想在3.0版本中使用SURF的话,暂时需要需要下载opencv_contrib,并自己对OpenCV进行编译。)
 程序说明:
(1)使用FeatureDetector接口发现感兴趣点
(2)使用SurFeatureDetector及其函数detect实现检测过程
(3)使用函数drawKeypoints绘制检测到的关键点
*/
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include <iostream>
using namespace cv;
using namespace std;

int main()
{
	//【1】载入原图片并显示
	Mat srcImage1 = imread("1.jpg", 1);
	Mat srcImage2 = imread("2.jpg", 1);
	if (!srcImage1.data || !srcImage2.data)
	{
		printf("读取图片失败~!");
		return false;
	}
	imshow("原始图1", srcImage1);
	imshow("原始图2", srcImage2);

	//【2】定义需要的变量和类
	int minHessian = 400;//定义SURF中的hessian阈值特征点检测算子
	SurfFeatureDetector detector(minHessian);//定义一个SurfFeatureDetector(SURF)特征检测类对象
	vector<KeyPoint> keypoints_1, keypoints_2;//vector模板类是能够存放任意类型的动态数组,能够增加和压缩数据

	//【3】调用detect函数检测出SURF特征关键点,保存vector容器
	detector.detect(srcImage1, keypoints_1);
	detector.detect(srcImage2, keypoints_2);

	//【4】绘制特征关键点
	Mat img_keypoints_1, img_keypoints_2;
	drawKeypoints(srcImage1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
	drawKeypoints(srcImage2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT);

	//【5】显示效果图
	imshow("特征点检测效果图1", img_keypoints_1);
	imshow("特征点检测效果图2", img_keypoints_2);

	waitKey(0);
	return 0;
}
  • 0
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值