コード例 #1
0
    // Load Regions related to a provided SfM_Data View container
  virtual bool load(
    const SfM_Data & sfm_data,
    const std::string & feat_directory,
    std::unique_ptr<features::Regions>& region_type)
  {
    C_Progress_display my_progress_bar( sfm_data.GetViews().size(),
      std::cout, "\n- Regions Loading -\n");
    // Read for each view the corresponding regions and store them
    for (Views::const_iterator iter = sfm_data.GetViews().begin();
      iter != sfm_data.GetViews().end(); ++iter, ++my_progress_bar)
    {
      const std::string sImageName = stlplus::create_filespec(sfm_data.s_root_path, iter->second.get()->s_Img_path);
      const std::string basename = stlplus::basename_part(sImageName);
      const std::string featFile = stlplus::create_filespec(feat_directory, basename, ".feat");
      const std::string descFile = stlplus::create_filespec(feat_directory, basename, ".desc");

      regions_per_view[iter->second.get()->id_view] = std::unique_ptr<features::Regions>(region_type->EmptyClone());
      if (!regions_per_view[iter->second.get()->id_view]->Load(featFile, descFile))
      {
        std::cerr << "Invalid regions files for the view: " << sImageName << std::endl;
        return false;
      }
    }
    return true;
  }
コード例 #2
0
ファイル: main.cpp プロジェクト: Jfck/openMVG
void load_textures()
{
	int nbCams = m_doc._vec_imageNames.size();
	m_image_vector.resize(nbCams);

  std::cout << "**\Textures loading, Please wait...\n";
  C_Progress_display my_progress_bar( nbCams );
	for ( int i_cam=0; i_cam<nbCams; ++i_cam, ++my_progress_bar) {
		std::string sImageName = stlplus::create_filespec( stlplus::folder_append_separator(m_doc._sDirectory)+"images",
			m_doc._vec_imageNames[i_cam]);

		std::vector<unsigned char> img;
		int w,h,depth;
		if (ReadImage(sImageName.c_str(),	&img,	&w,	&h,	&depth)) {
			glEnable(GL_TEXTURE_2D);
			//std::cout << "Read image : " << sImageName << "\n" << std::endl;
			glDeleteTextures(1, &m_image_vector[i_cam].texture);

			// Create texture
			glGenTextures( 1, &m_image_vector[i_cam].texture);
			// select our current texture
		  glBindTexture(GL_TEXTURE_2D, m_image_vector[i_cam].texture);

		  m_image_vector[i_cam].width = w;
		  m_image_vector[i_cam].height = h;
		  glTexImage2D(GL_TEXTURE_2D, 0, (depth == 1) ? GL_LUMINANCE : GL_RGB,  m_image_vector[i_cam].width,
		  		m_image_vector[i_cam].height, 0, (depth == 1) ? GL_LUMINANCE : GL_RGB, GL_UNSIGNED_BYTE,
				  &img[0]);

		  glBindTexture(GL_TEXTURE_2D, m_image_vector[i_cam].texture);
	  }
  }
   std::cout << "**\Textures loading, Done" << std::endl;
}
コード例 #3
0
  // Load features related to a provided SfM_Data View container
  virtual bool load(
    const SfM_Data & sfm_data,
    const std::string & feat_directory,
    std::unique_ptr<features::Image_describer>& image_describer)
  {
    C_Progress_display my_progress_bar( sfm_data.GetViews().size(),
      std::cout, "\n- Features Loading -\n" );
    // Read for each view the corresponding features and store them as PointFeatures
    std::unique_ptr<features::Regions> regions;
    image_describer->Allocate(regions);
    for (Views::const_iterator iter = sfm_data.GetViews().begin();
      iter != sfm_data.GetViews().end(); ++iter, ++my_progress_bar)
    {
      const std::string sImageName = stlplus::create_filespec(sfm_data.s_root_path, iter->second.get()->s_Img_path);
      const std::string basename = stlplus::basename_part(sImageName);
      const std::string featFile = stlplus::create_filespec(feat_directory, basename, ".feat");

      if (!image_describer->LoadFeatures(regions.get(), featFile))
      {
        std::cerr << "Invalid feature files for the view: " << sImageName << std::endl;
        return false;
      }
      // save loaded Features as PointFeature
      feats_per_view[iter->second.get()->id_view] = regions->GetRegionsPositions();
    }
    return true;
  }
