Skip to content

Commit 5c5b7d4

Browse files
committed
[WIP][filterSfM] augment observations with neighbors observations
1 parent 5828fa1 commit 5c5b7d4

File tree

1 file changed

+88
-17
lines changed

1 file changed

+88
-17
lines changed

src/software/pipeline/main_filterSfM.cpp

Lines changed: 88 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,6 @@ void filterLandmarks_step2(SfMData& sfmData,
400400
ALICEVISION_LOG_INFO("KdTree created for " << landmarksData.size() << " points.");
401401

402402
ALICEVISION_LOG_INFO("Computing landmarks neighbors: started.");
403-
// note that the landmark is a neighbor to itself with zero distance, hence the +/- 1
404403
int nbNeighbors_ = params.nbNeighbors3D;
405404
// contains the observing view ids and neighbors for each landmark
406405
std::vector<std::pair<std::vector<IndexT>, std::vector<size_t>>> viewData(landmarksData.size());
@@ -687,6 +686,60 @@ void computeNeighborsInfo(std::vector<Landmark*>& landmarksData, const FilterPar
687686
ALICEVISION_LOG_INFO("Computing landmark neighbors and distance-based weights: done");
688687
}
689688

689+
void augmentInitialObservations(std::vector<std::pair<std::vector<IndexT>, std::vector<double>>>& viewScoresData,
690+
std::vector<std::pair<std::vector<size_t>, std::vector<double>>>& neighborsData)
691+
{
692+
ALICEVISION_LOG_INFO("Augment initial observations based on neighbors observations: started");
693+
std::vector<std::vector<IndexT>> viewScoresData_t(viewScoresData.size());
694+
// for each landmark, identify the new observations coming from its neighborhood
695+
#pragma omp parallel for
696+
for(int id = 0; id < viewScoresData.size(); id++)
697+
{
698+
const auto& viewIds = viewScoresData[id].first;
699+
auto& viewIds_t = viewScoresData_t[id];
700+
const auto& neighborIds = neighborsData[id].first;
701+
702+
for (const auto& neighborId : neighborIds)
703+
{
704+
const auto& viewIds_neighbor = viewScoresData[neighborId].first;
705+
std::vector<IndexT> viewIds_union;
706+
std::set_union(viewIds_neighbor.begin(), viewIds_neighbor.end(), viewIds_t.begin(), viewIds_t.end(),
707+
std::back_inserter(viewIds_union));
708+
viewIds_t = std::move(viewIds_union);
709+
}
710+
std::vector<IndexT> viewIds_toAdd;
711+
std::set_difference(viewIds_t.begin(), viewIds_t.end(), viewIds.begin(), viewIds.end(),
712+
std::back_inserter(viewIds_toAdd));
713+
viewIds_t = std::move(viewIds_toAdd);
714+
}
715+
// for each landmark, add the previously identified observations
716+
#pragma omp parallel for
717+
for(int id = 0; id < viewScoresData.size(); id++)
718+
{
719+
auto& [viewIds, viewScores] = viewScoresData[id];
720+
const auto& viewIds_toAdd = viewScoresData_t[id];
721+
viewIds.insert(viewIds.end(), viewIds_toAdd.begin(), viewIds_toAdd.end());
722+
viewScores.insert(viewScores.end(), viewIds_toAdd.size(), 0.);
723+
724+
// sort by ascending view id order
725+
// for consequent faster access
726+
727+
// indices that sort the view ids
728+
std::vector<size_t> idx(viewIds.size());
729+
std::iota(idx.begin(), idx.end(), 0);
730+
std::stable_sort(idx.begin(), idx.end(), [&v = viewIds](size_t i1, size_t i2) { return v[i1] < v[i2]; });
731+
// apply sorting to both view ids and view scores for correspondance
732+
auto ids_temp = viewIds;
733+
auto scores_temp = viewScores;
734+
for(auto j = 0; j < viewIds.size(); j++)
735+
{
736+
viewIds[j] = ids_temp[idx[j]];
737+
viewScores[j] = scores_temp[idx[j]];
738+
}
739+
}
740+
ALICEVISION_LOG_INFO("Augment initial observations based on neighbors observations: done");
741+
}
742+
690743
void computeNewScores(const std::vector<Landmark*>& landmarksData,
691744
const FilterParams::FilterObservations3DParams& params,
692745
const std::vector<std::pair<std::vector<size_t>, std::vector<double>>>& neighborsData,
@@ -808,6 +861,25 @@ void propagateNeighborsInfo(std::vector<Landmark*>& landmarksData,
808861
ALICEVISION_LOG_INFO("Propagating neighbors observation scores: done");
809862
}
810863

864+
void removeNonObservedLandmarks(SfMData& sfmData)
865+
{
866+
// remove landmarks with no remaining observations
867+
ALICEVISION_LOG_INFO("Remove non-observed landmarks: started");
868+
const auto& initialNbLandmarks = sfmData.getLandmarks().size();
869+
for(auto it = sfmData.getLandmarks().begin(); it != sfmData.getLandmarks().end();)
870+
{
871+
if(it->second.observations.size() == 0)
872+
it = sfmData.getLandmarks().erase(it);
873+
else
874+
++it;
875+
}
876+
const auto& modifiedNbLandmarks = sfmData.getLandmarks().size();
877+
ALICEVISION_LOG_INFO(
878+
"Removed " << (initialNbLandmarks - modifiedNbLandmarks) << " landmarks out of " << initialNbLandmarks
879+
<< ", i.e. " << ((initialNbLandmarks - modifiedNbLandmarks) * 100.f / initialNbLandmarks) << " % ");
880+
ALICEVISION_LOG_INFO("Remove non-observed landmarks: done");
881+
}
882+
811883
bool filterObservations3D(SfMData& sfmData, const FilterParams::FilterObservations3DParams& params)
812884
{
813885
// store in vector for faster access
@@ -829,6 +901,7 @@ bool filterObservations3D(SfMData& sfmData, const FilterParams::FilterObservatio
829901
// contains the neighbor landmarks ids with their corresponding weights
830902
std::vector<std::pair<std::vector<size_t>, std::vector<double>>> neighborsData(landmarksData.size());
831903
computeNeighborsInfo(landmarksData, params, neighborsData);
904+
augmentInitialObservations(viewScoresData, neighborsData);
832905
propagateNeighborsInfo(landmarksData, params, neighborsData, viewScoresData);
833906
}
834907

@@ -837,12 +910,12 @@ bool filterObservations3D(SfMData& sfmData, const FilterParams::FilterObservatio
837910
for(auto i = 0; i < landmarksData.size(); i++)
838911
{
839912
sfmData::Landmark& landmark = *landmarksData[i];
840-
const auto& nbObservations = landmark.observations.size();
841913
auto& [viewIds, viewScores] = viewScoresData[i];
914+
const auto& nbObservations = viewIds.size();
842915

843-
// check number of observations
844-
if(landmark.observations.size() <= params.maxNbObservationsPerLandmark)
845-
continue;
916+
//// check number of observations
917+
//if(landmark.observations.size() <= params.maxNbObservationsPerLandmark)
918+
// continue;
846919

847920
// sort by descending view score order
848921
std::vector<size_t> idx(nbObservations);
@@ -854,16 +927,22 @@ bool filterObservations3D(SfMData& sfmData, const FilterParams::FilterObservatio
854927
//double threshold = 0.1 / params.maxNbObservationsPerLandmark;
855928
for(auto j = 0; j < params.maxNbObservationsPerLandmark; j++)
856929
{
857-
const auto& viewScore = viewScores[idx[j]];
930+
//const auto& viewScore = viewScores[idx[j]];
858931
/*if(viewScore < threshold)
859932
break;*/
933+
934+
// add observation only if it's an original observation and not augmented
860935
const auto& viewId = viewIds[idx[j]];
861-
filteredObservations[viewId] = landmark.observations[viewId];
936+
const auto& obsIt = landmark.observations.find(viewId);
937+
if(obsIt != landmark.observations.end())
938+
filteredObservations[viewId] = landmark.observations[viewId];
862939
}
863940
landmark.observations = std::move(filteredObservations);
864941
}
865942
ALICEVISION_LOG_INFO("Selecting observations with best scores: done");
866943

944+
removeNonObservedLandmarks(sfmData);
945+
867946
return true;
868947
}
869948

@@ -875,7 +954,6 @@ double filter2DView(SfMData& sfmData, const FilterParams::FilterObservations2DPa
875954
KdTree2D tree(2, data, nanoflann::KDTreeSingleIndexAdaptorParams(MAX_LEAF_ELEMENTS));
876955
tree.buildIndex();
877956

878-
// note that the observation is a neighbor to itself with zero distance, hence the +/- 1
879957
size_t nbNeighbors_ = params.nbNeighbors2D;
880958
// average neighbors distance for each observation
881959
std::vector<double> means(observations.size(), std::numeric_limits<double>::max());
@@ -988,21 +1066,14 @@ bool filterObservations2D(SfMData& sfmData, const FilterParams::FilterObservatio
9881066
}
9891067
}
9901068
}
991-
// remove landmarks with no remaining observations
992-
for(auto it = sfmData.getLandmarks().begin(); it != sfmData.getLandmarks().end();)
993-
{
994-
if(it->second.observations.size() == 0)
995-
it = sfmData.getLandmarks().erase(it);
996-
else
997-
++it;
998-
}
1069+
1070+
removeNonObservedLandmarks(sfmData);
9991071

10001072
return true;
10011073
}
10021074

10031075
int aliceVision_main(int argc, char *argv[])
10041076
{
1005-
std::cout << "hello" << std::endl;
10061077
// command-line parameters
10071078

10081079
std::string inputSfmFilename;

0 commit comments

Comments
 (0)