Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 5 additions & 33 deletions 38 src/colmap/scene/reconstruction_clustering.cc
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ std::unordered_map<frame_t, int> ClusterReconstructionFrames(
}
}

// Step 2: Filter edges to keep only reliable connections.
// Filter edges to keep only reliable connections.
std::unordered_map<image_pair_t, int> edge_weights;
for (const auto& [pair_id, count] : frame_covisibility_count) {
if (count < options.min_covisibility_count) continue;
Expand All @@ -185,36 +185,8 @@ std::unordered_map<frame_t, int> ClusterReconstructionFrames(
return {};
}

// Step 3: Keep only the largest connected component and de-register the rest.
std::vector<std::pair<frame_t, frame_t>> edges;
edges.reserve(edge_weights.size());
for (const auto& [pair_id, weight] : edge_weights) {
const auto [frame_id1, frame_id2] = PairIdToImagePair(pair_id);
edges.emplace_back(frame_id1, frame_id2);
}
const std::vector<frame_t> largest_cc_vec =
FindLargestConnectedComponent(nodes, edges);
const std::unordered_set<frame_t> largest_cc(largest_cc_vec.begin(),
largest_cc_vec.end());
for (const auto& [frame_id, frame] : reconstruction.Frames()) {
if (largest_cc.count(frame_id) == 0 && frame.HasPose()) {
reconstruction.DeRegisterFrame(frame_id);
}
}
LOG(INFO) << "Kept " << largest_cc.size() << " frames in largest component";

// Filter to keep only edges within the largest component.
for (auto it = edge_weights.begin(); it != edge_weights.end();) {
const auto [frame_id1, frame_id2] = PairIdToImagePair(it->first);
if (largest_cc.count(frame_id1) == 0 || largest_cc.count(frame_id2) == 0) {
it = edge_weights.erase(it);
} else {
++it;
}
}

// Step 4: Compute adaptive threshold using median minus median absolute
// deviation (MAD). Extract weight values after filtering to largest CC.
// Compute adaptive threshold using median minus median absolute
// deviation (MAD).
std::vector<int> weight_values;
weight_values.reserve(edge_weights.size());
for (const auto& [pair_id, weight] : edge_weights) {
Expand All @@ -225,8 +197,8 @@ std::unordered_map<frame_t, int> ClusterReconstructionFrames(
std::max(median - mad, options.min_edge_weight_threshold);
LOG(INFO) << "Threshold for Strong Clustering: " << threshold;

// Step 5: Cluster frames based on covisibility weights.
Comment thread
lpanaf marked this conversation as resolved.
return EstablishStrongClusters(options, largest_cc, edge_weights, threshold);
// Cluster frames based on covisibility weights.
return EstablishStrongClusters(options, nodes, edge_weights, threshold);
}

} // namespace colmap
10 changes: 3 additions & 7 deletions 10 src/colmap/scene/reconstruction_clustering.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,17 @@ struct ReconstructionClusteringOptions {
// Algorithm:
// 1. Build a covisibility graph where edges connect frames sharing >=
// min_covisibility_count points.
// 2. Find the largest connected component and de-register all frames outside
// it. This removes isolated or poorly connected parts of the
// reconstruction.
// 3. Compute an adaptive edge weight threshold using median minus median
// 2. Compute an adaptive edge weight threshold using median minus median
// absolute deviation (MAD).
// 4. Cluster frames using union-find: first merge strongly connected frames,
// 3. Cluster frames using union-find: first merge strongly connected frames,
// then iteratively merge clusters connected by multiple weaker edges.
//
// Args:
// options: Configuration options for clustering.
// reconstruction: The reconstruction containing frames and 3D points.
// Frames outside the largest connected component will be de-registered.
//
// Returns:
// Map from frame_id to cluster_id for frames in the largest component.
// Map from frame_id to cluster_id for all registered frames.
std::unordered_map<frame_t, int> ClusterReconstructionFrames(
const ReconstructionClusteringOptions& options,
Reconstruction& reconstruction);
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.