コード例 #4
0
  virtual bool load(
    const SfM_Data & sfm_data,
    const std::string & feat_directory,
    std::unique_ptr<features::Regions>& region_type)
  {
    C_Progress_display my_progress_bar( sfm_data.GetViews().size(),
      std::cout, "\n- Features Loading -\n" );
    // Read for each view the corresponding features and store them as PointFeatures
    bool bContinue = true;
#ifdef OPENMVG_USE_OPENMP
    #pragma omp parallel
#endif
    for (Views::const_iterator iter = sfm_data.GetViews().begin();
      iter != sfm_data.GetViews().end() && bContinue; ++iter)
    {
#ifdef OPENMVG_USE_OPENMP
    #pragma omp single nowait
#endif
      {
        const std::string sImageName = stlplus::create_filespec(sfm_data.s_root_path, iter->second.get()->s_Img_path);
        const std::string basename = stlplus::basename_part(sImageName);
        const std::string featFile = stlplus::create_filespec(feat_directory, basename, ".feat");

        std::unique_ptr<features::Regions> regions(region_type->EmptyClone());
        if (!regions->LoadFeatures(featFile))
        {
          std::cerr << "Invalid feature files for the view: " << sImageName << std::endl;
#ifdef OPENMVG_USE_OPENMP
      #pragma omp critical
#endif
          bContinue = false;
        }
#ifdef OPENMVG_USE_OPENMP
      #pragma omp critical
#endif
        {
          // save loaded Features as PointFeature
          feats_per_view[iter->second.get()->id_view] = regions->GetRegionsPositions();
          ++my_progress_bar;
        }
      }
    }
    return bContinue;
  }
