Skip to content

Commit

Permalink
sfmExpanding
Browse files Browse the repository at this point in the history
  • Loading branch information
servantftechnicolor committed May 27, 2024
1 parent 0ee29e7 commit 5c313fa
Show file tree
Hide file tree
Showing 12 changed files with 546 additions and 62 deletions.
5 changes: 5 additions & 0 deletions src/aliceVision/sfm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ set(sfm_files_headers
pipeline/expanding/ExpansionPolicy.hpp
pipeline/expanding/ExpansionPolicyLegacy.hpp
pipeline/expanding/ExpansionProcess.hpp
pipeline/expanding/ConnexityGraph.hpp
pipeline/expanding/LbaPolicy.hpp
pipeline/expanding/LbaPolicyConnexity.hpp
pipeline/regionsIO.hpp
utils/alignment.hpp
utils/statistics.hpp
Expand Down Expand Up @@ -70,6 +73,8 @@ set(sfm_files_sources
pipeline/expanding/ExpansionIteration.cpp
pipeline/expanding/ExpansionPolicyLegacy.cpp
pipeline/expanding/ExpansionProcess.cpp
pipeline/expanding/ConnexityGraph.cpp
pipeline/expanding/LbaPolicyConnexity.cpp
pipeline/regionsIO.cpp
utils/alignment.cpp
utils/statistics.cpp
Expand Down
228 changes: 228 additions & 0 deletions src/aliceVision/sfm/pipeline/expanding/ConnexityGraph.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
// This file is part of the AliceVision project.
// Copyright (c) 2023 AliceVision contributors.
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#include "ConnexityGraph.hpp"
//#include <aliceVision/stl/Counter.hpp>
#include <lemon/bfs.h>

namespace aliceVision {
namespace sfm {

struct viewIdScored
{
viewIdScored() = default;

viewIdScored(IndexT v, size_t c) : viewId(v), card(c)
{
}

bool operator<(const viewIdScored & other)
{
return (card < other.card);
}

bool operator>(const viewIdScored & other)
{
return (card > other.card);
}

IndexT viewId = UndefinedIndexT;
size_t card = 0;
};

bool ConnexityGraph::build(const sfmData::SfMData & sfmData, const std::set<IndexT> & viewsOfInterest)
{
lemon::ListGraph graph;
std::map<IndexT, lemon::ListGraph::Node> _nodePerViewId;
std::map<lemon::ListGraph::Node, IndexT> viewIdPerNode;

//Create a list of reconstructed views
std::vector<IndexT> views;
for (const auto & pv : sfmData.getViews())
{
if (sfmData.isPoseAndIntrinsicDefined(pv.first))
{
views.push_back(pv.first);

lemon::ListGraph::Node newNode = graph.addNode();
_nodePerViewId[pv.first] = newNode;
viewIdPerNode[newNode] = pv.first;
}
}


//Build a list of landmarks index per view
std::map<IndexT, std::set<IndexT>> landmarksPerView;
for (const auto & pl : sfmData.getLandmarks())
{
for (const auto & po : pl.second.getObservations())
{
landmarksPerView[po.first].insert(pl.first);
}
}

//For all possible unique pairs
std::map<IndexT, std::vector<viewIdScored>> covisibility;
for (int idref = 0; idref < views.size(); idref++)
{
IndexT viewRef = views[idref];

const auto & ptref = landmarksPerView[viewRef];

for (int idcur = idref + 1; idcur < views.size(); idcur++)
{
IndexT viewCur = views[idcur];

const auto & ptcur = landmarksPerView[viewCur];

std::vector<IndexT> intersection;
std::set_intersection(ptref.begin(), ptref.end(), ptcur.begin(), ptcur.end(),
std::back_inserter(intersection));

size_t s = intersection.size();
if (s == 0)
{
continue;
}

covisibility[viewRef].push_back({viewCur, s});
covisibility[viewCur].push_back({viewRef, s});
}
}

//Filter out connexions without enough information
for (auto & item : covisibility)
{
auto & vec = item.second;
if (vec.size() < _minLinksPerView)
{
continue;
}

std::sort(vec.begin(), vec.end(), std::greater<>());

size_t pos = 0;
for (; pos < vec.size(); pos++)
{
if (vec[pos].card < _minCardinality)
{
break;
}
}

pos = std::max(pos, _minLinksPerView);
vec.resize(pos);
}


/**
* For all covisible views,
* We establish a link in the graph
*/
for (const auto & item : covisibility)
{
IndexT viewId1 = item.first;

for (const auto & part : item.second)
{
IndexT viewId2 = part.viewId;

const lemon::ListGraph::Node & node1 = _nodePerViewId[viewId1];
const lemon::ListGraph::Node & node2 = _nodePerViewId[viewId2];

graph.addEdge(node1, node2);
}
}

/**
* For all views sharing a common intrinsic which is still refined,
* Make sure their distance is set to 1
*/
for (int idref = 0; idref < views.size(); idref++)
{
IndexT viewRef = views[idref];
IndexT intrinsicIdRef = sfmData.getView(viewRef).getIntrinsicId();

const auto * ptr = sfmData.getIntrinsicPtr(intrinsicIdRef);
if (ptr->getState() != EEstimatorParameterState::REFINED)
{
continue;
}

for (int idcur = idref + 1; idcur < views.size(); idcur++)
{
IndexT viewCur = views[idcur];
IndexT intrinsicIdCur = sfmData.getView(viewCur).getIntrinsicId();

if (intrinsicIdRef != intrinsicIdCur) continue;

const lemon::ListGraph::Node & node1 = _nodePerViewId[viewRef];
const lemon::ListGraph::Node & node2 = _nodePerViewId[viewCur];

graph.addEdge(node1, node2);
}
}

/**
* Breath first search on the graph
*/
lemon::Bfs<lemon::ListGraph> bfs(graph);
bfs.init();

for (auto id : viewsOfInterest)
{
auto it = _nodePerViewId.find(id);
if (it != _nodePerViewId.end())
{
bfs.addSource(it->second);
}
}

bfs.start();
for (const auto & x : _nodePerViewId)
{
//Retrieve the poseId associated to this view
IndexT poseId = sfmData.getView(x.first).getPoseId();
if (poseId == UndefinedIndexT)
{
continue;
}

auto& node = x.second;

if (bfs.reached(node))
{
int d = bfs.dist(node);

auto lookupIt = _distancesPerPoseId.find(poseId);
if (lookupIt == _distancesPerPoseId.end())
{
_distancesPerPoseId[x.first] = d;
}
else
{
_distancesPerPoseId[x.first] = std::min(lookupIt->second, d);
}

}
}

return true;
}

int ConnexityGraph::getDistance(IndexT poseId) const
{
const auto it = _distancesPerPoseId.find(poseId);
if (it == _distancesPerPoseId.end())
{
return std::numeric_limits<int>::max();
}

return it->second;
}

}
}
43 changes: 43 additions & 0 deletions src/aliceVision/sfm/pipeline/expanding/ConnexityGraph.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// This file is part of the AliceVision project.
// Copyright (c) 2024 AliceVision contributors.
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#pragma once

#include <aliceVision/sfmData/SfMData.hpp>
#include <lemon/list_graph.h>

namespace aliceVision {
namespace sfm {

class ConnexityGraph
{
public:
/**
* Compute distances of all the sfmData views to the viewsOfInterest views
* @param sfmData the sfmData containing all the views
* @param viewsOfInterest the list of views to compute the distance from. Those views must also be in the sfmData !
* @return false if an error occured
*/
bool build(const sfmData::SfMData & sfmData, const std::set<IndexT> & viewsOfInterest);

/**
* Get the distance for a particular poseId to one view of interest
* @param poseId the id of the pose to get the distance to
* @return a distance (minimal number of edges to join this view to a view of interest)
*/
int getDistance(IndexT poseId) const;


private:
std::map<IndexT, int> _distancesPerPoseId;

private:
size_t _minLinksPerView = 10;
size_t _minCardinality = 50;
};

}
}
48 changes: 1 addition & 47 deletions src/aliceVision/sfm/pipeline/expanding/ExpansionHistory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,53 +85,7 @@ void ExpansionHistory::saveState(const sfmData::SfMData & sfmData)
_focalHistory[pIntrinsic.first].push_back(std::make_pair(usage, iso->getScale().x()));
}

for (auto & pfh : _focalHistory)
{
const auto & vec = pfh.second;

size_t lastGood = std::numeric_limits<size_t>::max();
std::vector<std::pair<size_t, double>> filtered;

for (int id = vec.size() - 1; id >= 0; id--)
{
//Make sure the usage decrease
if (vec[id].first < lastGood)
{
lastGood = vec[id].first;
filtered.push_back(vec[id]);
}
}

std::vector<double> cropped;
std::vector<double> focals;
int largestCount = filtered.front().first;
bool nomore = false;
for (int id = 0; id < filtered.size(); id++)
{
if (!nomore)
{
cropped.push_back(filtered[id].second);
}

if (largestCount - filtered[id].first > 25)
{
nomore = true;
}

focals.push_back(filtered[id].second);
}


/*const double mean = std::accumulate(cropped.begin(), cropped.end(), 0.0) / cropped.size();
std::vector<double> diff(cropped.size());
std::transform(cropped.begin(), cropped.end(), diff.begin(), [mean](double x) { return x - mean; });
const double sqSum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
double stddev = std::sqrt(sqSum / cropped.size());
double minVal = *std::min_element(focals.begin(), focals.end());
double maxVal = *std::max_element(focals.begin(), focals.end());
double normStdev = stddev / (maxVal - minVal);*/
}

}

} // namespace sfm
Expand Down
10 changes: 10 additions & 0 deletions src/aliceVision/sfm/pipeline/expanding/ExpansionHistory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ class ExpansionHistory

void saveState(const sfmData::SfMData & sfmData);

/**
* Get the history of focals over time for a particular intrinsic id
* @param intrinsicId the id of the intrinsic
* @return a vector defining over time pairs of <count usage, focal value> where count usage is the number of views using this intrinsic
*/
const std::vector<std::pair<size_t, double>> & getFocalHistory(IndexT intrinsicId)
{
return _focalHistory[intrinsicId];
}

private:
// History of focals per intrinsics
std::map<IndexT, std::vector<std::pair<size_t, double>>> _focalHistory;
Expand Down
Loading

0 comments on commit 5c313fa

Please sign in to comment.