Beispiel #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]);
      }
    }
  }
Beispiel #2
0
  /// Build tracks for a given series of pairWise matches
  void Build( const matching::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)
    std::set<indexedFeaturePair> allFeatures;
    // For each couple of images list the used features
    for ( const auto & iter : map_pair_wise_matches )
    {
      const auto & I = iter.first.first;
      const auto & J = iter.first.second;
      const std::vector<matching::IndMatch> & vec_FilteredMatches = iter.second;

      // Retrieve all shared features and add them to a set
      for ( const auto & cur_filtered_match : vec_FilteredMatches )
      {
        allFeatures.emplace(I,cur_filtered_match.i_);
        allFeatures.emplace(J,cur_filtered_match.j_);
      }
    }

    // 2. Build the 'flat' representation where a tuple (the node)
    //  is attached to a unique index.
    map_node_to_index.reserve(allFeatures.size());
    uint32_t 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 ( const auto & iter : map_pair_wise_matches )
    {
      const auto & I = iter.first.first;
      const auto & J = iter.first.second;
      const std::vector<matching::IndMatch> & vec_FilteredMatches = iter.second;
      for (const matching::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]);
      }
    }
  }
Beispiel #3
0
  /// Remove bad tracks (too short or track with ids collision)
  bool Filter(size_t nLengthSupTo = 2)
  {
    // Remove bad tracks:
    // - track that are too short,
    // - track with id conflicts:
    //    i.e. tracks that have many times the same image index

    // From the UF tree, create tracks of the image indexes.
    //  If an image index appears two time the track must disappear
    //  If a track is too short it has to be removed.
    std::map<unsigned int, std::set<unsigned int> > tracks;

    std::set<unsigned int> problematic_track_id;
    // Build tracks from the UF tree, track problematic ids.
    for (unsigned int k = 0; k < map_node_to_index.size(); ++k)
    {
      const unsigned int & track_id = uf_tree.m_cc_parent[k];
      if (problematic_track_id.count(track_id) != 0)
        continue; // Track already marked

      const auto & feat = map_node_to_index[k];

      if (tracks[track_id].count(feat.first.first))
      {
        problematic_track_id.insert(track_id);
      }
      else
      {
        tracks[track_id].insert(feat.first.first);
      }
    }

    // - track that are too short,
    for (const auto & val : tracks)
    {
      if (val.second.size() < nLengthSupTo)
      {
        problematic_track_id.insert(val.first);
      }
    }

    for (unsigned int & root_index : uf_tree.m_cc_parent)
    {
      if (problematic_track_id.count(root_index) > 0)
      {
        // reset selected root
        uf_tree.m_cc_size[root_index] = 1;
        root_index = std::numeric_limits<unsigned int>::max();
      }
    }
    return false;
  }
Beispiel #4
0
 /// Export tracks as a map (each entry is a sequence of imageId and featureIndex):
 ///  {TrackIndex => {(imageIndex, featureIndex), ... ,(imageIndex, featureIndex)}
 void ExportToSTL(STLMAPTracks & map_tracks)
 {
   map_tracks.clear();
   for (unsigned int k = 0; k < map_node_to_index.size(); ++k)
   {
     const auto & feat = map_node_to_index[k];
     const unsigned int track_id = uf_tree.m_cc_parent[k];
     if
     (
       // ensure never add rejected elements (track marked as invalid)
       track_id != std::numeric_limits<unsigned int>::max()
       // ensure never add 1-length track element (it's not a track)
       && uf_tree.m_cc_size[track_id] > 1
     )
     {
       map_tracks[track_id].insert(feat.first);
     }
   }
 }