Berkeley SfM
landmark.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, The Regents of the University of California (Regents).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer in the documentation and/or other materials provided
15  * with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Please contact the author(s) of this library if you have any questions.
34  * Authors: Erik Nelson ( eanelson@eecs.berkeley.edu )
35  * David Fridovich-Keil ( dfk@eecs.berkeley.edu )
36  */
37 
38 #include "landmark.h"
39 #include "../sfm/view.h"
40 
41 namespace bsfm {
42 
43 // Declaration of static member variable.
44 std::unordered_map<LandmarkIndex, Landmark::Ptr> Landmark::landmark_registry_;
46 
47 // Factory method. Registers the landmark and newly created index in the
48 // landmark registry so that they can be accessed from the static GetLandmark()
49 // method. This guarantees that all landmarks will have unique indices.
51  // Create a new Landmark, implicitly assigning a unique index.
52  Landmark::Ptr landmark(new Landmark());
53  landmark_registry_.insert(std::make_pair(landmark->Index(), landmark));
54  return landmark;
55 }
56 
57 // Gets the landmark corresponding to the input index. If the landmark has not
58 // been created yet, this method returns a null pointer.
60  auto registry_element = landmark_registry_.find(landmark_index);
61  if (registry_element == landmark_registry_.end()) {
62  LOG(WARNING)
63  << "Landmark does not exist in registry. Returning a null pointer.";
64  return Landmark::Ptr();
65  }
66 
67  return registry_element->second;
68 }
69 
70 // Returns the total number of existing landmarks.
72  return landmark_registry_.size();
73 }
74 
75 // Returns whether the landmark index corresponds to a landmark that has been
76 // created.
78  return landmark_index <= current_landmark_index_;
79 }
80 
81 // Resets all landmarks and clears the landmark registry. This should rarely be
82 // called, except when completely resetting the program or reconstruction.
85  landmark_registry_.clear();
86 }
87 
88 // Returns the unique index of this landmark.
90  return landmark_index_;
91 }
92 
93 // Set the landmark's position.
94 void Landmark::SetPosition(const Point3D& position) {
95  position_ = position;
96 }
97 
98 // Set the landmark's descriptor.
100  descriptor_ = descriptor;
101 }
102 
103 // Remove all existing observations of the landmark.
105  observations_.clear();
106 }
107 
108 // Get position.
109 const Point3D& Landmark::Position() const {
110  return position_;
111 }
112 
113 // Get descriptor.
115  return descriptor_;
116 }
117 
118 // Get observations.
119 const std::vector<Observation::Ptr>& Landmark::Observations() const {
120  return observations_;
121 }
122 
123 // Returns a raw pointer to the data elements of the position of the landamark.
124 // This is useful for optimization on landmark positions (e.g. during bundle
125 // adjustment).
127  return position_.Get().data();
128 }
129 
130 // Add a new observation of the landmark. If 'retriangulate' is true, the
131 // landmark's position will be retriangulated from all observations of it.
133  bool retriangulate) {
134  CHECK_NOTNULL(observation.get());
135 
136  // If this is our first observation, store it, tell the observation that it
137  // has been matched with us, and return.
138  if (observations_.empty()) {
139  observation->SetIncorporatedLandmark(this->Index());
140  observations_.push_back(observation);
141  descriptor_ = observation->Descriptor();
142  return true;
143  }
144 
145  // Does our own descriptor match with the observation's descriptor?
146  std::vector<::bsfm::Descriptor> descriptors;
147  descriptors.push_back(descriptor_);
148  descriptors.push_back(observation->Descriptor());
150  distance.MaybeNormalizeDescriptors(descriptors);
151 
152  if (distance(descriptors[0], descriptors[1]) > distance.Max()) {
153  VLOG(1) << "Observation was not matched to landmark " << this->Index();
154  return false;
155  }
156 
157  // Triangulate the landmark's putative position if we were to incorporate the
158  // new observation.
159  if (retriangulate) {
160  std::vector<Camera> cameras;
161  std::vector<Feature> features;
162  for (const auto& obs : observations_) {
163  cameras.push_back(obs->GetView()->Camera());
164  features.push_back(obs->Feature());
165  }
166  cameras.push_back(observation->GetView()->Camera());
167  features.push_back(observation->Feature());
168 
169  // If triangulation fails, we don't have a match and won't update position.
170  Point3D new_position;
171  if (!Triangulate(features, cameras, new_position)) {
172  return false;
173  }
174  position_ = new_position;
175  }
176 
177  // Successfully triangulated the landmark. Update its position and store this
178  // observation. Also tell the observation that it has been matched with us.
179  observation->SetIncorporatedLandmark(this->Index());
180  observations_.push_back(observation);
181 
182  return true;
183 }
184 
185 // Return the first view to observe this landmark.
187  if (observations_.empty()) {
188  LOG(WARNING) << "Landmark has not been associated with any observations, "
189  "so source view is undefined. Returning null pointer.";
190  return View::Ptr();
191  }
192 
193  return observations_.front()->GetView();
194 }
195 
196 // Given a set of views, return whether or not this landmark has been seen by at
197 // least 2 of them.
198 bool Landmark::SeenByAtLeastTwoViews(const std::vector<ViewIndex>& view_indices) {
199  unsigned int count = 0;
200  for (const auto& view_index : view_indices) {
201  // If they gave us a bad input, ignore it and continue.
202  if (!View::IsValidView(view_index))
203  continue;
204 
205  // Make sure this view knows all landmarks its observations have seen.
206  View::Ptr view = View::GetView(view_index);
207  view->UpdateObservedLandmarks();
208  if (view->HasObservedLandmark(this->Index())) {
209  count++;
210  }
211 
212  if (count == 2) {
213  return true;
214  }
215  }
216 
217  return false;
218 }
219 
220 // Private constructor enforces creation via factory method. This will be called
221 // from the factory method.
223  : position_(Point3D(0.0, 0.0, 0.0)), landmark_index_(NextLandmarkIndex()) {}
224 
225 // Static method for determining the next index across all Landmarks constructed
226 // so far. This is called in the Landmark constructor.
228  return current_landmark_index_++;
229 }
230 
231 } //\namespace bsfm
std::shared_ptr< Observation > Ptr
Definition: observation.h:65
const std::vector< Observation::Ptr > & Observations() const
Definition: landmark.cpp:119
static LandmarkIndex NextLandmarkIndex()
Definition: landmark.cpp:227
::bsfm::Descriptor descriptor_
Definition: landmark.h:154
static Landmark::Ptr GetLandmark(LandmarkIndex landmark_index)
Definition: landmark.cpp:59
bool SeenByAtLeastTwoViews(const std::vector< ViewIndex > &view_indices)
Definition: landmark.cpp:198
LandmarkIndex landmark_index_
Definition: landmark.h:142
Point3D position_
Definition: landmark.h:139
static LandmarkIndex NumExistingLandmarks()
Definition: landmark.cpp:71
unsigned int LandmarkIndex
Definition: types.h:62
static void ResetLandmarks()
Definition: landmark.cpp:83
static DistanceMetric & Instance()
void ClearObservations()
Definition: landmark.cpp:104
const Point3D & Position() const
Definition: landmark.cpp:109
static Landmark::Ptr Create()
Definition: landmark.cpp:50
std::vector< Observation::Ptr > observations_
Definition: landmark.h:150
static LandmarkIndex current_landmark_index_
Definition: landmark.h:157
LandmarkIndex Index() const
Definition: landmark.cpp:89
static View::Ptr GetView(ViewIndex view_index)
Definition: view.cpp:60
Definition: camera.cpp:50
static std::unordered_map< LandmarkIndex, Landmark::Ptr > landmark_registry_
Definition: landmark.h:146
std::shared_ptr< Landmark > Ptr
Definition: landmark.h:66
std::shared_ptr< View > Ptr
Definition: view.h:66
std::shared_ptr< View > SourceView() const
Definition: landmark.cpp:186
static bool IsValidLandmark(LandmarkIndex landmark_index)
Definition: landmark.cpp:77
static bool IsValidView(ViewIndex view_index)
Definition: view.cpp:77
const ::bsfm::Descriptor & Descriptor() const
Definition: landmark.cpp:114
bool MaybeNormalizeDescriptors(std::vector< Descriptor > &descriptors) const
Vector3d & Get()
Definition: point_3d.cpp:98
bool IncorporateObservation(const Observation::Ptr &observation, bool retriangulate=true)
Definition: landmark.cpp:132
double * PositionData()
Definition: landmark.cpp:126
::Eigen::Matrix< double, Eigen::Dynamic, 1 > Descriptor
Definition: types.h:83
bool Triangulate(const FeatureList &features, const std::vector< Camera > &cameras, Point3D &point)
void SetDescriptor(const ::bsfm::Descriptor &descriptor)
Definition: landmark.cpp:99
void SetPosition(const Point3D &position)
Definition: landmark.cpp:94