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

来源:互联网 发布:c语言open函数 编辑:程序博客网 时间:2024/05/22 13:44

// 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 detectSiftFeatureDetector detector;vector<KeyPoint> kp1, kp2;detector.detect(src1, kp1);detector.detect(src2, kp2);SiftDescriptorExtractor extractor;Mat des1, des2;//descriptorextractor.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°得到的。

结果如下:

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

0 0