コード例 #5
0
  /// Use guided matching to find corresponding 2-view correspondences
  void match(
    const SfM_Data & sfm_data,
    const Pair_Set & pairs,
    const std::shared_ptr<Regions_Provider> & regions_provider)
  {
    C_Progress_display my_progress_bar( pairs.size(), std::cout,
      "Compute pairwise fundamental guided matching:\n" );
  #ifdef OPENMVG_USE_OPENMP
    #pragma omp parallel
  #endif // OPENMVG_USE_OPENMP
    for (Pair_Set::const_iterator it = pairs.begin(); it != pairs.end(); ++it)
    {
  #ifdef OPENMVG_USE_OPENMP
      #pragma omp single nowait
  #endif // OPENMVG_USE_OPENMP
      {
      // --
      // Perform GUIDED MATCHING
      // --
      // Use the computed model to check valid correspondences
      // - by considering geometric error and descriptor distance ratio.
      std::vector<IndMatch> vec_corresponding_indexes;

      const View * viewL = sfm_data.getViews().at(it->first).get();
      const Poses::const_iterator iterPoseL = sfm_data.getPoses().find(viewL->id_pose);
      const Intrinsics::const_iterator iterIntrinsicL = sfm_data.getIntrinsics().find(viewL->id_intrinsic);
      const View * viewR = sfm_data.getViews().at(it->second).get();
      const Poses::const_iterator iterPoseR = sfm_data.getPoses().find(viewR->id_pose);
      const Intrinsics::const_iterator iterIntrinsicR = sfm_data.getIntrinsics().find(viewR->id_intrinsic);

      Mat xL, xR;
      PointsToMat(iterIntrinsicL->second.get(), regions_provider->regions_per_view.at(it->first)->GetRegionsPositions(), xL);
      PointsToMat(iterIntrinsicR->second.get(), regions_provider->regions_per_view.at(it->second)->GetRegionsPositions(), xR);

      const Mat34 P_L = iterIntrinsicL->second.get()->get_projective_equivalent(iterPoseL->second);
      const Mat34 P_R = iterIntrinsicR->second.get()->get_projective_equivalent(iterPoseR->second);

      const Mat3 F_lr = F_from_P(P_L, P_R);
      const double thresholdF = 4.0;

#if defined(EXHAUSTIVE_MATCHING)
      // Guided matching considering geometric error and descriptor distance ratio
      geometry_aware::GuidedMatching
        <Mat3, openMVG::fundamental::kernel::EpipolarDistanceError,
        DescriptorT, L2_Vectorized<DescriptorT::bin_type> >(
        F_lr, xL, desc_provider.at(it->first), xR, desc_provider.at(it->second),
        Square(thresholdF), Square(0.8),
        vec_corresponding_indexes);
#else
      const Vec3 epipole2  = epipole_from_P(P_R, iterPoseL->second);

      const features::Regions * regions = regions_provider->regions_per_view.at(it->first).get();
      if (regions->IsScalar())
      {
        // L2 Metric (Handle descriptor internal type)
        if(regions->Type_id() == typeid(unsigned char).name())
        {
          geometry_aware::GuidedMatching_Fundamental_Fast<
          openMVG::fundamental::kernel::EpipolarDistanceError,
          L2_Vectorized<unsigned char> >
          ( F_lr,
            epipole2,
            regions_provider->regions_per_view.at(it->first).get(),
            iterIntrinsicR->second.get()->w(), iterIntrinsicR->second.get()->h(),
            regions_provider->regions_per_view.at(it->second).get(),
            Square(thresholdF), Square(0.8),
            vec_corresponding_indexes);
        }
        else
        if(regions->Type_id() == typeid(float).name())
        {
          geometry_aware::GuidedMatching_Fundamental_Fast<
          openMVG::fundamental::kernel::EpipolarDistanceError,
          L2_Vectorized<float> >
          ( F_lr,
            epipole2,
            regions_provider->regions_per_view.at(it->first).get(),
            iterIntrinsicR->second.get()->w(), iterIntrinsicR->second.get()->h(),
            regions_provider->regions_per_view.at(it->second).get(),
            Square(thresholdF), Square(0.8),
            vec_corresponding_indexes);
        }
        else
        if(regions->Type_id() == typeid(double).name())
        {
          geometry_aware::GuidedMatching_Fundamental_Fast<
          openMVG::fundamental::kernel::EpipolarDistanceError,
          L2_Vectorized<double> >
          ( F_lr,
            epipole2,
            regions_provider->regions_per_view.at(it->first).get(),
            iterIntrinsicR->second.get()->w(), iterIntrinsicR->second.get()->h(),
            regions_provider->regions_per_view.at(it->second).get(),
            Square(thresholdF), Square(0.8),
            vec_corresponding_indexes);
        }
      }
      else
      if (regions->IsBinary() && regions->Type_id() == typeid(unsigned char).name())
      {
        // Hamming metric
        geometry_aware::GuidedMatching_Fundamental_Fast<
        openMVG::fundamental::kernel::EpipolarDistanceError,
        Hamming<unsigned char> >
        ( F_lr,
          epipole2,
          regions_provider->regions_per_view.at(it->first).get(),
          iterIntrinsicR->second.get()->w(), iterIntrinsicR->second.get()->h(),
          regions_provider->regions_per_view.at(it->second).get(),
          Square(thresholdF), 0.8,
          vec_corresponding_indexes);
      }

#endif

  #ifdef OPENMVG_USE_OPENMP
      #pragma omp critical
  #endif // OPENMVG_USE_OPENMP
        {
          ++my_progress_bar;
          for (size_t i = 0; i < vec_corresponding_indexes.size(); ++i)
            putatives_matches[*it].push_back(vec_corresponding_indexes[i]);
        }
      }
    }
  }
