/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // $Id: dbregtest.cpp,v 1.24 2011/06/17 14:04:33 mbansal Exp $ #include "stdafx.h" #include "PgmImage.h" #include "../dbreg/dbreg.h" #include "../dbreg/dbstabsmooth.h" #include #include #include #if PROFILE #include #endif using namespace std; const int DEFAULT_NR_CORNERS=500; const double DEFAULT_MAX_DISPARITY=0.2; const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_AFFINE; //const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_R_T; //const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_TRANSLATION; const bool DEFAULT_QUARTER_RESOLUTION=false; const unsigned int DEFAULT_REFERENCE_UPDATE_PERIOD=3; const bool DEFAULT_DO_MOTION_SMOOTHING = false; const double DEFAULT_MOTION_SMOOTHING_GAIN = 0.75; const bool DEFAULT_LINEAR_POLISH = false; const int DEFAULT_MAX_ITERATIONS = 10; void usage(string name) { const char *helpmsg[] = { "Function: point-based frame to reference registration.", " -m [rt,a,p] : motion model, rt = rotation+translation, a = affine (default = affine).", " -c : number of corners (default 1000).", " -d : search disparity as portion of image size (default 0.1).", " -q : quarter the image resolution (i.e. half of each dimension) (default on)", " -r : the period (in nr of frames) for reference frame updates (default = 5)", " -s <0/1> : motion smoothing (1 activates motion smoothing, 0 turns it off - default value = 1)", " -g : motion smoothing gain, only used if smoothing is on (default value =0.75)", NULL }; cerr << "Usage: " << name << " [options] image_list.txt" << endl; const char **p = helpmsg; while (*p) { cerr << *p++ << endl; } } void parse_cmd_line(stringstream& cmdline, const int argc, const string& progname, string& image_list_file_name, int& nr_corners, double& max_disparity, int& motion_model_type, bool& quarter_resolution, unsigned int& reference_update_period, bool& do_motion_smoothing, double& motion_smoothing_gain ); int main(int argc, char* argv[]) { int nr_corners = DEFAULT_NR_CORNERS; double max_disparity = DEFAULT_MAX_DISPARITY; int motion_model_type = DEFAULT_MOTION_MODEL; bool quarter_resolution = DEFAULT_QUARTER_RESOLUTION; unsigned int reference_update_period = DEFAULT_REFERENCE_UPDATE_PERIOD; bool do_motion_smoothing = DEFAULT_DO_MOTION_SMOOTHING; double motion_smoothing_gain = DEFAULT_MOTION_SMOOTHING_GAIN; const bool DEFAULT_USE_SMALLER_MATCHING_WINDOW = true; int default_nr_samples = DB_DEFAULT_NR_SAMPLES/5; bool use_smaller_matching_window = DEFAULT_USE_SMALLER_MATCHING_WINDOW; bool linear_polish = DEFAULT_LINEAR_POLISH; if (argc < 2) { usage(argv[0]); exit(1); } stringstream cmdline; string progname(argv[0]); string image_list_file_name; #if PROFILE timeval ts1, ts2, ts3, ts4; #endif // put the options and image list file name into the cmdline stringstream for (int c = 1; c < argc; c++) { cmdline << argv[c] << " "; } 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); ifstream in(image_list_file_name.c_str(),ios::in); if ( !in.is_open() ) { cerr << "Could not open file " << image_list_file_name << ". Exiting" << endl; return false; } // feature-based image registration class: db_FrameToReferenceRegistration reg; // db_StabilizationSmoother stab_smoother; // input file name: string file_name; // look-up tables for image warping: float ** lut_x = NULL, **lut_y = NULL; // if the images are color, the input is saved in color_ref: PgmImage color_ref(0,0); // image width, height: int w,h; int frame_number = 0; while ( !in.eof() ) { getline(in,file_name); PgmImage ref(file_name); if ( ref.GetDataPointer() == NULL ) { cerr << "Could not open image" << file_name << ". Exiting." << endl; return -1; } cout << ref << endl; // color format: int format = ref.GetFormat(); // is the input image color?: bool color = format == PgmImage::PGM_BINARY_PIXMAP; w = ref.GetWidth(); h = ref.GetHeight(); if ( !reg.Initialized() ) { 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); lut_x = db_AllocImage_f(w,h); lut_y = db_AllocImage_f(w,h); } if ( color ) { // save the color image: color_ref = ref; } // make a grayscale image: ref.ConvertToGray(); // compute the homography: double H[9],Hinv[9]; db_Identity3x3(Hinv); db_Identity3x3(H); bool force_reference = false; #if PROFILE gettimeofday(&ts1, NULL); #endif reg.AddFrame(ref.GetRowPointers(),H,false,false); cout << reg.profile_string << std::endl; #if PROFILE gettimeofday(&ts2, NULL); double elapsedTime = (ts2.tv_sec - ts1.tv_sec)*1000.0; // sec to ms elapsedTime += (ts2.tv_usec - ts1.tv_usec)/1000.0; // us to ms cout <<"\nelapsedTime for Reg<< "<>>>>>>>>>>>>\n"; #endif if (frame_number == 0) { reg.UpdateReference(ref.GetRowPointers()); } //std::vector &inlier_indices = reg.GetInliers(); int *inlier_indices = reg.GetInliers(); int num_inlier_indices = reg.GetNrInliers(); printf("[%d] #Inliers = %d\n",frame_number,num_inlier_indices); reg.Get_H_dref_to_ins(H); db_GenerateHomographyLut(lut_x,lut_y,w,h,H); // create a new image and warp: PgmImage warped(w,h,format); #if PROFILE gettimeofday(&ts3, NULL); #endif if ( color ) db_WarpImageLutBilinear_rgb(color_ref.GetRowPointers(),warped.GetRowPointers(),w,h,lut_x,lut_y); else db_WarpImageLut_u(ref.GetRowPointers(),warped.GetRowPointers(),w,h,lut_x,lut_y,DB_WARP_FAST); #if PROFILE gettimeofday(&ts4, NULL); elapsedTime = (ts4.tv_sec - ts3.tv_sec)*1000.0; // sec to ms elapsedTime += (ts4.tv_usec - ts3.tv_usec)/1000.0; // us to ms cout <<"\nelapsedTime for Warp <<"<>>>>>>>>>>>>\n"; #endif // write aligned image: name is aligned_ stringstream s; s << "aligned_" << file_name; warped.WritePGM(s.str()); /* // Get the reference and inspection corners to write to file double *ref_corners = reg.GetRefCorners(); double *ins_corners = reg.GetInsCorners(); // get the image file name (without extension), so we // can generate the corresponding filenames for matches // and inliers string file_name_root(file_name.substr(0,file_name.rfind("."))); // write matches to file s.str(string("")); s << "Matches_" << file_name_root << ".txt"; ofstream match_file(s.str().c_str()); for (int i = 0; i < reg.GetNrMatches(); i++) { match_file << ref_corners[3*i] << " " << ref_corners[3*i+1] << " " << ins_corners[3*i] << " " << ins_corners[3*i+1] << endl; } match_file.close(); // write the inlier matches to file s.str(string("")); s << "InlierMatches_" << file_name_root << ".txt"; ofstream inlier_match_file(s.str().c_str()); for(int i=0; i> token) { --c; int pos = token.find("-"); if (pos == 0) { switch (token[1]) { case 'm': --c; cmdline >> token; if (token.compare("rt") == 0) { motion_model_type = DB_HOMOGRAPHY_TYPE_R_T; } else if (token.compare("a") == 0) { motion_model_type = DB_HOMOGRAPHY_TYPE_AFFINE; } else if (token.compare("p") == 0) { motion_model_type = DB_HOMOGRAPHY_TYPE_PROJECTIVE; } else { usage(progname); exit(1); } break; case 'c': --c; cmdline >> nr_corners; break; case 'd': --c; cmdline >> max_disparity; break; case 'q': quarter_resolution = true; break; case 'r': --c; cmdline >> reference_update_period; break; case 's': --c; cmdline >> do_motion_smoothing; break; case 'g': --c; cmdline >> motion_smoothing_gain; break; default: cerr << progname << "illegal option " << token << endl; case 'h': usage(progname); exit(1); break; } } else { if (c != 1) { usage(progname); exit(1); } else { --c; image_list_file_name = token; } } } if (c != 0) { usage(progname); exit(1); } }