java opencv如何确定sift匹配结果?

这几天继续看Lowe的SIFT大作,头晕,抽筋。也喝醉了!!!!我受不了了。来点干货。我们知道opencv有自己的SIFT特征检测和MATCH匹配库,完全可以让我们做傻事。但实际使用起来就没那么简单了。下面将分析一个基于OPENCV的SIFT特征点提取和匹配的典型例程,并详细介绍SIFT算法在OPENCV中的使用。

OPENCV下SIFT特征点提取和匹配的一般过程如下:

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

其中,提取特征点主要有两个步骤,参见上升黄色子部分。我们来具体分析一下。

1.用opencv内置库读两张图。

2.生成一个SiftFeatureDetector的对象,顾名思义就是SIFT特征的检测器,用它来检测衣服图片中SIFT点的特征,并存储在一个KeyPoint类型的向量中。这里有必要说一下keypoint的数据结构,涉及的内容很多。详细分析请查看opencv中keypoint的数据结构分析,你在里面说的还挺详细的(table beats me...).简而言之,最重要的一点是:

关键点只保留了opencv的sift库检测到的特征点的一些基本信息,而sift提取的特征向量不在其中。SiftDescriptorExtractor提取特征向量,并将结果存放在Mat数据结构中。这个数据结构真正保留了这个特征点对应的特征向量。详见后面SiftDescriptorExtractor生成对象的详细说明。

就因为不懂这个,耽误了一上午。哭死!

3、提取图像所有关键点特征向量:

关键点只有关键点的位置和方向,没有特征点的特征向量。如果要提取特征向量,需要做SiftDescriptorExtractor的工作。建立SiftDescriptorExtractor对象后,可以遍历之前SIFT生成的特征点,找到特征点对应的128维特征向量。具体方法可以参考opencv中SIFTDescriptor做的SIFT特征向量提取的简单分析。在这个步骤之后,所有关键点的特征向量作为特征被保存在MAT数据结构中。

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

在提取了两幅图片的特征向量后,我们可以使用BruteForceMatcher对象来匹配两幅图片的描述符,并将匹配结果得到匹配。具体匹配方式暂时没有仔细研究,后面会补充。

至此,sift已经完成了从特征点的检测到最终的匹配。虽然对匹配部分不是很了解,但对如何使用OPENCV提取SIFT特征只有一定的了解。接下来,我们可以开始下一步了。

附:OPENCV下使用SIFT库进行图像匹配的例程。

1

2

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

四十二个

43

四十四

45

46

47

48

四十九个

50

51

五十二个

53

54

55

五十六岁

57

58

59

60

61

62

63

64

65

66

67

六十八

六十九

70

71

七十二个

73

74

75

76

77

七十八

// opencv_empty_proj.cpp:定义控制台应用程序的入口点。

//

#包含" stdafx.h "

# include opencv.hpp & gt

# include features 2d/features 2d . HPP & gt;

# include non free/non free . HPP & gt;

# include elegacy/legacy . HPP & gt;

#包括

使用命名空间std

使用名称空间cv;

int _tmain(int argc,_TCHAR* argv[])

{

const char * imagename = " img.jpg

//从文件中读取图像

mat img = im read(imagename);

mat img 2 = im read(" img 2 . jpg ");

//如果读取图像失败,

if(img.empty())

{

fprintf(stderr,"无法加载图像%s\n ",imagename);

return-1;

}

if(img2.empty())

{

fprintf(stderr,"无法加载图像%s\n ",imagename);

return-1;

}

//显示图像

imshow(“前像”,img);

imshow("image2 before ",img 2);

//sift特征检测

SiftFeatureDetector

vectorkp1,kp2

siftdtc.detect(img,KP 1);

mat outimg 1;

drawKeypoints(img,kp1,outimg 1);

imshow("image1 keypoints ",outimg 1);

关键点KP;

vector::迭代器itvc

for(itvc = KP 1 . begin();itvc!= KP 1 . end();itvc++)

{

cout & lt& lt"角度:" & lt角度& lt& lt" \ t " & ltclass _ id & lt& lt" \ t " & ltoctave & lt& lt" \ t " & ltpt & lt& lt" \ t " & lt响应& lt& ltendl

}

siftdtc.detect(img2,kp2);

Mat outimg2

绘制关键点(img2、kp2、outi mg 2);

imshow("图像2关键点",outi mg 2);

提取器;

Mat descriptor1,descriptor2

BruteForceMatcher & ltL2 & gt;matcher

向量匹配;

Mat img _ matches

extractor.compute(img,kp1,descriptor 1);

extractor.compute(img2,kp2,descriptor 2);

imshow("desc ",descriptor 1);

cout & lt& ltendl & lt& ltdescriptor 1 & lt;& ltendl

matcher.match(描述符1,描述符2,matches);

drawMatches(img,kp1,img2,kp2,Matches,img _ matches);

imshow("matches ",img _ matches);

//这个函数等待键,然后按键盘上的任意键返回。

wait key();

返回0;

}