opencv下SIFT使用

OPENCV下SIFT特征点提取与匹配的大致流程如下:

读取图片-》特征点检测(位置,角度,层)-》特征点描述的提取(16*8维的特征向量)-》匹配-》显示

其中,特征点提取主要有两个步骤,见上行黄子部分。下面做具体分析。

1、使用opencv内置的库读取两幅图片

2、生成一个SiftFeatureDetector的对象,这个对象顾名思义就是SIFT特征的探测器,用它来探测衣服图片中SIFT点的特征,存到一个KeyPoint类型的vector中。简而言之最重要的一点在于:

keypoint只是保存了opencv的sift库检测到的特征点的一些基本信息,但sift所提取出来的特征向量其实不是在这个里面,特征向量通过SiftDescriptorExtractor 提取,结果放在一个Mat的数据结构中。这个数据结构才真正保存了该特征点所对应的特征向量。具体见后文对SiftDescriptorExtractor 所生成的对象的详解。

就因为这点没有理解明白耽误了一上午的时间。哭死!

3、对图像所有KEYPOINT提取其特征向量:

得到keypoint只是达到了关键点的位置,方向等信息,并无该特征点的特征向量,要想提取得到特征向量就还要进行SiftDescriptorExtractor 的工作,建立了SiftDescriptorExtractor 对象后,通过该对象,对之前SIFT产生的特征点进行遍历,找到该特征点所对应的128维特征向量。通过这一步后,所有keypoint关键点的特征向量被保存到了一个MAT的数据结构中,作为特征。

 4、对两幅图的特征向量进行匹配,得到匹配值。


opencv中keypoint数据结构分析

分析opencv中keypoint数据结构的相关信息,找到opencv的document(http://docs.opencv.org/java/org/opencv/features2d/KeyPoint.html)。可以看到KeyPoint这数据结构中有如下数据结构:

angle:角度,表示关键点的方向,通过Lowe大神的论文可以知道,为了保证方向不变形,SIFT算法通过对关键点周围邻域进行梯度运算,求得该点方向。-1为初值。

class_id:当要对图片进行分类时,我们可以用class_id对每个特征点进行区分,未设定时为-1,需要靠自己设定

octave:代表是从金字塔哪一层提取的得到的数据。

pt:关键点点的坐标

response:响应程度,代表该点强壮大小,一开始我也理解不了,看到两位stackoverflow大大的原话(http://stackoverflow.com/questions/10328298/what-does-size-and-response-exactly-represent-in-a-surf-keypointhttp://stackoverflow.com/questions/24699495/opencv-keypoints-response-greater-or-less?lq=1)——response代表着该关键点how good,更确切的说,是该点角点的程度。瞬间明白。

size:该点直径的大小

注意一个问题:keypoint只是保存了opencv的sift库检测到的特征点的一些基本信息,也就上面所说的这些,但sift所提取出来的特征向量其实不是在这个里面,特征向量通过SiftDescriptorExtractor 提取,结果放在一个Mat的数据结构中。这个数据结构才真正保存了该特征点所对应的特征向量。具体见后文对SiftDescriptorExtractor 所生成的对象的详解。


opencv中SiftDescriptorExtractor所做的SIFT特征向量提取工作简单分析

SiftDescriptorExtractor对应于SIFT算法中特征向量提取的工作,通过他对关键点周围邻域内的像素分块进行梯度运算,得到128维的特征向量。具体有如下几个操作:

0、首先,我们假设在之前关键点提取的步骤中,我们对一个三角形提取关键点,检测到其中一个关键点的坐标为三角形的一个角(如下面用红圈圈出的),如下图

image_thumb12

放大看,假设检测到该关键点的方向如下图:

image_thumb4

1、将关键点周围的像素旋转到一个统一的方向,以保证方向不变性。如下图

image_thumb11

2、将这些像素分成4X4的小块

image_thumb9

对每个格子进行分析,将格子中的像素计算梯度,映射到8个方向上,对于每一个格子,可以得到一个8维的向量,对于一个关键点周围16个格子,则得到了16X8=128维的向量,这就是一个关键点特征向量。

image_thumb10

使用举一个实际的例子分析:

用opencv对一个三角形进行特征点检测,得到如下结果:

image_thumb18

提取特征向量,得到如下结果:

image_thumb19

这幅图的每一行就是一个128维的特征向量,维度用0-255表示。黑一些就是小,白就是大。

粗略可以看出,这些特征点排布较为相似,因为都是角

再来一个:

image_thumb20

image_thumb23

引自:http://www.cnblogs.com/cj695/p/4041478.html



附:使用OPENCV下SIFT库做图像匹配的例程

// FeatureDetector.cpp : Defines the entry point for the console application.

#include<opencv2/nonfree/features2d.hpp> //使用SiftFeatureDetector需要加上此头文件
#include<opencv2\opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;



int main(int argc, char* argv[])
{
	//Load Image 
	Mat c_src1 = imread("image1.jpg");
	Mat c_src2 = imread("image2.jpg");
	Mat src1 = imread("image1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	Mat src2 = imread("image2.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	if (!src1.data || !src2.data)
	{
		std::cout << " --(!) Error reading images " << std::endl; return -1;
	}

	//sift feature detect
	SiftFeatureDetector detector;
	vector<KeyPoint> kp1, kp2;

	detector.detect(src1, kp1);
	detector.detect(src2, kp2);
	SiftDescriptorExtractor extractor;
	Mat des1, des2;//descriptor
	extractor.compute(src1, kp1, des1);
	extractor.compute(src2, kp2, des2);
	Mat res1, res2;
	int drawmode = DrawMatchesFlags::DRAW_RICH_KEYPOINTS;
	drawKeypoints(c_src1, kp1, res1, Scalar::all(-1), drawmode);//在内存中画出特征点
	drawKeypoints(c_src2, kp2, res2, Scalar::all(-1), drawmode);
	cout << "size of description of Img1: " << kp1.size() << endl;
	cout << "size of description of Img2: " << kp2.size() << endl;

	BFMatcher matcher(NORM_L2);
	vector<DMatch> matches;
	matcher.match(des1, des2, matches);
	Mat img_match;
	drawMatches(src1, kp1, src2, kp2, matches, img_match);//,Scalar::all(-1),Scalar::all(-1),vector<char>(),drawmode);
	cout << "number of matched points: " << matches.size() << endl;
	imshow("matches", img_match);
	cvWaitKey();
	cvDestroyAllWindows();

	return 0;
}




  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值