1 | #include "Registration/SurfRegistration/SurfRegistration.h"
|
2 |
|
3 | #include <cv.h>
|
4 | #include <cxcore.h>
|
5 | #include <highgui.h>
|
6 |
|
7 | using namespace cv;
|
8 |
|
9 | #define BROKEN 1
|
10 |
|
11 |
|
12 |
|
13 | const int HAAR_SIZE0 = 9;
|
14 |
|
15 | |
16 | such that the wavelet sizes in an octave are either all even or all odd.
|
17 | This ensures that when looking for the neighbours of a sample, the layers
|
18 | above and below are aligned correctly. */
|
19 | const int HAAR_SIZE_INC = 6;
|
20 |
|
21 | static int getPointOctave(const CvSURFPoint& kpt, const CvSURFParams& params)
|
22 | {
|
23 | int octave = 0, layer = 0, best_octave = 0;
|
24 | float min_diff = FLT_MAX;
|
25 | for( octave = 1; octave < params.nOctaves; octave++ )
|
26 | for( layer = 0; layer < params.nOctaveLayers; layer++ )
|
27 | {
|
28 | float diff = std::abs(kpt.size - (float)((HAAR_SIZE0 + HAAR_SIZE_INC*layer) << octave));
|
29 | if( min_diff > diff )
|
30 | {
|
31 | min_diff = diff;
|
32 | best_octave = octave;
|
33 | if( min_diff == 0 )
|
34 | return best_octave;
|
35 | }
|
36 | }
|
37 | return best_octave;
|
38 | }
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | SurfRegistration::SurfRegistration() {
|
44 | surf_class=cv::SURF(0.1);
|
45 | };
|
46 |
|
47 | SurfRegistration::~SurfRegistration() {};
|
48 |
|
49 | bool SurfRegistration::GetHomography(IplImage *img1_gray, IplImage *img2_gray,
|
50 | CvMat *homography)
|
51 | {
|
52 | assert(homography->cols==3 && homography->rows==3);
|
53 |
|
54 | Mat going_out;
|
55 | Mat no_info;
|
56 | vector<KeyPoint> img1_points, img2_points;
|
57 | vector<float> img1_descriptors, img2_descriptors;
|
58 | Seq<CvSURFPoint> img1_points_seq, img2_points_seq;
|
59 | CvSeq* img1_descriptors_seq = 0;
|
60 | CvSeq* img2_descriptors_seq = 0;
|
61 | CvSURFParams params = cvSURFParams(500,0);
|
62 | CvMemStorage* storage = cvCreateMemStorage(0);
|
63 |
|
64 | Mat match_indices, match_distances;
|
65 | vector<Point2f> img1_inliers, img2_inliers;
|
66 |
|
67 | cv::flann::AutotunedIndexParams my_params;
|
68 | my_params.build_weight=1;
|
69 | my_params.memory_weight=.1;
|
70 | my_params.sample_fraction=.5;
|
71 | my_params.target_precision=0.9;
|
72 |
|
73 | Mat tmp5=Mat(img1_gray);
|
74 | #ifdef BROKEN
|
75 | surf_class(tmp5,no_info,img1_points,img1_descriptors);
|
76 | assert( _CrtCheckMemory() );
|
77 | return true;
|
78 | #endif
|
79 |
|
80 | cvExtractSURF (img1_gray,0,&img1_points_seq.seq,&img1_descriptors_seq,storage,params);
|
81 | cvExtractSURF (img2_gray,0,&img2_points_seq.seq,&img2_descriptors_seq,storage,params);
|
82 |
|
83 |
|
84 | img1_descriptors.resize(img1_descriptors_seq ? img1_descriptors_seq->total*img1_descriptors_seq->elem_size/sizeof(float) : 0);
|
85 | if(img1_descriptors.size() != 0)
|
86 | cvCvtSeqToArray(img1_descriptors_seq, &img1_descriptors[0]);
|
87 | img2_descriptors.resize(img2_descriptors_seq ? img2_descriptors_seq->total*img2_descriptors_seq->elem_size/sizeof(float) : 0);
|
88 | if(img2_descriptors.size() != 0)
|
89 | cvCvtSeqToArray(img2_descriptors_seq, &img2_descriptors[0]);
|
90 |
|
91 | {
|
92 | Seq<CvSURFPoint>::iterator it = img1_points_seq.begin();
|
93 | size_t i, n = img1_points_seq.size();
|
94 | img1_points.resize(n);
|
95 | for( i = 0; i < n; i++, ++it )
|
96 | {
|
97 | const CvSURFPoint& kpt = *it;
|
98 | img1_points[i] = KeyPoint(kpt.pt, (float)kpt.size, kpt.dir,
|
99 | kpt.hessian, getPointOctave(kpt, params));
|
100 | }
|
101 | }
|
102 | {
|
103 | Seq<CvSURFPoint>::iterator it = img2_points_seq.begin();
|
104 | size_t i, n = img2_points_seq.size();
|
105 | img2_points.resize(n);
|
106 | for( i = 0; i < n; i++, ++it )
|
107 | {
|
108 | const CvSURFPoint& kpt = *it;
|
109 | img2_points[i] = KeyPoint(kpt.pt, (float)kpt.size, kpt.dir,
|
110 | kpt.hessian, getPointOctave(kpt, params));
|
111 | }
|
112 | }
|
113 |
|
114 |
|
115 |
|
116 | Mat tmp=Mat(img1_descriptors).reshape(1,img1_descriptors.size()/surf_class.descriptorSize());
|
117 |
|
118 | cv::flann::Index flann_class(tmp,
|
119 |
|
120 | my_params);
|
121 |
|
122 | match_indices.create(img2_points.size(),2,CV_32S);
|
123 | match_distances.create(img2_points.size(),2,CV_32F);
|
124 | Mat tmp2=Mat(img2_descriptors).reshape(1,img2_descriptors.size()/surf_class.descriptorSize());
|
125 | flann_class.knnSearch(tmp2,match_indices,match_distances,2,
|
126 | cv::flann::SearchParams());
|
127 | for (int i=0;i<img2_points.size();i++) {
|
128 | float dist1=match_distances.at<float>(i,0);
|
129 | if (dist1<0.6*match_distances.at<float>(i,1)) {
|
130 | img1_inliers.push_back(img1_points.at(match_indices.at<int>(i,0)).pt);
|
131 | img2_inliers.push_back(img2_points.at(i).pt);
|
132 | }
|
133 | }
|
134 | if (img1_inliers.size()<4) {
|
135 | printf ("The number of inliers was only %d\n",img1_inliers.size());
|
136 | return false;
|
137 | }
|
138 |
|
139 |
|
140 | going_out=findHomography(Mat(img1_inliers),Mat(img2_inliers),(int)cv::RANSAC,DISTANCE_THRESHOLD);
|
141 | for (int i=0;i<3;i++)
|
142 | memcpy(homography->data.ptr+homography->step*i,going_out.ptr(i),sizeof(float)*3);
|
143 | return true;
|
144 |
|
145 | }
|
146 |
|