Grider_GRID.h
Go to the documentation of this file.
1 /*
2  * OpenVINS: An Open Platform for Visual-Inertial Research
3  * Copyright (C) 2018-2023 Patrick Geneva
4  * Copyright (C) 2018-2023 Guoquan Huang
5  * Copyright (C) 2018-2023 OpenVINS Contributors
6  * Copyright (C) 2018-2019 Kevin Eckenhoff
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef OV_CORE_GRIDER_GRID_H
23 #define OV_CORE_GRIDER_GRID_H
24 
25 #include <Eigen/Eigen>
26 #include <functional>
27 #include <iostream>
28 #include <vector>
29 
30 #include <opencv2/highgui/highgui.hpp>
31 #include <opencv2/imgproc/imgproc.hpp>
32 #include <opencv2/opencv.hpp>
33 
35 
36 namespace ov_core {
37 
46 class Grider_GRID {
47 
48 public:
57  static bool compare_response(cv::KeyPoint first, cv::KeyPoint second) { return first.response > second.response; }
58 
74  static void perform_griding(const cv::Mat &img, const cv::Mat &mask, const std::vector<std::pair<int, int>> &valid_locs,
75  std::vector<cv::KeyPoint> &pts, int num_features, int grid_x, int grid_y, int threshold,
76  bool nonmaxSuppression) {
77 
78  // Return if there is nothing to extract
79  if (valid_locs.empty())
80  return;
81 
82  // We want to have equally distributed features
83  // NOTE: If we have more grids than number of total points, we calc the biggest grid we can do
84  // NOTE: Thus if we extract 1 point per grid we have
85  // NOTE: -> 1 = num_features / (grid_x * grid_y)
86  // NOTE: -> grid_x = ratio * grid_y (keep the original grid ratio)
87  // NOTE: -> grid_y = sqrt(num_features / ratio)
88  if (num_features < grid_x * grid_y) {
89  double ratio = (double)grid_x / (double)grid_y;
90  grid_y = std::ceil(std::sqrt(num_features / ratio));
91  grid_x = std::ceil(grid_y * ratio);
92  }
93  int num_features_grid = (int)((double)num_features / (double)(grid_x * grid_y)) + 1;
94  assert(grid_x > 0);
95  assert(grid_y > 0);
96  assert(num_features_grid > 0);
97 
98  // Calculate the size our extraction boxes should be
99  int size_x = img.cols / grid_x;
100  int size_y = img.rows / grid_y;
101 
102  // Make sure our sizes are not zero
103  assert(size_x > 0);
104  assert(size_y > 0);
105 
106  // Parallelize our 2d grid extraction!!
107  std::vector<std::vector<cv::KeyPoint>> collection(valid_locs.size());
108  parallel_for_(cv::Range(0, (int)valid_locs.size()), LambdaBody([&](const cv::Range &range) {
109  for (int r = range.start; r < range.end; r++) {
110 
111  // Calculate what cell xy value we are in
112  auto grid = valid_locs.at(r);
113  int x = grid.first * size_x;
114  int y = grid.second * size_y;
115 
116  // Skip if we are out of bounds
117  if (x + size_x > img.cols || y + size_y > img.rows)
118  continue;
119 
120  // Calculate where we should be extracting from
121  cv::Rect img_roi = cv::Rect(x, y, size_x, size_y);
122 
123  // Extract FAST features for this part of the image
124  std::vector<cv::KeyPoint> pts_new;
125  cv::FAST(img(img_roi), pts_new, threshold, nonmaxSuppression);
126 
127  // Now lets get the top number from this
128  std::sort(pts_new.begin(), pts_new.end(), Grider_FAST::compare_response);
129 
130  // Append the "best" ones to our vector
131  // Note that we need to "correct" the point u,v since we extracted it in a ROI
132  // So we should append the location of that ROI in the image
133  for (size_t i = 0; i < (size_t)num_features_grid && i < pts_new.size(); i++) {
134 
135  // Create keypoint
136  cv::KeyPoint pt_cor = pts_new.at(i);
137  pt_cor.pt.x += (float)x;
138  pt_cor.pt.y += (float)y;
139 
140  // Reject if out of bounds (shouldn't be possible...)
141  if ((int)pt_cor.pt.x < 0 || (int)pt_cor.pt.x > img.cols || (int)pt_cor.pt.y < 0 || (int)pt_cor.pt.y > img.rows)
142  continue;
143 
144  // Check if it is in the mask region
145  // NOTE: mask has max value of 255 (white) if it should be removed
146  if (mask.at<uint8_t>((int)pt_cor.pt.y, (int)pt_cor.pt.x) > 127)
147  continue;
148  collection.at(r).push_back(pt_cor);
149  }
150  }
151  }));
152 
153  // Combine all the collections into our single vector
154  for (size_t r = 0; r < collection.size(); r++) {
155  pts.insert(pts.end(), collection.at(r).begin(), collection.at(r).end());
156  }
157 
158  // Return if no points
159  if (pts.empty())
160  return;
161 
162  // Sub-pixel refinement parameters
163  cv::Size win_size = cv::Size(5, 5);
164  cv::Size zero_zone = cv::Size(-1, -1);
165  cv::TermCriteria term_crit = cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 20, 0.001);
166 
167  // Get vector of points
168  std::vector<cv::Point2f> pts_refined;
169  for (size_t i = 0; i < pts.size(); i++) {
170  pts_refined.push_back(pts.at(i).pt);
171  }
172 
173  // Finally get sub-pixel for all extracted features
174  cv::cornerSubPix(img, pts_refined, win_size, zero_zone, term_crit);
175 
176  // Save the refined points!
177  for (size_t i = 0; i < pts.size(); i++) {
178  pts.at(i).pt = pts_refined.at(i);
179  }
180  }
181 };
182 
183 } // namespace ov_core
184 
185 #endif /* OV_CORE_GRIDER_GRID_H */
ov_core::Grider_GRID::perform_griding
static void perform_griding(const cv::Mat &img, const cv::Mat &mask, const std::vector< std::pair< int, int >> &valid_locs, std::vector< cv::KeyPoint > &pts, int num_features, int grid_x, int grid_y, int threshold, bool nonmaxSuppression)
This function will perform grid extraction using FAST.
Definition: Grider_GRID.h:74
ov_core::Grider_GRID::compare_response
static bool compare_response(cv::KeyPoint first, cv::KeyPoint second)
Compare keypoints based on their response value.
Definition: Grider_GRID.h:57
ov_core::Grider_GRID
Extracts FAST features in a grid pattern.
Definition: Grider_GRID.h:46
ov_core::LambdaBody
Definition: opencv_lambda_body.h:37
ov_core
Core algorithms for OpenVINS.
Definition: CamBase.h:30
opencv_lambda_body.h


ov_core
Author(s): Patrick Geneva , Kevin Eckenhoff , Guoquan Huang
autogenerated on Mon Jan 22 2024 03:08:17