5
5
// You can obtain one at https://mozilla.org/MPL/2.0/.
6
6
7
7
#include " ConnexityGraph.hpp"
8
- // #include <aliceVision/stl/Counter .hpp>
8
+ #include < aliceVision/stl/stl .hpp>
9
9
#include < lemon/bfs.h>
10
10
11
11
namespace aliceVision {
12
12
namespace sfm {
13
13
14
+
14
15
struct viewIdScored
15
16
{
16
17
viewIdScored () = default ;
@@ -33,77 +34,166 @@ struct viewIdScored
33
34
size_t card = 0 ;
34
35
};
35
36
36
- bool ConnexityGraph::build (const sfmData::SfMData & sfmData, const std::set<IndexT> & viewsOfInterest)
37
+ bool ConnexityGraph::updateCocardinalities (const sfmData::SfMData & sfmData,
38
+ const track::TracksPerView& tracksPerViews)
37
39
{
38
- lemon::ListGraph graph;
39
- std::map<IndexT, lemon::ListGraph::Node> _nodePerViewId;
40
- std::map<lemon::ListGraph::Node, IndexT> viewIdPerNode;
41
-
42
40
// Create a list of reconstructed views
43
- std::vector <IndexT> views ;
44
- for (const auto & pv : sfmData.getViews ())
41
+ std::set <IndexT> setViews ;
42
+ for (const auto & [viewId, view] : sfmData.getViews ())
45
43
{
46
- if (sfmData.isPoseAndIntrinsicDefined (pv. first ))
44
+ if (sfmData.isPoseAndIntrinsicDefined (viewId ))
47
45
{
48
- views.push_back (pv.first );
49
-
50
- lemon::ListGraph::Node newNode = graph.addNode ();
51
- _nodePerViewId[pv.first ] = newNode;
52
- viewIdPerNode[newNode] = pv.first ;
46
+ setViews.insert (viewId);
53
47
}
54
48
}
55
49
50
+ // Get incoming views
51
+ std::set<IndexT> newViews;
52
+ std::set_difference (setViews.begin (), setViews.end (),
53
+ _previousViews.begin (), _previousViews.end (),
54
+ std::inserter (newViews, newViews.begin ()));
55
+
56
+ ALICEVISION_LOG_INFO (" Update cocardinalities with " << newViews.size () << " new views" );
56
57
57
- // Build a list of landmarks index per view
58
- std::map<IndexT, std::set<IndexT>> landmarksPerView;
59
- for (const auto & pl : sfmData.getLandmarks ())
58
+ // Retrieve landmarks
59
+ const sfmData::Landmarks & landmarks = sfmData.getLandmarks ();
60
+
61
+ // Get All landmark ids (keys)
62
+ std::set<IndexT> landmarkIds;
63
+ std::transform (landmarks.begin (), landmarks.end (),
64
+ std::inserter (landmarkIds, landmarkIds.begin ()),
65
+ stl::RetrieveKey ());
66
+
67
+ // For all incoming views only
68
+ for (const IndexT newView: newViews)
60
69
{
61
- for (const auto & po : pl.second .getObservations ())
70
+ const track::TrackIdSet & trackIds = tracksPerViews.at (newView);
71
+
72
+ // Build a list of landmarks observed by this view
73
+ std::vector<IndexT> newViewLandmarks;
74
+ newViewLandmarks.reserve (trackIds.size ());
75
+ std::set_intersection (trackIds.begin (), trackIds.end (),
76
+ landmarkIds.begin (), landmarkIds.end (),
77
+ std::back_inserter (newViewLandmarks));
78
+
79
+ // Loop over all landmarks
80
+ std::map<IndexT, size_t > commonLandmarksCountPerView;
81
+ for (const IndexT & idLandmark : newViewLandmarks)
82
+ {
83
+ // Loop over all view observing the landmark
84
+ const sfmData::Landmark & landmark = landmarks.at (idLandmark);
85
+ for (const auto & [idView, _] : landmark.getObservations ())
86
+ {
87
+ if (idView == newView)
88
+ {
89
+ continue ;
90
+ }
91
+
92
+ // Update the coobservation counter
93
+ auto it = commonLandmarksCountPerView.find (idView);
94
+ if (it != commonLandmarksCountPerView.end ())
95
+ {
96
+ it->second ++;
97
+ }
98
+ else
99
+ {
100
+ commonLandmarksCountPerView[idView] = 1 ;
101
+ }
102
+ }
103
+ }
104
+
105
+ // Update the cocardinalities sparse matrix
106
+ for (const auto [otherView, card]: commonLandmarksCountPerView)
62
107
{
63
- landmarksPerView[po.first ].insert (pl.first );
108
+ Pair p;
109
+ p.first = std::min (newView, otherView);
110
+ p.second = std::max (newView, otherView);
111
+ _cocardinalities[p] = card;
64
112
}
65
113
}
114
+
66
115
67
- // For all possible unique pairs
68
- std::map<IndexT, std::vector<viewIdScored>> covisibility;
69
- for (int idref = 0 ; idref < views.size (); idref++)
116
+
117
+ // Get Removed views
118
+ std::set<IndexT> removedViews;
119
+ std::set_difference (_previousViews.begin (), _previousViews.end (),
120
+ setViews.begin (), setViews.end (),
121
+ std::inserter (removedViews, removedViews.begin ()));
122
+
123
+ ALICEVISION_LOG_INFO (" Update cocardinalities with " << removedViews.size () << " removed views" );
124
+
125
+ for (const IndexT removedView : removedViews)
70
126
{
71
- IndexT viewRef = views[idref];
127
+ std::erase_if (_cocardinalities,
128
+ [removedView](const auto & item)
129
+ {
130
+ const auto & pair = item.first ;
131
+ return ((pair.first == removedView) || (pair.second == removedView));
132
+ }
133
+ );
134
+ }
72
135
73
- const auto & ptref = landmarksPerView[viewRef];
74
-
75
- for ( int idcur = idref + 1 ; idcur < views. size (); idcur++)
76
- {
77
- IndexT viewCur = views[idcur];
136
+ // Copy for next iteration
137
+ _previousViews = setViews;
138
+
139
+ return true ;
140
+ }
78
141
79
- const auto & ptcur = landmarksPerView[viewCur];
142
+ bool ConnexityGraph::build (const sfmData::SfMData & sfmData,
143
+ const track::TracksPerView& tracksPerViews,
144
+ const std::set<IndexT> & viewsOfInterest)
145
+ {
146
+ lemon::ListGraph graph;
147
+ std::map<IndexT, lemon::ListGraph::Node> nodePerViewId;
148
+ std::map<lemon::ListGraph::Node, IndexT> viewIdPerNode;
80
149
81
- std::vector<IndexT> intersection;
82
- std::set_intersection (ptref.begin (), ptref.end (), ptcur.begin (), ptcur.end (),
83
- std::back_inserter (intersection));
150
+ if (!updateCocardinalities (sfmData, tracksPerViews))
151
+ {
152
+ return false ;
153
+ }
84
154
85
- size_t s = intersection.size ();
86
- if (s == 0 )
87
- {
88
- continue ;
89
- }
155
+ ALICEVISION_LOG_INFO (" Connexity graph begin" );
156
+ // Reset result
157
+ _distancesPerPoseId.clear ();
90
158
91
- covisibility[viewRef].push_back ({viewCur, s});
92
- covisibility[viewCur].push_back ({viewRef, s});
159
+ // Create a list of reconstructed views
160
+ std::vector<IndexT> views;
161
+ for (const auto & [viewId, view] : sfmData.getViews ())
162
+ {
163
+ if (sfmData.isPoseAndIntrinsicDefined (viewId))
164
+ {
165
+ views.push_back (viewId);
166
+
167
+ lemon::ListGraph::Node newNode = graph.addNode ();
168
+ nodePerViewId[viewId] = newNode;
169
+ viewIdPerNode[newNode] = viewId;
93
170
}
94
171
}
95
172
173
+
174
+ // For all possible unique pairs
175
+ std::map<IndexT, std::vector<viewIdScored>> covisibility;
176
+ for (const auto & [pair, s]: _cocardinalities)
177
+ {
178
+ covisibility[pair.first ].push_back ({pair.second , s});
179
+ covisibility[pair.second ].push_back ({pair.first , s});
180
+ }
181
+
96
182
// Filter out connexions without enough information
97
183
for (auto & item : covisibility)
98
184
{
99
185
auto & vec = item.second ;
186
+
187
+ // Just skip filtering if we don't have more than _minLinksPerView links
100
188
if (vec.size () < _minLinksPerView)
101
189
{
102
190
continue ;
103
191
}
104
192
193
+ // Sort the vector by descending order of shared observations
105
194
std::sort (vec.begin (), vec.end (), std::greater<>());
106
195
196
+ // Count the number of items with enough observations
107
197
size_t pos = 0 ;
108
198
for (; pos < vec.size (); pos++)
109
199
{
@@ -113,6 +203,7 @@ bool ConnexityGraph::build(const sfmData::SfMData & sfmData, const std::set<Inde
113
203
}
114
204
}
115
205
206
+ // Keep at LEAST _minLinksPerView
116
207
pos = std::max (pos, _minLinksPerView);
117
208
vec.resize (pos);
118
209
}
@@ -130,8 +221,8 @@ bool ConnexityGraph::build(const sfmData::SfMData & sfmData, const std::set<Inde
130
221
{
131
222
IndexT viewId2 = part.viewId ;
132
223
133
- const lemon::ListGraph::Node & node1 = _nodePerViewId [viewId1];
134
- const lemon::ListGraph::Node & node2 = _nodePerViewId [viewId2];
224
+ const lemon::ListGraph::Node & node1 = nodePerViewId [viewId1];
225
+ const lemon::ListGraph::Node & node2 = nodePerViewId [viewId2];
135
226
136
227
graph.addEdge (node1, node2);
137
228
}
@@ -159,8 +250,8 @@ bool ConnexityGraph::build(const sfmData::SfMData & sfmData, const std::set<Inde
159
250
160
251
if (intrinsicIdRef != intrinsicIdCur) continue ;
161
252
162
- const lemon::ListGraph::Node & node1 = _nodePerViewId [viewRef];
163
- const lemon::ListGraph::Node & node2 = _nodePerViewId [viewCur];
253
+ const lemon::ListGraph::Node & node1 = nodePerViewId [viewRef];
254
+ const lemon::ListGraph::Node & node2 = nodePerViewId [viewCur];
164
255
165
256
graph.addEdge (node1, node2);
166
257
}
@@ -174,15 +265,15 @@ bool ConnexityGraph::build(const sfmData::SfMData & sfmData, const std::set<Inde
174
265
175
266
for (auto id : viewsOfInterest)
176
267
{
177
- auto it = _nodePerViewId .find (id);
178
- if (it != _nodePerViewId .end ())
268
+ auto it = nodePerViewId .find (id);
269
+ if (it != nodePerViewId .end ())
179
270
{
180
271
bfs.addSource (it->second );
181
272
}
182
273
}
183
274
184
275
bfs.start ();
185
- for (const auto & x : _nodePerViewId )
276
+ for (const auto & x : nodePerViewId )
186
277
{
187
278
// Retrieve the poseId associated to this view
188
279
IndexT poseId = sfmData.getView (x.first ).getPoseId ();
@@ -210,6 +301,8 @@ bool ConnexityGraph::build(const sfmData::SfMData & sfmData, const std::set<Inde
210
301
}
211
302
}
212
303
304
+ ALICEVISION_LOG_INFO (" Connexity graph end" );
305
+
213
306
return true ;
214
307
}
215
308
0 commit comments