| /* |
| * 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 <db_utilities_camera.h> |
| |
| #include <iostream> |
| #include <iomanip> |
| |
| #if PROFILE |
| #include <sys/time.h> |
| #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 <int> : number of corners (default 1000).", |
| " -d <double>: search disparity as portion of image size (default 0.1).", |
| " -q : quarter the image resolution (i.e. half of each dimension) (default on)", |
| " -r <int> : 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 <double>: 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<< "<<elapsedTime<<" ms >>>>>>>>>>>>>\n"; |
| #endif |
| |
| if (frame_number == 0) |
| { |
| reg.UpdateReference(ref.GetRowPointers()); |
| } |
| |
| |
| //std::vector<int> &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 <<"<<elapsedTime<<" ms >>>>>>>>>>>>>\n"; |
| #endif |
| |
| // write aligned image: name is aligned_<corresponding input file name> |
| 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<num_inlier_indices; i++) |
| { |
| int k = inlier_indices[i]; |
| inlier_match_file << ref_corners[3*k] << " " |
| << ref_corners[3*k+1] << " " |
| << ins_corners[3*k] << " " |
| << ins_corners[3*k+1] << endl; |
| } |
| inlier_match_file.close(); |
| */ |
| |
| frame_number++; |
| } |
| |
| if ( reg.Initialized() ) |
| { |
| db_FreeImage_f(lut_x,h); |
| db_FreeImage_f(lut_y,h); |
| } |
| |
| return 0; |
| } |
| |
| 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) |
| { |
| // for counting down the parsed arguments. |
| int c = argc; |
| |
| // a holder |
| string token; |
| |
| while (cmdline >> 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); |
| } |
| } |
| |