利用opencv实现sift matching

实际上在opencv的example里有一个matcher_simple.cpp的文件就实现了SURF的匹配。在做sift matching的时候只要把surf改成sift就可以了。接下来还是先上源码

#include 
#include 
#include 
#include 
#include 

using namespace cv;
int main(int argc, char ** argv){
	Mat img1 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
	Mat img2 = imread(argv[2], CV_LOAD_IMAGE_GRAYSCALE);
	Mat img1_mask = imread(argv[3], CV_LOAD_IMAGE_GRAYSCALE);
	SiftFeatureDetector detector;
	vector keypoints1, keypoints2;

	detector.detect(img1, keypoints1, img1_mask);
	detector.detect(img2, keypoints2);
	
	
	SiftDescriptorExtractor extractor;
	Mat descriptors1, descriptors2;
	extractor.compute(img1, keypoints1, descriptors1);
	extractor.compute(img2, keypoints2, descriptors2);

	BFMatcher matcher(NORM_L2);
	vector matches;
	matcher.match(descriptors1, descriptors2, matches);
	namedWindow("matches", 1);
	Mat img_matches;
	drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
	imshow("matches", img_matches);
	waitKey(0);
	return 0;
}

在这里的SiftFeatureDetector和SiftDescriptorExtractor如果我们去看源码的话会发觉都是typedef SIFT。而detect和compute两个方法一个是用来检测key point,另一个是用来计算找到的keypoint的descriptors。这里不再多说。

对于BFMatcher,这里用的是L2 norm,当然这个是看个人的需求的。这里需要多说的一点就是,假设我不想要在图上画,而是要将对应的点保存起来,比如说保存成txt模式要怎么办?这里的每个DMatch都代表了一对对应点的match信息,而DMatch类里的queryIdx和trainIdx分别代表了第一个点集和第二个点集中对应的下标。也就是说keypoints1下标为queryIdx的点和keypoints下标为trainIdx的点是对应的。所以如果要保存对应信息可以在之前的代码最后就加入以下代码段:

FILE *fp = fopen("matches.txt", "w");
vector::iterator itr;
for (itr = matches.begin(); itr!= matches.end(); itr++)
{
	Point p1 = keypoints1[(*itr).queryIdx].pt;
	Point p2 = keypoints2[(*itr).trainIdx].pt;
	fprintf(fp, "x1=%d y1=%d x2=%d y2=%d distance=%f\n", p1.x, p1.y, p2.x, p2.y, (*itr).distance);
}
fclose(fp);


你可能感兴趣的:(OpenCV)