place_recognition.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2013, Intelligent Robotics Lab, DLUT.
00005  *  Author: Qinghua Li, Yan Zhuang, Fei Yan
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Intelligent Robotics Lab, DLUT. nor the names
00020  *     of its contributors may be used to endorse or promote products
00021  *     derived from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  */
00036 
00037 #include "dlut_place_recognition/place_recognition.h"
00038 
00039 #define SAMPLINGSTEP 1
00040 #define CV_SURF_EXTENDED 1
00041 #define FEATURE_LOWE_COLOR CV_RGB(255, 0, 255)
00042 #define SURF_KDTREE_BBF_MAX_NN_CHKS 400
00043 #define SURF_NN_SQ_DIST_RATIO_THR 0.6  /* the threshold value of distance ratio */
00044 #define MINPQ_INIT_NALLOCD 512
00045 #define MAXDIM 9
00046 #define CLUSTERINGNUM 2
00047 #define DANGLE 4
00048 #define MINN 17
00049 #define DISMAX 0.1
00050 #define MIN_AMOUNT 4
00051 
00052 template <typename T> int cvSign (T t)
00053 {
00054   return ((t < 0) ? -1 : 1);
00055 }
00056 
00057 static __inline int parent (int i)
00058 {
00059   return (i - 1) / 2;
00060 }
00061 
00062 /* Returns the array index of element */
00063 static __inline int right (int i)
00064 {
00065   return 2 * i + 2;
00066 }
00067 
00068 /* Returns the array index of element */
00069 static __inline int left (int i)
00070 {
00071   return 2 * i + 1;
00072 }
00073 
00074 
00075 PlaceRecognition::PlaceRecognition ()
00076 {
00077   wrap = 0;
00078 }
00079 
00080 PlaceRecognition::~PlaceRecognition ()
00081 {
00082 }
00083 
00084 
00085 bool PlaceRecognition::extractGlobalFeature (std::vector< std::vector<pcl::PointXYZ> > &points, GlobalFeature* global_feature)
00086 {
00087   // Calculate the global area and duty cycle of scene
00088   if (points.size () > 0)
00089   {
00090     int r = points.size ();
00091     int k_r = 35;       /* Test row */
00092     double area = 0;    /* Area assessment */
00093     double dis = 0;
00094 
00095     for (int i = 0; i < (int) points[k_r].size () - 1; i++)
00096     {
00097       dis = sqrt ((points[k_r][i].x * points[k_r][i].x) + (points[k_r][i].y * points[k_r][i].y) +
00098                   (points[k_r][i].z * points[k_r][i].z));
00099       area += 0.5 * (0.5 / 360) * 2 * PI * dis * dis;
00100     }
00101     global_feature->duty_cycle = area;
00102 
00103     // The whole spatial volume assessment
00104     for (int i = k_r - 1; i < r - 1; i++)
00105     {
00106       double w_a = 0;
00107       for (int j = 0; j < (int) points[i].size () - 1; j++)
00108       {
00109         dis = sqrt ((points[i][j].x * points[i][j].x) + (points[i][j].y * points[i][j].y) +
00110                     (points[i][j].z * points[i][j].z));
00111         w_a += 0.5 * (0.5 / 360) * 2 * PI * dis * dis;
00112       }
00113 
00114       if (w_a > area)
00115       {
00116         area = w_a;
00117       }
00118     }
00119     global_feature->area = area;
00120     return true;
00121   }
00122   else
00123   {
00124     QMessageBox::critical (NULL, "Critical", "Extract global spatial features failed!\n"
00125                                  "NO available data, please load data at first!",
00126                                  QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
00127     return false;
00128   }
00129 }
00130 
00131 void PlaceRecognition::cvSURFInitialize ()
00132 {
00133   wrap = cvCreateMat (2, 3, CV_32FC1);
00134   int k = 0;
00135   for (int i = 0; i < SCANOCTAVE; i++)
00136   {
00137     for (int j = 0; j < FILTERSCALE; j++)
00138     {
00139       double scal = ((j * 6 + 9) << i) * 1.2 / 9.;
00140       regions_cache[k] = cvCreateImage (cvSize (cvRound (21 * scal), cvRound (21 * scal)), 8, 1);
00141       k++;
00142     }
00143   }
00144 
00145   region_cache = cvCreateImage (cvSize (21, 21), 8, 1);
00146   dx_cache = cvCreateMat (20, 20, CV_64FC1);
00147   dy_cache = cvCreateMat (20, 20, CV_64FC1);
00148   gauss_kernel_cache = cvCreateMat (20, 20, CV_64FC1);
00149   cvSURFGaussian (gauss_kernel_cache, 3.3);
00150 
00151   for (int i = 0; i < 3600; i++)
00152   {
00153     cos_cache[i] = cos (i * 0.001745329);
00154     sin_cache[i] = sin (i * 0.001745329);
00155   }
00156 }
00157 
00158 void PlaceRecognition::cvSURFGaussian (CvMat* mat, double s)
00159 {
00160   int w = mat->cols;
00161   int h = mat->rows;
00162   double x, y;
00163   double c2 = 1. / (s * s * 2);
00164   double over_exp = 1. / (3.14159 * 2 * s * s);
00165   for (int i = 0; i < w; i++)
00166     for (int j = 0; j < h; j++)
00167     {
00168       x = i - w / 2.;
00169       y = j - h / 2.;
00170       cvmSet (mat, j, i, exp (-(x * x + y * y) * c2) * over_exp);
00171     }
00172 }
00173 
00174 CvSeq* PlaceRecognition::cvSURFDescriptor (const CvArr* _img, CvMemStorage* storage, double quality, int flags)
00175 {
00176   IplImage* img = (IplImage*) _img;
00177   CvMat* sum = 0;
00178   sum = cvCreateMat (img->height + 1, img->width + 1, CV_32SC1);
00179   cvIntegral (img, sum);
00180   CvMemStorage* point_storage = cvCreateChildMemStorage (storage);
00181   CvSeq* points = cvFastHessianDetector (sum, point_storage, quality);
00182 
00183   CvSeq* descriptors = cvCreateSeq (0, sizeof (CvSeq), sizeof (SURFDescriptor), storage);
00184   int dx_s[] = { 2, 0, 0, 2, 4, 0, -1, 2, 0, 4, 4, 0, 1 };
00185   int dy_s[] = { 2, 0, 0, 4, 2, 0, -1, 0, 2, 4, 4, 0, 1 };
00186   int dx_t[] = { 2, 0, 0, 2, 4, 0, -1, 2, 0, 4, 4, 0, 1 };
00187   int dy_t[] = { 2, 0, 0, 4, 2, 0, -1, 0, 2, 4, 4, 0, 1 };
00188   double x[81], *iter_x;
00189   double y[81], *iter_y;
00190   double angle[81], *iter_angle;
00191   double sumx, sumy;
00192   double temp_mod;
00193   int angle_n;
00194   for (int k = 0; k < points->total; k++)
00195   {
00196     SURFPoint* point = (SURFPoint*) cvGetSeqElem (points, k);
00197     SURFDescriptor descriptor;
00198     descriptor.feature_data = point;
00199     descriptor.x = cvRound (point->x);
00200     descriptor.y = cvRound (point->y);
00201     descriptor.laplacian = point->laplacian;
00202     int size = point->size;
00203     int layer = point->octave * FILTERSCALE + point->scale;
00204     descriptor.s = size * 1.2 / 9.;
00205     descriptor.mod = 0;
00206 
00207     /* Repeatable orientation */
00208     iter_x = x;
00209     iter_y = y;
00210     iter_angle = angle;
00211     angle_n = 0;
00212     cvResizeHaarPattern (dx_s, dx_t, 9, size);
00213     cvResizeHaarPattern (dy_s, dy_t, 9, size);
00214     int* sum_ptr = (int*) sum->data.ptr;
00215     double c2 = 1. / (descriptor.s * descriptor.s * 2.5 * 2.5 * 2);
00216     double over_exp = 1. / (3.14159 * 2 * descriptor.s * descriptor.s * 2.5 * 2.5);
00217     for (int j = -6; j <= 2; j++)
00218     {
00219       int y = descriptor.y + j * size / 9;
00220       if ((y >= 0) && (y < sum->rows - size))
00221       {
00222         double ry = j + 2;
00223         for (int i = -6; i <= 2; i++)
00224         {
00225           int x = descriptor.x + i * size / 9;
00226           if ((x >= 0) && (x < sum->cols - size))
00227           {
00228             double rx = j + 2;
00229             double radius = rx * rx + ry * ry;
00230             if (radius <= 16)
00231             {
00232               rx *= descriptor.s;
00233               ry *= descriptor.s;
00234               *iter_x = cvCalHaarPattern (sum_ptr + x + y * sum->cols, dx_t, sum->cols) * exp (-radius * c2) * over_exp;
00235               *iter_y = cvCalHaarPattern (sum_ptr + x + y * sum->cols, dy_t, sum->cols) * exp (-radius * c2) * over_exp;
00236               *iter_angle = cvFastArctan (*iter_y, *iter_x);
00237               iter_x++;
00238               iter_y++;
00239               iter_angle++;
00240               angle_n++;
00241             }
00242           }
00243         }
00244       }
00245     }
00246     double bestx = 0;
00247     double besty = 0;
00248     for (int i = 0; i < 360; i += 5)
00249     {
00250       sumx = 0;
00251       sumy = 0;
00252       iter_x = x;
00253       iter_y = y;
00254       iter_angle = angle;
00255       for (int j = 0; j < angle_n; j++)
00256       {
00257         if (((*iter_angle < i + 60) && (*iter_angle > i)) ||
00258            (((*iter_angle + 360) < i + 60) && ((*iter_angle + 360) > i)))
00259         {
00260           sumx += *iter_x;
00261           sumy += *iter_y;
00262         }
00263         iter_x++;
00264         iter_y++;
00265         iter_angle++;
00266       }
00267       temp_mod = sumx * sumx + sumy * sumy;
00268       if (temp_mod > descriptor.mod)
00269       {
00270         descriptor.mod = temp_mod;
00271         bestx = sumx;
00272         besty = sumy;
00273       }
00274     }
00275     descriptor.dir = cvFastArctan (besty, bestx);
00276 
00277     /* Get sub-region (CV_INTER_AREA approximately retain the information of total image for
00278        haar feature while reduce the time consuming */
00279     double cos_dir = cos_cache[MAX (cvRound (descriptor.dir * 10) + 3600, 0) % 3600];
00280     double sin_dir = sin_cache[MAX (cvRound (descriptor.dir * 10) + 3600, 0) % 3600];
00281     cvmSet (wrap, 0, 0, cos_dir);
00282     cvmSet (wrap, 0, 1, -sin_dir);
00283     cvmSet (wrap, 0, 2, descriptor.x);
00284     cvmSet (wrap, 1, 0, sin_dir);
00285     cvmSet (wrap, 1, 1, cos_dir);
00286     cvmSet (wrap, 1, 2, descriptor.y);
00287 
00288     cvGetQuadrangleSubPix (img, regions_cache[layer], wrap);
00289     cvResize (regions_cache[layer], region_cache, CV_INTER_AREA);
00290     uchar* region_d;
00291     int region_step;
00292     cvGetImageRawData (region_cache, &region_d, &region_step);
00293     uchar* region_x = region_d + 1;
00294     uchar* region_y = region_d + region_step;
00295     uchar* region_xy = region_d + 1 + region_step;
00296     region_step -= 20;
00297     double* iter_dx = (double*) dx_cache->data.ptr;
00298     double* iter_dy = (double*) dy_cache->data.ptr;
00299     for (int i = 0; i < 20; i++)
00300     {
00301       for (int j = 0; j < 20; j++)
00302       {
00303         *iter_dx = *region_y - *region_d - *region_x + *region_xy;
00304         *iter_dy = *region_x - *region_d - *region_y + *region_xy;
00305         iter_dx++;
00306         iter_dy++;
00307         region_d++;
00308         region_x++;
00309         region_y++;
00310         region_xy++;
00311       }
00312       region_d += region_step;
00313       region_x += region_step;
00314       region_y += region_step;
00315       region_xy += region_step;
00316     }
00317     cvMul (gauss_kernel_cache, dx_cache, dx_cache);
00318     cvMul (gauss_kernel_cache, dy_cache, dy_cache);
00319 
00320     double tx, ty;
00321     double* iter_vector = descriptor.vector;
00322     if (flags & CV_SURF_EXTENDED)
00323     {
00324       /* 128-bin descriptor */
00325       for (int i = 0; i < 4; i++)
00326         for (int j = 0; j < 4; j++)
00327         {
00328           iter_vector[0] = 0;
00329           iter_vector[1] = 0;
00330           iter_vector[2] = 0;
00331           iter_vector[3] = 0;
00332           iter_vector[4] = 0;
00333           iter_vector[5] = 0;
00334           iter_vector[6] = 0;
00335           iter_vector[7] = 0;
00336           for (int x = i * 5; x < i * 5 + 5; x++)
00337           {
00338             for (int y = j * 5; y < j * 5 + 5; y++)
00339             {
00340               tx = cvGetReal2D (dx_cache, x, y);
00341               ty = cvGetReal2D (dy_cache, x, y);
00342               if (ty >= 0)
00343               {
00344                 iter_vector[0] += tx;
00345                 iter_vector[1] += fabs (tx);
00346               }
00347               else
00348               {
00349                 iter_vector[2] += tx;
00350                 iter_vector[3] += fabs (tx);
00351               }
00352               if (tx >= 0)
00353               {
00354                 iter_vector[4] += ty;
00355                 iter_vector[5] += fabs (ty);
00356               }
00357               else
00358               {
00359                 iter_vector[6] += ty;
00360                 iter_vector[7] += fabs (ty);
00361               }
00362             }
00363           }
00364           /* Unit vector is essential for contrast invariant */
00365           double normalize = 0;
00366           for (int k = 0; k < 8; k++)
00367             normalize += iter_vector[k] * iter_vector[k];
00368           normalize = sqrt (normalize);
00369           for (int k = 0; k < 8; k++)
00370             iter_vector[k] = iter_vector[k] / normalize;
00371           iter_vector += 8;
00372         }
00373     }
00374     else
00375     {
00376       /* 64-bin descriptor */
00377       for (int i = 0; i < 4; i++)
00378         for (int j = 0; j < 4; j++)
00379         {
00380           iter_vector[0] = 0;
00381           iter_vector[1] = 0;
00382           iter_vector[2] = 0;
00383           iter_vector[3] = 0;
00384           for (int x = i * 5; x < i * 5 + 5; x++)
00385           {
00386             for (int y = j * 5; y < j * 5 + 5; y++)
00387             {
00388               tx = cvGetReal2D (dx_cache, x, y);
00389               ty = cvGetReal2D (dy_cache, x, y);
00390               iter_vector[0] += tx;
00391               iter_vector[1] += ty;
00392               iter_vector[2] += fabs (tx);
00393               iter_vector[3] += fabs (ty);
00394             }
00395           }
00396           double normalize = 0;
00397           for (int k = 0; k < 4; k++)
00398             normalize += iter_vector[k] * iter_vector[k];
00399           normalize = sqrt (normalize);
00400           for (int k = 0; k < 4; k++)
00401             iter_vector[k] = iter_vector[k] / normalize;
00402           iter_vector += 4;
00403         }
00404     }
00405 
00406     cvSeqPush (descriptors, &descriptor);
00407   }
00408   cvReleaseMemStorage (&point_storage);
00409   cvReleaseMat (&sum);
00410 
00411   return descriptors;
00412 }
00413 
00414 CvSeq* PlaceRecognition::cvFastHessianDetector (const CvMat* sum, CvMemStorage* storage, double quality)
00415 {
00416   CvSeq* points = cvCreateSeq (0, sizeof (CvSeq), sizeof (SURFPoint), storage);
00417   CvMat* hessians[SCANOCTAVE * (FILTERSCALE + 2)];
00418   CvMat* traces[SCANOCTAVE * (FILTERSCALE + 2)];
00419   int size, size_cache[SCANOCTAVE * (FILTERSCALE + 2)];
00420   int scale, scale_cache[SCANOCTAVE * (FILTERSCALE + 2)];
00421   double *hessian_ptr, *hessian_ptr_cache[SCANOCTAVE * (FILTERSCALE + 2)];
00422   double *trace_ptr, *trace_ptr_cache[SCANOCTAVE * (FILTERSCALE + 2)];
00423   int dx_s[] = { 3, 0, 2, 3, 7, 0, 1, 3, 2, 6, 7, 0, -2, 6, 2, 9, 7, 0, 1 };
00424   int dy_s[] = { 3, 2, 0, 7, 3, 0, 1, 2, 3, 7, 6, 0, -2, 2, 6, 7, 9, 0, 1 };
00425   int dxy_s[] = { 4, 1, 1, 4, 4, 0, 1, 5, 1, 8, 4, 0, -1, 1, 5, 4, 8, 0, -1, 5, 5, 8, 8, 0, 1 };
00426   int dx_t[] = { 3, 0, 2, 3, 7, 0, 1, 3, 2, 6, 7, 0, -2, 6, 2, 9, 7, 0, 1 };
00427   int dy_t[] = { 3, 2, 0, 7, 3, 0, 1, 2, 3, 7, 6, 0, -2, 2, 6, 7, 9, 0, 1 };
00428   int dxy_t[] = { 4, 1, 1, 4, 4, 0, 1, 5, 1, 8, 4, 0, -1, 1, 5, 4, 8, 0, -1, 5, 5, 8, 8, 0, 1 };
00429   double dx = 0, dy = 0, dxy = 0;
00430   int k = 0;
00431   int hessian_rows, hessian_rows_cache[SCANOCTAVE * (FILTERSCALE + 2)];
00432   int hessian_cols, hessian_cols_cache[SCANOCTAVE * (FILTERSCALE + 2)];
00433 
00434   /* Hessian detector */
00435   for (int o = 0; o < SCANOCTAVE; o++)
00436   {
00437     for (int s = -1; s < FILTERSCALE + 1; s++)
00438     {
00439       if (s < 0)
00440         size_cache[k] = size = 7 << o; // Gaussian scale 1.0
00441       else
00442         size_cache[k] = size = (s * 6 + 9) << o; // Gaussian scale size*1.2/9.
00443 
00444       scale_cache[k] = scale = MAX (size, 9) * SAMPLINGSTEP;
00445       hessian_rows_cache[k] = hessian_rows = (sum->rows) * 9 / scale;
00446       hessian_cols_cache[k] = hessian_cols = (sum->cols) * 9 / scale;
00447       hessians[k] = cvCreateMat (hessian_rows, hessian_cols, CV_64FC1);
00448       traces[k] = cvCreateMat (hessian_rows, hessian_cols, CV_64FC1);
00449       int* sum_ptr = (int*) sum->data.ptr;
00450       cvResizeHaarPattern (dx_s, dx_t, 9, size);
00451       cvResizeHaarPattern (dy_s, dy_t, 9, size);
00452       cvResizeHaarPattern (dxy_s, dxy_t, 9, size);
00453       hessian_ptr_cache[k] = hessian_ptr = (double*) hessians[k]->data.ptr;
00454       trace_ptr_cache[k] = trace_ptr = (double*) traces[k]->data.ptr;
00455       hessian_ptr += 4 / SAMPLINGSTEP + (4 / SAMPLINGSTEP) * hessian_cols;
00456       trace_ptr += 4 / SAMPLINGSTEP + (4 / SAMPLINGSTEP) * hessian_cols;
00457       int oy = 0, y = 0;
00458       for (int j = 0; j < hessian_rows - 9 / SAMPLINGSTEP; j++)
00459       {
00460         int* sum_line_ptr = sum_ptr;
00461         double* trace_line_ptr = trace_ptr;
00462         double* hessian_line_ptr = hessian_ptr;
00463         int ox = 0, x = 0;
00464         for (int i = 0; i < hessian_cols - 9 / SAMPLINGSTEP; i++)
00465         {
00466           dx = cvCalHaarPattern (sum_line_ptr, dx_t, sum->cols);
00467           dy = cvCalHaarPattern (sum_line_ptr, dy_t, sum->cols);
00468           dxy = cvCalHaarPattern (sum_line_ptr, dxy_t, sum->cols);
00469           *hessian_line_ptr = (dx * dy - dxy * dxy * 0.81);
00470           *trace_line_ptr = dx + dy;
00471           x = (i + 1) * scale / 9;
00472           sum_line_ptr += x - ox;
00473           ox = x;
00474           trace_line_ptr++;
00475           hessian_line_ptr++;
00476         }
00477         y = (j + 1) * scale / 9;
00478         sum_ptr += (y - oy) * sum->cols;
00479         oy = y;
00480         trace_ptr += hessian_cols;
00481         hessian_ptr += hessian_cols;
00482       }
00483       k++;
00484     }
00485   }
00486   double min_accept = quality * 300;
00487 
00488   k = 0;
00489   for (int o = 0; o < SCANOCTAVE; o++)
00490   {
00491     k++;
00492     for (int s = 0; s < FILTERSCALE; s++)
00493     {
00494       size = size_cache[k];
00495       scale = scale_cache[k];
00496       hessian_rows = hessian_rows_cache[k];
00497       hessian_cols = hessian_cols_cache[k];
00498       int margin = (5 / SAMPLINGSTEP) * scale_cache[k + 1] / scale;
00499       hessian_ptr = hessian_ptr_cache[k] + margin + margin * hessian_cols;
00500       trace_ptr = trace_ptr_cache[k];
00501       for (int j = margin; j < hessian_rows - margin; j++)
00502       {
00503         double* hessian_line_ptr = hessian_ptr;
00504         for (int i = margin; i < hessian_cols - margin; i++)
00505         {
00506           if (*hessian_line_ptr > min_accept)
00507           {
00508             bool suppressed = false;
00509             /* Non-maxima suppression */
00510             for (int z = k - 1; z < k + 2; z++)
00511             {
00512               double* temp_hessian_ptr = hessian_ptr_cache[z] + i * scale / scale_cache[z] - 1 +
00513                                          (j * scale / scale_cache[z] - 1) * hessian_cols_cache[z];
00514               for (int y = 0; y < 3; y++)
00515               {
00516                 double* temp_hessian_line_ptr = temp_hessian_ptr;
00517                 for (int x = 0; x < 3; x++)
00518                 {
00519                   if (((z != k) || (y != 1) || (x != 1)) && (*temp_hessian_line_ptr > *hessian_line_ptr))
00520                   {
00521                     suppressed = true;
00522                     break;
00523                   }
00524                   temp_hessian_line_ptr++;
00525                 }
00526                 if (suppressed)
00527                 break;
00528                 temp_hessian_ptr += hessian_cols_cache[z];
00529               }
00530               if (suppressed)
00531               break;
00532             }
00533             if (!suppressed)
00534             {
00535               SURFPoint point = cvSURFPoint (i * scale / 9, j * scale / 9, cvSign (trace_ptr[i + j * hessian_cols]),
00536                                              size_cache[k], o, s);
00537               cvSeqPush (points, &point);
00538             }
00539           }
00540           hessian_line_ptr++;
00541         }
00542         hessian_ptr += hessian_cols;
00543       }
00544       k++;
00545     }
00546     k++;
00547   }
00548 
00549   k = 0;
00550   for (int o = 0; o < SCANOCTAVE; o++)
00551     for (int s = -1; s < FILTERSCALE + 1; s++)
00552     {
00553       cvReleaseMat (&hessians[k]);
00554       cvReleaseMat (&traces[k]);
00555       k++;
00556     }
00557 
00558   return points;
00559 }
00560 
00561 void PlaceRecognition::cvResizeHaarPattern (int* t_s, int* t_d, int OldSize, int NewSize)
00562 {
00563   int n = t_d[0] = t_s[0];
00564   for (int k = 0; k < n; k++)
00565   {
00566     t_d[1] = t_s[1] * NewSize / OldSize;
00567     t_d[2] = t_s[2] * NewSize / OldSize;
00568     t_d[3] = t_s[3] * NewSize / OldSize;
00569     t_d[4] = t_s[4] * NewSize / OldSize;
00570     t_d[5] = (t_d[3] - t_d[1] + 1) * (t_d[4] - t_d[2] + 1);
00571     t_d[6] = t_s[6];
00572     t_d += 6;
00573     t_s += 6;
00574   }
00575 }
00576 
00577 double PlaceRecognition::cvCalHaarPattern (int* origin, int* t, int widthStep)
00578 {
00579   double d = 0;
00580   int *p0 = 0, *p1 = 0, *p2 = 0, *p3 = 0;
00581   int n = t[0];
00582   for (int k = 0; k < n; k++)
00583   {
00584     p0 = origin + t[1] + t[2] * widthStep;
00585     p1 = origin + t[1] + t[4] * widthStep;
00586     p2 = origin + t[3] + t[2] * widthStep;
00587     p3 = origin + t[3] + t[4] * widthStep;
00588     d += (double) ((*p3 - *p2 - *p1 + *p0) * t[6]) / (double) (t[5]);
00589     t += 6;
00590   }
00591   return d;
00592 }
00593 
00594 SURFPoint PlaceRecognition::cvSURFPoint (int x, int y, int laplacian, int size, int octave, int scale)
00595 {
00596   SURFPoint p;
00597   p.x = x;
00598   p.y = y;
00599   p.laplacian = laplacian;
00600   p.size = size;
00601   p.octave = octave;
00602   p.scale = scale;
00603   return p;
00604 }
00605 
00606 bool PlaceRecognition::drawSURFFeatures (IplImage* img, CvSeq* feat, int n)
00607 {
00608   if (n <= 0 || !feat)
00609   {
00610     QMessageBox::critical (NULL, "Critical", "No corresponding features!\n" 
00611                                  "Please replace another scene to continue!",
00612                                  QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
00613     return false;
00614   }
00615   else
00616   {
00617     drawSURFLoweFeatures (img, feat, n);
00618     return true;
00619   }
00620 }
00621 
00622 void PlaceRecognition::drawSURFLoweFeatures (IplImage* img, CvSeq* feat, int n)
00623 {
00624   CvScalar color = CV_RGB (255, 0, 255);
00625 
00626   if (img->nChannels > 1)
00627     color = FEATURE_LOWE_COLOR;
00628 
00629   for (int i = 0; i < n; i++)
00630   {
00631     SURFDescriptor* feat1 = (SURFDescriptor*) cvGetSeqElem (feat, i);
00632     drawSURFLoweFeature (img, feat1, color);
00633   }
00634 }
00635 
00636 void PlaceRecognition::drawSURFLoweFeature (IplImage* img, SURFDescriptor* feat, CvScalar color)
00637 {
00638   int len, hlen, blen, start_x, start_y, end_x, end_y, h1_x, h1_y, h2_x, h2_y;
00639   double scl, ori;
00640   double scale = 5.0;
00641   double hscale = 0.75;
00642   CvPoint start, end, h1, h2;
00643 
00644   /* Compute points for an arrow scaled and rotated by feat's scl and ori */
00645   start_x = cvRound (feat->x);
00646   start_y = cvRound (feat->y);
00647   scl = feat->s;
00648   ori = feat->dir;
00649   len = cvRound (scl * scale);
00650   hlen = cvRound (scl * hscale);
00651   blen = len - hlen;
00652   end_x = cvRound (len * cos (ori)) + start_x;
00653   end_y = cvRound (len * -sin (ori)) + start_y;
00654   h1_x = cvRound (blen * cos (ori + CV_PI / 18.0)) + start_x;
00655   h1_y = cvRound (blen * -sin (ori + CV_PI / 18.0)) + start_y;
00656   h2_x = cvRound (blen * cos (ori - CV_PI / 18.0)) + start_x;
00657   h2_y = cvRound (blen * -sin (ori - CV_PI / 18.0)) + start_y;
00658   start = cvPoint (start_x, start_y);
00659   end = cvPoint (end_x, end_y);
00660   h1 = cvPoint (h1_x, h1_y);
00661   h2 = cvPoint (h2_x, h2_y);
00662 
00663   cvLine (img, start, end, color, 1, 8, 0);
00664   cvLine (img, end, h1, color, 1, 8, 0);
00665   cvLine (img, end, h2, color, 1, 8, 0);
00666 }
00667 
00668 
00669 void PlaceRecognition::readFeaturesFromFile ()
00670 {
00671   surf_descriptors.clear ();
00672   global_descriptors.clear ();
00673 
00674   files = QFileDialog::getOpenFileNames (0, "Load database files", ".", "TXT Files (*.txt)");
00675 
00676   if (!files.isEmpty ())
00677   {
00678     int file_number = files.size ();
00679 
00680     BOOST_FOREACH (QString s, files)
00681     {
00682       QFile file (s);
00683       if (file.open (QIODevice::ReadOnly | QIODevice::Text))
00684       {
00685         GlobalFeature global_feature;
00686         SURFDescriptor tmp_feature;
00687         std::vector< SURFDescriptor > tmp_surf_descriptors;
00688         tmp_surf_descriptors.clear ();
00689 
00690         // Read global features
00691         QByteArray line = file.readLine ();
00692         char* sep_str = line.data ();
00693         char sepr[] = " \t\n";
00694 
00695         char* str = strtok (sep_str, sepr);
00696         if (str != NULL)
00697           global_feature.area = atof (str);
00698         str = strtok (NULL, sepr);
00699         if (str != NULL)
00700           global_feature.duty_cycle = atof (str);
00701         global_descriptors.push_back (global_feature);
00702 
00703         // Read SURF features
00704         while (!file.atEnd ())
00705         {
00706           line = file.readLine ();
00707           sep_str = line.data ();
00708 
00709           //Read the pixel position(x,y)
00710           str = strtok (sep_str, sepr);
00711           if (str != NULL)
00712             tmp_feature.x = atof (str);
00713           str = strtok (NULL, sepr);
00714           if (str != NULL)
00715             tmp_feature.y = atof (str);
00716 
00717           str = strtok (NULL, sepr);
00718           if (str != NULL)
00719             tmp_feature.laplacian = atof (str);
00720 
00721           // Read the scale
00722           str = strtok (NULL, sepr);
00723           if (str != NULL)
00724             tmp_feature.s = atof (str);
00725 
00726           // Read the principal direction
00727           str = strtok (NULL, sepr);
00728           if (str != NULL)
00729             tmp_feature.dir = atof (str);
00730 
00731           str = strtok (NULL, sepr);
00732           if (str != NULL)
00733             tmp_feature.mod = atof (str);
00734 
00735           // Read the corresponding laser point for this feature
00736           str = strtok (NULL, sepr);
00737           if (str != NULL)
00738             tmp_feature.cor_point.x = atof (str);
00739           str = strtok (NULL, sepr);
00740           if (str != NULL)
00741             tmp_feature.cor_point.y = atof (str);
00742           str = strtok (NULL, sepr);
00743           if (str != NULL)
00744           tmp_feature.cor_point.z = atof (str);
00745 
00746           for (int i = 0; i < 128; i++)
00747           {
00748             str = strtok (NULL, sepr);
00749             if (str != NULL)
00750             tmp_feature.vector[i] = atof (str);
00751           }
00752 
00753           tmp_surf_descriptors.push_back (tmp_feature);
00754         }
00755 
00756         surf_descriptors.push_back (tmp_surf_descriptors);
00757         file.close ();
00758       }
00759       else
00760       {
00761         switch (QMessageBox::critical (NULL, "Critical", "Failed to read one database file!\n"
00762                 "Would you like to read database files again, ignore it to continue or abort this option?",
00763                 QMessageBox::Retry | QMessageBox::Ignore | QMessageBox::Abort, QMessageBox::Retry))
00764         {
00765           case QMessageBox::Retry:
00766             readFeaturesFromFile ();
00767             break;
00768 
00769           case QMessageBox::Ignore:
00770             break;
00771 
00772           case QMessageBox::Abort:
00773             return;
00774         }
00775       }
00776     }
00777   }
00778   else
00779   {
00780     switch (QMessageBox::critical (NULL, "Critical", "Failed to load database files!\n"
00781                                          "Would you like to reload them or abort this option?",
00782                                          QMessageBox::Retry | QMessageBox::Abort, QMessageBox::Retry))
00783     {
00784       case QMessageBox::Retry:
00785         readFeaturesFromFile ();
00786         break;
00787 
00788       case QMessageBox::Abort:
00789         break;
00790     }
00791   }
00792 }
00793 
00794 
00795 CvSeq* PlaceRecognition::findSURFMatchPairs (CvSeq* sep, int n, std::vector<SURFDescriptor> sfeat, CvMemStorage* storage)
00796 {
00797   SURFDescriptor* feat = 0;
00798   SURFDescriptor** nbrs;
00799   SURFKDNode* kd_root;
00800 
00801   CvSeq* correspond = cvCreateSeq (0, sizeof (CvSeq), sizeof (SURFDescriptor), storage);
00802 
00803   // Build KD-Tree
00804   kd_root = buildKDTree (&sfeat[0], (int) (sfeat.size ()), 1);
00805 
00806   int match_num = 0;
00807   // Matching based on BBF
00808   for (int i = 0; i < n; i++)
00809   {
00810     // Take feature in the scene
00811     feat = (SURFDescriptor*) cvGetSeqElem (sep, i);
00812     // Use BBF to search matching pairs
00813     int k = KDTreeBbfKnn (kd_root, feat, 2, &nbrs, SURF_KDTREE_BBF_MAX_NN_CHKS, 1);
00814     if (k == 2)
00815     {
00816       double d0 = (double) descrDistSq (feat, nbrs[0], 1);
00817       double d1 = (double) descrDistSq (feat, nbrs[1], 1);
00818       if (d0 < d1 * SURF_NN_SQ_DIST_RATIO_THR)
00819       {
00820         cvSeqPush (correspond, feat);
00821         cvSeqPush (correspond, nbrs[0]);
00822         match_num++;
00823       }
00824     }
00825     free (nbrs);
00826   }
00827 
00828   // Filter the match results
00829   return correspond;
00830 }
00831 
00832 
00833 /******************************** KD-Tree ********************************/
00834 
00835 SURFKDNode* PlaceRecognition::buildKDTree (SURFDescriptor* features, int n, int flags)
00836 {
00837   SURFKDNode* kd_root;
00838 
00839   if (!features || n <= 0)
00840   {
00841     fprintf (stderr, "Warning: kdtree_build(): no features, %s, line %d\n", __FILE__, __LINE__);
00842     return NULL;
00843   }
00844 
00845   kd_root = initKDNode (features, n);
00846   expandKDNodeSubtree (kd_root, flags);
00847 
00848   return kd_root;
00849 }
00850 
00851 SURFKDNode* PlaceRecognition::initKDNode (SURFDescriptor* features, int n)
00852 {
00853   SURFKDNode* kd_node;
00854   kd_node = (SURFKDNode*) malloc (sizeof (SURFKDNode));
00855   memset (kd_node, 0, sizeof (SURFKDNode));
00856   kd_node->ki = -1;
00857   kd_node->features = features;
00858   kd_node->n = n;
00859 
00860   return kd_node;
00861 }
00862 
00863 void PlaceRecognition::expandKDNodeSubtree (SURFKDNode* kd_node, int flags)
00864 {
00865   /* Base case: leaf node */
00866   if (kd_node->n == 1 || kd_node->n == 0)
00867   {
00868     kd_node->leaf = 1;
00869     return;
00870   }
00871 
00872   assignPartKey (kd_node, flags);
00873   partitionFeatures (kd_node);
00874 
00875   if (kd_node->kd_left)
00876     expandKDNodeSubtree (kd_node->kd_left, flags);
00877   if (kd_node->kd_right)
00878     expandKDNodeSubtree (kd_node->kd_right, flags);
00879 }
00880 
00881 void PlaceRecognition::assignPartKey (SURFKDNode* kd_node, int flags)
00882 {
00883   SURFDescriptor* features;
00884   double kv, x, mean, var, var_max = 0;
00885   double* tmp;
00886   int d, n, i, j, ki = 0;
00887 
00888   features = kd_node->features;
00889   n = kd_node->n;
00890   d = (flags & CV_SURF_EXTENDED) ? 128 : 64;
00891 
00892   /* Partition key index is that along which descriptors have most variance */
00893   for (j = 0; j < d; j++)
00894   {
00895     mean = var = 0;
00896     for (i = 0; i < n; i++)
00897       mean += features[i].vector[j];
00898     mean /= n;
00899     for (i = 0; i < n; i++)
00900     {
00901       x = features[i].vector[j] - mean;
00902       var += x * x;
00903     }
00904     var /= n;
00905 
00906     if (var > var_max)
00907     {
00908       ki = j;
00909       var_max = var;
00910     }
00911   }
00912 
00913   /* Partition key value is median of descriptor values at ki */
00914   tmp = reinterpret_cast < double* >(calloc (n, sizeof (double)));
00915   for (i = 0; i < n; i++)
00916   tmp[i] = features[i].vector[ki];
00917   kv = selectMedian (tmp, n);
00918   free (tmp);
00919 
00920   kd_node->ki = ki;
00921   kd_node->kv = kv;
00922 }
00923 
00924 double PlaceRecognition::selectMedian (double* array, int n)
00925 {
00926   return selectRank (array, n, (n - 1) / 2);
00927 }
00928 
00929 double PlaceRecognition::selectRank (double* array, int n, int r)
00930 {
00931   double *tmp, med;
00932   int gr_5, gr_tot, rem_elts, i, j;
00933 
00934   /* Base case */
00935   if (n == 1)
00936     return array[0];
00937 
00938   /* Divide array into groups of 5 and sort them */
00939   gr_5 = n / 5;
00940   gr_tot = cvCeil (n / 5.0);
00941   rem_elts = n % 5;
00942   tmp = array;
00943   for (i = 0; i < gr_5; i++)
00944   {
00945     sortInsertion (tmp, 5);
00946     tmp += 5;
00947   }
00948   sortInsertion (tmp, rem_elts);
00949 
00950   /* Recursively find the median of the medians of the groups of 5 */
00951   tmp = reinterpret_cast < double* >(calloc (gr_tot, sizeof (double)));
00952   for (i = 0, j = 2; i < gr_5; i++, j += 5)
00953     tmp[i] = array[j];
00954   if (rem_elts)
00955     tmp[i++] = array[n - 1 - rem_elts / 2];
00956   med = selectRank (tmp, i, (i - 1) / 2);
00957   free (tmp);
00958 
00959   /* Partition around median of medians and recursively select if necessary */
00960   j = partitionArray (array, n, med);
00961   if (r == j)
00962     return med;
00963   else if (r < j)
00964     return selectRank (array, j, r);
00965   else
00966   {
00967     array += j + 1;
00968     return selectRank (array, (n - j - 1), (r - j - 1));
00969   }
00970 }
00971 
00972 void PlaceRecognition::sortInsertion (double* array, int n)
00973 {
00974   double k;
00975   int i, j;
00976 
00977   for (i = 1; i < n; i++)
00978   {
00979     k = array[i];
00980     j = i - 1;
00981     while (j >= 0 && array[j] > k)
00982     {
00983       array[j + 1] = array[j];
00984       j -= 1;
00985     }
00986     array[j + 1] = k;
00987   }
00988 }
00989 
00990 int PlaceRecognition::partitionArray (double* array, int n, double pivot)
00991 {
00992   double tmp;
00993   int p, i, j;
00994 
00995   i = -1;
00996   for (j = 0; j < n; j++)
00997     if (array[j] <= pivot)
00998     {
00999       tmp = array[++i];
01000       array[i] = array[j];
01001       array[j] = tmp;
01002       if (array[i] == pivot)
01003         p = i;
01004     }
01005 
01006   array[p] = array[i];
01007   array[i] = pivot;
01008 
01009   return i;
01010 }
01011 
01012 void PlaceRecognition::partitionFeatures (SURFKDNode* kd_node)
01013 {
01014   SURFDescriptor* features, tmp;
01015   double kv;
01016   int n, ki, p, i, j = -1;
01017 
01018   features = kd_node->features;
01019   n = kd_node->n;
01020   ki = kd_node->ki;
01021   kv = kd_node->kv;
01022   for (i = 0; i < n; i++)
01023   if (features[i].vector[ki] <= kv)
01024   {
01025     tmp = features[++j];
01026     features[j] = features[i];
01027     features[i] = tmp;
01028     if (features[j].vector[ki] == kv)
01029       p = j;
01030   }
01031   tmp = features[p];
01032   features[p] = features[j];
01033   features[j] = tmp;
01034 
01035   /* If all records fall on same side of partition, make node a leaf */
01036   if (j == n - 1)
01037   {
01038     kd_node->leaf = 1;
01039     return;
01040   }
01041 
01042   kd_node->kd_left = initKDNode (features, j + 1);
01043   
01044   kd_node->kd_right = initKDNode (features + (j + 1), (n - j - 1));
01045 }
01046 
01047 /********************************** End **********************************/
01048 
01049 
01050 int PlaceRecognition::KDTreeBbfKnn (SURFKDNode* kd_root, SURFDescriptor* feat, int k,
01051                                 SURFDescriptor*** nbrs, int max_nn_chks, int flags)
01052 {
01053   SURFKDNode* expl;
01054   MinPq* min_pq;
01055   SURFDescriptor* tree_feat, **_nbrs;
01056   BbfData* bbf_data;
01057   int i, t = 0, n = 0;
01058 
01059   if (!nbrs || !feat || !kd_root)
01060   {
01061     fprintf (stderr, "Warning: NULL pointer error, %s, line %d\n", __FILE__, __LINE__);
01062     return -1;
01063   }
01064 
01065   _nbrs = reinterpret_cast < SURFDescriptor** >(calloc (k, sizeof (SURFDescriptor*)));
01066   min_pq = initMinPq ();
01067   insertMinPq (min_pq, kd_root, 0);
01068   while (min_pq->n > 0 && t < max_nn_chks)
01069   {
01070     expl = (SURFKDNode*) minPqExtractMin (min_pq);
01071     if (!expl)
01072     {
01073       fprintf (stderr, "Warning: PQ unexpectedly empty, %s line %d\n", __FILE__, __LINE__);
01074       goto fail;
01075     }
01076 
01077     expl = exploreToLeaf (expl, feat, min_pq, flags);
01078     if (!expl)
01079     {
01080       fprintf (stderr, "Warning: PQ unexpectedly empty, %s line %d\n", __FILE__, __LINE__);
01081       goto fail;
01082     }
01083 
01084     for (i = 0; i < expl->n; i++)
01085     {
01086       tree_feat = &expl->features[i];
01087       bbf_data = (BbfData*) malloc (sizeof (BbfData));
01088       if (!bbf_data)
01089       {
01090         fprintf (stderr, "Warning: unable to allocate memory, %s line %d\n", __FILE__, __LINE__);
01091         goto fail;
01092       }
01093 
01094       bbf_data->old_data = tree_feat->feature_data;
01095       bbf_data->d = descrDistSq (feat, tree_feat, flags);
01096       tree_feat->feature_data = bbf_data;
01097       n += insertIntoNbrArray (tree_feat, _nbrs, n, k);
01098     }
01099     t++;
01100   }
01101 
01102   releaseMinPq (&min_pq);
01103   for (i = 0; i < n; i++)
01104   {
01105     bbf_data = (BbfData*) _nbrs[i]->feature_data;
01106     _nbrs[i]->feature_data = bbf_data->old_data;
01107     free (bbf_data);
01108   }
01109   *nbrs = _nbrs;
01110   return n;
01111 
01112   fail:
01113   releaseMinPq (&min_pq);
01114   for (i = 0; i < n; i++)
01115   {
01116     bbf_data = (BbfData*) _nbrs[i]->feature_data;
01117     _nbrs[i]->feature_data = bbf_data->old_data;
01118     free (bbf_data);
01119   }
01120   free (_nbrs);
01121   *nbrs = NULL;
01122   return -1;
01123 }
01124 
01125 MinPq* PlaceRecognition::initMinPq ()
01126 {
01127   MinPq* min_pq;
01128   min_pq = (MinPq*) malloc (sizeof (MinPq));
01129   min_pq->pq_array = (PqNode*) calloc (MINPQ_INIT_NALLOCD, sizeof (PqNode));
01130   min_pq->nallocd = MINPQ_INIT_NALLOCD;
01131   min_pq->n = 0;
01132 
01133   return min_pq;
01134 }
01135 
01136 int PlaceRecognition::insertMinPq (MinPq* min_pq, void* data, int key)
01137 {
01138   int n = min_pq->n;
01139 
01140   /* Double array allocation if necessary */
01141   if (min_pq->nallocd == n)
01142   {
01143     min_pq->nallocd = doubleArray ((void**) &min_pq->pq_array, min_pq->nallocd, sizeof (PqNode));
01144     if (!min_pq->nallocd)
01145     {
01146       fprintf (stderr, "Warning: unable to allocate memory, %s, line %d\n", __FILE__, __LINE__);
01147       return 1;
01148     }
01149   }
01150 
01151   min_pq->pq_array[n].data = data;
01152   min_pq->pq_array[n].key = INT_MAX;
01153   decreasePqNodeKey (min_pq->pq_array, min_pq->n, key);
01154   min_pq->n++;
01155 
01156   return 0;
01157 }
01158 
01159 
01160 void PlaceRecognition::decreasePqNodeKey (PqNode* pq_array, int i, int key)
01161 {
01162   PqNode tmp;
01163 
01164   if (key > pq_array[i].key)
01165     return;
01166 
01167   pq_array[i].key = key;
01168   while (i > 0 && pq_array[i].key < pq_array[parent (i)].key)
01169   {
01170     tmp = pq_array[parent (i)];
01171     pq_array[parent (i)] = pq_array[i];
01172     pq_array[i] = tmp;
01173     i = parent (i);
01174   }
01175 }
01176 
01177 
01178 /*
01179 * Recursively restores correct priority queue order to a minimizing pq array
01180 *  @param pq_array a minimizing priority queue array
01181 *  @param i index at which to start reordering
01182 *  @param n number of elements in \a pq_array
01183 */
01184 void PlaceRecognition::restoreMinPqOrder (PqNode* pq_array, int i, int n)
01185 {
01186   PqNode tmp;
01187   int l, r, min = i;
01188 
01189   l = left (i);
01190   r = right (i);
01191   if (l < n)
01192     if (pq_array[l].key < pq_array[i].key)
01193       min = l;
01194   if (r < n)
01195     if (pq_array[r].key < pq_array[min].key)
01196       min = r;
01197 
01198   if (min != i)
01199   {
01200     tmp = pq_array[min];
01201     pq_array[min] = pq_array[i];
01202     pq_array[i] = tmp;
01203     restoreMinPqOrder (pq_array, min, n);
01204   }
01205 }
01206 
01207 void* PlaceRecognition::minPqExtractMin (MinPq* min_pq)
01208 {
01209   void* data;
01210 
01211   if (min_pq->n < 1)
01212   {
01213     fprintf (stderr, "Warning: PQ empty, %s line %d\n", __FILE__, __LINE__);
01214     return NULL;
01215   }
01216   data = min_pq->pq_array[0].data;
01217   min_pq->n--;
01218   min_pq->pq_array[0] = min_pq->pq_array[min_pq->n];
01219   restoreMinPqOrder (min_pq->pq_array, 0, min_pq->n);
01220 
01221   return data;
01222 }
01223 
01224 SURFKDNode* PlaceRecognition::exploreToLeaf (SURFKDNode* kd_node, SURFDescriptor* feat, MinPq* min_pq, int flags)
01225 {
01226   SURFKDNode* unexpl, *expl = kd_node;
01227   double kv;
01228   int ki;
01229   int d = (flags & CV_SURF_EXTENDED) ? 128 : 64;
01230 
01231   while (expl && !expl->leaf)
01232   {
01233     ki = expl->ki;
01234     kv = expl->kv;
01235 
01236     if (ki >= d)
01237     {
01238       fprintf (stderr, "Warning: comparing imcompatible descriptors, %s line %d\n", __FILE__, __LINE__);
01239       return NULL;
01240     }
01241     if (feat->vector[ki] <= kv)
01242     {
01243       unexpl = expl->kd_right;
01244       expl = expl->kd_left;
01245     }
01246     else
01247     {
01248       unexpl = expl->kd_left;
01249       expl = expl->kd_right;
01250     }
01251 
01252     if (insertMinPq (min_pq, unexpl, (int) abs (kv - feat->vector[ki])))
01253     {
01254       fprintf (stderr, "Warning: unable to insert into PQ, %s, line %d\n", __FILE__, __LINE__);
01255       return NULL;
01256     }
01257   }
01258 
01259   return expl;
01260 }
01261 
01262 double PlaceRecognition::descrDistSq (SURFDescriptor* f1, SURFDescriptor* f2, int flags)
01263 {
01264   double diff, dsq = 0;
01265   double *descr1, *descr2;
01266   int i;
01267   int d = (flags & CV_SURF_EXTENDED) ? 128 : 64;
01268 
01269   descr1 = f1->vector;
01270   descr2 = f2->vector;
01271 
01272   for (i = 0; i < d; i++)
01273   {
01274     diff = descr1[i] - descr2[i];
01275     dsq += diff * diff;
01276   }
01277 
01278   return dsq;
01279 }
01280 
01281 int PlaceRecognition::insertIntoNbrArray (SURFDescriptor* feat, SURFDescriptor** nbrs, int n, int k)
01282 {
01283   BbfData *fdata, *ndata;
01284   double dn, df;
01285   int i, ret = 0;
01286 
01287   if (n == 0)
01288   {
01289     nbrs[0] = feat;
01290     return 1;
01291   }
01292 
01293   /* Check at end of array */
01294   fdata = (BbfData*) feat->feature_data;
01295   df = fdata->d;
01296   ndata = (BbfData*) nbrs[n - 1]->feature_data;
01297   dn = ndata->d;
01298   if (df >= dn)
01299   {
01300     if (n == k)
01301       {
01302         feat->feature_data = fdata->old_data;
01303         free (fdata);
01304         return 0;
01305       }
01306       nbrs[n] = feat;
01307       return 1;
01308   }
01309 
01310   /* Find the right place in the array */
01311   if (n < k)
01312   {
01313     nbrs[n] = nbrs[n - 1];
01314     ret = 1;
01315   }
01316   else
01317   {
01318     nbrs[n - 1]->feature_data = ndata->old_data;
01319     free (ndata);
01320   }
01321   i = n - 2;
01322   while (i >= 0)
01323   {
01324     ndata = (BbfData*) nbrs[i]->feature_data;
01325     dn = ndata->d;
01326     if (dn <= df)
01327       break;
01328     nbrs[i + 1] = nbrs[i];
01329     i--;
01330   }
01331   i++;
01332   nbrs[i] = feat;
01333 
01334   return ret;
01335 }
01336 
01337 void PlaceRecognition::releaseMinPq (MinPq** min_pq)
01338 {
01339   if (!min_pq)
01340   {
01341     fprintf (stderr, "Warning: NULL pointer error, %s line %d\n", __FILE__, __LINE__);
01342     return;
01343   }
01344   if (*min_pq && (*min_pq)->pq_array)
01345   {
01346     free ((*min_pq)->pq_array);
01347     free (*min_pq);
01348     *min_pq = NULL;
01349   }
01350 }
01351 
01352 int PlaceRecognition::doubleArray (void** array, int n, int size)
01353 {
01354   void* tmp;
01355 
01356   tmp = realloc (*array, 2 * n * size);
01357   if (!tmp)
01358   {
01359     fprintf (stderr, "Warning: unable to allocate memory in array_double(), %s line %d\n", __FILE__, __LINE__);
01360     if (*array)
01361       free (*array);
01362     *array = NULL;
01363     return 0;
01364   }
01365   *array = tmp;
01366   return n * 2;
01367 }
01368 
01369 double PlaceRecognition::getMatchDegree (CvSeq* seq)
01370 {
01371   // Calculate the ratation translation matrix, excluding mismatching
01372   execute (seq);
01373 
01374   /***************** calculate error *****************/
01375   int n = seq->total / 2;
01376   if_false_pairs.resize (n);
01377   for (int eff = 0; eff < n; eff++)
01378   {
01379     if_false_pairs[eff] = false;
01380   }
01381   eff_match_pairs = 0;
01382   if ((int) RMatrixPlist.size () <= 0)
01383     for (int eff = 0; eff < n; eff++)
01384     {
01385       if_false_pairs[eff] = true;
01386     }
01387 
01388   double RMatrixt[9];
01389   double TVectort[3];
01390   double max_match = -111, match_deg;
01391 
01392   for (int i = 0; i < (int) RMatrixPlist.size (); i++)
01393   {
01394     for (int j = 0; j < 9; j++)
01395     {
01396       RMatrixt[j] = RMatrixPlist[i][j];
01397     }
01398     for (int j = 0; j < 3; j++)
01399       TVectort[j] = TVectorPlist[i][j];
01400 
01401     match_deg = calculateErr (seq, RMatrixt, TVectort);
01402 
01403     if (match_deg > max_match)
01404     {
01405       eff_match_pairs = 0;
01406       for (int number = 0; number < n; number++)
01407       {
01408         if (if_false_pairs[number] == false)
01409           eff_match_pairs++;
01410       }
01411       if (eff_match_pairs >= MIN_AMOUNT)
01412       {
01413         max_match = match_deg;
01414       }
01415     }
01416   }
01417 
01418   return (max_match);
01419 }
01420 
01421 void PlaceRecognition::execute (CvSeq* seq)
01422 {
01423   transMatrix (seq);
01424   initSelect (seq);
01425   do
01426   {
01427     cutFalseMatrix ();
01428   } while ((int) RMatrixPlist.size () > 10);
01429 }
01430 
01431 void PlaceRecognition::transMatrix (CvSeq* seq)
01432 {
01433   RMatrixPlist.clear ();
01434   TVectorPlist.clear ();
01435   int surfpairmum = (seq->total / 2);
01436   if ((seq->total / 2) < 4)
01437     return;
01438 
01439   for (int n = 3; n < surfpairmum; n++)
01440   {
01441     if ((int) RMatrixPlist.size () >= 1000)
01442     {
01443       break;
01444     }
01445     for (int m = 2; m < n; m++)
01446     {
01447       if ((int) RMatrixPlist.size () >= 1000)
01448       {
01449         break;
01450       }
01451       for (int j = 1; j < m; j++)
01452       {
01453         if ((int) RMatrixPlist.size () >= 1000)
01454         {
01455           break;
01456         }
01457         for (int i = 0; i < j; i++)
01458         {
01459           SURFDescriptor * tmp = (SURFDescriptor*) cvGetSeqElem (seq, 2 * i);
01460           sce_points.push_back (tmp->cor_point);
01461           tmp = (SURFDescriptor*) cvGetSeqElem (seq, 2 * j);
01462           sce_points.push_back (tmp->cor_point);
01463           tmp = (SURFDescriptor*) cvGetSeqElem (seq, 2 * m);
01464           sce_points.push_back (tmp->cor_point);
01465           tmp = (SURFDescriptor*) cvGetSeqElem (seq, 2 * n);
01466           sce_points.push_back (tmp->cor_point);
01467           tmp = (SURFDescriptor*) cvGetSeqElem (seq, 2 * i + 1);
01468           lib_points.push_back (tmp->cor_point);
01469           tmp = (SURFDescriptor*) cvGetSeqElem (seq, 2 * j + 1);
01470           lib_points.push_back (tmp->cor_point);
01471           tmp = (SURFDescriptor*) cvGetSeqElem (seq, 2 * m + 1);
01472           lib_points.push_back (tmp->cor_point);
01473           tmp = (SURFDescriptor*) cvGetSeqElem (seq, 2 * n + 1);
01474           lib_points.push_back (tmp->cor_point);
01475           Matrix ();
01476           SVD ();
01477           double* RMatrixp;
01478           double* TVectorp;
01479           RMatrixp = new double[9];
01480           TVectorp = new double[3];
01481           for (int i = 0; i < 9; i++)
01482           {
01483             RMatrixp[i] = RMatrix[i];
01484           }
01485           for (int j = 0; j < 3; j++)
01486           {
01487             TVectorp[j] = TVector[j];
01488           }
01489           RMatrixPlist.push_back (RMatrixp);
01490           TVectorPlist.push_back (TVectorp);
01491           sce_points.clear ();
01492           lib_points.clear ();
01493           if ((int) RMatrixPlist.size () >= 1000)
01494           {
01495             break;
01496           }
01497         }
01498       }
01499     }
01500   }
01501 }
01502 
01503 /* Calculate A*AH and AH*A matrix */
01504 void PlaceRecognition::Matrix ()
01505 {
01506   std::vector < pcl::PointXYZ >::iterator IT1;
01507   std::vector < pcl::PointXYZ >::iterator IT2;
01508   centroid1.x = 0;
01509   centroid1.y = 0;
01510   centroid1.z = 0;
01511   centroid2.x = 0;
01512   centroid2.y = 0;
01513   centroid2.z = 0;
01514 
01515   for (IT1 = lib_points.begin (); IT1 != lib_points.end (); IT1++)
01516   {
01517     centroid1.x = centroid1.x + (*IT1).x;
01518     centroid1.y = centroid1.y + (*IT1).y;
01519     centroid1.z = centroid1.z + (*IT1).z;
01520   }
01521   centroid1.x = centroid1.x / lib_points.size ();
01522   centroid1.y = centroid1.y / lib_points.size ();
01523   centroid1.z = centroid1.z / lib_points.size ();
01524   for (IT1 = lib_points.begin (); IT1 != lib_points.end (); IT1++)
01525   {
01526     (*IT1).x = (*IT1).x - centroid1.x;
01527     (*IT1).y = (*IT1).y - centroid1.y;
01528     (*IT1).z = (*IT1).z - centroid1.z;
01529   }
01530 
01531   for (IT2 = sce_points.begin (); IT2 != sce_points.end (); IT2++)
01532   {
01533     centroid2.x = centroid2.x + (*IT2).x;
01534     centroid2.y = centroid2.y + (*IT2).y;
01535     centroid2.z = centroid2.z + (*IT2).z;
01536   }
01537   centroid2.x = centroid2.x / sce_points.size ();
01538   centroid2.y = centroid2.y / sce_points.size ();
01539   centroid2.z = centroid2.z / sce_points.size ();
01540   for (IT2 = sce_points.begin (); IT2 != sce_points.end (); IT2++)
01541   {
01542     (*IT2).x = (*IT2).x - centroid2.x;
01543     (*IT2).y = (*IT2).y - centroid2.y;
01544     (*IT2).z = (*IT2).z - centroid2.z;
01545   }
01546 
01547   /* Initialization */
01548   A[0] = 0;
01549   A[1] = 0;
01550   A[2] = 0;
01551   A[3] = 0;
01552   A[4] = 0;
01553   A[5] = 0;
01554   A[6] = 0;
01555   A[7] = 0;
01556   A[8] = 0;
01557 
01558   for (IT1 = lib_points.begin (), IT2 = sce_points.begin (); IT1 != lib_points.end (); IT1++, IT2++)
01559   {
01560     /* A */
01561     A[0] = A[0] + (*IT2).x * (*IT1).x;
01562     A[1] = A[1] + (*IT2).x * (*IT1).y;
01563     A[2] = A[2] + (*IT2).x * (*IT1).z;
01564     A[3] = A[3] + (*IT2).y * (*IT1).x;
01565     A[4] = A[4] + (*IT2).y * (*IT1).y;
01566     A[5] = A[5] + (*IT2).y * (*IT1).z;
01567     A[6] = A[6] + (*IT2).z * (*IT1).x;
01568     A[7] = A[7] + (*IT2).z * (*IT1).y;
01569     A[8] = A[8] + (*IT2).z * (*IT1).z;
01570   }
01571 
01572   /* A*AH */
01573   A_AH[0] = A[0] * A[0] + A[1] * A[1] + A[2] * A[2];
01574   A_AH[1] = A[0] * A[3] + A[1] * A[4] + A[2] * A[5];
01575   A_AH[2] = A[0] * A[6] + A[1] * A[7] + A[2] * A[8];
01576   A_AH[3] = A[3] * A[0] + A[4] * A[1] + A[5] * A[2];
01577   A_AH[4] = A[3] * A[3] + A[4] * A[4] + A[5] * A[5];
01578   A_AH[5] = A[3] * A[6] + A[4] * A[7] + A[5] * A[8];
01579   A_AH[6] = A[6] * A[0] + A[7] * A[1] + A[8] * A[2];
01580   A_AH[7] = A[6] * A[3] + A[7] * A[4] + A[8] * A[5];
01581   A_AH[8] = A[6] * A[6] + A[7] * A[7] + A[8] * A[8];
01582 
01583   /* AH*A */
01584   AH_A[0] = A[0] * A[0] + A[3] * A[3] + A[6] * A[6];
01585   AH_A[1] = A[0] * A[1] + A[3] * A[4] + A[6] * A[7];
01586   AH_A[2] = A[0] * A[2] + A[3] * A[5] + A[6] * A[8];
01587   AH_A[3] = A[1] * A[0] + A[4] * A[3] + A[7] * A[6];
01588   AH_A[4] = A[1] * A[1] + A[4] * A[4] + A[7] * A[7];
01589   AH_A[5] = A[1] * A[2] + A[4] * A[5] + A[7] * A[8];
01590   AH_A[6] = A[2] * A[0] + A[5] * A[3] + A[8] * A[6];
01591   AH_A[7] = A[2] * A[1] + A[5] * A[4] + A[8] * A[7];
01592   AH_A[8] = A[2] * A[2] + A[5] * A[5] + A[8] * A[8];
01593 }
01594 
01595 /* Calculate rotation matrix R and translation vector T */
01596 void PlaceRecognition::SVD ()
01597 {
01598   int SUC1 = Jcbi (A_AH, U); /* Calculate eigenvector and eigenvalue of A*AH */
01599   int SUC2 = Jcbi (AH_A, V); /* Calculate eigenvector and eigenvalue of AH*A */
01600 
01601   RMatrix[0] = V[0] * U[0] + V[1] * U[1] + V[2] * U[2];
01602   RMatrix[1] = V[0] * U[3] + V[1] * U[4] + V[2] * U[5];
01603   RMatrix[2] = V[0] * U[6] + V[1] * U[7] + V[2] * U[8];
01604   RMatrix[3] = V[3] * U[0] + V[4] * U[1] + V[5] * U[2];
01605   RMatrix[4] = V[3] * U[3] + V[4] * U[4] + V[5] * U[5];
01606   RMatrix[5] = V[3] * U[6] + V[4] * U[7] + V[5] * U[8];
01607   RMatrix[6] = V[6] * U[0] + V[7] * U[1] + V[8] * U[2];
01608   RMatrix[7] = V[6] * U[3] + V[7] * U[4] + V[8] * U[5];
01609   RMatrix[8] = V[6] * U[6] + V[7] * U[7] + V[8] * U[8];
01610 
01611   TVector[0] = centroid1.x - RMatrix[0] * centroid2.x - RMatrix[1] * centroid2.y - RMatrix[2] * centroid2.z;
01612   TVector[1] = centroid1.y - RMatrix[3] * centroid2.x - RMatrix[4] * centroid2.y - RMatrix[5] * centroid2.z;
01613   TVector[2] = centroid1.z - RMatrix[6] * centroid2.x - RMatrix[7] * centroid2.y - RMatrix[8] * centroid2.z;
01614 }
01615 
01616 /* Calculate eigenvalue and eigenvector */
01617 int PlaceRecognition::Jcbi (double A[], double V[])
01618 {
01619   int i, j, p, q, u, w, t, s, l;
01620   double fm, cn, sn, omega, x, y, d;
01621   l = 1;
01622   double eps = 0.1;
01623   int jt = 10;
01624   int n = 3;
01625   for (i = 0; i <= n - 1; i++)
01626   {
01627     V[i * n + i] = 1.0;
01628     for (j = 0; j <= n - 1; j++)
01629       if (i != j)
01630         V[i * n + j] = 0.0;
01631   }
01632   while (1 == 1)
01633   {
01634     fm = 0.0;
01635     for (i = 1; i <= n - 1; i++)
01636       for (j = 0; j <= i - 1; j++)
01637         {
01638           d = fabs (A[i * n + j]);
01639           if ((i != j) && (d > fm))
01640           {
01641             fm = d;
01642             p = i;
01643             q = j;
01644           }
01645         }
01646 
01647     if (fm < eps)
01648       return (1);
01649     if (l > jt)
01650       return (-1);
01651     l = l + 1;
01652     u = p * n + q;
01653     w = p * n + p;
01654     t = q * n + p;
01655     s = q * n + q;
01656     x = -A[u];
01657     y = (A[s] - A[w]) / 2.0;
01658     omega = x / sqrt (x * x + y * y);
01659     if (y < 0.0)
01660       omega = -omega;
01661     sn = 1.0 + sqrt (1.0 - omega * omega);
01662     sn = omega / sqrt (2.0 * sn);
01663     cn = sqrt (1.0 - sn * sn);
01664     fm = A[w];
01665     A[w] = fm * cn * cn + A[s] * sn * sn + A[u] * omega;
01666     A[s] = fm * sn * sn + A[s] * cn * cn - A[u] * omega;
01667     A[u] = 0.0;
01668     A[t] = 0.0;
01669     for (j = 0; j <= n - 1; j++)
01670     {
01671       if ((j != p) && (j != q))
01672       {
01673         u = p * n + j;
01674         w = q * n + j;
01675         fm = A[u];
01676         A[u] = fm * cn + A[w] * sn;
01677         A[w] = -fm * sn + A[w] * cn;
01678       }
01679     }
01680 
01681     for (i = 0; i <= n - 1; i++)
01682     {
01683       if ((i != p) && (i != q))
01684       {
01685         u = i * n + p;
01686         w = i * n + q;
01687         fm = A[u];
01688         A[u] = fm * cn + A[w] * sn;
01689         A[w] = -fm * sn + A[w] * cn;
01690       }
01691     }
01692 
01693     for (i = 0; i <= n - 1; i++)
01694     {
01695       u = i * n + p;
01696       w = i * n + q;
01697       fm = V[u];
01698       V[u] = fm * cn + V[w] * sn;
01699       V[w] = -fm * sn + V[w] * cn;
01700     }
01701   }
01702 
01703   return (1);
01704 }
01705 
01706 void PlaceRecognition::initSelect (CvSeq* seq)
01707 {
01708   std::vector < double* >::iterator Riter;
01709   std::vector < double* >::iterator Titer;
01710   for (Riter = RMatrixPlist.begin (), Titer = TVectorPlist.begin (); Riter < RMatrixPlist.end ();)
01711   {
01712     if (!Marix (seq, *Riter, *Titer))
01713     {
01714       delete[](*Riter);
01715       Riter = RMatrixPlist.erase (Riter);
01716       delete[](*Titer);
01717       Titer = TVectorPlist.erase (Titer);
01718     }
01719     else
01720     {
01721       Riter++;
01722       Titer++;
01723     }
01724   }
01725 }
01726 
01727 bool PlaceRecognition::Marix (CvSeq* seq, double* RMatrix, double* TVector)
01728 {
01729   for (int i = 0; i < (seq->total / 2); i++)
01730   {
01731     pcl::PointXYZ tem_point;
01732     SURFDescriptor* tmp = (SURFDescriptor*) cvGetSeqElem (seq, 2 * i);
01733 
01734     tem_point.x = RMatrix[0] * tmp->cor_point.x + RMatrix[1] * tmp->cor_point.y +
01735                   RMatrix[2] * tmp->cor_point.z + TVector[0];
01736 
01737     tem_point.y = RMatrix[3] * tmp->cor_point.x + RMatrix[4] * tmp->cor_point.y +
01738                   RMatrix[5] * tmp->cor_point.z + TVector[1];
01739 
01740     tem_point.z = RMatrix[6] * tmp->cor_point.x + RMatrix[7] * tmp->cor_point.y +
01741                   RMatrix[8] * tmp->cor_point.z + TVector[2];
01742 
01743     tmp = (SURFDescriptor*) cvGetSeqElem (seq, 2 * i + 1);
01744     double dist = sqrt ((tem_point.x - tmp->cor_point.x) * (tem_point.x - tmp->cor_point.x) +
01745                         (tem_point.y - tmp->cor_point.y) * (tem_point.y - tmp->cor_point.y) +
01746                         (tem_point.z - tmp->cor_point.z) * (tem_point.z - tmp->cor_point.z));
01747 
01748     if (dist <= DISMAX)
01749     {
01750       return true;
01751     }
01752   }
01753 
01754   return false;
01755 }
01756 
01757 /* Delete the false rotation matrix */
01758 void PlaceRecognition::cutFalseMatrix ()
01759 {
01760   int rawDataNum = int (RMatrixPlist.size ());
01761   if (rawDataNum >= 2)
01762   {
01763     CvMat* rawData_matrix = cvCreateMat (rawDataNum, MAXDIM, CV_32FC1);
01764     CvMat* clusters = cvCreateMat (rawDataNum, 1, CV_32SC1);  /* After cluster */
01765 
01766     for (int i = 0; i < rawDataNum; i++)
01767     {
01768       rawData_matrix->data.fl[i * MAXDIM] = RMatrixPlist[i][0];
01769       rawData_matrix->data.fl[i * MAXDIM + 1] = RMatrixPlist[i][1];
01770       rawData_matrix->data.fl[i * MAXDIM + 2] = RMatrixPlist[i][2];
01771       rawData_matrix->data.fl[i * MAXDIM + 3] = RMatrixPlist[i][3];
01772       rawData_matrix->data.fl[i * MAXDIM + 4] = RMatrixPlist[i][4];
01773       rawData_matrix->data.fl[i * MAXDIM + 5] = RMatrixPlist[i][5];
01774       rawData_matrix->data.fl[i * MAXDIM + 6] = RMatrixPlist[i][6];
01775       rawData_matrix->data.fl[i * MAXDIM + 7] = RMatrixPlist[i][7];
01776       rawData_matrix->data.fl[i * MAXDIM + 8] = RMatrixPlist[i][8];
01777     }
01778     /* Use K-means clustering into two groups */
01779     cvKMeans2 (rawData_matrix, CLUSTERINGNUM, clusters,
01780                cvTermCriteria (CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 20, 0.01));
01781     int Cluster1Num = 0;
01782     int Clsuter2Num = 0;
01783     for (int j = 0; j < rawDataNum; j++)
01784     {
01785       if (clusters->data.i[j] == 0)
01786       {
01787         Cluster1Num++;
01788       }
01789       else
01790       Clsuter2Num++;
01791     }
01792  
01793     int TrueTag;
01794     TrueTag = (int) (Cluster1Num > Clsuter2Num ? 0 : 1);
01795     std::vector < double* >::iterator Riter;
01796     std::vector < double* >::iterator Titer;
01797     int j = 0;
01798     for (Riter = RMatrixPlist.begin (), Titer = TVectorPlist.begin (); Riter < RMatrixPlist.end ();)
01799     {
01800       if (clusters->data.i[j] != TrueTag)
01801       {
01802         delete[](*Riter);
01803         Riter = RMatrixPlist.erase (Riter);
01804         delete[](*Titer);
01805         Titer = TVectorPlist.erase (Titer);
01806       }
01807       else
01808       {
01809         Riter++;
01810         Titer++;
01811       }
01812       j++;
01813     }
01814   }
01815   else
01816   {
01817     return;
01818   }
01819 }
01820 
01821 double PlaceRecognition::calculateErr (CvSeq* seq, double RMatrix[9], double TVector[3])
01822 {
01823   /* All participating checkout */
01824   int n = seq->total;
01825   if_false_pairs.resize (n);
01826   for (int eff = 0; eff < n; eff++)
01827   {
01828     if_false_pairs[eff] = false;
01829   } 
01830   double sum_err = 0;
01831   int counter = n;
01832   for (int i = 0; i < n; i++)
01833   {
01834     SURFDescriptor* tmp1 = (SURFDescriptor*) cvGetSeqElem (seq, 2 * i);
01835     pcl::PointXYZ data = tmp1->cor_point;  /* Corresponding laser scanning data */
01836     pcl::PointXYZ data4;
01837     data4.x = RMatrix[0] * data.x + RMatrix[1] * data.y + RMatrix[2] * data.z + TVector[0];
01838     data4.y = RMatrix[3] * data.x + RMatrix[4] * data.y + RMatrix[5] * data.z + TVector[1];
01839     data4.z = RMatrix[6] * data.x + RMatrix[7] * data.y + RMatrix[8] * data.z + TVector[2];
01840     bool flag = false;
01841     double max = 0.0;
01842     tmp1 = (SURFDescriptor*) cvGetSeqElem (seq, 2 * i + 1);
01843     pcl::PointXYZ data3 = tmp1->cor_point;
01844 
01845     double d1 = sqrt ((data4.x - data3.x) * (data4.x - data3.x) +
01846                       (data4.y - data3.y) * (data4.y - data3.y) +
01847                       (data4.z - data3.z) * (data4.z - data3.z));
01848     double d2 = sqrt ((data4.x * data4.x) + (data4.y * data4.y) + (data4.z * data4.z));
01849     double d3 = sqrt ((data3.x * data3.x) + (data3.y * data3.y) + (data3.z * data3.z));
01850 
01851     double alph = acos ((d2 * d2 + d3 * d3 - d1 * d1) / (2 * d2 * d3));
01852     alph = alph * 180 / PI;
01853     if (alph < DANGLE)      /* A range of given angle */
01854     {
01855       flag = true;
01856       if (max < (1 - alph / DANGLE))
01857       max = (1 - alph / DANGLE);
01858     }
01859 
01860     if (flag == false)
01861     {
01862       if_false_pairs[i] = true;
01863       counter--;
01864     }
01865     sum_err += max;
01866   }
01867 
01868   double s = 0;
01869   if (counter > 0 && counter < MINN)
01870   {
01871     double t = -(counter - MINN) * (counter - MINN) / (2 * 3 * 3);
01872     s = (1.0 / counter) * (sum_err) * exp (t);
01873   }
01874   else if (counter <= 0)
01875     s = 0;
01876   else
01877     s = (1.0 / counter) * (sum_err);
01878 
01879   return s;
01880 }


dlut_place_recognition
Author(s): Qinghua Li, Yan Zhuang, Fei Yan
autogenerated on Sun Oct 5 2014 23:29:57