diff --git a/src/aliceVision/track/TracksBuilder.cpp b/src/aliceVision/track/TracksBuilder.cpp index 7b979a9edb..2399ce1593 100644 --- a/src/aliceVision/track/TracksBuilder.cpp +++ b/src/aliceVision/track/TracksBuilder.cpp @@ -40,8 +40,6 @@ namespace track { using namespace aliceVision::matching; using namespace lemon; -// IndexedFeaturePair is: pair -using IndexedFeaturePair = std::pair; using IndexMap = lemon::ListDigraph::NodeMap; using UnionFindObject = lemon::UnionFindEnum< IndexMap >; @@ -76,7 +74,8 @@ TracksBuilder::TracksBuilder() TracksBuilder::~TracksBuilder() = default; void mergeTracks(const feature::MapFeaturesPerView& featuresPerView, const MapIndexToNode& map_indexToNode, - const PairwiseMatches& pairwiseMatches, std::unique_ptr& _d) + const PairwiseMatches& pairwiseMatches, std::unique_ptr& _d, + stl::flat_map& _duplicateFeaturesMap) { // make the union according to duplicate features // (same position, scale and describer type, but different orientations) @@ -86,7 +85,7 @@ void mergeTracks(const feature::MapFeaturesPerView& featuresPerView, const MapIn // map of DuplicateFeatureId(x, y, scale) to // pair of (set, node) HashMap, const MapIndexToNode::mapped_type*>>>> + HashMap, const MapIndexToNode::mapped_type*>>>> duplicateFeaturesPerView; // per viewId pair @@ -150,6 +149,20 @@ void mergeTracks(const feature::MapFeaturesPerView& featuresPerView, const MapIn } } } + + // fill duplicate features map + for(const auto& [viewId, duplicateFeaturesPerDesc] : duplicateFeaturesPerView) + for(const auto& [descType, duplicateFeatures] : duplicateFeaturesPerDesc) + for(const auto& [duplicateFeatureId, duplicateFeature] : duplicateFeatures) + { + auto& duplicateFeatureIdsSet = duplicateFeature.first; + size_t indexedFeaturePair_0 = *duplicateFeatureIdsSet.begin(); + for(const auto& featureId : duplicateFeatureIdsSet) + { + const auto& indexedFeaturePair_i = IndexedFeaturePair(viewId, KeypointId(descType, featureId)); + _duplicateFeaturesMap[indexedFeaturePair_i] = indexedFeaturePair_0; + } + } } void TracksBuilder::build(const PairwiseMatches& pairwiseMatches, const feature::MapFeaturesPerView* featuresPerView) @@ -225,7 +238,7 @@ void TracksBuilder::build(const PairwiseMatches& pairwiseMatches, const feature: } if(featuresPerView != NULL) - mergeTracks(*featuresPerView, map_indexToNode, pairwiseMatches, _d); + mergeTracks(*featuresPerView, map_indexToNode, pairwiseMatches, _d, _duplicateFeaturesMap); } void TracksBuilder::filter(bool clearForks, std::size_t minTrackLength, bool multithreaded) @@ -244,14 +257,31 @@ void TracksBuilder::filter(bool clearForks, std::size_t minTrackLength, bool mul #pragma omp single nowait { - std::size_t cpt = 0; - std::set myset; + bool flag = false; + stl::flat_map myset; for(lemon::UnionFindEnum::ItemIt iit(*_d->tracksUF, cit); iit != INVALID; ++iit) { - myset.insert(_d->map_nodeToIndex[iit].first); - ++cpt; + IndexedFeaturePair currentPair = _d->map_nodeToIndex[iit]; + { + const auto& duplicateIt = _duplicateFeaturesMap.find(currentPair); + if(duplicateIt != _duplicateFeaturesMap.end()) + currentPair.second.featIndex = duplicateIt->second; + } + const auto& myIt = myset.find(currentPair.first); + if(myIt != myset.end()) + { + if(myIt->second < currentPair || currentPair < myIt->second) + { + flag = true; + // break if no minTrackLength ? + } + } + else + { + myset[currentPair.first] = currentPair; + } } - if((clearForks && myset.size() != cpt) || myset.size() < minTrackLength) + if((clearForks && flag) || myset.size() < minTrackLength) { #pragma omp critical set_classToErase.insert(cit.operator int()); @@ -302,7 +332,11 @@ void TracksBuilder::exportToSTL(TracksMap& allTracks) const // all descType inside the track will be the same outTrack.descType = currentPair.second.descType; // overwrites featureIndex if clearForks is False (value is False by default in Meshroom and True by default in AliceVision) - outTrack.featPerView[currentPair.first] = currentPair.second.featIndex; + const auto& duplicateIt = _duplicateFeaturesMap.find(currentPair); + if(duplicateIt != _duplicateFeaturesMap.end()) + outTrack.featPerView[currentPair.first] = duplicateIt->second; + else + outTrack.featPerView[currentPair.first] = currentPair.second.featIndex; } } } diff --git a/src/aliceVision/track/TracksBuilder.hpp b/src/aliceVision/track/TracksBuilder.hpp index 298b2530b9..911f0605d1 100644 --- a/src/aliceVision/track/TracksBuilder.hpp +++ b/src/aliceVision/track/TracksBuilder.hpp @@ -15,6 +15,9 @@ namespace aliceVision { namespace track { +// IndexedFeaturePair is: pair +using IndexedFeaturePair = std::pair; + struct TracksBuilderData; /** @@ -84,6 +87,7 @@ class TracksBuilder private: std::unique_ptr _d; + stl::flat_map _duplicateFeaturesMap; }; } // namespace track