int main(int argc, char *argv[]) { CmdLine cmd; std::string first_frame_name; std::string second_frame_name; std::string third_frame_name; cmd.add(make_option('f', first_frame_name, "firstname")); cmd.add(make_option('s', second_frame_name, "secondname")); cmd.add(make_option('t', third_frame_name, "thirdname")); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch (const std::string& s) { std::cerr << "Feature detector \nUsage: " << argv[0] << "\n" << "[-f|--firstname name]\n" << "[-s|--secondname name]\n" << "[-t|--thirdname name]\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } cv::Mat first_img(cv::imread(first_frame_name, 0)); cv::Mat second_img(cv::imread(second_frame_name, 0)); cv::Mat third_img(cv::imread(third_frame_name, 0)); assert(first_img.type() == CV_8UC1 && !first_img.empty()); assert(second_img.type() == CV_8UC1 && !second_img.empty()); assert(third_img.type() == CV_8UC1 && !third_img.empty()); AbstractCamera* cam = new PinholeCamera(752, 480, 315.5, 315.5, 376.0, 240.0); FramePtr fisrt_frame(new Frame(cam, first_img, 0.0)); FramePtr second_frame(new Frame(cam, second_img, 1.0)); FramePtr third_frame(new Frame(cam, third_img, 1.0)); Initialization init; init.addFirstFrame(fisrt_frame); init.addSecondFrame(second_frame); third_frame->T_f_w_ = second_frame->T_f_w_; SparseImgAlign img_align(4, 1, 30, SparseImgAlign::GaussNewton, false, false); size_t img_align_n_tracked = img_align.run(second_frame, third_frame); std::cout << "Img Align:\t Tracked = " << img_align_n_tracked << std::endl; mvo::Map map; fisrt_frame->setKeyframe(); second_frame->setKeyframe(); map.addKeyframe(fisrt_frame); map.addKeyframe(second_frame); Reprojector reprojector(cam,map); std::vector< std::pair<FramePtr, size_t> > overlap_kfs; reprojector.reprojectMap(third_frame, overlap_kfs); const size_t repr_n_new_references = reprojector.n_matches_; const size_t repr_n_mps = reprojector.n_trials_; std::cout << "Reprojection:\t Points = " << repr_n_mps << "\t \t Matches = " << repr_n_new_references<<std::endl; getchar(); return 0; }
int main( int argc , char ** argv ) { CmdLine cmd; std::string sSfM_Data_Filename; std::string sOutDir = ""; cmd.add( make_option( 'i', sSfM_Data_Filename, "sfmdata" ) ); cmd.add( make_option( 'o', sOutDir, "outdir" ) ); std::cout << "Note: this program writes output in Colmap file format.\n"; try { if ( argc == 1 ) { throw std::string( "Invalid command line parameter." ); } cmd.process( argc, argv ); } catch ( const std::string& s ) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--sfmdata] filename, the SfM_Data file to convert\n" << "[-o|--outdir] path where cameras.txt, images.txt and points3D.txt will be saved\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } if ( !stlplus::folder_exists( sOutDir ) ) { stlplus::folder_create( sOutDir ); } // Read the input SfM scene SfM_Data sfm_data; if ( !Load( sfm_data, sSfM_Data_Filename, ESfM_Data( ALL ) ) ) { std::cerr << std::endl << "The input SfM_Data file \"" << sSfM_Data_Filename << "\" cannot be read." << std::endl; return EXIT_FAILURE; } if ( ! exportToColmap( sfm_data , sOutDir ) ) { std::cerr << "There was an error during export of the file" << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
// Convert from a SfM_Data format to another int main(int argc, char **argv) { CmdLine cmd; std::string sSfM_Data_Filename_In, sOutputPLY_Out; cmd.add(make_option('i', sSfM_Data_Filename_In, "input_file")); cmd.add(make_option('o', sOutputPLY_Out, "output_file")); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--input_file] path to the input SfM_Data scene\n" << "[-o|--output_file] path to the output PLY file\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } // Load input SfM_Data scene SfM_Data sfm_data; if (!Load(sfm_data, sSfM_Data_Filename_In, ESfM_Data(ALL))) { std::cerr << std::endl << "The input SfM_Data file \"" << sSfM_Data_Filename_In << "\" cannot be read." << std::endl; return EXIT_FAILURE; } // Compute the scene structure color std::vector<Vec3> vec_3dPoints, vec_tracksColor, vec_camPosition; ColorizeTracks(sfm_data, vec_3dPoints, vec_tracksColor); GetCameraPositions(sfm_data, vec_camPosition); // Export the SfM_Data scene in the expected format if (plyHelper::exportToPly(vec_3dPoints, vec_camPosition, sOutputPLY_Out, &vec_tracksColor)) { return EXIT_SUCCESS; } else { return EXIT_FAILURE; } }
int main(int argc, char *argv[]) { CmdLine cmd; std::string input_image; cmd.add(make_option('i', input_image, "imagefile")); try{ if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch (const std::string &s){ std::cerr << "Usage: " << argv[0] << ' ' << "[-i|--imagefile path] " << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } std::cout << "You called: " << std::endl << argv[0] << std::endl << "--imagefile " << input_image << std::endl; fblib::image::EXIFSimple exif_sample; exif_sample.open(input_image); std::cout << "width : " << exif_sample.getWidth() << std::endl; std::cout << "height : " << exif_sample.getHeight() << std::endl; std::cout << "focal : " << exif_sample.getFocalLength() << std::endl; std::cout << "brand : " << exif_sample.getBrand() << std::endl; std::cout << "model : " << exif_sample.getModel() << std::endl; getchar(); return EXIT_SUCCESS; }
int main(int argc, char **argv) { #ifdef TEST_CMD_LINE string in; // Create command line options. CmdLine cmdLine; cmdLine.add(make_switch('h', "help")); // Verbose option for debug. cmdLine.add(make_option('i', in, "input folder")); // Image file name. // Try to process try { if (argc == 1) throw std::string("Invalid command line parameter."); cmdLine.process(argc, argv); if (!cmdLine.used('i')) throw std::string("Invalid command line parameter."); if (cmdLine.used('h')) print_usage(argv); } catch(const std::string& s) { print_usage(argv); return false; } #endif // Get image filenames. vector<string> filenames; getImageFilePaths(filenames, srcPath("../../datasets/")); return 0; }
int main(int argc, char *argv[]) { CmdLine cmd; std::string sSfM_Data_Filename; std::string sOutDir = ""; cmd.add( make_option('i', sSfM_Data_Filename, "sfmdata") ); cmd.add( make_option('o', sOutDir, "outdir") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--sfmdata] filename, the SfM_Data file to convert\n" << "[-o|--outdir] path\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } // Create output dir if (!stlplus::folder_exists(sOutDir)) stlplus::folder_create( sOutDir ); // Read the input SfM scene SfM_Data sfm_data; if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(ALL))) { std::cerr << std::endl << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl; return EXIT_FAILURE; } if (exportToCMPMVSFormat(sfm_data, stlplus::folder_append_separator(sOutDir) + "CMPMVS")) return( EXIT_SUCCESS ); else return( EXIT_FAILURE ); }
int main(int argc, char *argv[]) { CmdLine cmd; std::string first_frame_name; std::string second_frame_name; cmd.add(make_option('f', first_frame_name, "firstname")); cmd.add(make_option('s', second_frame_name, "secondname")); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch (const std::string& s) { std::cerr << "Feature detector \nUsage: " << argv[0] << "\n" << "[-f|--firstname name]\n" << "[-s|--secondname name]\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } cv::Mat first_img(cv::imread(first_frame_name, 0)); cv::Mat second_img(cv::imread(second_frame_name, 0)); assert(first_img.type() == CV_8UC1 && !first_img.empty()); assert(second_img.type() == CV_8UC1 && !second_img.empty()); AbstractCamera* cam = new PinholeCamera(752, 480, 315.5, 315.5, 376.0, 240.0); FramePtr fisrt_frame(new Frame(cam, first_img, 0.0)); FramePtr second_frame(new Frame(cam, second_img, 1.0)); Initialization init; init.addFirstFrame(fisrt_frame); init.addSecondFrame(second_frame); std::cout << second_frame->T_f_w_ << std::endl; return 0; }
int main(int argc, char *argv[]) { CmdLine cmd; std::string first_frame_name; std::string second_frame_name; cmd.add(make_option('f', first_frame_name, "firstname")); cmd.add(make_option('s', second_frame_name, "secondname")); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch (const std::string& s) { std::cerr << "Feature detector \nUsage: " << argv[0] << "\n" << "[-f|--firstname name]\n" << "[-s|--secondname name]\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } cv::Mat first_img(cv::imread(first_frame_name, 0)); cv::Mat second_img(cv::imread(second_frame_name, 0)); assert(first_img.type() == CV_8UC1 && !first_img.empty()); assert(second_img.type() == CV_8UC1 && !second_img.empty()); AbstractCamera* cam = new MonocularCamera(752, 480, 315.5, 315.5, 376.0, 240.0); ORBextractor *extractor = new ORBextractor(2*1000); System system("D:\\dataset\\Vocabulary\\ORBvoc.bin", "D:\\dataset\\TUM1.yaml"); system.addImage(first_img, 0); system.addImage(second_img, 1); delete extractor; delete cam; return 0; }
int main(int argc, char *argv[]) { CmdLine cmd; std::string img_name; cmd.add(make_option('i', img_name, "imgname")); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch (const std::string& s) { std::cerr << "Feature detector \nUsage: " << argv[0] << "\n" << "[-i|--imgname name]\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } cv::Mat img(cv::imread(img_name, 0)); assert(img.type() == CV_8UC1 && !img.empty()); AbstractCamera* cam = new PinholeCamera(752, 480, 315.5, 315.5, 376.0, 240.0); FramePtr frame(new Frame(cam, img, 0.0)); Features fts; FastDetector fast_detector(img.cols, img.rows, 25, 3); Timer t; for (int i = 0; i < 100; ++i) { fast_detector.detect(frame.get(), frame->img_pyr_, 20.0, fts); } printf("Fast corner detection took %f ms, %d corners detected (ref i7-W520: 7.166360ms, 40000)\n", t.stop() * 10, fts.size()); printf("Note, in this case, feature detection also contains the cam2world projection of the feature.\n"); cv::Mat img_rgb = cv::Mat(img.size(), CV_8UC3); cv::cvtColor(img, img_rgb, CV_GRAY2RGB); std::for_each(fts.begin(), fts.end(), [&](Feature* i){ cv::circle(img_rgb, cv::Point2f(i->px[0], i->px[1]), 4 * (i->level + 1), cv::Scalar(0, 255, 0), 1); }); cv::imshow("ref_img", img_rgb); cv::waitKey(0); std::for_each(fts.begin(), fts.end(), [&](Feature* i){ delete i; }); return 0; }
int main(int argc, char **argv) { CmdLine cmd; std::string sSfM_Data_Filename; cmd.add( make_option('i', sSfM_Data_Filename, "input_file") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Display stats about a sfm_data.X file.\nUsage: " << argv[0] << "\n" << "[-i|--input_file file] path to a SfM_Data scene\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } //--------------------------------------- // Read SfM Scene (image view names) //--------------------------------------- SfM_Data sfm_data; if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(ALL))) { std::cerr << std::endl << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl; return EXIT_FAILURE; } // Display some stats about the loaded data: std::cout << "Loaded a sfm_data scene with:\n" << " #views: " << sfm_data.GetViews().size() << "\n" << " #poses: " << sfm_data.GetPoses().size() << "\n" << " #intrinsics: " << sfm_data.GetIntrinsics().size() << "\n" << " #tracks: " << sfm_data.GetLandmarks().size() << std::endl; return 0; }
int main(int argc, char *argv[]) { CmdLine cmd; std::string sSfMDir; std::string sOutDir = ""; cmd.add( make_option('i', sSfMDir, "sfmdir") ); cmd.add( make_option('o', sOutDir, "outdir") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << ' ' << "[-i|--sfmdir path, the SfM_output path] " << "[-o|--outdir path] " << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } // Create output dir if (!stlplus::folder_exists(sOutDir)) stlplus::folder_create( sOutDir ); Document m_doc; if (m_doc.load(sSfMDir)) { exportToCMPMVSFormat(m_doc, stlplus::folder_append_separator(sOutDir) + "CMPMVS", stlplus::folder_append_separator(sSfMDir) + "images"); return( EXIT_SUCCESS ); } // Exit program return( EXIT_FAILURE ); }
int main(int argc, char **argv) { CmdLine cmd; std::string sInputImage; cmd.add( make_option('i', sInputImage, "imafile") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << ' ' << "[-i|--imafile path] " << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } std::cout << " You called : " <<std::endl << argv[0] << std::endl << "--imafile " << sInputImage << std::endl; #ifdef USE_EXIV2 Exif_IO* exif_io = new Exif_IO_Exiv2( sInputImage ); #else Exif_IO* exif_io = new Exif_IO_OpenExif( sInputImage ); #endif std::cout << "width : " << exif_io->getWidth() << std::endl; std::cout << "height : " << exif_io->getHeight() << std::endl; std::cout << "focal : " << exif_io->getFocal() << std::endl; std::cout << "brand : " << exif_io->getBrand() << std::endl; std::cout << "model : " << exif_io->getModel() << std::endl; delete exif_io; return EXIT_SUCCESS; }
/// Main Program int main(int argc, char *argv[]) { CmdLine cmd; std::string combine; ParamDisparity p; // Parameters for adaptive weights cmd.add( make_option('R',p.radius) ); cmd.add( make_option(0,p.gammaCol,"gcol") ); cmd.add( make_option(0,p.gammaPos,"gpos") ); cmd.add( make_option('c', combine) ); try { cmd.process(argc, argv); } catch(std::string str) { std::cerr << "Error: " << str << std::endl<<std::endl; argc = 1; // To display usage } if(argc!=5 && argc!=7) { usage(argv[0]); return 1; } // Load images Image im1 = loadImage(argv[1]); Image im2; if(argc>5) im2 = loadImage(argv[5]); int x,y; if(! ((std::istringstream(argv[2])>>x).eof() && (std::istringstream(argv[3])>>y).eof())) { std::cerr << "Error reading x or y" << std::endl; return 1; } int disp=0; if(argc>6 && !((std::istringstream(argv[6])>>disp).eof()) ) { std::cerr << "Error reading disparity" << std::endl; return 1; } Comb* comb=0; if(cmd.used('c') && im2.channels()!=0) { if(combine == "left") comb = new Comb(left); else if(combine == "max") comb = new Comb(max); else if(combine == "min") comb = new Comb(min); else if(combine == "mult") comb = new Comb(mult); else if(combine == "plus") comb = new Comb(plus); else { std::cerr << "Unrecognized option for weights combination " << "(should be left,max,min,mult or plus)" << std::endl; return 1; } } Image w = show_weights(im1, im2, x, y, x+disp, comb, p.radius, p.gammaCol, p.gammaPos); rescale(w); if(io_png_write_f32(argv[4], &w(0,0), w.width(), w.height(), 1) != 0) { std::cerr << "Unable to write file " << argv[4] << std::endl; return 1; } return 0; }
/// - Compute view image description (feature & descriptor extraction) /// - Export computed data int main(int argc, char **argv) { CmdLine cmd; std::string sSfM_Data_Filename; std::string sOutDir = ""; bool bUpRight = false; std::string sImage_Describer_Method = "SIFT"; bool bForce = false; std::string sFeaturePreset = ""; #ifdef OPENMVG_USE_OPENMP int iNumThreads = 0; #endif // required cmd.add( make_option('i', sSfM_Data_Filename, "input_file") ); cmd.add( make_option('o', sOutDir, "outdir") ); // Optional cmd.add( make_option('m', sImage_Describer_Method, "describerMethod") ); cmd.add( make_option('u', bUpRight, "upright") ); cmd.add( make_option('f', bForce, "force") ); cmd.add( make_option('p', sFeaturePreset, "describerPreset") ); #ifdef OPENMVG_USE_OPENMP cmd.add( make_option('n', iNumThreads, "numThreads") ); #endif try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch (const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--input_file] a SfM_Data file \n" << "[-o|--outdir path] \n" << "\n[Optional]\n" << "[-f|--force] Force to recompute data\n" << "[-m|--describerMethod]\n" << " (method to use to describe an image):\n" << " SIFT (default),\n" << " SIFT_ANATOMY,\n" << " AKAZE_FLOAT: AKAZE with floating point descriptors,\n" << " AKAZE_MLDB: AKAZE with binary descriptors\n" << "[-u|--upright] Use Upright feature 0 or 1\n" << "[-p|--describerPreset]\n" << " (used to control the Image_describer configuration):\n" << " NORMAL (default),\n" << " HIGH,\n" << " ULTRA: !!Can take long time!!\n" #ifdef OPENMVG_USE_OPENMP << "[-n|--numThreads] number of parallel computations\n" #endif << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } std::cout << " You called : " <<std::endl << argv[0] << std::endl << "--input_file " << sSfM_Data_Filename << std::endl << "--outdir " << sOutDir << std::endl << "--describerMethod " << sImage_Describer_Method << std::endl << "--upright " << bUpRight << std::endl << "--describerPreset " << (sFeaturePreset.empty() ? "NORMAL" : sFeaturePreset) << std::endl << "--force " << bForce << std::endl #ifdef OPENMVG_USE_OPENMP << "--numThreads " << iNumThreads << std::endl #endif << std::endl; if (sOutDir.empty()) { std::cerr << "\nIt is an invalid output directory" << std::endl; return EXIT_FAILURE; } // Create output dir if (!stlplus::folder_exists(sOutDir)) { if (!stlplus::folder_create(sOutDir)) { std::cerr << "Cannot create output directory" << std::endl; return EXIT_FAILURE; } } //--------------------------------------- // a. Load input scene //--------------------------------------- SfM_Data sfm_data; if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(VIEWS|INTRINSICS))) { std::cerr << std::endl << "The input file \""<< sSfM_Data_Filename << "\" cannot be read" << std::endl; return EXIT_FAILURE; } // b. Init the image_describer // - retrieve the used one in case of pre-computed features // - else create the desired one using namespace openMVG::features; std::unique_ptr<Image_describer> image_describer; const std::string sImage_describer = stlplus::create_filespec(sOutDir, "image_describer", "json"); if (!bForce && stlplus::is_file(sImage_describer)) { // Dynamically load the image_describer from the file (will restore old used settings) std::ifstream stream(sImage_describer.c_str()); if (!stream.is_open()) return EXIT_FAILURE; try { cereal::JSONInputArchive archive(stream); archive(cereal::make_nvp("image_describer", image_describer)); } catch (const cereal::Exception & e) { std::cerr << e.what() << std::endl << "Cannot dynamically allocate the Image_describer interface." << std::endl; return EXIT_FAILURE; } } else { // Create the desired Image_describer method. // Don't use a factory, perform direct allocation if (sImage_Describer_Method == "SIFT") { image_describer.reset(new SIFT_Image_describer (SIFT_Image_describer::Params(), !bUpRight)); } else if (sImage_Describer_Method == "SIFT_ANATOMY") { image_describer.reset( new SIFT_Anatomy_Image_describer(SIFT_Anatomy_Image_describer::Params())); } else if (sImage_Describer_Method == "AKAZE_FLOAT") { image_describer = AKAZE_Image_describer::create (AKAZE_Image_describer::Params(AKAZE::Params(), AKAZE_MSURF), !bUpRight); } else if (sImage_Describer_Method == "AKAZE_MLDB") { image_describer = AKAZE_Image_describer::create (AKAZE_Image_describer::Params(AKAZE::Params(), AKAZE_MLDB), !bUpRight); } if (!image_describer) { std::cerr << "Cannot create the designed Image_describer:" << sImage_Describer_Method << "." << std::endl; return EXIT_FAILURE; } else { if (!sFeaturePreset.empty()) if (!image_describer->Set_configuration_preset(stringToEnum(sFeaturePreset))) { std::cerr << "Preset configuration failed." << std::endl; return EXIT_FAILURE; } } // Export the used Image_describer and region type for: // - dynamic future regions computation and/or loading { std::ofstream stream(sImage_describer.c_str()); if (!stream.is_open()) return EXIT_FAILURE; cereal::JSONOutputArchive archive(stream); archive(cereal::make_nvp("image_describer", image_describer)); auto regionsType = image_describer->Allocate(); archive(cereal::make_nvp("regions_type", regionsType)); } } // Feature extraction routines // For each View of the SfM_Data container: // - if regions file exists continue, // - if no file, compute features { system::Timer timer; Image<unsigned char> imageGray; C_Progress_display my_progress_bar(sfm_data.GetViews().size(), std::cout, "\n- EXTRACT FEATURES -\n" ); // Use a boolean to track if we must stop feature extraction std::atomic<bool> preemptive_exit(false); #ifdef OPENMVG_USE_OPENMP const unsigned int nb_max_thread = omp_get_max_threads(); if (iNumThreads > 0) { omp_set_num_threads(iNumThreads); } else { omp_set_num_threads(nb_max_thread); } #pragma omp parallel for schedule(dynamic) if (iNumThreads > 0) private(imageGray) #endif for (int i = 0; i < static_cast<int>(sfm_data.views.size()); ++i) { Views::const_iterator iterViews = sfm_data.views.begin(); std::advance(iterViews, i); const View * view = iterViews->second.get(); const std::string sView_filename = stlplus::create_filespec(sfm_data.s_root_path, view->s_Img_path), sFeat = stlplus::create_filespec(sOutDir, stlplus::basename_part(sView_filename), "feat"), sDesc = stlplus::create_filespec(sOutDir, stlplus::basename_part(sView_filename), "desc"); // If features or descriptors file are missing, compute them if (!preemptive_exit && (bForce || !stlplus::file_exists(sFeat) || !stlplus::file_exists(sDesc))) { if (!ReadImage(sView_filename.c_str(), &imageGray)) continue; // // Look if there is occlusion feature mask // Image<unsigned char> * mask = nullptr; // The mask is null by default const std::string mask_filename_local = stlplus::create_filespec(sfm_data.s_root_path, stlplus::basename_part(sView_filename) + "_mask", "png"), mask__filename_global = stlplus::create_filespec(sfm_data.s_root_path, "mask", "png"); Image<unsigned char> imageMask; // Try to read the local mask if (stlplus::file_exists(mask_filename_local)) { if (!ReadImage(mask_filename_local.c_str(), &imageMask)) { std::cerr << "Invalid mask: " << mask_filename_local << std::endl << "Stopping feature extraction." << std::endl; preemptive_exit = true; continue; } // Use the local mask only if it fits the current image size if (imageMask.Width() == imageGray.Width() && imageMask.Height() == imageGray.Height()) mask = &imageMask; } else { // Try to read the global mask if (stlplus::file_exists(mask__filename_global)) { if (!ReadImage(mask__filename_global.c_str(), &imageMask)) { std::cerr << "Invalid mask: " << mask__filename_global << std::endl << "Stopping feature extraction." << std::endl; preemptive_exit = true; continue; } // Use the global mask only if it fits the current image size if (imageMask.Width() == imageGray.Width() && imageMask.Height() == imageGray.Height()) mask = &imageMask; } } // Compute features and descriptors and export them to files auto regions = image_describer->Describe(imageGray, mask); if (regions && !image_describer->Save(regions.get(), sFeat, sDesc)) { std::cerr << "Cannot save regions for images: " << sView_filename << std::endl << "Stopping feature extraction." << std::endl; preemptive_exit = true; continue; } } ++my_progress_bar; } std::cout << "Task done in (s): " << timer.elapsed() << std::endl; } return EXIT_SUCCESS; }
// // Create the description of an input image dataset for OpenMVG toolsuite // - Export a SfM_Data file with View & Intrinsic data // int main(int argc, char **argv) { CmdLine cmd; std::string sImageDir, sGroundTruthDir, sOutputDir = ""; int ground_truth_Dataset = 0; cmd.add( make_option('i', sImageDir, "imageDirectory") ); cmd.add( make_option('g', sGroundTruthDir, "groundTruthDirectory") ); cmd.add( make_option('t', ground_truth_Dataset, "groundTruthDataset")); cmd.add( make_option('o', sOutputDir, "outputDirectory") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch (const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--imageDirectory]\n" << "[-g|--groundTruthDirectory]\n" << "[-t]--groundTruthDataset]\n" << "\t 1: Strecha's Dataset\n" << "\t 2: MiddleBury's Dataset\n" << "\t 3: DTU MVS Dataset\n" << "\t 4: ETH 3D Dataset\n" << "\t 5: Kitti Odometry Dataset\n" << "[-o|--outputDirectory]\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } std::cout << " You called : " <<std::endl << argv[0] << std::endl << "--imageDirectory " << sImageDir << std::endl << "--groundTruthDirectory " << sGroundTruthDir << std::endl << "--groundTruthDataset " << ground_truth_Dataset << std::endl << "--outputDirectory " << sOutputDir << std::endl; if ( !stlplus::folder_exists( sImageDir ) ) { std::cerr << "\nThe input directory doesn't exist" << std::endl; return EXIT_FAILURE; } if ( !stlplus::folder_exists( sGroundTruthDir ) ) { std::cerr << "\nThe input ground truth directory doesn't exist" << std::endl; return EXIT_FAILURE; } if (sOutputDir.empty()) { std::cerr << "\nInvalid output directory" << std::endl; return EXIT_FAILURE; } if ( !stlplus::folder_exists( sOutputDir ) ) { if ( !stlplus::folder_create( sOutputDir )) { std::cerr << "\nCannot create output directory" << std::endl; return EXIT_FAILURE; } } // Configure an empty scene with Views and their corresponding cameras std::shared_ptr<SfM_Data_GT_Loader_Interface> sfm_data_gt; switch(ground_truth_Dataset) { case 1: sfm_data_gt = std::make_shared<SfM_Data_GT_Loader_Strecha>(); break; case 2: sfm_data_gt = std::make_shared<SfM_Data_GT_Loader_MiddleBury>(); break; case 3: sfm_data_gt = std::make_shared<SfM_Data_GT_Loader_DTU_MVS>(); break; case 4: sfm_data_gt = std::make_shared<SfM_Data_GT_Loader_ETH_3D>(); break; case 5: sfm_data_gt = std::make_shared<SfM_Data_GT_Loader_Kitti>(); break; default: std::cerr<<"Error: Not Support Dataset \n"; return EXIT_FAILURE; } // Load the gt data if (!sfm_data_gt->run(sGroundTruthDir, sImageDir)) { return EXIT_FAILURE; } // Store SfM_Data views & intrinsic data if (!Save( sfm_data_gt->GetSfMData(), stlplus::create_filespec( sOutputDir, "sfm_data.json" ).c_str(), ESfM_Data(ALL))) { return EXIT_FAILURE; } std::cout << std::endl << "SfMInit_ImageListing report:\n" << "listed #File(s): " << sfm_data_gt->GetImageNumber() << "\n" << "usable #File(s) listed in sfm_data: " << sfm_data_gt->GetSfMData().GetViews().size() << "\n" << "usable #Pose(s) listed in sfm_data: " << sfm_data_gt->GetSfMData().GetPoses().size() << "\n" << "usable #Intrinsic(s) listed in sfm_data: " << sfm_data_gt->GetSfMData().GetIntrinsics().size() << std::endl; return EXIT_SUCCESS; }
int main(int argc, char ** argv) { CmdLine cmd; std::string sImaDirectory; std::string sMatchesDir; std::string sOutDir = ""; cmd.add( make_option('i', sImaDirectory, "imadir") ); cmd.add( make_option('d', sMatchesDir, "matchdir") ); cmd.add( make_option('o', sOutDir, "outdir") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Export pairwise matches.\nUsage: " << argv[0] << ' ' << "[-i|--imadir path] " << "[-d|--matchdir path] " << "[-o|--outdir path] " << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } if (sOutDir.empty()) { std::cerr << "\nIt is an invalid output directory" << std::endl; return EXIT_FAILURE; } //--------------------------------------- // Read images names //--------------------------------------- std::vector<std::string> vec_fileNames; { std::ifstream in(stlplus::create_filespec(sMatchesDir, "lists", "txt").c_str()); std::string sValue; while(in>>sValue) vec_fileNames.push_back(sValue); in.close(); } if (vec_fileNames.empty()) { std::cerr << "\nEmpty input image list" << std::endl; return EXIT_FAILURE; } // ------------ // For each image, export visually the keypoints // ------------ //-- //- Preprocess the images size Image<RGBColor> image; std::map< std::string, std::pair<size_t, size_t> > map_imageSize; for (std::vector<std::string>::const_iterator iterFilename = vec_fileNames.begin(); iterFilename != vec_fileNames.end(); ++iterFilename) { ReadImage( stlplus::create_filespec(sImaDirectory,*iterFilename).c_str() , &image); map_imageSize.insert( std::make_pair(*iterFilename, std::make_pair(image.Width(), image.Height()))); } stlplus::folder_create(sOutDir); std::cout << "\n Export extracted keypoints for all images" << std::endl; C_Progress_display my_progress_bar( vec_fileNames.size() ); for (std::vector<std::string>::const_iterator iterFilename = vec_fileNames.begin(); iterFilename != vec_fileNames.end(); ++iterFilename, ++my_progress_bar) { const size_t I = std::distance( (std::vector<std::string>::const_iterator)vec_fileNames.begin(), iterFilename); const std::pair<size_t, size_t> dimImage = map_imageSize.find(*iterFilename)->second; svgDrawer svgStream( dimImage.first, dimImage.second); svgStream.drawImage(stlplus::create_filespec(sImaDirectory,*iterFilename), dimImage.first, dimImage.second); // Load the features for the file std::vector<SIOPointFeature> vec_feat; loadFeatsFromFile( stlplus::create_filespec(sMatchesDir, stlplus::basename_part(*iterFilename), ".feat"), vec_feat); //-- Draw features for (size_t i=0; i< vec_feat.size(); ++i) { const SIOPointFeature & feature = vec_feat[i]; svgStream.drawCircle(feature.x(), feature.y(), feature.scale(), svgStyle().stroke("yellow", 2.0)); } // Write the SVG file std::ostringstream os; os << stlplus::folder_append_separator(sOutDir) << stlplus::basename_part(*iterFilename) << "_" << vec_feat.size() << "_.svg"; ofstream svgFile( os.str().c_str() ); svgFile << svgStream.closeSvgFile().str(); svgFile.close(); } return EXIT_SUCCESS; }
int main(int argc, char **argv) { CmdLine cmd; std::string sImageDir, sOutputDir = ""; int i_User_camera_model = PINHOLE_CAMERA; bool b_Group_camera_model = true; cmd.add( make_option('i', sImageDir, "imageDirectory") ); cmd.add( make_option('o', sOutputDir, "outputDirectory") ); cmd.add( make_option('c', i_User_camera_model, "camera_model") ); cmd.add( make_option('g', b_Group_camera_model, "group_camera_model") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--imageDirectory]\n" << "[-o|--outputDirectory]\n" << "[-c|--camera_model] Camera model type:\n" << "\t 1: Pinhole (default)\n" << "\t 2: Pinhole radial 1\n" << "\t 3: Pinhole radial 3\n" << "\t 4: Pinhole brown with radial 3 and tangential 2\n" << "[-g|--group_camera_model]\n" << "\t 0-> each view have it's own camera intrinsic parameters,\n" << "\t 1-> views can share some camera intrinsic parameters (default)\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } std::cout << " You called : " <<std::endl << argv[0] << std::endl << "--imageDirectory " << sImageDir << std::endl << "--outputDirectory " << sOutputDir << std::endl << "--camera_model " << i_User_camera_model << std::endl << "--group_camera_model " << b_Group_camera_model << std::endl; // Expected properties for each image double width = -1, height = -1, focal = -1, ppx = -1, ppy = -1; const EINTRINSIC e_User_camera_model = EINTRINSIC(i_User_camera_model); if ( !stlplus::folder_exists( sImageDir ) ) { std::cerr << "\nThe input directory doesn't exist" << std::endl; return EXIT_FAILURE; } if (sOutputDir.empty()) { std::cerr << "\nInvalid output directory" << std::endl; return EXIT_FAILURE; } if ( !stlplus::folder_exists( sOutputDir ) ) { if ( !stlplus::folder_create( sOutputDir )) { std::cerr << "\nCannot create output directory" << std::endl; return EXIT_FAILURE; } } // Check if the sOutputDir/lists.txt file is present const std::string sListsFile = stlplus::create_filespec( sOutputDir, "lists.txt" ); if ( !stlplus::is_file( sListsFile ) ) { std::cerr << "\nThe input lists.txt file doesn't exist" << std::endl; return EXIT_FAILURE; } // Parse the lists.txt file and create the corresponding View & Intrinsic data std::vector<openMVG::SfMIO::CameraInfo> vec_camImageNames; std::vector<openMVG::SfMIO::IntrinsicCameraInfo> vec_intrinsicGroups; if (!openMVG::SfMIO::loadImageList( vec_camImageNames, vec_intrinsicGroups, sListsFile) ) { std::cerr << "\nEmpty image list." << std::endl; return false; } // Configure an empty scene with Views and their corresponding cameras SfM_Data sfm_data; sfm_data.s_root_path = sImageDir; // Setup main image root_path Views & views = sfm_data.views; Intrinsics & intrinsics = sfm_data.intrinsics; // Find to which intrinsic groups each image belong for (std::vector<openMVG::SfMIO::CameraInfo>::const_iterator iter = vec_camImageNames.begin(); iter != vec_camImageNames.end(); ++iter) { const openMVG::SfMIO::CameraInfo & camInfo = *iter; // Find the index of the correponding cameraInfo const size_t idx = std::distance((std::vector<openMVG::SfMIO::CameraInfo>::const_iterator)vec_camImageNames.begin(), iter); double width = height = ppx = ppy = focal = -1.0; std::shared_ptr<IntrinsicBase> intrinsic (NULL); const openMVG::SfMIO::IntrinsicCameraInfo & camIntrinsic = vec_intrinsicGroups[camInfo.m_intrinsicId]; width = camIntrinsic.m_w; height = camIntrinsic.m_h; if (camIntrinsic.m_bKnownIntrinsic) { ppx = camIntrinsic.m_K(0,2); ppy = camIntrinsic.m_K(1,2); focal = camIntrinsic.m_focal; // Create the user defined camera model corresponding to the intrinsic loaded data switch(e_User_camera_model) { case PINHOLE_CAMERA: intrinsic = std::make_shared<Pinhole_Intrinsic>(width, height, focal, ppx, ppy); break; case PINHOLE_CAMERA_RADIAL1: intrinsic = std::make_shared<Pinhole_Intrinsic_Radial_K1>(width, height, focal, ppx, ppy); break; case PINHOLE_CAMERA_RADIAL3: intrinsic = std::make_shared<Pinhole_Intrinsic_Radial_K3>(width, height, focal, ppx, ppy); break; case PINHOLE_CAMERA_BROWN: intrinsic = std::make_shared<Pinhole_Intrinsic_Brown_T2>(width, height, focal, ppx, ppy); break; default: std::cerr << "Invalid camera model." << std::endl; return EXIT_FAILURE; } } // else -> no intrinsic data // Create the corresponding view const IndexT id_view = idx; const IndexT id_intrinsic = (camIntrinsic.m_bKnownIntrinsic) ? (b_Group_camera_model ? camInfo.m_intrinsicId : id_view) : UndefinedIndexT; const IndexT id_pose = id_view; // Build the view corresponding to the image View v( iter->m_sImageName, id_view, id_intrinsic, id_pose, width, height); // Add the view to the sfm_container views[v.id_view] = std::make_shared<View>(v); // Add intrinsic related to the image (if any) if (intrinsic == NULL) { //Since the view have invalid intrinsic data // (export the view, with an invalid intrinsic field value) v.id_intrinsic = UndefinedIndexT; } else { // Add the intrinsic to the sfm_container intrinsics[v.id_intrinsic] = intrinsic; } } // Store SfM_Data views & intrinsic data if (Save( sfm_data, stlplus::create_filespec( sOutputDir, "sfm_data.json" ).c_str(), ESfM_Data(VIEWS|INTRINSICS)) ) return EXIT_SUCCESS; else return EXIT_FAILURE; }
/// Compute between the Views /// Compute view image description (feature & descriptor extraction using OpenCV) /// Compute putative local feature matches (descriptor matching) /// Compute geometric coherent feature matches (robust model estimation from putative matches) /// Export computed data int main(int argc, char **argv) { CmdLine cmd; std::string sSfM_Data_Filename; std::string sOutDir = ""; bool bForce = false; #ifdef USE_OCVSIFT std::string sImage_Describer_Method = "AKAZE_OPENCV"; #endif // required cmd.add( make_option('i', sSfM_Data_Filename, "input_file") ); cmd.add( make_option('o', sOutDir, "outdir") ); // Optional cmd.add( make_option('f', bForce, "force") ); #ifdef USE_OCVSIFT cmd.add( make_option('m', sImage_Describer_Method, "describerMethod") ); #endif try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--input_file]: a SfM_Data file \n" << "[-o|--outdir] path \n" << "\n[Optional]\n" << "[-f|--force: Force to recompute data]\n" #ifdef USE_OCVSIFT << "[-m|--describerMethod\n" << " (method to use to describe an image):\n" << " AKAZE_OPENCV (default),\n" << " SIFT_OPENCV: SIFT FROM OPENCV,\n" #endif << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } std::cout << " You called : " <<std::endl << argv[0] << std::endl << "--input_file " << sSfM_Data_Filename << std::endl << "--outdir " << sOutDir << std::endl #ifdef USE_OCVSIFT << "--describerMethod " << sImage_Describer_Method << std::endl #endif ; if (sOutDir.empty()) { std::cerr << "\nIt is an invalid output directory" << std::endl; return EXIT_FAILURE; } // Create output dir if (!stlplus::folder_exists(sOutDir)) { if (!stlplus::folder_create(sOutDir)) { std::cerr << "Cannot create output directory" << std::endl; return EXIT_FAILURE; } } //--------------------------------------- // a. Load input scene //--------------------------------------- SfM_Data sfm_data; if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(VIEWS|INTRINSICS))) { std::cerr << std::endl << "The input file \""<< sSfM_Data_Filename << "\" cannot be read" << std::endl; return false; } // Init the image_describer // - retrieve the used one in case of pre-computed features // - else create the desired one using namespace openMVG::features; std::unique_ptr<Image_describer> image_describer; const std::string sImage_describer = stlplus::create_filespec(sOutDir, "image_describer", "json"); if (stlplus::is_file(sImage_describer)) { // Dynamically load the image_describer from the file (will restore old used settings) std::ifstream stream(sImage_describer.c_str()); if (!stream.is_open()) return false; cereal::JSONInputArchive archive(stream); archive(cereal::make_nvp("image_describer", image_describer)); } else { #ifdef USE_OCVSIFT if (sImage_Describer_Method == "AKAZE_OPENCV") { image_describer.reset(new AKAZE_OCV_Image_describer); } else if (sImage_Describer_Method == "SIFT_OPENCV") { image_describer.reset(new SIFT_OPENCV_Image_describer()); } else { std::cerr << "Unknown image describer method." << std::endl; return EXIT_FAILURE; } #else image_describer.reset(new AKAZE_OCV_Image_describer); #endif // Export the used Image_describer and region type for: // - dynamic future regions computation and/or loading { std::ofstream stream(sImage_describer.c_str()); if (!stream.is_open()) return false; cereal::JSONOutputArchive archive(stream); archive(cereal::make_nvp("image_describer", image_describer)); std::unique_ptr<Regions> regionsType; image_describer->Allocate(regionsType); archive(cereal::make_nvp("regions_type", regionsType)); } } // Feature extraction routines // For each View of the SfM_Data container: // - if regions file exist continue, // - if no file, compute features { system::Timer timer; Image<unsigned char> imageGray; C_Progress_display my_progress_bar( sfm_data.GetViews().size(), std::cout, "\n- EXTRACT FEATURES -\n" ); for(Views::const_iterator iterViews = sfm_data.views.begin(); iterViews != sfm_data.views.end(); ++iterViews, ++my_progress_bar) { const View * view = iterViews->second.get(); const std::string sView_filename = stlplus::create_filespec(sfm_data.s_root_path, view->s_Img_path); const std::string sFeat = stlplus::create_filespec(sOutDir, stlplus::basename_part(sView_filename), "feat"); const std::string sDesc = stlplus::create_filespec(sOutDir, stlplus::basename_part(sView_filename), "desc"); //If features or descriptors file are missing, compute them if (bForce || !stlplus::file_exists(sFeat) || !stlplus::file_exists(sDesc)) { if (!ReadImage(sView_filename.c_str(), &imageGray)) continue; // Compute features and descriptors and export them to files std::unique_ptr<Regions> regions; image_describer->Describe(imageGray, regions); image_describer->Save(regions.get(), sFeat, sDesc); } } std::cout << "Task done in (s): " << timer.elapsed() << std::endl; } return EXIT_SUCCESS; }
int main(int argc, char **argv) { CmdLine cmd; std::string sImaDirectory; std::string sOutDir = ""; std::string sGeometricModel = "f"; float fDistRatio = .6f; bool bOctMinus1 = false; float dPeakThreshold = 0.04f; int sequentialLimit = 0; cmd.add( make_option('i', sImaDirectory, "imadir") ); cmd.add( make_option('o', sOutDir, "outdir") ); cmd.add( make_option('r', fDistRatio, "distratio") ); cmd.add( make_option('s', bOctMinus1, "octminus1") ); cmd.add( make_option('p', dPeakThreshold, "peakThreshold") ); cmd.add( make_option('g', sGeometricModel, "geometricModel") ); cmd.add(make_option('l', sequentialLimit, "sequentialLimit"));// try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--imadir path] \n" << "[-o|--outdir path] \n" << "\n[Optional]\n" << "[-r|--distratio 0.6] \n" << "[-s|--octminus1 0 or 1] \n" << "[-p|--peakThreshold 0.04 -> 0.01] \n" << "[-g|--geometricModel f, e or h] \n" << "[-l|--sequentialLimit 1 or greater]" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } std::cout << " You called : " <<std::endl << argv[0] << std::endl << "--imadir " << sImaDirectory << std::endl << "--outdir " << sOutDir << std::endl << "--distratio " << fDistRatio << std::endl << "--octminus1 " << bOctMinus1 << std::endl << "--peakThreshold " << dPeakThreshold << std::endl << "--geometricModel " << sGeometricModel << std::endl << "--sequentialLimit " << sequentialLimit << std::endl; if (sOutDir.empty()) { std::cerr << "\nIt is an invalid output directory" << std::endl; return EXIT_FAILURE; } eGeometricModel eGeometricModelToCompute = FUNDAMENTAL_MATRIX; std::string sGeometricMatchesFilename = ""; switch(sGeometricModel[0]) { case 'f': case 'F': eGeometricModelToCompute = FUNDAMENTAL_MATRIX; sGeometricMatchesFilename = "matches.f.txt"; break; case 'e': case 'E': eGeometricModelToCompute = ESSENTIAL_MATRIX; sGeometricMatchesFilename = "matches.e.txt"; break; case 'h': case 'H': eGeometricModelToCompute = HOMOGRAPHY_MATRIX; sGeometricMatchesFilename = "matches.h.txt"; break; default: std::cerr << "Unknown geometric model" << std::endl; return EXIT_FAILURE; } // ----------------------------- // a. List images // b. Compute features and descriptors // c. Compute putative descriptor matches // d. Geometric filtering of putative matches // e. Export some statistics // ----------------------------- // Create output dir if (!stlplus::folder_exists(sOutDir)) stlplus::folder_create( sOutDir ); //--------------------------------------- // a. List images //--------------------------------------- std::string sListsFile = stlplus::create_filespec(sOutDir, "lists.txt" ); if (!stlplus::is_file(sListsFile)) { std::cerr << std::endl << "The input file \""<< sListsFile << "\" is missing" << std::endl; return false; } std::vector<openMVG::SfMIO::CameraInfo> vec_camImageName; std::vector<openMVG::SfMIO::IntrinsicCameraInfo> vec_focalGroup; // if (!openMVG::SfMIO::loadImageList( vec_camImageName, // vec_focalGroup, // sListsFile) ) if (!readImageList(vec_camImageName, vec_focalGroup, sListsFile)) { std::cerr << "\nEmpty image list." << std::endl; return false; } if (eGeometricModelToCompute == ESSENTIAL_MATRIX) { //-- In the case of the essential matrix we check if only one K matrix is present. //-- Due to the fact that the generic framework allows only one K matrix for the // robust essential matrix estimation in image collection. std::vector<openMVG::SfMIO::IntrinsicCameraInfo>::iterator iterF = std::unique(vec_focalGroup.begin(), vec_focalGroup.end(), testIntrinsicsEquality); vec_focalGroup.resize( std::distance(vec_focalGroup.begin(), iterF) ); if (vec_focalGroup.size() == 1) { // Set all the intrinsic ID to 0 for (size_t i = 0; i < vec_camImageName.size(); ++i) vec_camImageName[i].m_intrinsicId = 0; } else { std::cerr << "There is more than one focal group in the lists.txt file." << std::endl << "Only one focal group is supported for the image collection robust essential matrix estimation." << std::endl; return EXIT_FAILURE; } } //-- Two alias to ease access to image filenames and image sizes std::vector<std::string> vec_fileNames; std::vector<std::pair<size_t, size_t> > vec_imagesSize; for ( std::vector<openMVG::SfMIO::CameraInfo>::const_iterator iter_camInfo = vec_camImageName.begin(); iter_camInfo != vec_camImageName.end(); iter_camInfo++ ) { vec_imagesSize.push_back( std::make_pair( vec_focalGroup[iter_camInfo->m_intrinsicId].m_w, vec_focalGroup[iter_camInfo->m_intrinsicId].m_h ) ); vec_fileNames.push_back( stlplus::create_filespec( sImaDirectory, iter_camInfo->m_sImageName) ); } //--------------------------------------- // b. Compute features and descriptor // - extract sift features and descriptor // - if keypoints already computed, re-load them // - else save features and descriptors on disk //--------------------------------------- typedef Descriptor<unsigned char, 128> DescriptorT; typedef SIOPointFeature FeatureT; typedef std::vector<FeatureT> FeatsT; typedef vector<DescriptorT > DescsT; typedef KeypointSet<FeatsT, DescsT > KeypointSetT; { std::cout << "\n\nEXTRACT FEATURES" << std::endl; vec_imagesSize.resize(vec_fileNames.size()); Image<unsigned char> imageGray; C_Progress_display my_progress_bar(vec_fileNames.size()); for (size_t i = 0; i < vec_fileNames.size(); ++i) { std::string sFeat = stlplus::create_filespec(sOutDir, stlplus::basename_part(vec_fileNames[i]), "feat"); std::string sDesc = stlplus::create_filespec(sOutDir, stlplus::basename_part(vec_fileNames[i]), "desc"); //If descriptors or features file are missing, compute them if (!stlplus::file_exists(sFeat) || !stlplus::file_exists(sDesc)) { if (!ReadImage(vec_fileNames[i].c_str(), &imageGray)) continue; // Compute features and descriptors and export them to files KeypointSetT kpSet; SIFTDetector(imageGray, kpSet.features(), kpSet.descriptors(), bOctMinus1, true, dPeakThreshold); kpSet.saveToBinFile(sFeat, sDesc); } ++my_progress_bar; } } //--------------------------------------- // c. Compute putative descriptor matches // - L2 descriptor matching // - Keep correspondences only if NearestNeighbor ratio is ok //--------------------------------------- PairWiseMatches map_PutativesMatches; // Define the matcher and the used metric (Squared L2) // ANN matcher could be defined as follow: typedef flann::L2<DescriptorT::bin_type> MetricT; typedef ArrayMatcher_Kdtree_Flann<DescriptorT::bin_type, MetricT> MatcherT; // Brute force matcher can be defined as following: //typedef L2_Vectorized<DescriptorT::bin_type> MetricT; //typedef ArrayMatcherBruteForce<DescriptorT::bin_type, MetricT> MatcherT; // If the matches already exists, reload them if (stlplus::file_exists(sOutDir + "/matches.putative.txt")) { PairedIndMatchImport(sOutDir + "/matches.putative.txt", map_PutativesMatches); std::cout << std::endl << "PUTATIVE MATCHES -- PREVIOUS RESULTS LOADED" << std::endl; } else // Compute the putatives matches { //Matcher_AllInMemory<KeypointSetT, MatcherT> collectionMatcher(fDistRatio); SparseMatcher<KeypointSetT, MatcherT> collectionMatcher(fDistRatio, sequentialLimit); if (collectionMatcher.loadData(vec_fileNames, sOutDir)) { std::cout << std::endl << "PUTATIVE MATCHES" << std::endl; collectionMatcher.Match(vec_fileNames, map_PutativesMatches); //--------------------------------------- //-- Export putative matches //--------------------------------------- std::ofstream file(std::string(sOutDir + "/matches.putative.txt").c_str()); if (file.is_open()) PairedIndMatchToStream(map_PutativesMatches, file); file.close(); } } //-- export putative matches Adjacency matrix PairWiseMatchingToAdjacencyMatrixSVG(vec_fileNames.size(), map_PutativesMatches, stlplus::create_filespec(sOutDir, "PutativeAdjacencyMatrix", "svg")); //--------------------------------------- // d. Geometric filtering of putative matches // - AContrario Estimation of the desired geometric model // - Use an upper bound for the a contrario estimated threshold //--------------------------------------- PairWiseMatches map_GeometricMatches; ImageCollectionGeometricFilter<FeatureT> collectionGeomFilter; const double maxResidualError = 4.0; size_t iterations = 8192; // 4096 if (collectionGeomFilter.loadData(vec_fileNames, sOutDir)) { std::cout << std::endl << " - GEOMETRIC FILTERING - " << std::endl; switch (eGeometricModelToCompute) { case FUNDAMENTAL_MATRIX: { collectionGeomFilter.Filter( GeometricFilter_FMatrix_AC(maxResidualError, iterations), map_PutativesMatches, map_GeometricMatches, vec_imagesSize); } break; case ESSENTIAL_MATRIX: { collectionGeomFilter.Filter( GeometricFilter_EMatrix_AC(vec_focalGroup[0].m_K, maxResidualError), map_PutativesMatches, map_GeometricMatches, vec_imagesSize); //-- Perform an additional check to remove pairs with poor overlap std::vector<PairWiseMatches::key_type> vec_toRemove; for (PairWiseMatches::const_iterator iterMap = map_GeometricMatches.begin(); iterMap != map_GeometricMatches.end(); ++iterMap) { size_t putativePhotometricCount = map_PutativesMatches.find(iterMap->first)->second.size(); size_t putativeGeometricCount = iterMap->second.size(); float ratio = putativeGeometricCount / (float)putativePhotometricCount; if (putativeGeometricCount < 50 || ratio < .3f) { // the pair will be removed vec_toRemove.push_back(iterMap->first); } } //-- remove discarded pairs for (std::vector<PairWiseMatches::key_type>::const_iterator iter = vec_toRemove.begin(); iter != vec_toRemove.end(); ++iter) { map_GeometricMatches.erase(*iter); } } break; case HOMOGRAPHY_MATRIX: { collectionGeomFilter.Filter( GeometricFilter_HMatrix_AC(maxResidualError), map_PutativesMatches, map_GeometricMatches, vec_imagesSize); } break; } //--------------------------------------- //-- Export geometric filtered matches //--------------------------------------- std::ofstream file (string(sOutDir + "/" + sGeometricMatchesFilename).c_str()); if (file.is_open()) PairedIndMatchToStream(map_GeometricMatches, file); file.close(); //-- export Adjacency matrix std::cout << "\n Export Adjacency Matrix of the pairwise's geometric matches" << std::endl; PairWiseMatchingToAdjacencyMatrixSVG(vec_fileNames.size(), map_GeometricMatches, stlplus::create_filespec(sOutDir, "GeometricAdjacencyMatrix", "svg")); } return EXIT_SUCCESS; }
int main(int argc, char **argv) { CmdLine cmd; std::string sImaDirectory; std::string sOutDir = ""; std::string sGeometricModel = "f"; float fDistRatio = .6f; cmd.add( make_option('i', sImaDirectory, "imadir") ); cmd.add( make_option('o', sOutDir, "outdir") ); cmd.add( make_option('r', fDistRatio, "distratio") ); cmd.add( make_option('g', sGeometricModel, "f") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--imadir path] \n" << "[-o|--outdir path] \n" << "\n[Optional]\n" << "[-g]--geometricModel f, e or h]" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } std::cout << " You called : " <<std::endl << argv[0] << std::endl << "--imadir " << sImaDirectory << std::endl << "--outdir " << sOutDir << std::endl << "--geometricModel " << sGeometricModel << std::endl; if (sOutDir.empty()) { std::cerr << "\nIt is an invalid output directory" << std::endl; return EXIT_FAILURE; } eGeometricModel eGeometricModelToCompute = FUNDAMENTAL_MATRIX; std::string sGeometricMatchesFilename = ""; switch(sGeometricModel[0]) { case 'f': case 'F': eGeometricModelToCompute = FUNDAMENTAL_MATRIX; sGeometricMatchesFilename = "matches.f.txt"; break; case 'e': case 'E': eGeometricModelToCompute = ESSENTIAL_MATRIX; sGeometricMatchesFilename = "matches.e.txt"; break; case 'h': case 'H': eGeometricModelToCompute = HOMOGRAPHY_MATRIX; sGeometricMatchesFilename = "matches.h.txt"; break; default: std::cerr << "Unknown geometric model" << std::endl; return EXIT_FAILURE; } // ----------------------------- // a. List images // b. Compute features and descriptors // c. Compute putative descriptor matches // d. Geometric filtering of putative matches // e. Export some statistics // ----------------------------- // Create output dir if (!stlplus::folder_exists(sOutDir)) stlplus::folder_create( sOutDir ); //--------------------------------------- // a. List images //--------------------------------------- std::string sListsFile = stlplus::create_filespec(sOutDir, "lists.txt" ); if (!stlplus::is_file(sListsFile)) { std::cerr << std::endl << "The input file \""<< sListsFile << "\" is missing" << std::endl; return false; } std::vector<openMVG::SfMIO::CameraInfo> vec_camImageName; std::vector<openMVG::SfMIO::IntrinsicCameraInfo> vec_focalGroup; if (!openMVG::SfMIO::loadImageList( vec_camImageName, vec_focalGroup, sListsFile) ) { std::cerr << "\nEmpty image list." << std::endl; return false; } if (eGeometricModelToCompute == ESSENTIAL_MATRIX) { //-- In the case of the essential matrix we check if only one K matrix is present. //-- Due to the fact that the generic framework allows only one K matrix for the // robust essential matrix estimation in image collection. std::vector<openMVG::SfMIO::IntrinsicCameraInfo>::iterator iterF = std::unique(vec_focalGroup.begin(), vec_focalGroup.end(), testIntrinsicsEquality); vec_focalGroup.resize( std::distance(vec_focalGroup.begin(), iterF) ); if (vec_focalGroup.size() == 1) { // Set all the intrinsic ID to 0 for (size_t i = 0; i < vec_camImageName.size(); ++i) vec_camImageName[i].m_intrinsicId = 0; } else { std::cerr << "There is more than one focal group in the lists.txt file." << std::endl << "Only one focal group is supported for the image collection robust essential matrix estimation." << std::endl; return EXIT_FAILURE; } } //-- Two alias to ease access to image filenames and image sizes std::vector<std::string> vec_fileNames; std::vector<std::pair<size_t, size_t> > vec_imagesSize; for ( std::vector<openMVG::SfMIO::CameraInfo>::const_iterator iter_camInfo = vec_camImageName.begin(); iter_camInfo != vec_camImageName.end(); iter_camInfo++ ) { vec_imagesSize.push_back( std::make_pair( vec_focalGroup[iter_camInfo->m_intrinsicId].m_w, vec_focalGroup[iter_camInfo->m_intrinsicId].m_h ) ); vec_fileNames.push_back( stlplus::create_filespec( sImaDirectory, iter_camInfo->m_sImageName) ); } //--------------------------------------- // b. Compute features and descriptor // - extract sift features and descriptor // - if keypoints already computed, re-load them // - else save features and descriptors on disk //--------------------------------------- //-- Make your choice about the Feature Detector your want to use //-- Note that the openCV + openMVG interface is working only for // floating point descriptor. //-- Surf opencv => default 64 floating point values typedef cv::SURF cvFeature2DInterfaceT; typedef Descriptor<float, 64> DescriptorT; std::cout << "\nUse the opencv SURF interface" << std::endl; //-- Sift opencv => default 128 floating point values //typedef cv::SIFT cvFeature2DInterfaceT; //typedef Descriptor<float, 128> DescriptorT; //std::cout << "\nUse the opencv SIFT interface" << std::endl; typedef SIOPointFeature FeatureT; typedef std::vector<FeatureT> FeatsT; typedef vector<DescriptorT > DescsT; typedef KeypointSet<FeatsT, DescsT > KeypointSetT; std::cout << "\n\nEXTRACT FEATURES" << std::endl; extractFeaturesAndDescriptors<KeypointSetT, DescriptorT, cvFeature2DInterfaceT>( vec_fileNames, // input filenames sOutDir, // Output directory where features and descriptor will be saved vec_imagesSize); //--------------------------------------- // c. Compute putative descriptor matches // - L2 descriptor matching // - Keep correspondences only if NearestNeighbor ratio is ok //--------------------------------------- IndexedMatchPerPair map_PutativesMatches; // Define the matcher and the used metric (Squared L2) // ANN matcher could be defined as follow: typedef flann::L2<DescriptorT::bin_type> MetricT; typedef ArrayMatcher_Kdtree_Flann<DescriptorT::bin_type, MetricT> MatcherT; // Brute force matcher can be defined as following: //typedef L2_Vectorized<DescriptorT::bin_type> MetricT; //typedef ArrayMatcherBruteForce<DescriptorT::bin_type, MetricT> MatcherT; // If the matches already exists, reload them if (stlplus::file_exists(sOutDir + "/matches.putative.txt")) { PairedIndMatchImport(sOutDir + "/matches.putative.txt", map_PutativesMatches); std::cout << std::endl << "PUTATIVE MATCHES -- PREVIOUS RESULTS LOADED" << std::endl; } else // Compute the putatives matches { Matcher_AllInMemory<KeypointSetT, MatcherT> collectionMatcher(fDistRatio); if (collectionMatcher.loadData(vec_fileNames, sOutDir)) { std::cout << std::endl << "PUTATIVE MATCHES" << std::endl; collectionMatcher.Match(vec_fileNames, map_PutativesMatches); //--------------------------------------- //-- Export putative matches //--------------------------------------- std::ofstream file (std::string(sOutDir + "/matches.putative.txt").c_str()); if (file.is_open()) PairedIndMatchToStream(map_PutativesMatches, file); file.close(); } } //-- export putative matches Adjacency matrix PairWiseMatchingToAdjacencyMatrixSVG(vec_fileNames.size(), map_PutativesMatches, stlplus::create_filespec(sOutDir, "PutativeAdjacencyMatrix", "svg")); //--------------------------------------- // d. Geometric filtering of putative matches // - AContrario Estimation of the desired geometric model // - Use an upper bound for the a contrario estimated threshold //--------------------------------------- IndexedMatchPerPair map_GeometricMatches; ImageCollectionGeometricFilter<FeatureT> collectionGeomFilter; const double maxResidualError = 4.0; if (collectionGeomFilter.loadData(vec_fileNames, sOutDir)) { std::cout << std::endl << " - GEOMETRIC FILTERING - " << std::endl; switch (eGeometricModelToCompute) { case FUNDAMENTAL_MATRIX: { collectionGeomFilter.Filter( GeometricFilter_FMatrix_AC(maxResidualError), map_PutativesMatches, map_GeometricMatches, vec_imagesSize); } break; case ESSENTIAL_MATRIX: { collectionGeomFilter.Filter( GeometricFilter_EMatrix_AC(vec_focalGroup[0].m_K, maxResidualError), map_PutativesMatches, map_GeometricMatches, vec_imagesSize); //-- Perform an additional check to remove pairs with poor overlap std::vector<IndexedMatchPerPair::key_type> vec_toRemove; for (IndexedMatchPerPair::const_iterator iterMap = map_GeometricMatches.begin(); iterMap != map_GeometricMatches.end(); ++iterMap) { size_t putativePhotometricCount = map_PutativesMatches.find(iterMap->first)->second.size(); size_t putativeGeometricCount = iterMap->second.size(); float ratio = putativeGeometricCount / (float)putativePhotometricCount; if (putativeGeometricCount < 50 || ratio < .3f) { // the pair will be removed vec_toRemove.push_back(iterMap->first); } } //-- remove discarded pairs for (std::vector<IndexedMatchPerPair::key_type>::const_iterator iter = vec_toRemove.begin(); iter != vec_toRemove.end(); ++iter) { map_GeometricMatches.erase(*iter); } } break; case HOMOGRAPHY_MATRIX: { collectionGeomFilter.Filter( GeometricFilter_HMatrix_AC(maxResidualError), map_PutativesMatches, map_GeometricMatches, vec_imagesSize); } break; } //--------------------------------------- //-- Export geometric filtered matches //--------------------------------------- std::ofstream file (string(sOutDir + "/" + sGeometricMatchesFilename).c_str()); if (file.is_open()) PairedIndMatchToStream(map_GeometricMatches, file); file.close(); //-- export Adjacency matrix std::cout << "\n Export Adjacency Matrix of the pairwise's geometric matches" << std::endl; PairWiseMatchingToAdjacencyMatrixSVG(vec_fileNames.size(), map_GeometricMatches, stlplus::create_filespec(sOutDir, "GeometricAdjacencyMatrix", "svg")); } return EXIT_SUCCESS; }
int main(int argc, char ** argv) { CmdLine cmd; std::string sImaDirectory; std::string sMatchesDir; std::string sOutDir = ""; cmd.add( make_option('i', sImaDirectory, "imadir") ); cmd.add( make_option('d', sMatchesDir, "matchdir") ); cmd.add( make_option('o', sOutDir, "outdir") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Export pairwise matches.\nUsage: " << argv[0] << "\n" << "[-i|--imadir path]\n" << "[-d|--matchdir path]\n" << "[-o|--outdir path]\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } if (sOutDir.empty()) { std::cerr << "\nIt is an invalid output directory" << std::endl; return EXIT_FAILURE; } //--------------------------------------- // Read images names //--------------------------------------- std::vector<SfMIO::CameraInfo> vec_camImageName; std::vector<SfMIO::IntrinsicCameraInfo> vec_focalGroup; if (!SfMIO::loadImageList( vec_camImageName, vec_focalGroup, stlplus::create_filespec(sMatchesDir, "lists", "txt"))) { std::cerr << "\nEmpty image list." << std::endl; return false; } // ------------ // For each image, export visually the keypoints // ------------ stlplus::folder_create(sOutDir); std::cout << "\n Export extracted keypoints for all images" << std::endl; C_Progress_display my_progress_bar( vec_camImageName.size() ); for (std::vector<SfMIO::CameraInfo>::const_iterator iterFilename = vec_camImageName.begin(); iterFilename != vec_camImageName.end(); ++iterFilename, ++my_progress_bar) { const size_t I = std::distance( (std::vector<SfMIO::CameraInfo>::const_iterator)vec_camImageName.begin(), iterFilename); const std::pair<size_t, size_t> dimImage = std::make_pair(vec_focalGroup[I].m_w, vec_focalGroup[I].m_h); svgDrawer svgStream( dimImage.first, dimImage.second); svgStream.drawImage(stlplus::create_filespec(sImaDirectory,iterFilename->m_sImageName), dimImage.first, dimImage.second); // Load the features from the feature file std::vector<SIOPointFeature> vec_feat; loadFeatsFromFile( stlplus::create_filespec(sMatchesDir, stlplus::basename_part(iterFilename->m_sImageName), ".feat"), vec_feat); //-- Draw features for (size_t i=0; i< vec_feat.size(); ++i) { const SIOPointFeature & feature = vec_feat[i]; svgStream.drawCircle(feature.x(), feature.y(), feature.scale(), svgStyle().stroke("yellow", 2.0)); } // Write the SVG file std::ostringstream os; os << stlplus::folder_append_separator(sOutDir) << stlplus::basename_part(iterFilename->m_sImageName) << "_" << vec_feat.size() << "_.svg"; ofstream svgFile( os.str().c_str() ); svgFile << svgStream.closeSvgFile().str(); svgFile.close(); } return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { CmdLine cmd; std::string sSfM_Data_Filename; cmd.add( make_option('i', sSfM_Data_Filename, "sfmdata") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--sfmdata filename, the SfM_Data file to read]\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } // Read the SfM scene if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(ALL))) { std::cerr << std::endl << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl; return EXIT_FAILURE; } // List valid camera (view that have a pose & a valid intrinsic data) for(Views::const_iterator iter = sfm_data.GetViews().begin(); iter != sfm_data.GetViews().end(); ++iter) { const View * view = iter->second.get(); if (!sfm_data.IsPoseAndIntrinsicDefined(view)) continue; vec_cameras.push_back(iter->first); } current_cam = 0; std::cout << "Press left or right key to navigate between cameras ;-)" << std::endl << "Move viewpoint with Q,W,E,A,S,D" << std::endl << "Change Normalized focal (camera cones size) with '+' and '-'" << std::endl << "Reset viewpoint position with R" << std::endl << "Esc to quit" << std::endl; //-- Create the GL window context GLFWwindow* window; int width, height; if( !glfwInit() ) { fprintf( stderr, "Failed to initialize GLFW\n" ); exit( EXIT_FAILURE ); } glfwWindowHint(GLFW_DEPTH_BITS, 16); window = glfwCreateWindow( 1000, 600, "SfmViewer", NULL, NULL ); if (!window) { fprintf( stderr, "Failed to open GLFW window\n" ); glfwTerminate(); exit( EXIT_FAILURE ); } // Set callback functions glfwSetWindowCloseCallback(window, window_close_callback); glfwSetWindowSizeCallback(window, reshape); glfwSetKeyCallback(window, key); glfwMakeContextCurrent(window); glfwSwapInterval( 1 ); glfwGetWindowSize(window, &width, &height); reshape(window, width, height); load_textures(); // Main loop while( running ) { // Draw SfM Scene draw(); // Swap buffers glfwSwapBuffers(window); glfwPollEvents(); } // Terminate GLFW glfwTerminate(); // Exit program exit( EXIT_SUCCESS ); }
void parseOptions ( int argc, char** argv ) { try { CmdLine cmd ( "keypoints", ' ', kVersion ); MyOutput my; cmd.setOutput ( &my ); SwitchArg aArgFullScale ( "","fullscale", "Uses full scale image to detect keypoints (default:false)\n", false ); // SURF has a better performance than the other descriptors, use it by default, if it is enabled ValueArg<int> aArgSurfScoreThreshold ( "","surfscore", "Detection score threshold (default : 1000)\n", false, 1000, "int" ); ValueArg<int> aArgSieve1Width ( "","sievewidth", "Interest point sieve: Number of buckets on width (default : 10)", false, 10, "int" ); ValueArg<int> aArgSieve1Height ( "","sieveheight", "Interest point sieve : Number of buckets on height (default : 10)", false, 10, "int" ); ValueArg<int> aArgSieve1Size ( "","sievesize", "Interest point sieve : Max points per bucket (default : 10)\n", false, 10, "int" ); ValueArg<std::string> aArgOutputFormat ( "","format", "Output format (text, autopano-xml, descperf), default text\n", false, "text", "string" ); ValueArg<std::string> aArgOutputFile ( "o","output", "Output file. If not specified, print to standard out\n", false, "", "string" ); SwitchArg aArgInterestPoints ( "","interestpoints", "output only the interest points and the scale (default:false)\n", false ); ValueArg<std::string> aArgFixedInterestPoint ( "","ip", "Compute descriptor at x,y,scale,ori \n", false, "", "string" ); cmd.add ( aArgSurfScoreThreshold ); cmd.add ( aArgFullScale ); cmd.add ( aArgSieve1Width ); cmd.add ( aArgSieve1Height ); cmd.add ( aArgSieve1Size ); cmd.add ( aArgOutputFormat ); cmd.add ( aArgOutputFile ); cmd.add ( aArgInterestPoints ); cmd.add ( aArgFixedInterestPoint ); /* SwitchArg aArgTest("t","test", "Enables test mode\n", false); cmd.add( aArgTest ); */ UnlabeledMultiArg<string> aArgFiles ( "fileName", "Image files", true, "string" ); cmd.add ( aArgFiles ); cmd.parse ( argc,argv ); // // Set variables // vector<string> aFiles = aArgFiles.getValue(); if ( aFiles.size() != 1 ) { exit ( 1 ); } double surfScoreThreshold=1000; if ( aArgSurfScoreThreshold.isSet() ) { surfScoreThreshold = ( aArgSurfScoreThreshold.getValue() ); } bool downscale = true; if ( aArgFullScale.isSet() ) { downscale = false; } int sieveWidth = 10; if ( aArgSieve1Width.isSet() ) { sieveWidth = aArgSieve1Width.getValue(); } int sieveHeight = 10; if ( aArgSieve1Height.isSet() ) { sieveHeight = aArgSieve1Height.getValue(); } int sieveSize = 10; if ( aArgSieve1Size.isSet() ) { sieveSize = aArgSieve1Size.getValue(); } bool onlyInterestPoints = false; if ( aArgInterestPoints.isSet() ) { onlyInterestPoints = true; } std::ostream* outstream; if ( aArgOutputFile.isSet() ) { outstream = new std::ofstream(aArgOutputFile.getValue().c_str()); } else { outstream = & std::cout; } KeypointWriter* writer = 0; std::string outputformat = "text"; if ( aArgOutputFormat.isSet() ) { outputformat = aArgOutputFormat.getValue(); } if (outputformat == "text") { writer = new SIFTFormatWriter(*outstream); } else if (outputformat == "autopano-sift-xml") { writer = new AutopanoSIFTWriter(*outstream); } else if (outputformat == "descperf") { writer = new DescPerfFormatWriter(*outstream); } else { std::cerr << "Unknown output format, valid values are text, autopano-sift-xml, descperf" << std::endl; exit(1); } KeyPointPtr preKPPtr; if ( aArgFixedInterestPoint.isSet() ) { preKPPtr = KeyPointPtr(new KeyPoint()); preKPPtr->_x = -10001; preKPPtr->_ori = -10001; int nf = sscanf(aArgFixedInterestPoint.getValue().c_str(), "%lf:%lf:%lf:%lf", &(preKPPtr->_x), &(preKPPtr->_y), &(preKPPtr->_scale), &(preKPPtr->_ori)); std::cerr << "passed orientation: " << preKPPtr->_ori << std::endl; if (nf < 3) { std::cerr << "Invalid value for --ip option, expected --ip x:y:scale:ori" << std::endl; exit(1); } } DetectKeypoints ( aFiles[0], downscale, surfScoreThreshold, preKPPtr, onlyInterestPoints, sieveWidth, sieveHeight, sieveSize, *writer ); if ( aArgOutputFile.isSet() ) { delete outstream; } } catch ( ArgException& e ) { cout << "ERROR: " << e.error() << " " << e.argId() << endl; } }
// Convert from a SfM_Data format to another int main(int argc, char **argv) { CmdLine cmd; std::string sSfM_Data_Filename_In, sSfM_Data_Filename_Out; cmd.add(make_option('i', sSfM_Data_Filename_In, "input_file")); cmd.add(make_switch('V', "VIEWS")); cmd.add(make_switch('I', "INTRINSICS")); cmd.add(make_switch('E', "EXTRINSICS")); cmd.add(make_switch('S', "STRUCTURE")); cmd.add(make_switch('C', "CONTROL_POINTS")); cmd.add(make_option('o', sSfM_Data_Filename_Out, "output_file")); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--input_file] path to the input SfM_Data scene\n" << "[-o|--output_file] path to the output SfM_Data scene\n" << "\t .json, .bin, .xml, .ply, .baf\n" << "\n[Options to export partial data (by default all data are exported)]\n" << "\nUsable for json/bin/xml format" << "[-V|--VIEWS] export views\n" << "[-I|--INTRINSICS] export intrinsics (view orientations)\n" << "[-E|--EXTRINSICS] export extrinsics (view poses)\n" << "[-S|--STRUCTURE] export structure\n" << "[-C|--CONTROL_POINTS] export control points\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } if (sSfM_Data_Filename_In.empty() || sSfM_Data_Filename_Out.empty()) { std::cerr << "Invalid input or output filename." << std::endl; return EXIT_FAILURE; } // OptionSwitch is cloned in cmd.add(), // so we must use cmd.used() instead of testing OptionSwitch.used int flags = (cmd.used('V') ? VIEWS : 0) | (cmd.used('I') ? INTRINSICS : 0) | (cmd.used('E') ? EXTRINSICS : 0) | (cmd.used('S') ? STRUCTURE : 0); flags = (flags) ? flags : ALL; // Load input SfM_Data scene SfM_Data sfm_data; if (!Load(sfm_data, sSfM_Data_Filename_In, ESfM_Data(ALL))) { std::cerr << std::endl << "The input SfM_Data file \"" << sSfM_Data_Filename_In << "\" cannot be read." << std::endl; return EXIT_FAILURE; } // Export the SfM_Data scene in the expected format if (Save( sfm_data, sSfM_Data_Filename_Out.c_str(), ESfM_Data(flags))) { return EXIT_SUCCESS; } else { std::cerr << std::endl << "An error occured while trying to save \"" << sSfM_Data_Filename_Out << "\"." << std::endl; return EXIT_FAILURE; } }
int main(int argc, char *argv[]) { CmdLine cmd; std::string sSfM_Data_Filename; std::string sOutDir = ""; bool bExportOnlyReconstructedViews = false; #ifdef OPENMVG_USE_OPENMP int iNumThreads = 0; #endif cmd.add( make_option('i', sSfM_Data_Filename, "sfmdata") ); cmd.add( make_option('o', sOutDir, "outdir") ); cmd.add( make_option('r', bExportOnlyReconstructedViews, "exportOnlyReconstructed") ); #ifdef OPENMVG_USE_OPENMP cmd.add( make_option('n', iNumThreads, "numThreads") ); #endif try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Export undistorted images related to a sfm_data file.\n" << "Usage: " << argv[0] << '\n' << "[-i|--sfmdata] filename, the SfM_Data file to convert\n" << "[-o|--outdir] path\n" << "[-r|--exportOnlyReconstructed] boolean 1/0 (default = 0)\n" #ifdef OPENMVG_USE_OPENMP << "[-n|--numThreads] number of thread(s)\n" #endif << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } // Create output dir if (!stlplus::folder_exists(sOutDir)) stlplus::folder_create( sOutDir ); SfM_Data sfm_data; if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(VIEWS|INTRINSICS|EXTRINSICS))) { std::cerr << std::endl << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl; return EXIT_FAILURE; } bool bOk = true; { system::Timer timer; // Export views as undistorted images (those with valid Intrinsics) Image<RGBColor> image, image_ud; C_Progress_display my_progress_bar( sfm_data.GetViews().size(), std::cout, "\n- EXTRACT UNDISTORTED IMAGES -\n" ); #ifdef OPENMVG_USE_OPENMP const unsigned int nb_max_thread = omp_get_max_threads(); #endif #ifdef OPENMVG_USE_OPENMP omp_set_num_threads(iNumThreads); #pragma omp parallel for schedule(dynamic) if(iNumThreads > 0) private(image,image_ud) #endif for (int i = 0; i < static_cast<int>(sfm_data.views.size()); ++i) { #ifdef OPENMVG_USE_OPENMP if(iNumThreads == 0) omp_set_num_threads(nb_max_thread); #endif Views::const_iterator iterViews = sfm_data.views.begin(); std::advance(iterViews, i); const View * view = iterViews->second.get(); // Check if the view is in reconstruction if (bExportOnlyReconstructedViews && !sfm_data.IsPoseAndIntrinsicDefined(view)) continue; const bool bIntrinsicDefined = view->id_intrinsic != UndefinedIndexT && sfm_data.GetIntrinsics().find(view->id_intrinsic) != sfm_data.GetIntrinsics().end(); if (!bIntrinsicDefined) continue; Intrinsics::const_iterator iterIntrinsic = sfm_data.GetIntrinsics().find(view->id_intrinsic); const std::string srcImage = stlplus::create_filespec(sfm_data.s_root_path, view->s_Img_path); const std::string dstImage = stlplus::create_filespec( sOutDir, stlplus::filename_part(srcImage)); const IntrinsicBase * cam = iterIntrinsic->second.get(); if (cam->have_disto()) { // undistort the image and save it if (ReadImage( srcImage.c_str(), &image)) { UndistortImage(image, cam, image_ud, BLACK); const bool bRes = WriteImage(dstImage.c_str(), image_ud); #ifdef OPENMVG_USE_OPENMP #pragma omp critical #endif bOk &= bRes; } } else // (no distortion) { // copy the image since there is no distortion stlplus::file_copy(srcImage, dstImage); } #ifdef OPENMVG_USE_OPENMP #pragma omp critical #endif ++my_progress_bar; } std::cout << "Task done in (s): " << timer.elapsed() << std::endl; } // Exit program if (bOk) return( EXIT_SUCCESS ); else return( EXIT_FAILURE ); }
int main(int argc, char **argv) { using namespace std; std::cout << "Sequential/Incremental reconstruction" << std::endl << " Perform incremental SfM (Initial Pair Essential + Resection)." << std::endl << std::endl; CmdLine cmd; std::string sSfM_Data_Filename; std::string sMatchesDir; std::string sOutDir = ""; std::pair<std::string,std::string> initialPairString("",""); std::string sIntrinsic_refinement_options = "ADJUST_ALL"; int i_User_camera_model = PINHOLE_CAMERA_RADIAL3; cmd.add( make_option('i', sSfM_Data_Filename, "input_file") ); cmd.add( make_option('m', sMatchesDir, "matchdir") ); cmd.add( make_option('o', sOutDir, "outdir") ); cmd.add( make_option('a', initialPairString.first, "initialPairA") ); cmd.add( make_option('b', initialPairString.second, "initialPairB") ); cmd.add( make_option('c', i_User_camera_model, "camera_model") ); cmd.add( make_option('f', sIntrinsic_refinement_options, "refineIntrinsics") ); try { if (argc == 1) throw std::string("Invalid parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--input_file] path to a SfM_Data scene\n" << "[-m|--matchdir] path to the matches that corresponds to the provided SfM_Data scene\n" << "[-o|--outdir] path where the output data will be stored\n" << "[-a|--initialPairA] filename of the first image (without path)\n" << "[-b|--initialPairB] filename of the second image (without path)\n" << "[-c|--camera_model] Camera model type for view with unknown intrinsic:\n" << "\t 1: Pinhole \n" << "\t 2: Pinhole radial 1\n" << "\t 3: Pinhole radial 3 (default)\n" << "\t 4: Pinhole radial 3 + tangential 2\n" << "\t 5: Pinhole fisheye\n" << "[-f|--refineIntrinsics] Intrinsic parameters refinement option\n" << "\t ADJUST_ALL -> refine all existing parameters (default) \n" << "\t NONE -> intrinsic parameters are held as constant\n" << "\t ADJUST_FOCAL_LENGTH -> refine only the focal length\n" << "\t ADJUST_PRINCIPAL_POINT -> refine only the principal point position\n" << "\t ADJUST_DISTORTION -> refine only the distortion coefficient(s) (if any)\n" << "\t -> NOTE: options can be combined thanks to '|'\n" << "\t ADJUST_FOCAL_LENGTH|ADJUST_PRINCIPAL_POINT\n" << "\t\t-> refine the focal length & the principal point position\n" << "\t ADJUST_FOCAL_LENGTH|ADJUST_DISTORTION\n" << "\t\t-> refine the focal length & the distortion coefficient(s) (if any)\n" << "\t ADJUST_PRINCIPAL_POINT|ADJUST_DISTORTION\n" << "\t\t-> refine the principal point position & the distortion coefficient(s) (if any)\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } if (i_User_camera_model < PINHOLE_CAMERA || i_User_camera_model > PINHOLE_CAMERA_FISHEYE ) { std::cerr << "\n Invalid camera type" << std::endl; return EXIT_FAILURE; } const cameras::Intrinsic_Parameter_Type intrinsic_refinement_options = cameras::StringTo_Intrinsic_Parameter_Type(sIntrinsic_refinement_options); // Load input SfM_Data scene SfM_Data sfm_data; if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(VIEWS|INTRINSICS))) { std::cerr << std::endl << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl; return EXIT_FAILURE; } // Init the regions_type from the image describer file (used for image regions extraction) using namespace openMVG::features; const std::string sImage_describer = stlplus::create_filespec(sMatchesDir, "image_describer", "json"); std::unique_ptr<Regions> regions_type = Init_region_type_from_file(sImage_describer); if (!regions_type) { std::cerr << "Invalid: " << sImage_describer << " regions type file." << std::endl; return EXIT_FAILURE; } // Features reading std::shared_ptr<Features_Provider> feats_provider = std::make_shared<Features_Provider>(); if (!feats_provider->load(sfm_data, sMatchesDir, regions_type)) { std::cerr << std::endl << "Invalid features." << std::endl; return EXIT_FAILURE; } // Matches reading std::shared_ptr<Matches_Provider> matches_provider = std::make_shared<Matches_Provider>(); if // Try to read the two matches file formats ( !(matches_provider->load(sfm_data, stlplus::create_filespec(sMatchesDir, "matches.f.txt")) || matches_provider->load(sfm_data, stlplus::create_filespec(sMatchesDir, "matches.f.bin"))) ) { std::cerr << std::endl << "Invalid matches file." << std::endl; return EXIT_FAILURE; } if (sOutDir.empty()) { std::cerr << "\nIt is an invalid output directory" << std::endl; return EXIT_FAILURE; } if (!stlplus::folder_exists(sOutDir)) { if (!stlplus::folder_create(sOutDir)) { std::cerr << "\nCannot create the output directory" << std::endl; } } //--------------------------------------- // Sequential reconstruction process //--------------------------------------- openMVG::system::Timer timer; SequentialSfMReconstructionEngine sfmEngine( sfm_data, sOutDir, stlplus::create_filespec(sOutDir, "Reconstruction_Report.html")); // Configure the features_provider & the matches_provider sfmEngine.SetFeaturesProvider(feats_provider.get()); sfmEngine.SetMatchesProvider(matches_provider.get()); // Configure reconstruction parameters sfmEngine.Set_Intrinsics_Refinement_Type(intrinsic_refinement_options); sfmEngine.SetUnknownCameraType(EINTRINSIC(i_User_camera_model)); // Handle Initial pair parameter if (!initialPairString.first.empty() && !initialPairString.second.empty()) { Pair initialPairIndex; if(!computeIndexFromImageNames(sfm_data, initialPairString, initialPairIndex)) { std::cerr << "Could not find the initial pairs <" << initialPairString.first << ", " << initialPairString.second << ">!\n"; return EXIT_FAILURE; } sfmEngine.setInitialPair(initialPairIndex); } if (sfmEngine.Process()) { std::cout << std::endl << " Total Ac-Sfm took (s): " << timer.elapsed() << std::endl; std::cout << "...Generating SfM_Report.html" << std::endl; Generate_SfM_Report(sfmEngine.Get_SfM_Data(), stlplus::create_filespec(sOutDir, "SfMReconstruction_Report.html")); //-- Export to disk computed scene (data & visualizable results) std::cout << "...Export SfM_Data to disk." << std::endl; Save(sfmEngine.Get_SfM_Data(), stlplus::create_filespec(sOutDir, "sfm_data", ".bin"), ESfM_Data(ALL)); Save(sfmEngine.Get_SfM_Data(), stlplus::create_filespec(sOutDir, "cloud_and_poses", ".ply"), ESfM_Data(ALL)); return EXIT_SUCCESS; } return EXIT_FAILURE; }
int main(int argc, char *argv[]) { CmdLine cmd; std::string sSfM_Dir; cmd.add( make_option('i', sSfM_Dir, "sfmdir") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--sfmdir SfM_Output path]\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } if (m_doc.load(sSfM_Dir)) { current_cam = 0; std::cout << "Press left or right key to navigate between cameras ;-)" << std::endl << "Move viewpoint with Q,W,E,A,S,D" << std::endl << "Change Normalized focal with Z and X" << std::endl << "Reset viewpoint position with R" << std::endl << "Esc to quit" << std::endl; } else { exit( EXIT_FAILURE); } //-- Create the GL window context GLFWwindow* window; int width, height; if( !glfwInit() ) { fprintf( stderr, "Failed to initialize GLFW\n" ); exit( EXIT_FAILURE ); } glfwWindowHint(GLFW_DEPTH_BITS, 16); window = glfwCreateWindow( 1000, 600, "SfmViewer", NULL, NULL ); if (!window) { fprintf( stderr, "Failed to open GLFW window\n" ); glfwTerminate(); exit( EXIT_FAILURE ); } // Set callback functions glfwSetWindowCloseCallback(window, window_close_callback); glfwSetWindowSizeCallback(window, reshape); glfwSetKeyCallback(window, key); glfwMakeContextCurrent(window); glfwSwapInterval( 1 ); glfwGetWindowSize(window, &width, &height); reshape(window, width, height); load_textures(); // Main loop while( running ) { // Draw SfM Scene draw(); // Swap buffers glfwSwapBuffers(window); glfwPollEvents(); } // Terminate GLFW glfwTerminate(); // Exit program exit( EXIT_SUCCESS ); }
int main(int argc, char **argv) { CmdLine cmd; std::string sImageDir, sChannelFile = "", smacAddress = "", sOutputDir = "", sMountPoint = "", sTimestampLow= "", sTimestampUp=""; li_Real_t focalPixPermm = -1.0; bool bRigidRig = true; bool bUseCalibPrincipalPoint = false; cmd.add( make_option('i', sImageDir, "imageDirectory") ); cmd.add( make_option('m', smacAddress, "macAddress") ); cmd.add( make_option('o', sOutputDir, "outputDirectory") ); cmd.add( make_option('d', sMountPoint, "mountPoint") ); cmd.add( make_option('c', sChannelFile, "channelFile") ); cmd.add( make_option('r', bRigidRig, "rigidRig") ); cmd.add( make_option('p', bUseCalibPrincipalPoint, "useCalibPrincipalPoint") ); cmd.add( make_option('f', focalPixPermm, "focal") ); cmd.add( make_option('a', sTimestampLow, "lowerBound") ); cmd.add( make_option('b', sTimestampUp, "upperBound") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--imageDirectory]\n" << "[-m|--macAddress\n" << "[-o|--outputDirectory]\n" << "[-d|--mountPoint]\n" << "[-c|--channelFile]\n" << "[-r|--rigidRig \n" << " -r 0 : no rigid rig \n" << " -r 1 : with rigid rig structure\n" << "[-p|--useCalibPrincipalPoint\n" << " -p 0 : do not use calibration principal point \n" << " -p 1 : use calibration principal point \n" << "[-a|--lowerBound \n" << "[-b|--upperBound \n" << "[-f|--focal] (pixels)\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } // verify that input argumet are valid const bool bValidInput = isInputValid ( argv[0], sImageDir, sOutputDir, smacAddress, sMountPoint, sChannelFile, bRigidRig, bUseCalibPrincipalPoint, focalPixPermm, sTimestampLow, sTimestampUp ); if( !bValidInput ) { std::cerr << " Input data are not valid. Please check your input\n" << std::endl; return EXIT_FAILURE; } else // if input data is valid, go ahead { // now extract calibration information related to each module std::vector < sensorData > vec_sensorData; const bool bLoadCalibration = loadCalibrationData( vec_sensorData, sMountPoint, smacAddress); if( !bLoadCalibration ) { return EXIT_FAILURE; } else // if calibration information are loaded, go ahead { // load image filename std::vector<std::string> vec_image = stlplus::folder_files( sImageDir ); // load kept channel std::vector< li_Size_t > keptChan; loadChannelFile( keptChan, sChannelFile ); //create and export list to folder bool isExported = computeInstrinsicPerImages( vec_image, vec_sensorData, keptChan, sImageDir, sOutputDir, focalPixPermm, bUseCalibPrincipalPoint, bRigidRig, sTimestampLow, sTimestampUp); // do final check to ensure all went well if( isExported ) { std::cout << "Sucessfully exported list to folder. Quit" << std::endl; return EXIT_SUCCESS; } else { std::cerr << "Could not export list to folder. Exit " << std::endl; return EXIT_FAILURE; } } } }
int main(int argc, char **argv) { using namespace std; std::cout << std::endl << "-----------------------------------------------------------\n" << "Global Structure from Motion:\n" << "-----------------------------------------------------------\n" << "Open Source implementation of the paper:\n" << "\"Global Fusion of Relative Motions for " << "Robust, Accurate and Scalable Structure from Motion.\"\n" << "Pierre Moulon, Pascal Monasse and Renaud Marlet. " << " ICCV 2013." << std::endl << "------------------------------------------------------------" << std::endl; CmdLine cmd; std::string sSfM_Data_Filename; std::string sMatchesDir; std::string sOutDir = ""; int iRotationAveragingMethod = int (ROTATION_AVERAGING_L2); int iTranslationAveragingMethod = int (TRANSLATION_AVERAGING_SOFTL1); std::string sIntrinsic_refinement_options = "ADJUST_ALL"; cmd.add( make_option('i', sSfM_Data_Filename, "input_file") ); cmd.add( make_option('m', sMatchesDir, "matchdir") ); cmd.add( make_option('o', sOutDir, "outdir") ); cmd.add( make_option('r', iRotationAveragingMethod, "rotationAveraging") ); cmd.add( make_option('t', iTranslationAveragingMethod, "translationAveraging") ); cmd.add( make_option('f', sIntrinsic_refinement_options, "refineIntrinsics") ); try { if (argc == 1) throw std::string("Invalid parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Usage: " << argv[0] << '\n' << "[-i|--input_file] path to a SfM_Data scene\n" << "[-m|--matchdir] path to the matches that corresponds to the provided SfM_Data scene\n" << "[-o|--outdir] path where the output data will be stored\n" << "\n[Optional]\n" << "[-r|--rotationAveraging]\n" << "\t 1 -> L1 minimization\n" << "\t 2 -> L2 minimization (default)\n" << "[-t|--translationAveraging]:\n" << "\t 1 -> L1 minimization\n" << "\t 2 -> L2 minimization of sum of squared Chordal distances\n" << "\t 3 -> SoftL1 minimization (default)\n" << "[-f|--refineIntrinsics] Intrinsic parameters refinement option\n" << "\t ADJUST_ALL -> refine all existing parameters (default) \n" << "\t NONE -> intrinsic parameters are held as constant\n" << "\t ADJUST_FOCAL_LENGTH -> refine only the focal length\n" << "\t ADJUST_PRINCIPAL_POINT -> refine only the principal point position\n" << "\t ADJUST_DISTORTION -> refine only the distortion coefficient(s) (if any)\n" << "\t -> NOTE: options can be combined thanks to '|'\n" << "\t ADJUST_FOCAL_LENGTH|ADJUST_PRINCIPAL_POINT\n" << "\t\t-> refine the focal length & the principal point position\n" << "\t ADJUST_FOCAL_LENGTH|ADJUST_DISTORTION\n" << "\t\t-> refine the focal length & the distortion coefficient(s) (if any)\n" << "\t ADJUST_PRINCIPAL_POINT|ADJUST_DISTORTION\n" << "\t\t-> refine the principal point position & the distortion coefficient(s) (if any)\n" << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } if (iRotationAveragingMethod < ROTATION_AVERAGING_L1 || iRotationAveragingMethod > ROTATION_AVERAGING_L2 ) { std::cerr << "\n Rotation averaging method is invalid" << std::endl; return EXIT_FAILURE; } const cameras::Intrinsic_Parameter_Type intrinsic_refinement_options = cameras::StringTo_Intrinsic_Parameter_Type(sIntrinsic_refinement_options); if (iTranslationAveragingMethod < TRANSLATION_AVERAGING_L1 || iTranslationAveragingMethod > TRANSLATION_AVERAGING_SOFTL1 ) { std::cerr << "\n Translation averaging method is invalid" << std::endl; return EXIT_FAILURE; } // Load input SfM_Data scene SfM_Data sfm_data; if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(VIEWS|INTRINSICS))) { std::cerr << std::endl << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl; return EXIT_FAILURE; } // Init the regions_type from the image describer file (used for image regions extraction) using namespace openMVG::features; const std::string sImage_describer = stlplus::create_filespec(sMatchesDir, "image_describer", "json"); std::unique_ptr<Regions> regions_type = Init_region_type_from_file(sImage_describer); if (!regions_type) { std::cerr << "Invalid: " << sImage_describer << " regions type file." << std::endl; return EXIT_FAILURE; } // Features reading std::shared_ptr<Features_Provider> feats_provider = std::make_shared<Features_Provider>(); std::string sFeaturesDirectory = sSfM_Data_Filename.substr(0, sSfM_Data_Filename.find_last_of("\\/")); //if (!feats_provider->load(sfm_data, sMatchesDir, regions_type)) { if (!feats_provider->load(sfm_data, sFeaturesDirectory, regions_type)) { std::cerr << std::endl << "Invalid features." << std::endl; return EXIT_FAILURE; } // Matches reading std::shared_ptr<Matches_Provider> matches_provider = std::make_shared<Matches_Provider>(); if // Try to read the two matches file formats ( !(matches_provider->load(sfm_data, stlplus::create_filespec(sMatchesDir, "matches.e.txt")) || matches_provider->load(sfm_data, stlplus::create_filespec(sMatchesDir, "matches.e.bin"))) ) { std::cerr << std::endl << "Invalid matches file." << std::endl; return EXIT_FAILURE; } if (sOutDir.empty()) { std::cerr << "\nIt is an invalid output directory" << std::endl; return EXIT_FAILURE; } if (!stlplus::folder_exists(sOutDir)) { if (!stlplus::folder_create(sOutDir)) { std::cerr << "\nCannot create the output directory" << std::endl; } } //--------------------------------------- // Global SfM reconstruction process //--------------------------------------- openMVG::system::Timer timer; GlobalSfMReconstructionEngine_RelativeMotions sfmEngine( sfm_data, sOutDir, stlplus::create_filespec(sOutDir, "Reconstruction_Report.html")); // Configure the features_provider & the matches_provider sfmEngine.SetFeaturesProvider(feats_provider.get()); sfmEngine.SetMatchesProvider(matches_provider.get()); // Configure reconstruction parameters sfmEngine.Set_Intrinsics_Refinement_Type(intrinsic_refinement_options); // Configure motion averaging method sfmEngine.SetRotationAveragingMethod( ERotationAveragingMethod(iRotationAveragingMethod)); sfmEngine.SetTranslationAveragingMethod( ETranslationAveragingMethod(iTranslationAveragingMethod)); if (sfmEngine.Process()) { std::cout << std::endl << " Total Ac-Global-Sfm took (s): " << timer.elapsed() << std::endl; std::cout << "...Generating SfM_Report.html" << std::endl; Generate_SfM_Report(sfmEngine.Get_SfM_Data(), stlplus::create_filespec(sOutDir, "SfMReconstruction_Report.html")); //-- Export to disk computed scene (data & visualizable results) std::cout << "...Export SfM_Data to disk." << std::endl; Save(sfmEngine.Get_SfM_Data(), stlplus::create_filespec(sOutDir, "sfm_data", ".bin"), ESfM_Data(ALL)); Save(sfmEngine.Get_SfM_Data(), stlplus::create_filespec(sOutDir, "cloud_and_poses", ".ply"), ESfM_Data(ALL)); return EXIT_SUCCESS; } return EXIT_FAILURE; }
int main(int argc, char ** argv) { CmdLine cmd; std::string sImaDirectory; std::string sMatchesDir; std::string sMatchFile; std::string sOutDir = ""; cmd.add( make_option('i', sImaDirectory, "imadir") ); cmd.add( make_option('d', sMatchesDir, "matchdir") ); cmd.add( make_option('m', sMatchFile, "matchfile") ); cmd.add( make_option('o', sOutDir, "outdir") ); try { if (argc == 1) throw std::string("Invalid command line parameter."); cmd.process(argc, argv); } catch(const std::string& s) { std::cerr << "Export pairwise tracks.\nUsage: " << argv[0] << ' ' << "[-i|--imadir path] " << "[-d|--matchdir path] " << "[-m|--sMatchFile filename] " << "[-o|--outdir path] " << std::endl; std::cerr << s << std::endl; return EXIT_FAILURE; } if (sOutDir.empty()) { std::cerr << "\nIt is an invalid output directory" << std::endl; return EXIT_FAILURE; } //--------------------------------------- // Read images names //--------------------------------------- std::vector<std::string> vec_fileNames; if (!SfMIO::loadImageList( vec_fileNames, stlplus::create_filespec(sMatchesDir, "lists", "txt"),false)) { std::cerr << "\nEmpty input image list" << std::endl; return EXIT_FAILURE; } //--------------------------------------- // Read matches //--------------------------------------- typedef std::map< std::pair<size_t, size_t>, std::vector<IndMatch> > map_pairWiseMatches; map_pairWiseMatches map_Matches; PairedIndMatchImport(sMatchFile, map_Matches); //--------------------------------------- // Compute tracks from matches //--------------------------------------- TracksBuilder tracksBuilder; tracks::STLMAPTracks map_tracks; { tracksBuilder.Build(map_Matches); tracksBuilder.Filter(); //-- Build tracks with STL compliant type : tracksBuilder.ExportToSTL(map_tracks); } // ------------ // For each pair, export the matches // ------------ //-- //- Preprocess the images size Image<RGBColor> image; std::map< std::string, std::pair<size_t, size_t> > map_imageSize; for (std::vector<std::string>::const_iterator iterFilename = vec_fileNames.begin(); iterFilename != vec_fileNames.end(); ++iterFilename) { ReadImage( stlplus::create_filespec(sImaDirectory,*iterFilename).c_str() , &image); map_imageSize.insert( std::make_pair(*iterFilename, std::make_pair(image.Width(), image.Height()))); } stlplus::folder_create(sOutDir); std::cout << "\n Export pairwise tracks" << std::endl; C_Progress_display my_progress_bar( (vec_fileNames.size()*(vec_fileNames.size()-1)) / 2.0 ); for (size_t I = 0; I < vec_fileNames.size(); ++I) { for (size_t J = I+1; J < vec_fileNames.size(); ++J, ++my_progress_bar) { const std::pair<size_t, size_t> dimImage0 = map_imageSize.find(vec_fileNames[I])->second, dimImage1 = map_imageSize.find(vec_fileNames[J])->second; //Get common tracks between view I and J tracks::STLMAPTracks map_tracksCommon; std::set<size_t> set_imageIndex; set_imageIndex.insert(I); set_imageIndex.insert(J); TracksUtilsMap::GetTracksInImages(set_imageIndex, map_tracks, map_tracksCommon); if (!map_tracksCommon.empty()) { svgDrawer svgStream( dimImage0.first + dimImage1.first, max(dimImage0.second, dimImage1.second)); svgStream.drawImage(stlplus::create_filespec(sImaDirectory,vec_fileNames[I]), dimImage0.first, dimImage0.second); svgStream.drawImage(stlplus::create_filespec(sImaDirectory,vec_fileNames[J]), dimImage1.first, dimImage1.second, dimImage0.first); // Load the features from the features files std::vector<SIOPointFeature> vec_featI, vec_featJ; loadFeatsFromFile( stlplus::create_filespec(sMatchesDir, stlplus::basename_part(vec_fileNames[I]), ".feat"), vec_featI); loadFeatsFromFile( stlplus::create_filespec(sMatchesDir, stlplus::basename_part(vec_fileNames[J]), ".feat"), vec_featJ); //-- Draw link between features : for (tracks::STLMAPTracks::const_iterator iterT = map_tracksCommon.begin(); iterT != map_tracksCommon.end(); ++ iterT) { tracks::submapTrack::const_iterator iter = iterT->second.begin(); const SIOPointFeature & imaA = vec_featI[ iter->second]; ++iter; const SIOPointFeature & imaB = vec_featJ[ iter->second]; svgStream.drawLine(imaA.x(), imaA.y(), imaB.x()+dimImage0.first, imaB.y(), svgStyle().stroke("green", 2.0)); } //-- Draw features (in two loop, in order to have the features upper the link, svg layer order): for (tracks::STLMAPTracks::const_iterator iterT = map_tracksCommon.begin(); iterT != map_tracksCommon.end(); ++ iterT) { tracks::submapTrack::const_iterator iter = iterT->second.begin(); const SIOPointFeature & imaA = vec_featI[ iter->second]; ++iter; const SIOPointFeature & imaB = vec_featJ[ iter->second]; svgStream.drawCircle(imaA.x(), imaA.y(), imaA.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(imaB.x() + dimImage0.first,imaB.y(), imaB.scale(), svgStyle().stroke("yellow", 2.0)); } std::ostringstream os; os << stlplus::folder_append_separator(sOutDir) << I << "_" << J << "_" << map_tracksCommon.size() << "_.svg"; ofstream svgFile( os.str().c_str() ); svgFile << svgStream.closeSvgFile().str(); } } } return EXIT_SUCCESS; }