ISAAC  0.2.11
Flight software for the ISAAC project, adding functionality to the Astrobee robot, operating inside the International Space Station.
All Classes Functions Variables Pages
interest_point.h
1 /* Copyright (c) 2021, United States Government, as represented by the
2  * Administrator of the National Aeronautics and Space Administration.
3  *
4  * All rights reserved.
5  *
6  * The "ISAAC - Integrated System for Autonomous and Adaptive Caretaking
7  * platform" software is licensed under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with the
9  * License. You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16  * License for the specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef INTEREST_POINT_H_
21 #define INTEREST_POINT_H_
22 
23 #include <ff_common/thread.h>
24 #include <camera/camera_params.h>
25 
26 #include <opencv2/imgproc.hpp>
27 
28 #include <glog/logging.h>
29 
30 
31 #include <Eigen/Core>
32 #include <Eigen/Geometry>
33 
34 #include <string>
35 #include <vector>
36 #include <map>
37 #include <mutex>
38 #include <utility>
39 
40 namespace dense_map {
41 
44 // for visualization)
45 struct InterestPoint {
46  typedef std::vector<float> descriptor_type;
47  typedef descriptor_type::iterator iterator;
48  typedef descriptor_type::const_iterator const_iterator;
49 
50  // The best way of creating interest points is:
51  // ip = InterestPoint(x, y). But in the worst case, when the user
52  // chooses to simply create a blank interest point, like
53  // InterestPoint ip;
54  // at least make sure that its members are always initialized,
55  // as seen in the constructor below.
56  // TODO(Oleg): There is no way to enforce that ix be in sync with x or
57  // iy with y.
58  InterestPoint(float x = 0, float y = 0, float scale = 1.0, float interest = 0.0, float ori = 0.0, bool pol = false,
59  uint32_t octave = 0, uint32_t scale_lvl = 0)
60  : x(x),
61  y(y),
62  scale(scale),
63  ix(int32_t(x)),
64  iy(int32_t(y)),
65  orientation(ori),
67  polarity(pol),
68  octave(octave),
69  scale_lvl(scale_lvl) {}
70 
72  float x, y;
73 
77  float scale;
78 
80  int32_t ix;
81  int32_t iy;
82 
89  float orientation;
90 
92  float interest;
93 
95  bool polarity;
98  uint32_t octave, scale_lvl;
99 
102  descriptor_type descriptor;
103 
104  const_iterator begin() const { return descriptor.begin(); }
105  iterator begin() { return descriptor.begin(); }
106  const_iterator end() const { return descriptor.end(); }
107  iterator end() { return descriptor.end(); }
108 
109  size_t size() const { return descriptor.size(); }
110  float operator[](int index) { return descriptor[index]; }
111 
114  bool operator<(const InterestPoint& other) const { return (other.interest < interest); }
115 
117  std::string to_string() const {
118  std::stringstream s;
119  s << "IP: (" << x << "," << y << ") scale: " << scale << " orientation: " << orientation
120  << " interest: " << interest << " polarity: " << polarity << " octave: " << octave
121  << " scale_lvl: " << scale_lvl << "\n";
122  s << " descriptor: ";
123  for (size_t i = 0; i < descriptor.size(); ++i) s << descriptor[i] << " ";
124  s << std::endl;
125  return s.str();
126  }
127 
129  void setFromCvKeypoint(Eigen::Vector2d const& key, cv::Mat const& cv_descriptor) {
130  x = key[0];
131  y = key[1];
132  ix = round(x);
133  iy = round(y);
134  interest = 0;
135  octave = 0;
136  scale_lvl = 1;
137  scale = 1;
138  orientation = 0;
139  polarity = false;
140 
141  if (cv_descriptor.rows != 1 || cv_descriptor.cols < 2)
142  LOG(FATAL) << "The descriptors must be in one row, and have at least two columns.";
143 
144  descriptor.resize(cv_descriptor.cols);
145  for (size_t it = 0; it < descriptor.size(); it++) {
146  descriptor[it] = cv_descriptor.at<float>(0, it);
147  }
148  }
149 }; // End class InterestPoint
150 
151 typedef std::pair<std::vector<InterestPoint>, std::vector<InterestPoint> > MATCH_PAIR;
152 typedef std::map<std::pair<int, int>, dense_map::MATCH_PAIR> MATCH_MAP;
153 
154 void detectFeatures(const cv::Mat& image, bool verbose,
155  // Outputs
156  cv::Mat* descriptors, Eigen::Matrix2Xd* keypoints);
157 
158 // This really likes haz cam first and nav cam second
159 void matchFeatures(std::mutex* match_mutex, int left_image_index, int right_image_index,
160  cv::Mat const& left_descriptors, cv::Mat const& right_descriptors,
161  Eigen::Matrix2Xd const& left_keypoints, Eigen::Matrix2Xd const& right_keypoints, bool verbose,
162  // Output
163  MATCH_PAIR* matches);
164 
165 // Routines for reading & writing interest point match files
166 void writeMatchFile(std::string match_file, std::vector<InterestPoint> const& ip1,
167  std::vector<InterestPoint> const& ip2);
168 
169 void saveImagesAndMatches(std::string const& left_prefix, std::string const& right_prefix,
170  std::pair<int, int> const& index_pair, MATCH_PAIR const& match_pair,
171  std::vector<cv::Mat> const& images);
172 
173 // Triangulate two rays emanating from given undistorted and centered pixels
174 Eigen::Vector3d TriangulatePair(double focal_length1, double focal_length2, Eigen::Affine3d const& world_to_cam1,
175  Eigen::Affine3d const& world_to_cam2, Eigen::Vector2d const& pix1,
176  Eigen::Vector2d const& pix2);
177 
178 // Triangulate n rays emanating from given undistorted and centered pixels
179 Eigen::Vector3d Triangulate(std::vector<double> const& focal_length_vec,
180  std::vector<Eigen::Affine3d> const& world_to_cam_vec,
181  std::vector<Eigen::Vector2d> const& pix_vec);
182 
183 struct cameraImage;
184 
185 void detectMatchFeatures( // Inputs
186  std::vector<dense_map::cameraImage> const& cams,
187  std::vector<std::string> const& cam_names,
188  std::vector<camera::CameraParameters> const& cam_params,
189  std::vector<Eigen::Affine3d> const& world_to_cam, int num_overlaps,
190  int initial_max_reprojection_error, int num_match_threads,
191  bool verbose,
192  // Outputs
193  std::vector<std::vector<std::pair<float, float>>>& keypoint_vec,
194  std::vector<std::map<int, int>>& pid_to_cid_fid,
195  std::vector<std::string> & image_files);
196 
197 } // namespace dense_map
198 
199 #endif // INTEREST_POINT_H_
dense_map::InterestPoint::interest
float interest
The interest measure (could be Harris, LoG, etc.).
Definition: interest_point.h:92
dense_map::InterestPoint::octave
uint32_t octave
Definition: interest_point.h:98
dense_map::InterestPoint::descriptor
descriptor_type descriptor
Definition: interest_point.h:102
dense_map::InterestPoint::to_string
std::string to_string() const
Generates a human readable string.
Definition: interest_point.h:117
dense_map::InterestPoint::polarity
bool polarity
These are some extras for SURF-like implementations.
Definition: interest_point.h:95
dense_map::InterestPoint::x
float x
Subpixel (col, row) location of point.
Definition: interest_point.h:72
dense_map::InterestPoint::setFromCvKeypoint
void setFromCvKeypoint(Eigen::Vector2d const &key, cv::Mat const &cv_descriptor)
Copy IP information from an OpenCV KeyPoint object.
Definition: interest_point.h:129
dense_map::InterestPoint::operator<
bool operator<(const InterestPoint &other) const
Definition: interest_point.h:114
dense_map::InterestPoint::ix
int32_t ix
Integer location (unnormalized), mainly for internal use.
Definition: interest_point.h:80
dense_map::InterestPoint::scale
float scale
Definition: interest_point.h:77
dense_map::InterestPoint
Definition: interest_point.h:45
dense_map::InterestPoint::orientation
float orientation
Definition: interest_point.h:89