MVE - Multi-View Environment mve-devel
Loading...
Searching...
No Matches
bundler_tracks.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015, Simon Fuhrmann
3 * TU Darmstadt - Graphics, Capture and Massively Parallel Computing
4 * All rights reserved.
5 *
6 * This software may be modified and distributed under the terms
7 * of the BSD 3-Clause license. See the LICENSE.txt file for details.
8 */
9
10#include <iostream>
11#include <set>
12
13#include "mve/image_tools.h"
14#include "mve/image_drawing.h"
15#include "sfm/bundler_tracks.h"
16
19
20/*
21 * Merges tracks and updates viewports accordingly.
22 */
23void
24unify_tracks(int view1_tid, int view2_tid,
25 TrackList* tracks, ViewportList* viewports)
26{
27 /* Unify in larger track. */
28 if (tracks->at(view1_tid).features.size()
29 < tracks->at(view2_tid).features.size())
30 std::swap(view1_tid, view2_tid);
31
32 Track& track1 = tracks->at(view1_tid);
33 Track& track2 = tracks->at(view2_tid);
34
35 for (std::size_t k = 0; k < track2.features.size(); ++k)
36 {
37 int const view_id = track2.features[k].view_id;
38 int const feat_id = track2.features[k].feature_id;
39 viewports->at(view_id).track_ids[feat_id] = view1_tid;
40 }
41 track1.features.insert(track1.features.end(),
42 track2.features.begin(), track2.features.end());
43 /* Free old track's memory. clear() does not work. */
45}
46
47/* ---------------------------------------------------------------- */
48
49void
50Tracks::compute (PairwiseMatching const& matching,
51 ViewportList* viewports, TrackList* tracks)
52{
53 /* Initialize per-viewport track IDs. */
54 for (std::size_t i = 0; i < viewports->size(); ++i)
55 {
56 Viewport& viewport = viewports->at(i);
57 viewport.track_ids.resize(viewport.features.positions.size(), -1);
58 }
59
60 /* Propagate track IDs. */
61 if (this->opts.verbose_output)
62 std::cout << "Propagating track IDs..." << std::endl;
63
64 /* Iterate over all pairwise matchings and create tracks. */
65 tracks->clear();
66 for (std::size_t i = 0; i < matching.size(); ++i)
67 {
68 TwoViewMatching const& tvm = matching[i];
69 Viewport& viewport1 = viewports->at(tvm.view_1_id);
70 Viewport& viewport2 = viewports->at(tvm.view_2_id);
71
72 /* Iterate over matches for a pair. */
73 for (std::size_t j = 0; j < tvm.matches.size(); ++j)
74 {
75 CorrespondenceIndex idx = tvm.matches[j];
76 int const view1_tid = viewport1.track_ids[idx.first];
77 int const view2_tid = viewport2.track_ids[idx.second];
78 if (view1_tid == -1 && view2_tid == -1)
79 {
80 /* No track ID associated with the match. Create track. */
81 viewport1.track_ids[idx.first] = tracks->size();
82 viewport2.track_ids[idx.second] = tracks->size();
83 tracks->push_back(Track());
84 tracks->back().features.push_back(
85 FeatureReference(tvm.view_1_id, idx.first));
86 tracks->back().features.push_back(
87 FeatureReference(tvm.view_2_id, idx.second));
88 }
89 else if (view1_tid == -1 && view2_tid != -1)
90 {
91 /* Propagate track ID from first to second view. */
92 viewport1.track_ids[idx.first] = view2_tid;
93 tracks->at(view2_tid).features.push_back(
94 FeatureReference(tvm.view_1_id, idx.first));
95 }
96 else if (view1_tid != -1 && view2_tid == -1)
97 {
98 /* Propagate track ID from second to first view. */
99 viewport2.track_ids[idx.second] = view1_tid;
100 tracks->at(view1_tid).features.push_back(
101 FeatureReference(tvm.view_2_id, idx.second));
102 }
103 else if (view1_tid == view2_tid)
104 {
105 /* Track ID already propagated. */
106 }
107 else
108 {
109 /*
110 * A track ID is already associated with both ends of a match,
111 * however, is not consistent. Unify tracks.
112 */
113 unify_tracks(view1_tid, view2_tid, tracks, viewports);
114 }
115 }
116 }
117
118 /* Find and remove invalid tracks or tracks with conflicts. */
119 if (this->opts.verbose_output)
120 std::cout << "Removing tracks with conflicts..." << std::flush;
121 std::size_t const num_invalid_tracks
122 = this->remove_invalid_tracks(viewports, tracks);
123 if (this->opts.verbose_output)
124 std::cout << " deleted " << num_invalid_tracks
125 << " tracks." << std::endl;
126
127 /* Compute color for every track. */
128 if (this->opts.verbose_output)
129 std::cout << "Colorizing tracks..." << std::endl;
130 for (std::size_t i = 0; i < tracks->size(); ++i)
131 {
132 Track& track = tracks->at(i);
133 math::Vec4f color(0.0f, 0.0f, 0.0f, 0.0f);
134 for (std::size_t j = 0; j < track.features.size(); ++j)
135 {
136 FeatureReference const& ref = track.features[j];
137 FeatureSet const& features = viewports->at(ref.view_id).features;
138 math::Vec3f const feature_color(features.colors[ref.feature_id]);
139 color += math::Vec4f(feature_color, 1.0f);
140 }
141 track.color[0] = static_cast<uint8_t>(color[0] / color[3] + 0.5f);
142 track.color[1] = static_cast<uint8_t>(color[1] / color[3] + 0.5f);
143 track.color[2] = static_cast<uint8_t>(color[2] / color[3] + 0.5f);
144 }
145}
146
147/* ---------------------------------------------------------------- */
148
149int
150Tracks::remove_invalid_tracks (ViewportList* viewports, TrackList* tracks)
151{
152 /*
153 * Detect invalid tracks where a track contains no features, or
154 * multiple features from a single view.
155 */
156 std::vector<bool> delete_tracks(tracks->size());
157 int num_invalid_tracks = 0;
158 for (std::size_t i = 0; i < tracks->size(); ++i)
159 {
160 if (tracks->at(i).features.empty())
161 {
162 num_invalid_tracks += 1;
163 delete_tracks[i] = true;
164 continue;
165 }
166
167 std::set<int> view_ids;
168 for (std::size_t j = 0; j < tracks->at(i).features.size(); ++j)
169 {
170 FeatureReference const& ref = tracks->at(i).features[j];
171 if (view_ids.insert(ref.view_id).second == false)
172 {
173 num_invalid_tracks += 1;
174 delete_tracks[i] = true;
175 break;
176 }
177 }
178 }
179
180 /* Create a mapping from old to new track IDs. */
181 std::vector<int> id_mapping(delete_tracks.size(), -1);
182 int valid_track_counter = 0;
183 for (std::size_t i = 0; i < delete_tracks.size(); ++i)
184 {
185 if (delete_tracks[i])
186 continue;
187 id_mapping[i] = valid_track_counter;
188 valid_track_counter += 1;
189 }
190
191 /* Fix track IDs stored in the viewports. */
192 for (std::size_t i = 0; i < viewports->size(); ++i)
193 {
194 std::vector<int>& track_ids = viewports->at(i).track_ids;
195 for (std::size_t j = 0; j < track_ids.size(); ++j)
196 if (track_ids[j] >= 0)
197 track_ids[j] = id_mapping[track_ids[j]];
198 }
199
200 /* Clean the tracks from the vector. */
201 math::algo::vector_clean(delete_tracks, tracks);
202
203 return num_invalid_tracks;
204}
205
Vector class for arbitrary dimensions and types.
Definition vector.h:87
The FeatureSet holds per-feature information for a single view, and allows to transparently compute a...
Definition feature_set.h:28
std::vector< math::Vec3uc > colors
Per-feature image color.
Definition feature_set.h:68
std::vector< math::Vec2f > positions
Per-feature image position.
Definition feature_set.h:66
void vector_clean(std::vector< bool > const &delete_list, std::vector< T > *vector)
Erases all elements from 'vector' that are marked with 'true' in 'delete_list'.
Definition algo.h:166
Vector< float, 4 > Vec4f
Definition vector.h:32
std::vector< Viewport > ViewportList
The list of all viewports considered for bundling.
std::vector< Track > TrackList
The list of all tracks.
std::vector< FeatureReference > FeatureReferenceList
The list of all feature references inside a track.
std::vector< TwoViewMatching > PairwiseMatching
The matching result between several pairs of views.
void unify_tracks(int view1_tid, int view2_tid, TrackList *tracks, ViewportList *viewports)
std::pair< int, int > CorrespondenceIndex
The IDs of a matching feature pair in two images.
void swap(mve::Image< T > &a, mve::Image< T > &b)
Specialization of std::swap for efficient image swapping.
Definition image.h:478
#define SFM_BUNDLER_NAMESPACE_END
Definition defines.h:17
#define SFM_BUNDLER_NAMESPACE_BEGIN
Definition defines.h:16
#define SFM_NAMESPACE_END
Definition defines.h:14
#define SFM_NAMESPACE_BEGIN
Definition defines.h:13
References a 2D feature in a specific view.
Representation of a feature track.
FeatureReferenceList features
The matching result between two views.
CorrespondenceIndices matches
Per-viewport information.
std::vector< int > track_ids
Per-feature track ID, -1 if not part of a track.
FeatureSet features
Per-feature information.