コード例 #6
0
  /// Filter inconsistent correspondences by using 3-view correspondences on view triplets
  void filter(
    const SfM_Data & sfm_data,
    const Pair_Set & pairs,
    const std::shared_ptr<Regions_Provider> & regions_provider)
  {
    // Compute triplets
    // Triangulate triplet tracks
    //  - keep valid one

    typedef std::vector< graphUtils::Triplet > Triplets;
    const Triplets triplets = graphUtils::tripletListing(pairs);

    C_Progress_display my_progress_bar( triplets.size(), std::cout,
      "Per triplet tracks validation (discard spurious correspondences):\n" );
  #ifdef OPENMVG_USE_OPENMP
      #pragma omp parallel
  #endif // OPENMVG_USE_OPENMP
    for( Triplets::const_iterator it = triplets.begin(); it != triplets.end(); ++it)
    {
  #ifdef OPENMVG_USE_OPENMP
      #pragma omp single nowait
  #endif // OPENMVG_USE_OPENMP
      {
        #ifdef OPENMVG_USE_OPENMP
          #pragma omp critical
        #endif // OPENMVG_USE_OPENMP
        {++my_progress_bar;}

        const graphUtils::Triplet & triplet = *it;
        const IndexT I = triplet.i, J = triplet.j , K = triplet.k;

        openMVG::tracks::STLMAPTracks map_tracksCommon;
        openMVG::tracks::TracksBuilder tracksBuilder;
        {
          PairWiseMatches map_matchesIJK;
          if(putatives_matches.find(std::make_pair(I,J)) != putatives_matches.end())
            map_matchesIJK.insert(*putatives_matches.find(std::make_pair(I,J)));

          if(putatives_matches.find(std::make_pair(I,K)) != putatives_matches.end())
            map_matchesIJK.insert(*putatives_matches.find(std::make_pair(I,K)));

          if(putatives_matches.find(std::make_pair(J,K)) != putatives_matches.end())
            map_matchesIJK.insert(*putatives_matches.find(std::make_pair(J,K)));

          if (map_matchesIJK.size() >= 2) {
            tracksBuilder.Build(map_matchesIJK);
            tracksBuilder.Filter(3);
            tracksBuilder.ExportToSTL(map_tracksCommon);
          }

          // Triangulate the tracks
          for (tracks::STLMAPTracks::const_iterator iterTracks = map_tracksCommon.begin();
            iterTracks != map_tracksCommon.end(); ++iterTracks) {
            {
              const tracks::submapTrack & subTrack = iterTracks->second;
              Triangulation trianObj;
              for (tracks::submapTrack::const_iterator iter = subTrack.begin(); iter != subTrack.end(); ++iter) {
                const size_t imaIndex = iter->first;
                const size_t featIndex = iter->second;
                const View * view = sfm_data.getViews().at(imaIndex).get();
                const IntrinsicBase * cam = sfm_data.getIntrinsics().at(view->id_intrinsic).get();
                const Pose3 & pose = sfm_data.poses.at(view->id_pose);
                const Vec2 pt = regions_provider->regions_per_view.at(imaIndex)->GetRegionPosition(featIndex);
                trianObj.add(cam->get_projective_equivalent(pose), cam->get_ud_pixel(pt));
              }
              const Vec3 Xs = trianObj.compute();
              if (trianObj.minDepth() > 0 && trianObj.error() < 4.0)
              // TODO: Add an angular check ?
              {
                #ifdef OPENMVG_USE_OPENMP
                  #pragma omp critical
                #endif // OPENMVG_USE_OPENMP
                {
                  openMVG::tracks::submapTrack::const_iterator iterI, iterJ, iterK;
                  iterI = iterJ = iterK = subTrack.begin();
                  std::advance(iterJ,1);
                  std::advance(iterK,2);

                  triplets_matches[std::make_pair(I,J)].push_back(IndMatch(iterI->second, iterJ->second));
                  triplets_matches[std::make_pair(J,K)].push_back(IndMatch(iterJ->second, iterK->second));
                  triplets_matches[std::make_pair(I,K)].push_back(IndMatch(iterI->second, iterK->second));
                }
              }
            }
          }
        }
      }
    }
    // Clear putatives matches since they are no longer required
    matching::PairWiseMatches().swap(putatives_matches);
  }
