使用SIFT描述子计算模板旋转角度

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26671711/article/details/62891143

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

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

using namespace cv;
using namespace std;



int main(int argc, char* argv[])
{
	//ofstream fileo("data.txt");


	//Load Image 
	Mat c_src1 = imread("E:\\P\\case2\\CV_RoiImage.bmp");
	Mat c_src2 = imread("E:\\P\\case2\\cv_temp.bmp");
	Mat src1 = imread("E:\\P\\case2\\cv_temp.bmp", CV_LOAD_IMAGE_GRAYSCALE);
	Mat src2 = imread("E:\\P\\case2\\CV_RoiImage.bmp", 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 << kp1.at(matches.at(1).queryIdx).angle << endl;
	//cout<<kp2.at(matches.at(1).trainIdx).angle << endl;


	//投票表决,获得近似的角度
	int angle_count[361] = {0};
	int count = 0;
	for (int i = 0; i < matches.size(); i++)
	{
		int index = kp2.at(matches.at(i).trainIdx).angle - kp1.at(matches.at(i).queryIdx).angle+0.5;

		//fileo << kp2.at(matches.at(i).trainIdx).angle - kp1.at(matches.at(i).queryIdx).angle << endl;

		index=index > 0 ? index : index + 360;

		//cout << index << endl;
		angle_count[index]++;
	}
	int maxindex = 0;
	for (int i = 0; i < 361; i++)
	{
		//cout << i << " " << angle_count[i]<<endl;
		if (angle_count[i] >= angle_count[maxindex])
		{
			maxindex = i;
		}
	}
	maxindex = (maxindex - 360) < 0 ? maxindex : (maxindex - 360);
	cout << "旋转角度:" << maxindex << endl;

	//对临界值的处理,存在一些问题
	int down, up;
	down = maxindex - 1 < 0 ? maxindex : maxindex - 1;
	up = maxindex + 1 > 360 ? maxindex : maxindex + 1;
	double angle = 0;
	count = 0;
	for (int i = 0; i < matches.size(); i++)
	{
		double temp = kp2.at(matches.at(i).trainIdx).angle - kp1.at(matches.at(i).queryIdx).angle;
		if (temp >= down&&temp <= up)
		{
			count++;
			angle += temp;
		}
	}
	angle /= count;
	cout << "精确角度:" << angle << endl;

	cout << "number of matched points: " << matches.size() << endl;
	imshow("matches", img_match);
	cvWaitKey();
	cvDestroyAllWindows();

	return 0;
}

SIFT描述子具有旋转不变性,在这个方法中,给出了使用SIFT描述子进行匹配并进行投票计算旋转角度的方法。

(目标区域)

  模板,没有找到很好的例子,就直接拍了键盘,模板是原图顺时针旋转30°得到的。

结果如下:

可以看到,角度还是算的蛮准的,缺点就是速度比较慢。不过,目前使用的是投票然后求平均值,平均值在很多时候并不能有效,可以换用中位数。

猜你喜欢

转载自blog.csdn.net/qq_26671711/article/details/62891143