Exemplo n.º 1
0
  /// Build tracks for a given series of pairWise matches
  void Build( const PairWiseMatches &  map_pair_wise_matches)
  {
    // 1. We need to know how much single set we will have.
    //   i.e each set is made of a tuple : (imageIndex, featureIndex)
    typedef std::set<indexedFeaturePair> SetIndexedPair;
    SetIndexedPair allFeatures;
    // For each couple of images list the used features
    for (PairWiseMatches::const_iterator iter = map_pair_wise_matches.begin();
      iter != map_pair_wise_matches.end();
      ++iter)
    {
      const size_t & I = iter->first.first;
      const size_t & J = iter->first.second;
      const std::vector<IndMatch> & vec_FilteredMatches = iter->second;

      // Retrieve all shared features and add them to a set
      for( size_t k = 0; k < vec_FilteredMatches.size(); ++k)
      {
        allFeatures.emplace(I,vec_FilteredMatches[k].i_);
        allFeatures.emplace(J,vec_FilteredMatches[k].j_);
      }
    }

    // 2. Build the 'flat' representation where a tuple (the node)
    //  is attached to an unique index.
    map_node_to_index.reserve(allFeatures.size());
    unsigned int cpt = 0;
    for (const auto & feat : allFeatures)
    {
      map_node_to_index.emplace_back(feat, cpt);
      ++cpt;
    }
    // Sort the flat_pair_map
    map_node_to_index.sort();
    // Clean some memory
    allFeatures.clear();

    // 3. Add the node and the pairwise correpondences in the UF tree.
    uf_tree.InitSets(map_node_to_index.size());

    // 4. Union of the matched features corresponding UF tree sets
    for (PairWiseMatches::const_iterator iter = map_pair_wise_matches.begin();
      iter != map_pair_wise_matches.end();
      ++iter)
    {
      const auto & I = iter->first.first;
      const auto & J = iter->first.second;
      const std::vector<IndMatch> & vec_FilteredMatches = iter->second;
      for (const IndMatch & match : vec_FilteredMatches)
      {
        const indexedFeaturePair pairI(I, match.i_);
        const indexedFeaturePair pairJ(J, match.j_);
        // Link feature correspondences to the corresponding containing sets.
        uf_tree.Union(map_node_to_index[pairI], map_node_to_index[pairJ]);
      }
    }
  }