コード例 #7
0
void Match
(
  const sfm::SfM_Data & sfm_data,
  const sfm::Regions_Provider & regions_provider,
  const Pair_Set & pairs,
  float fDistRatio,
  PairWiseMatchesContainer & map_PutativesMatches // the pairwise photometric corresponding points
)
{
  C_Progress_display my_progress_bar( pairs.size() );

  // Collect used view indexes
  std::set<IndexT> used_index;
  // Sort pairs according the first index to minimize later memory swapping
  using Map_vectorT = std::map<IndexT, std::vector<IndexT>>;
  Map_vectorT map_Pairs;
  for (Pair_Set::const_iterator iter = pairs.begin(); iter != pairs.end(); ++iter)
  {
    map_Pairs[iter->first].push_back(iter->second);
    used_index.insert(iter->first);
    used_index.insert(iter->second);
  }

  using BaseMat = Eigen::Matrix<ScalarT, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;

  // Init the cascade hasher
  CascadeHasher cascade_hasher;
  if (!used_index.empty())
  {
    const IndexT I = *used_index.begin();
    std::shared_ptr<features::Regions> regionsI = regions_provider.get(I);
    const size_t dimension = regionsI.get()->DescriptorLength();
    cascade_hasher.Init(dimension);
  }

  std::map<IndexT, HashedDescriptions> hashed_base_;

  // Compute the zero mean descriptor that will be used for hashing (one for all the image regions)
  Eigen::VectorXf zero_mean_descriptor;
  {
    Eigen::MatrixXf matForZeroMean;
    for (int i =0; i < used_index.size(); ++i)
    {
      std::set<IndexT>::const_iterator iter = used_index.begin();
      std::advance(iter, i);
      const IndexT I = *iter;
      std::shared_ptr<features::Regions> regionsI = regions_provider.get(I);
      const ScalarT * tabI =
        reinterpret_cast<const ScalarT*>(regionsI.get()->DescriptorRawData());
      const size_t dimension = regionsI.get()->DescriptorLength();
      if (i==0)
      {
        matForZeroMean.resize(used_index.size(), dimension);
        matForZeroMean.fill(0.0f);
      }
      if (regionsI.get()->RegionCount() > 0)
      {
        Eigen::Map<BaseMat> mat_I( (ScalarT*)tabI, regionsI.get()->RegionCount(), dimension);
        matForZeroMean.row(i) = CascadeHasher::GetZeroMeanDescriptor(mat_I);
      }
    }
    zero_mean_descriptor = CascadeHasher::GetZeroMeanDescriptor(matForZeroMean);
  }

  // Index the input regions
#ifdef OPENMVG_USE_OPENMP
  #pragma omp parallel for schedule(dynamic)
#endif
  for (int i =0; i < used_index.size(); ++i)
  {
    std::set<IndexT>::const_iterator iter = used_index.begin();
    std::advance(iter, i);
    const IndexT I = *iter;
    std::shared_ptr<features::Regions> regionsI = regions_provider.get(I);
    const ScalarT * tabI =
      reinterpret_cast<const ScalarT*>(regionsI.get()->DescriptorRawData());
    const size_t dimension = regionsI.get()->DescriptorLength();

    Eigen::Map<BaseMat> mat_I( (ScalarT*)tabI, regionsI.get()->RegionCount(), dimension);
    HashedDescriptions hashed_description = cascade_hasher.CreateHashedDescriptions(mat_I,
      zero_mean_descriptor);
#ifdef OPENMVG_USE_OPENMP
    #pragma omp critical
#endif
    {
      hashed_base_[I] = std::move(hashed_description);
    }
  }

  // Perform matching between all the pairs
  for (Map_vectorT::const_iterator iter = map_Pairs.begin();
    iter != map_Pairs.end(); ++iter)
  {
    const IndexT I = iter->first;
    const std::vector<IndexT> & indexToCompare = iter->second;

    std::shared_ptr<features::Regions> regionsI = regions_provider.get(I);
    if (regionsI.get()->RegionCount() == 0)
    {
      my_progress_bar += indexToCompare.size();
      continue;
    }

    const std::vector<features::PointFeature> pointFeaturesI = regionsI.get()->GetRegionsPositions();
    const ScalarT * tabI =
      reinterpret_cast<const ScalarT*>(regionsI.get()->DescriptorRawData());
    const size_t dimension = regionsI.get()->DescriptorLength();
    Eigen::Map<BaseMat> mat_I( (ScalarT*)tabI, regionsI.get()->RegionCount(), dimension);

#ifdef OPENMVG_USE_OPENMP
    #pragma omp parallel for schedule(dynamic)
#endif
    for (int j = 0; j < (int)indexToCompare.size(); ++j)
    {
      size_t J = indexToCompare[j];
      std::shared_ptr<features::Regions> regionsJ = regions_provider.get(J);

      if (regionsI.get()->Type_id() != regionsJ.get()->Type_id())
      {
#ifdef OPENMVG_USE_OPENMP
        #pragma omp critical
#endif
        ++my_progress_bar;
        continue;
      }

      // Matrix representation of the query input data;
      const ScalarT * tabJ = reinterpret_cast<const ScalarT*>(regionsJ.get()->DescriptorRawData());
      Eigen::Map<BaseMat> mat_J( (ScalarT*)tabJ, regionsJ.get()->RegionCount(), dimension);

      IndMatches pvec_indices;
      using ResultType = typename Accumulator<ScalarT>::Type;
      std::vector<ResultType> pvec_distances;
      pvec_distances.reserve(regionsJ.get()->RegionCount() * 2);
      pvec_indices.reserve(regionsJ.get()->RegionCount() * 2);

      // Match the query descriptors to the database
      cascade_hasher.Match_HashedDescriptions<BaseMat, ResultType>(
        hashed_base_[J], mat_J,
        hashed_base_[I], mat_I,
        &pvec_indices, &pvec_distances);

      std::vector<int> vec_nn_ratio_idx;
      // Filter the matches using a distance ratio test:
      //   The probability that a match is correct is determined by taking
      //   the ratio of distance from the closest neighbor to the distance
      //   of the second closest.
      matching::NNdistanceRatio(
        pvec_distances.begin(), // distance start
        pvec_distances.end(),   // distance end
        2, // Number of neighbor in iterator sequence (minimum required 2)
        vec_nn_ratio_idx, // output (indices that respect the distance Ratio)
        Square(fDistRatio));

      matching::IndMatches vec_putative_matches;
      vec_putative_matches.reserve(vec_nn_ratio_idx.size());
      for (size_t k=0; k < vec_nn_ratio_idx.size(); ++k)
      {
        const size_t index = vec_nn_ratio_idx[k];
        vec_putative_matches.emplace_back(pvec_indices[index*2].j_, pvec_indices[index*2].i_);
      }

      // Remove duplicates
      matching::IndMatch::getDeduplicated(vec_putative_matches);

      // Remove matches that have the same (X,Y) coordinates
      const std::vector<features::PointFeature> pointFeaturesJ = regionsJ.get()->GetRegionsPositions();
      matching::IndMatchDecorator<float> matchDeduplicator(vec_putative_matches,
        pointFeaturesI, pointFeaturesJ);
      matchDeduplicator.getDeduplicated(vec_putative_matches);

#ifdef OPENMVG_USE_OPENMP
#pragma omp critical
#endif
      {
        ++my_progress_bar;
        if (!vec_putative_matches.empty())
        {
          map_PutativesMatches.insert( make_pair( make_pair(I,J), std::move(vec_putative_matches) ));
        }
      }
    }
  }
}