source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/SURF-V1.0.8/OcluMatchRConS_thre.cpp_tmp @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

File size: 16.1 KB
Line 
1/*
2 * Speeded-Up Robust Features (SURF)
3 * http://people.ee.ethz.ch/~surf
4 *
5 * Sample application for feature matching using nearest-neighbor
6 * ratio method.
7 *
8 * BUILD USING "make match.ln".
9 *
10 * Author: Andreas Ess
11 *
12 * Copyright (2006): ETH Zurich, Switzerland
13 * Katholieke Universiteit Leuven, Belgium
14 * All rights reserved.
15 *
16 * For details, see the paper:
17 * Herbert Bay,  Tinne Tuytelaars,  Luc Van Gool,
18 *  "SURF: Speeded Up Robust Features"
19 * Proceedings of the ninth European Conference on Computer Vision, May 2006
20 *
21 * Permission to use, copy, modify, and distribute this software and
22 * its documentation for educational, research, and non-commercial
23 * purposes, without fee and without a signed licensing agreement, is
24 * hereby granted, provided that the above copyright notice and this
25 * paragraph appear in all copies modifications, and distributions.
26 *
27 * Any commercial use or any redistribution of this software
28 * requires a license from one of the above mentioned establishments.
29 *
30 * For further details, contact Andreas Ess (aess@vision.ee.ethz.ch).
31 */
32
33/**
34   modified by Jeff Michels to add the requirement that matches
35   are only output if the point in im2 is the best match for the
36   point in im1 AND vice versa.
37**/
38
39#include <vector>
40#include <string>
41#include <cstdlib>
42#include <iostream>
43#include <fstream>
44#include <cmath>
45
46#include "ipoint.h"
47
48
49#include "image.h"
50#include "imload.h"
51
52
53using namespace std;
54using namespace surf;
55
56// Length of descriptor vector, ugly, global variable
57unsigned int vlen;
58
59// Calculate square distance of two vectors
60inline double distSquare(double *v1, double *v2, int n) {
61        double dsq = 0.;
62        while (n--) {
63                dsq += (*v1 - *v2) * (*v1 - *v2);
64                v1++;
65                v2++;
66        }
67        return dsq;
68}
69
70// Calculate square distance of two vectors
71inline double distSquare(double *v1, double *v2, int n, double *limit) {
72        double dsq = 0.;
73        while (n-- && dsq <= *limit) {
74                dsq += (*v1 - *v2) * (*v1 - *v2);
75                v1++;
76                v2++;
77        }
78        return dsq;
79}
80
81
82// Find closest interest point in a list, given one interest point
83int findMatch(const Ipoint& ip1, const vector< Ipoint >& ipts) {
84        double mind = 1e100, second = 1e100; //Magic number Min??
85        int match = -1;
86
87        for (unsigned i = 0; i < ipts.size(); i++) {
88                // Take advantage of Laplacian to speed up matching
89                if (ipts[i].laplace != ip1.laplace)
90                        continue;
91
92                double d = distSquare(ipts[i].ivec, ip1.ivec, vlen);
93
94                if (d < mind) {
95                        second = mind;
96                        mind = d;
97                        match = i;
98                } else if (d < second) {
99                        second = d;
100                }
101        }
102
103        if (mind < 0.7 * second) //0.8 //Magic number Min??
104            //Answer: in SIFT paper 0.8 is used for discarding 90% of false match but discard only 5% of correct matches
105                return match;
106
107        return -1;
108}
109
110void printAllDistances(const vector< Ipoint >& ipts1, const vector< Ipoint >& ipts2) {
111  for (unsigned int i = 0; i < ipts1.size(); i++) {
112    for (unsigned int j = 0; j < ipts2.size(); j++) {
113      double dist = distSquare(ipts1[i].ivec, ipts2[j].ivec, vlen);
114      cout << i << " " << j << " " << dist << endl;
115    }
116  }
117}
118
119//Min add RoughConstrainCheck to check if the Constrain been meet
120inline bool RoughConstrainCheck(const Ipoint& ipts1, const Ipoint& ipts2, const Ipoint& ConS1, const Ipoint& ConS2){
121
122//      bool Sat = false;
123        // check if ipts2 satisfy constrain1 or ipts1 satisfy constrain2
124
125/*      if (ipts2.x <= ConS1.ivec[1] && ipts2.x >= ConS1.ivec[0] && ipts2.y >= ConS1.ivec[2] && ipts2.y <= ConS1.ivec[3])
126                                        return true;
127
128        if (ipts1.x <= ConS2.ivec[1] && ipts1.x >= ConS2.ivec[0] && ipts1.y >= ConS2.ivec[2] && ipts1.y <= ConS2.ivec[3])
129                        return true;
130*/
131       
132        return  (ipts2.x <= ConS1.ivec[1] && ipts2.x >= ConS1.ivec[0] && ipts2.y >= ConS1.ivec[2] && ipts2.y <= ConS1.ivec[3]) ||
133                (ipts1.x <= ConS2.ivec[1] && ipts1.x >= ConS2.ivec[0] && ipts1.y >= ConS2.ivec[2] && ipts1.y <= ConS2.ivec[3]);
134}
135
136//Min add ConstrainCheck to check if the Constrain been meet
137inline bool ConstrainCheck(const Ipoint& ipts1, const Ipoint& ipts2, const Ipoint& ConS1, const Ipoint& ConS2){
138
139//      bool Sat = false;
140        // check if ipts2 satisfy constrain1 or ipts1 satisfy constrain2
141
142        float y2 = (ipts2.x - ConS1.ivec[4])*ConS1.ivec[2] + (ipts2.y - ConS1.ivec[5])*ConS1.ivec[3];
143        if (y2 <= ConS1.ivec[7] && y2 >= -ConS1.ivec[7] ){
144                float x2 = (ipts2.x - ConS1.ivec[4])*ConS1.ivec[0] + (ipts2.y - ConS1.ivec[5])*ConS1.ivec[1];
145                if (x2 >= 0 && x2 <= ConS1.ivec[6]){
146                                        return true;
147                }
148        }
149
150        float y1 = (ipts1.x - ConS2.ivec[4])*ConS2.ivec[2] + (ipts1.y - ConS2.ivec[5])*ConS2.ivec[3];
151        if (y1 <= ConS2.ivec[7] && y1 >= -ConS2.ivec[7]){
152                float x1 = (ipts1.x - ConS2.ivec[4])*ConS2.ivec[0] + (ipts1.y - ConS2.ivec[5])*ConS2.ivec[1];
153                if (x1 >= 0 && x1 <= ConS2.ivec[6]){
154                        return true;
155                }
156        }
157       
158        return false;       
159}
160
161// essentially the same as findMatches except that it deletes matches that
162// aren't symetric.
163// Really time-consuming function
164vector <int> symMatches(const vector< Ipoint >& ipts1, const vector< Ipoint >& ipts2, const vector< Ipoint >& ConS1, const vector< Ipoint >& ConS2, const vector< Ipoint >& ConSRough1, const vector< Ipoint >& ConSRough2, const double abs_thre, const double ratio_thre) {
165  vector< int > bestIndex1(ipts1.size());
166  vector< int > bestIndex2(ipts2.size());
167  vector< double > bestScore1(ipts1.size());
168  vector< double > bestScore2(ipts2.size());
169  vector< double > secondScore1(ipts1.size());
170  vector< double > secondScore2(ipts2.size());
171
172  // Initialize all of the vectors
173  for (unsigned int i = 0; i < ipts1.size(); i++) {
174    bestIndex1[i] = -1;
175    bestScore1[i]= 1e100;
176    secondScore1[i] = 1e100;
177  }
178  for (unsigned int j = 0; j < ipts2.size(); j++) {
179    bestIndex2[j] = -1;
180    bestScore2[j]= 1e100;
181    secondScore2[j] = 1e100;
182  }
183
184  // Main loop - per point in im1 do a linear scan of points in im2
185  int total = 0;
186  double limit = 1e100;
187  for (unsigned int i = 0; i < ipts1.size(); i++) {
188    for (unsigned int j = 0; j < ipts2.size(); j++) {
189       if (ipts1[i].laplace != ipts2[j].laplace)
190                        continue;
191        // do a super-fast rough check
192        if ( !RoughConstrainCheck(ipts1[i], ipts2[j], ConSRough1[i], ConSRough2[j]))
193                        continue;
194        //Min add ConstrainCheck();
195        //if ( !ConstrainCheck(ipts1[i], ipts2[j], ConS1[i], ConS2[j]))
196        //                continue;
197
198        //record best and second best scores and best index for each
199      //point in each image
200//      double dist = distSquare(ipts1[i].ivec, ipts2[j].ivec, vlen);
201      limit = (secondScore1[i] > secondScore2[j]) ? secondScore1[i] : secondScore2[j];
202      double dist = distSquare(ipts1[i].ivec, ipts2[j].ivec, vlen, &limit);
203      if (dist < bestScore1[i]) {
204        bestIndex1[i] = j;
205        secondScore1[i] = bestScore1[i];
206        bestScore1[i] = dist;
207      } else if (dist < secondScore1[i]) {
208        secondScore1[i] = dist;
209      }
210      if (dist < bestScore2[j]) {
211        bestIndex2[j] = i;
212        secondScore2[j] = bestScore2[j];
213        bestScore2[j] = dist;
214      } else if (dist < secondScore2[j]) {
215        secondScore2[j] = dist;
216      }
217    }
218  }
219  //cout << "Matched " << total << " points." << endl;
220  //return bestIndex1; //for threshold
221
222  /*******************************
223     //killed same img matches - should be covered by match symetry anyway
224 
225  //update second scores with best match from same image (for image 1)
226  for (int i = 0; i < ipts1.size(); i++) {
227    for (int j = i+1; j < ipts1.size(); j++) {
228      double dist = distSquare(ipts1[i].ivec, ipts1[j].ivec, vlen);
229      if (dist < secondScore1[i]){// && dist < 0.3) {
230        //cout << "im1 point " << i << " best: " << bestScore1[i] << " second: " << secondScore1[i] <<
231        //  "im1 point " << j << ": " << dist << endl;
232        secondScore1[i] = dist;
233      }
234    }
235  }
236
237  //update second scores with best match from same image (for image 2)
238  for (int i = 0; i < ipts2.size(); i++) {
239    for (int j = i+1; j < ipts2.size(); j++) {
240      double dist = distSquare(ipts2[i].ivec, ipts2[j].ivec, vlen);
241      if (dist < secondScore2[j]){// && dist < 0.3){
242        //cout << "im2 point " << i << " best: " << bestScore2[i] << " second: " << secondScore2[i] <<
243        //  "im2 point " << j << ": " << dist << endl;
244        secondScore2[i] = dist;
245      }
246    }
247  }
248  ******************************/
249
250  //if the best score is no longer the best or isn't good enough relative
251  // to the second, kill the index
252
253  //image 1 //Min change 0.85 to 0.7
254  for (unsigned int i = 0; i < ipts1.size(); i++) {
255    if (secondScore1[i] * ratio_thre < bestScore1[i] || bestScore1[i] > abs_thre) {
256      bestIndex1[i] = -1;
257    }
258  }
259
260  //image 2 //Min change 0.85 to 0.7
261  for (unsigned int i = 0; i < ipts2.size(); i++) {
262    if (secondScore2[i] * ratio_thre < bestScore2[i] || bestScore2[i] > abs_thre) {
263      bestIndex2[i] = -1;
264    }
265  }
266
267  //if the best matches are mutual, kill the redundent match in bestIndex2
268  for (unsigned int i = 0; i < ipts1.size(); i++) {
269    int index = bestIndex1[i];
270    if (index != -1) {
271      if (bestIndex2[index] != i && bestIndex2[index] != -1) {
272        //cout << "Non symetric match.  im1(" << i << ")->" << index << " but im2(" << index <<
273        //  ")->" << bestIndex2[index] << endl;
274        bestIndex1[i] = -1;
275        bestIndex2[index] = -1;
276      } else if(bestIndex2[index] == i ){
277        bestIndex2[index] = -1;
278        cout << " Matched feature " << i << " in image 1 with feature "
279             << index << " in image 2." << endl;
280        total++;
281      } else{
282        cout << " Matched feature " << i << " in image 1 with feature "
283             << index << " in image 2." << endl;
284        total++;
285      }
286    }
287  }
288
289  for (unsigned int i = 0; i < ipts2.size(); i++) {
290    int index = bestIndex2[i];
291    if (index != -1) {
292        bestIndex1[index] = i;
293        cout << " Matched feature " << index << " in image 1 with feature "
294             << i << " in image 2." << endl;
295        total++;
296    }
297  }
298
299//  cout << "Matched " << total << " points." << endl;
300  return bestIndex1;
301}
302
303// Find all possible matches between two images
304// need to change to reduce the search space by knowing GPS information Min
305vector< int > findMatches(const vector< Ipoint >& ipts1, const vector< Ipoint >& ipts2) {
306        vector< int > matches(ipts1.size());
307        int c = 0;
308        for (unsigned i = 0; i < ipts1.size(); i++) {
309                int match = findMatch(ipts1[i], ipts2);
310                matches[i] = match;
311                if (match != -1) {
312                        cout << " Matched feature " << i << " in image 1 with feature "
313                                << match << " in image 2." << endl;
314                        c++;
315                }
316        }
317        cout << " --> Matched " << c << " features of " << ipts1.size() << " in image 1." << endl;
318        return matches;
319}
320
321// Load the interest points from a regular ASCII file
322void loadIpoints(string sFileName, vector< Ipoint >& ipts) {
323        ifstream ipfile(sFileName.c_str());
324        if( !ipfile ) {
325                cerr << "ERROR in loadIpoints(): "
326                        << "Couldn't open file '" << sFileName.c_str() << "'!" << endl;
327                return;
328        }
329
330        // Load the file header
331        unsigned count;
332        ipfile >> vlen >> count;
333
334        // create a new interest point vector
335        ipts.clear();
336        ipts.resize(count);
337        //cout << "The number of features" << count << endl;
338
339        // Load the interest points in Mikolajczyk's format
340        for (unsigned n = 0; n < count; n++) {
341                // circular regions with diameter 5 x scale
342                float x, y, a, b, c;
343
344                // Read in region data, though not needed for actual matching
345                ipfile >> x >> y >> a >> b >> c;
346
347                float det = sqrt((a-c)*(a-c) + 4.0*b*b);
348                float e1 = 0.5*(a+c + det);
349                float e2 = 0.5*(a+c - det);
350                float l1 = (1.0/sqrt(e1));
351                float l2 = (1.0/sqrt(e2));
352                float sc = sqrt( l1*l2 );
353
354                ipts[n].x = x;
355                ipts[n].y = y;
356                ipts[n].scale = sc/2.5;
357
358                // Read in Laplacian
359                ipfile >> ipts[n].laplace;
360
361                // SURF makes Laplacian part of descriptor, so skip it..
362                ipts[n].ivec = new double[vlen - 1];
363                for (unsigned j = 0; j < vlen - 1; j++)
364                        ipfile >> ipts[n].ivec[j];
365        }
366}
367
368void drawLine(Image *im, int x1, int y1, int x2, int y2) {
369        if ((x1 < 0 && x2 < 0) || (y1 < 0 && y2 < 0) ||
370            (x1 >= im->getWidth() && x2 >= im->getWidth()) ||
371            (y1 >= im->getHeight() && y2 >= im->getHeight()))
372                return;
373
374        bool steep = std::abs(y2 - y1) > std::abs(x2 - x1);
375        if (steep) {
376                int t;
377                t = x1;
378                x1 = y1;
379                y1 = t;
380                t = y2;
381                y2 = x2;
382                x2 = t;
383        }
384
385        if (x1 > x2) {
386                // Swap points
387                int t;
388                t = x1;
389                x1 = x2;
390                x2 = t;
391                t = y1;
392                y1 = y2;
393                y2 = t;
394        }
395
396        int deltax = x2 - x1;
397        int deltay = std::abs(y2 - y1);
398
399        int error = 0;
400        int y = y1;
401        int ystep = y1 < y2 ? 1 : -1;
402
403        for (int x = x1; x < x2; x++) {
404                if (steep) {
405                        if (x >= 0 && y >= 0 && y < im->getWidth() && x < im->getHeight())
406                                im->setPix(y, x, 1);
407                } else {
408                        if (x >= 0 && y >= 0 && x < im->getWidth() && y < im->getHeight())
409                                im->setPix(x, y, 1);
410
411                }
412                error += deltay;
413
414                if (2 * error > deltax) {
415                        y += ystep;
416                        error -= deltax;
417                }
418        }
419}
420
421void drawCross(Image *im, int x, int y, int s = 5) {
422        for (int x1 = x - s; x1 <= x + s; x1++)
423                im->setPix(x1, y, 1);
424        for (int y1 = y - s; y1 <= y + s; y1++)
425                im->setPix(x, y1, 1);
426}
427
428int main(int argc, char **argv) {
429        Image *im1, *im2;
430
431        ImLoad ImageLoader;
432        vector< Ipoint > ipts1, ipts2, ConS1, ConS2, ConSRough1, ConSRough2; //Min
433        bool drawc = false;
434        bool usesym = false;
435        bool printAllDist = false;
436        double abs_thre = 0.3;
437        double ratio_thre = 0.7;
438       
439        char ofname[100];
440
441        im1 = im2 = NULL;
442        ofname[0] = 0;
443
444        // Read the arguments
445        int arg = 0;
446        while (++arg < argc) {
447                if (! strcmp(argv[arg], "-k1"))
448                        loadIpoints(argv[++arg], ipts1);
449                if (! strcmp(argv[arg], "-k2"))
450                        loadIpoints(argv[++arg], ipts2);
451                //Min -------------------------------------
452                if (! strcmp(argv[arg], "-S1"))
453                        loadIpoints(argv[++arg], ConS1);
454                if (! strcmp(argv[arg], "-S2"))
455                        loadIpoints(argv[++arg], ConS2);
456                if (! strcmp(argv[arg], "-RS1"))
457                        loadIpoints(argv[++arg], ConSRough1);
458                if (! strcmp(argv[arg], "-RS2"))
459                        loadIpoints(argv[++arg], ConSRough2);
460                //Min -------------------------------------
461
462                if (! strcmp(argv[arg], "-im1"))
463                        im1 = ImageLoader.readImage(argv[++arg]);
464                if (! strcmp(argv[arg], "-im2"))
465                        im2 = ImageLoader.readImage(argv[++arg]);
466                if (! strcmp(argv[arg], "-o"))
467                        strcpy(ofname, argv[++arg]);
468                if (! strcmp(argv[arg], "-c"))
469                        drawc = true;
470                if (! strcmp(argv[arg], "-s"))
471                        usesym = true;
472                if (! strcmp(argv[arg], "-d"))
473                        printAllDist = true;
474                if (! strcmp(argv[arg], "-abs"))
475                        abs_thre = strtod( argv[++arg], NULL);
476                if (! strcmp(argv[arg], "-ratio"))
477                        ratio_thre = strtod( argv[++arg], NULL);
478
479        }
480       
481
482        if (ipts1.size() == 0 || ipts2.size() == 0) {
483                cout << "Usage:" << endl;
484                cout << " match [-s] -k1 out1.surf -k2 out2.surf -im1 img1.pgm -im2 img2.pgm -o out.pgm" << endl << endl;
485                cout << "For each feature in first descriptor file, find best in second according to "
486                        << "nearest neighbor ratio strategy. Display matches in out.pgm, generated "
487                        << "from img1.pgm and img2.pgm. Use -c to draw crosses at interest points." << endl;
488
489                cout << "use -s to require that the best match be symetric."<<endl;
490                cout << "use -d to print out all of the n*m distances between points instead of matching."<<endl;
491                cout << "use -abs to set absolute threshould and -ratio to set rative threshould."<<endl;
492                return 1;
493        }
494
495        vector< int > matches;
496         
497        if (usesym) {
498          cerr << "Using symmetricConS matches, using descriptor length " << vlen << ConSRough1[0].ivec[3] << abs_thre << ratio_thre<< endl;
499//        cout << "test CONSRough" << ConSRough1[1].ivec[1] << endl;
500                matches = symMatches(ipts1, ipts2, ConS1, ConS2, ConSRough1, ConSRough2, abs_thre, ratio_thre);//Min
501        } else if (printAllDist){
502          printAllDistances(ipts1, ipts2);
503        } else {
504          matches = findMatches(ipts1, ipts2);
505        }
506
507
508        if (im1 != NULL && im2 != NULL && ofname[0] != 0) {
509                Image res(max(im1->getWidth(), im2->getWidth()), im1->getHeight() + im2->getHeight());
510                for (int x = 0; x < im1->getWidth(); x++)
511                        for (int y = 0; y < im1->getHeight(); y++)
512                                res.setPix(x, y, im1->getPix(x, y));
513                for (int x = 0; x < im2->getWidth(); x++)
514                        for (int y = 0; y < im2->getHeight(); y++)
515                                res.setPix(x, y + im1->getHeight(), im2->getPix(x, y));
516
517                // Draw lines for matches
518                for (unsigned i = 0; i < matches.size(); i++) {
519                        if (matches[i] != -1) {
520                                drawLine(&res, (int)ipts1[i].x, (int)ipts1[i].y,
521                                        (int)ipts2[matches[i]].x, (int)(ipts2[matches[i]].y + im1->getHeight()));
522                        }
523                }
524
525                // Draw crosses at interest point locations
526                if (drawc) {
527                        for (unsigned i = 0; i < ipts1.size(); i++)
528                                drawCross(&res, (int)ipts1[i].x, (int)ipts1[i].y);
529                        for (unsigned i = 0; i < ipts2.size(); i++)
530                                drawCross(&res, (int)ipts2[i].x, (int)ipts2[i].y + im1->getHeight());
531                }
532
533                ImageLoader.saveImage(ofname, &res);
534        }
535
536       
537        return 0;
538}
Note: See TracBrowser for help on using the repository browser.