Home | History | Annotate | Download | only in dbregtest
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // $Id: dbregtest.cpp,v 1.24 2011/06/17 14:04:33 mbansal Exp $
     18 #include "stdafx.h"
     19 #include "PgmImage.h"
     20 #include "../dbreg/dbreg.h"
     21 #include "../dbreg/dbstabsmooth.h"
     22 #include <db_utilities_camera.h>
     23 
     24 #include <iostream>
     25 #include <iomanip>
     26 
     27 #if PROFILE
     28     #include <sys/time.h>
     29 #endif
     30 
     31 
     32 using namespace std;
     33 
     34 const int DEFAULT_NR_CORNERS=500;
     35 const double DEFAULT_MAX_DISPARITY=0.2;
     36 const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_AFFINE;
     37 //const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_R_T;
     38 //const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_TRANSLATION;
     39 const bool DEFAULT_QUARTER_RESOLUTION=false;
     40 const unsigned int DEFAULT_REFERENCE_UPDATE_PERIOD=3;
     41 const bool DEFAULT_DO_MOTION_SMOOTHING = false;
     42 const double DEFAULT_MOTION_SMOOTHING_GAIN = 0.75;
     43 const bool DEFAULT_LINEAR_POLISH = false;
     44 const int DEFAULT_MAX_ITERATIONS = 10;
     45 
     46 void usage(string name) {
     47 
     48   const char *helpmsg[] = {
     49     "Function: point-based frame to reference registration.",
     50     "  -m [rt,a,p]  : motion model, rt = rotation+translation, a = affine (default = affine).",
     51     "  -c <int>   : number of corners (default 1000).",
     52     "  -d <double>: search disparity as portion of image size (default 0.1).",
     53     "  -q         : quarter the image resolution (i.e. half of each dimension) (default on)",
     54     "  -r <int>   : the period (in nr of frames) for reference frame updates (default = 5)",
     55     "  -s <0/1>   : motion smoothing (1 activates motion smoothing, 0 turns it off - default value = 1)",
     56     "  -g <double>: motion smoothing gain, only used if smoothing is on (default value =0.75)",
     57     NULL
     58   };
     59 
     60   cerr << "Usage: " << name << " [options] image_list.txt" << endl;
     61 
     62   const char **p = helpmsg;
     63 
     64   while (*p)
     65   {
     66     cerr << *p++ << endl;
     67   }
     68 }
     69 
     70 void parse_cmd_line(stringstream& cmdline,
     71             const int argc,
     72             const string& progname,
     73             string& image_list_file_name,
     74             int& nr_corners,
     75             double& max_disparity,
     76             int& motion_model_type,
     77             bool& quarter_resolution,
     78             unsigned int& reference_update_period,
     79             bool& do_motion_smoothing,
     80             double& motion_smoothing_gain
     81             );
     82 
     83 int main(int argc, char* argv[])
     84 {
     85   int    nr_corners = DEFAULT_NR_CORNERS;
     86   double max_disparity = DEFAULT_MAX_DISPARITY;
     87   int    motion_model_type = DEFAULT_MOTION_MODEL;
     88   bool   quarter_resolution = DEFAULT_QUARTER_RESOLUTION;
     89 
     90   unsigned int reference_update_period = DEFAULT_REFERENCE_UPDATE_PERIOD;
     91 
     92   bool   do_motion_smoothing = DEFAULT_DO_MOTION_SMOOTHING;
     93   double motion_smoothing_gain = DEFAULT_MOTION_SMOOTHING_GAIN;
     94   const bool DEFAULT_USE_SMALLER_MATCHING_WINDOW = true;
     95 
     96   int default_nr_samples = DB_DEFAULT_NR_SAMPLES/5;
     97 
     98   bool   use_smaller_matching_window = DEFAULT_USE_SMALLER_MATCHING_WINDOW;
     99 
    100 
    101   bool   linear_polish = DEFAULT_LINEAR_POLISH;
    102 
    103   if (argc < 2) {
    104     usage(argv[0]);
    105     exit(1);
    106   }
    107 
    108   stringstream cmdline;
    109   string progname(argv[0]);
    110   string image_list_file_name;
    111 
    112 #if PROFILE
    113   timeval ts1, ts2, ts3, ts4;
    114 #endif
    115 
    116   // put the options and image list file name into the cmdline stringstream
    117   for (int c = 1; c < argc; c++)
    118   {
    119     cmdline << argv[c] << " ";
    120   }
    121 
    122   parse_cmd_line(cmdline, argc, progname, image_list_file_name, nr_corners, max_disparity, motion_model_type,quarter_resolution,reference_update_period,do_motion_smoothing,motion_smoothing_gain);
    123 
    124   ifstream in(image_list_file_name.c_str(),ios::in);
    125 
    126   if ( !in.is_open() )
    127   {
    128     cerr << "Could not open file " << image_list_file_name << ".  Exiting" << endl;
    129 
    130     return false;
    131   }
    132 
    133   // feature-based image registration class:
    134   db_FrameToReferenceRegistration reg;
    135 //  db_StabilizationSmoother stab_smoother;
    136 
    137   // input file name:
    138   string file_name;
    139 
    140   // look-up tables for image warping:
    141   float ** lut_x = NULL, **lut_y = NULL;
    142 
    143   // if the images are color, the input is saved in color_ref:
    144   PgmImage color_ref(0,0);
    145 
    146   // image width, height:
    147   int w,h;
    148 
    149   int frame_number = 0;
    150 
    151   while ( !in.eof() )
    152   {
    153     getline(in,file_name);
    154 
    155     PgmImage ref(file_name);
    156 
    157     if ( ref.GetDataPointer() == NULL )
    158     {
    159       cerr << "Could not open image" << file_name << ". Exiting." << endl;
    160       return -1;
    161     }
    162 
    163     cout << ref << endl;
    164 
    165     // color format:
    166     int format = ref.GetFormat();
    167 
    168     // is the input image color?:
    169     bool color = format == PgmImage::PGM_BINARY_PIXMAP;
    170 
    171     w = ref.GetWidth();
    172     h = ref.GetHeight();
    173 
    174     if ( !reg.Initialized() )
    175     {
    176       reg.Init(w,h,motion_model_type,DEFAULT_MAX_ITERATIONS,linear_polish,quarter_resolution,DB_POINT_STANDARDDEV,reference_update_period,do_motion_smoothing,motion_smoothing_gain,default_nr_samples,DB_DEFAULT_CHUNK_SIZE,nr_corners,max_disparity,use_smaller_matching_window);
    177       lut_x = db_AllocImage_f(w,h);
    178       lut_y = db_AllocImage_f(w,h);
    179 
    180     }
    181 
    182     if ( color )
    183     {
    184       // save the color image:
    185       color_ref = ref;
    186     }
    187 
    188     // make a grayscale image:
    189     ref.ConvertToGray();
    190 
    191     // compute the homography:
    192     double H[9],Hinv[9];
    193     db_Identity3x3(Hinv);
    194     db_Identity3x3(H);
    195 
    196     bool force_reference = false;
    197 
    198 #if PROFILE
    199     gettimeofday(&ts1, NULL);
    200 #endif
    201 
    202     reg.AddFrame(ref.GetRowPointers(),H,false,false);
    203     cout << reg.profile_string << std::endl;
    204 
    205 #if PROFILE
    206     gettimeofday(&ts2, NULL);
    207 
    208     double elapsedTime = (ts2.tv_sec - ts1.tv_sec)*1000.0; // sec to ms
    209     elapsedTime += (ts2.tv_usec - ts1.tv_usec)/1000.0; // us to ms
    210     cout <<"\nelapsedTime for Reg<< "<<elapsedTime<<" ms >>>>>>>>>>>>>\n";
    211 #endif
    212 
    213     if (frame_number == 0)
    214     {
    215       reg.UpdateReference(ref.GetRowPointers());
    216     }
    217 
    218 
    219     //std::vector<int> &inlier_indices = reg.GetInliers();
    220     int *inlier_indices = reg.GetInliers();
    221     int num_inlier_indices = reg.GetNrInliers();
    222     printf("[%d] #Inliers = %d\n",frame_number,num_inlier_indices);
    223 
    224     reg.Get_H_dref_to_ins(H);
    225 
    226     db_GenerateHomographyLut(lut_x,lut_y,w,h,H);
    227 
    228     // create a new image and warp:
    229     PgmImage warped(w,h,format);
    230 
    231 #if PROFILE
    232     gettimeofday(&ts3, NULL);
    233 #endif
    234 
    235     if ( color )
    236       db_WarpImageLutBilinear_rgb(color_ref.GetRowPointers(),warped.GetRowPointers(),w,h,lut_x,lut_y);
    237     else
    238       db_WarpImageLut_u(ref.GetRowPointers(),warped.GetRowPointers(),w,h,lut_x,lut_y,DB_WARP_FAST);
    239 
    240 #if PROFILE
    241     gettimeofday(&ts4, NULL);
    242     elapsedTime = (ts4.tv_sec - ts3.tv_sec)*1000.0; // sec to ms
    243     elapsedTime += (ts4.tv_usec - ts3.tv_usec)/1000.0;     // us to ms
    244     cout <<"\nelapsedTime for Warp <<"<<elapsedTime<<" ms >>>>>>>>>>>>>\n";
    245 #endif
    246 
    247     // write aligned image: name is aligned_<corresponding input file name>
    248     stringstream s;
    249     s << "aligned_" << file_name;
    250     warped.WritePGM(s.str());
    251 
    252     /*
    253     // Get the reference and inspection corners to write to file
    254     double *ref_corners = reg.GetRefCorners();
    255     double *ins_corners = reg.GetInsCorners();
    256 
    257     // get the image file name (without extension), so we
    258     // can generate the corresponding filenames for matches
    259     // and inliers
    260     string file_name_root(file_name.substr(0,file_name.rfind(".")));
    261 
    262     // write matches to file
    263     s.str(string(""));
    264     s << "Matches_" << file_name_root << ".txt";
    265 
    266     ofstream  match_file(s.str().c_str());
    267 
    268     for (int i = 0; i < reg.GetNrMatches(); i++)
    269     {
    270       match_file << ref_corners[3*i] << " " << ref_corners[3*i+1] << " " << ins_corners[3*i] << " " << ins_corners[3*i+1] << endl;
    271     }
    272 
    273     match_file.close();
    274 
    275     // write the inlier matches to file
    276     s.str(string(""));
    277     s << "InlierMatches_" << file_name_root << ".txt";
    278 
    279     ofstream inlier_match_file(s.str().c_str());
    280 
    281     for(int i=0; i<num_inlier_indices; i++)
    282     {
    283       int k = inlier_indices[i];
    284       inlier_match_file << ref_corners[3*k] << " "
    285             << ref_corners[3*k+1] << " "
    286             << ins_corners[3*k] << " "
    287             << ins_corners[3*k+1] << endl;
    288     }
    289     inlier_match_file.close();
    290     */
    291 
    292     frame_number++;
    293   }
    294 
    295   if ( reg.Initialized() )
    296   {
    297     db_FreeImage_f(lut_x,h);
    298     db_FreeImage_f(lut_y,h);
    299   }
    300 
    301   return 0;
    302 }
    303 
    304 void parse_cmd_line(stringstream& cmdline,
    305             const int argc,
    306             const string& progname,
    307             string& image_list_file_name,
    308             int& nr_corners,
    309             double& max_disparity,
    310             int& motion_model_type,
    311             bool& quarter_resolution,
    312             unsigned int& reference_update_period,
    313             bool& do_motion_smoothing,
    314             double& motion_smoothing_gain)
    315 {
    316   // for counting down the parsed arguments.
    317   int c = argc;
    318 
    319   // a holder
    320   string token;
    321 
    322   while (cmdline >> token)
    323   {
    324     --c;
    325 
    326     int pos = token.find("-");
    327 
    328     if (pos == 0)
    329     {
    330       switch (token[1])
    331       {
    332       case 'm':
    333     --c; cmdline >> token;
    334     if (token.compare("rt") == 0)
    335     {
    336       motion_model_type = DB_HOMOGRAPHY_TYPE_R_T;
    337     }
    338     else if (token.compare("a") == 0)
    339     {
    340       motion_model_type = DB_HOMOGRAPHY_TYPE_AFFINE;
    341     }
    342     else if (token.compare("p") == 0)
    343     {
    344       motion_model_type = DB_HOMOGRAPHY_TYPE_PROJECTIVE;
    345     }
    346     else
    347     {
    348       usage(progname);
    349       exit(1);
    350     }
    351     break;
    352       case 'c':
    353     --c; cmdline >> nr_corners;
    354     break;
    355       case 'd':
    356     --c; cmdline >> max_disparity;
    357     break;
    358       case 'q':
    359     quarter_resolution = true;
    360     break;
    361       case 'r':
    362     --c; cmdline >> reference_update_period;
    363     break;
    364       case 's':
    365     --c; cmdline >> do_motion_smoothing;
    366     break;
    367       case 'g':
    368     --c; cmdline >> motion_smoothing_gain;
    369     break;
    370       default:
    371     cerr << progname << "illegal option " << token << endl;
    372       case 'h':
    373     usage(progname);
    374     exit(1);
    375     break;
    376       }
    377     }
    378     else
    379     {
    380       if (c != 1)
    381       {
    382     usage(progname);
    383     exit(1);
    384       }
    385       else
    386       {
    387     --c;
    388     image_list_file_name = token;
    389       }
    390     }
    391   }
    392 
    393   if (c != 0)
    394   {
    395     usage(progname);
    396     exit(1);
    397   }
    398 }
    399 
    400