Exemplo n.º 2
0
TEST(IndMatch, IO)
{
  PairWiseMatches matches;

  // Test save + load of empty data
  EXPECT_TRUE(Save(matches, "matches.txt"));
  EXPECT_TRUE(Load(matches, "matches.txt"));
  EXPECT_EQ(0, matches.size());

  EXPECT_TRUE(Save(matches, "matches.bin"));
  EXPECT_TRUE(Load(matches, "matches.bin"));
  EXPECT_EQ(0, matches.size());

  // Test export with not empty data
  matches[std::make_pair(0,1)] = {{0,0},{1,1}};
  matches[std::make_pair(1,2)] = {{0,0},{1,1}, {2,2}};

  EXPECT_TRUE(Save(matches, "matches.txt"));
  EXPECT_TRUE(Load(matches, "matches.txt"));
  EXPECT_EQ(2, matches.size());
  EXPECT_EQ(1, matches.count(std::make_pair(0,1)));
  EXPECT_EQ(1, matches.count(std::make_pair(1,2)));
  EXPECT_EQ(2, matches.at(std::make_pair(0,1)).size());
  EXPECT_EQ(3, matches.at(std::make_pair(1,2)).size());

  matches.clear();
  matches[std::make_pair(0,1)] = {{0,0},{1,1}};
  matches[std::make_pair(1,2)] = {{0,0},{1,1}, {2,2}};

  EXPECT_TRUE(Save(matches, "matches.bin"));
  EXPECT_TRUE(Load(matches, "matches.bin"));
  EXPECT_EQ(2, matches.size());
  EXPECT_EQ(1, matches.count(std::make_pair(0,1)));
  EXPECT_EQ(1, matches.count(std::make_pair(1,2)));
  EXPECT_EQ(2, matches.at(std::make_pair(0,1)).size());
  EXPECT_EQ(3, matches.at(std::make_pair(1,2)).size());
}
Exemplo n.º 3
0
  void Filter(
    const GeometricFilterT & geometricFilter,  // geometric filter functor
    PairWiseMatches & map_PutativesMatchesPair, // putative correspondences to filter
    PairWiseMatches & map_GeometricMatches,
    const std::vector<std::pair<size_t, size_t> > & vec_imagesSize) const
  {
    C_Progress_display my_progress_bar( map_PutativesMatchesPair.size() );

#ifdef OPENMVG_USE_OPENMP
  #pragma omp parallel for schedule(dynamic)
#endif
    for (int i = 0; i < (int)map_PutativesMatchesPair.size(); ++i)
    {
      PairWiseMatches::const_iterator iter = map_PutativesMatchesPair.begin();
      advance(iter,i);

      const size_t iIndex = iter->first.first;
      const size_t jIndex = iter->first.second;
      const std::vector<IndMatch> & vec_PutativeMatches = iter->second;

      // Load features of Inth and Jnth images
      const features::PointFeatures & kpSetI = _feat_provider->getFeatures(iIndex);
      const features::PointFeatures & kpSetJ = _feat_provider->getFeatures(jIndex);

      //-- Copy point to array in order to estimate fundamental matrix :
      const size_t n = vec_PutativeMatches.size();
      Mat xI(2,n), xJ(2,n);

      for (size_t i=0; i < vec_PutativeMatches.size(); ++i)  {
        const features::PointFeature & imaA = kpSetI[vec_PutativeMatches[i]._i];
        const features::PointFeature & imaB = kpSetJ[vec_PutativeMatches[i]._j];
        xI.col(i) = Vec2f(imaA.coords()).cast<double>();
        xJ.col(i) = Vec2f(imaB.coords()).cast<double>();
      }

      //-- Apply the geometric filter
      {
        std::vector<size_t> vec_inliers;
        geometricFilter.Fit(
          iter->first,
          xI, vec_imagesSize[iIndex],
          xJ, vec_imagesSize[jIndex],
          vec_inliers);

        if(!vec_inliers.empty())
        {
          std::vector<IndMatch> vec_filteredMatches;
          vec_filteredMatches.reserve(vec_inliers.size());
          for (size_t i=0; i < vec_inliers.size(); ++i)  {
            vec_filteredMatches.push_back( vec_PutativeMatches[vec_inliers[i]] );
          }
#ifdef OPENMVG_USE_OPENMP
  #pragma omp critical
#endif
          {
            map_GeometricMatches.insert(std::make_pair(std::make_pair(iIndex, jIndex), std::move(vec_filteredMatches)));
          }
        }
      }
#ifdef OPENMVG_USE_OPENMP
#pragma omp critical
#endif
      {
        ++my_progress_bar;
      }
    }
  }
