in opensfm/src/sfm/src/ba_helpers.cc [69:113]
std::unordered_set<map::Shot*> BAHelpers::DirectShotNeighbors(
map::Map& map, const std::unordered_set<map::Shot*>& shot_ids,
const size_t min_common_points, const size_t max_neighbors) {
std::unordered_set<map::Landmark*> points;
for (auto* shot : shot_ids) {
for (const auto& lm_obs : shot->GetLandmarkObservations()) {
points.insert(lm_obs.first);
}
}
std::unordered_map<map::Shot*, size_t> common_points;
for (auto* pt : points) {
for (const auto& neighbor_p : pt->GetObservations()) {
auto* shot = neighbor_p.first;
if (shot_ids.find(shot) == shot_ids.end()) {
++common_points[shot];
}
}
}
std::vector<std::pair<map::Shot*, size_t>> pairs(common_points.begin(),
common_points.end());
std::sort(pairs.begin(), pairs.end(),
[](const std::pair<map::Shot*, size_t>& val1,
const std::pair<map::Shot*, size_t>& val2) {
return val1.second > val2.second;
});
const size_t max_n = std::min(max_neighbors, pairs.size());
std::unordered_set<map::Shot*> neighbors;
size_t idx = 0;
for (auto& p : pairs) {
if (p.second >= min_common_points && idx < max_n) {
const auto instance_shots =
map.GetRigInstance(p.first->GetRigInstanceId()).GetShotIDs();
for (const auto& s : instance_shots) {
neighbors.insert(&map.GetShot(s));
}
} else {
break;
}
++idx;
}
return neighbors;
}