Example #1
0
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;
  }
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
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 );
}
Example #7
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 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;
}
Example #8
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;
}
Example #9
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;
}
Example #10
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 );
}
Example #12
0
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;
}
Example #16
0
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;
}
Example #17
0
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;
}
Example #21
0
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;
}
Example #22
0
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;
  }
}
Example #25
0
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;
}
Example #27
0
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;
}
Example #30
0
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;
}