Exemplo n.º 4
0
  void Filter(
    const GeometricFilterT & geometricFilter,
    PairWiseMatches & map_PutativesMatchesPair, // putative correspondences to filter
    PairWiseMatches & map_GeometricMatches,
    const std::vector<std::pair<size_t, size_t> > & vec_imagesSize) const
  {
    C_Progress_display my_progress_bar( map_PutativesMatchesPair.size() );

#ifdef USE_OPENMP
  #pragma omp parallel for schedule(dynamic, 1)
#endif
    for (int i = 0; i < (int)map_PutativesMatchesPair.size(); ++i)
    {
      PairWiseMatches::const_iterator iter = map_PutativesMatchesPair.begin();
      advance(iter,i);

      const size_t iIndex = iter->first.first;
      const size_t jIndex = iter->first.second;
      const std::vector<IndMatch> & vec_PutativeMatches = iter->second;

      // Load features of Inth and Jnth images
      typename std::map<size_t, std::vector<FeatureT> >::const_iterator iterFeatsI = map_Feat.begin();
      typename std::map<size_t, std::vector<FeatureT> >::const_iterator iterFeatsJ = map_Feat.begin();
      std::advance(iterFeatsI, iIndex);
      std::advance(iterFeatsJ, jIndex);
      const std::vector<FeatureT> & kpSetI = iterFeatsI->second;
      const std::vector<FeatureT> & kpSetJ = iterFeatsJ->second;

      //-- Copy point to array in order to estimate fundamental matrix :
      const size_t n = vec_PutativeMatches.size();
      Mat xI(2,n), xJ(2,n);

      for (size_t i=0; i < vec_PutativeMatches.size(); ++i)  {
        const FeatureT & imaA = kpSetI[vec_PutativeMatches[i]._i];
        const FeatureT & imaB = kpSetJ[vec_PutativeMatches[i]._j];
        xI.col(i) = Vec2f(imaA.coords()).cast<double>();
        xJ.col(i) = Vec2f(imaB.coords()).cast<double>();
      }

      //-- Apply the geometric filter
      {
        std::vector<size_t> vec_inliers;
        // Use a copy in order to copy use internal functor parameters
        // and use it safely in multi-thread environment
        GeometricFilterT filter = geometricFilter;
        filter.Fit(xI, vec_imagesSize[iIndex], xJ, vec_imagesSize[jIndex], vec_inliers);

        if(!vec_inliers.empty())
        {
          std::vector<IndMatch> vec_filteredMatches;
          vec_filteredMatches.reserve(vec_inliers.size());
          for (size_t i=0; i < vec_inliers.size(); ++i)  {
            vec_filteredMatches.push_back( vec_PutativeMatches[vec_inliers[i]] );
          }
#ifdef USE_OPENMP
  #pragma omp critical
#endif
          {
            map_GeometricMatches[std::make_pair(iIndex,jIndex)] = vec_filteredMatches;
          }
        }
      }
      ++my_progress_bar;
    }
  }
void Matcher_Regions_AllInMemory::Match(
  const sfm::SfM_Data & sfm_data,
  const std::shared_ptr<sfm::Regions_Provider> & regions_provider,
  const Pair_Set & pairs,
  PairWiseMatches & map_PutativesMatches)const // the pairwise photometric corresponding points
{
#ifdef OPENMVG_USE_OPENMP
  std::cout << "Using the OPENMP thread interface" << std::endl;
#endif
  const bool b_multithreaded_pair_search = (eMatcherType_ == CASCADE_HASHING_L2);
  // -> set to true for CASCADE_HASHING_L2, since OpenMP instructions are not used in this matcher

  C_Progress_display my_progress_bar( pairs.size() );

  // Sort pairs according the first index to minimize the MatcherT build operations
  typedef std::map<size_t, std::vector<size_t> > Map_vectorT;
  Map_vectorT map_Pairs;
  for (Pair_Set::const_iterator iter = pairs.begin(); iter != pairs.end(); ++iter)
  {
    map_Pairs[iter->first].push_back(iter->second);
  }

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

    const features::Regions & regionsI = *regions_provider->regions_per_view.at(I).get();
    if (regionsI.RegionCount() == 0)
    {
      my_progress_bar += indexToCompare.size();
      continue;
    }

    // Initialize the matching interface
    matching::Matcher_Regions_Database matcher(eMatcherType_, regionsI);

#ifdef OPENMVG_USE_OPENMP
    #pragma omp parallel for schedule(dynamic) if(b_multithreaded_pair_search)
#endif
    for (int j = 0; j < (int)indexToCompare.size(); ++j)
    {
      const size_t J = indexToCompare[j];

      const features::Regions &regionsJ = *regions_provider->regions_per_view.at(J).get();
      if (regionsJ.RegionCount() == 0
          || regionsI.Type_id() != regionsJ.Type_id())
      {
#ifdef OPENMVG_USE_OPENMP
  #pragma omp critical
#endif
        ++my_progress_bar;
        continue;
      }

      IndMatches vec_putatives_matches;
      matcher.Match(f_dist_ratio_, regionsJ, vec_putatives_matches);

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