Grider_FAST.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_FAST_H
23 #define OV_CORE_GRIDER_FAST_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_FAST {
47 
48 public:
57  static bool compare_response(cv::KeyPoint first, cv::KeyPoint second) { return first.response > second.response; }
58 
73  static void perform_griding(const cv::Mat &img, const cv::Mat &mask, std::vector<cv::KeyPoint> &pts, int num_features, int grid_x,
74  int grid_y, int threshold, bool nonmaxSuppression) {
75 
76  // We want to have equally distributed features
77  // NOTE: If we have more grids than number of total points, we calc the biggest grid we can do
78  // NOTE: Thus if we extract 1 point per grid we have
79  // NOTE: -> 1 = num_features / (grid_x * grid_y))
80  // NOTE: -> grid_x = ratio * grid_y (keep the original grid ratio)
81  // NOTE: -> grid_y = sqrt(num_features / ratio)
82  if (num_features < grid_x * grid_y) {
83  double ratio = (double)grid_x / (double)grid_y;
84  grid_y = std::ceil(std::sqrt(num_features / ratio));
85  grid_x = std::ceil(grid_y * ratio);
86  }
87  int num_features_grid = (int)((double)num_features / (double)(grid_x * grid_y)) + 1;
88  assert(grid_x > 0);
89  assert(grid_y > 0);
90  assert(num_features_grid > 0);
91 
92  // Calculate the size our extraction boxes should be
93  int size_x = img.cols / grid_x;
94  int size_y = img.rows / grid_y;
95 
96  // Make sure our sizes are not zero
97  assert(size_x > 0);
98  assert(size_y > 0);
99 
100  // Parallelize our 2d grid extraction!!
101  int ct_cols = std::floor(img.cols / size_x);
102  int ct_rows = std::floor(img.rows / size_y);
103  std::vector<std::vector<cv::KeyPoint>> collection(ct_cols * ct_rows);
104  parallel_for_(cv::Range(0, ct_cols * ct_rows), LambdaBody([&](const cv::Range &range) {
105  for (int r = range.start; r < range.end; r++) {
106  // Calculate what cell xy value we are in
107  int x = r % ct_cols * size_x;
108  int y = r / ct_cols * size_y;
109 
110  // Skip if we are out of bounds
111  if (x + size_x > img.cols || y + size_y > img.rows)
112  continue;
113 
114  // Calculate where we should be extracting from
115  cv::Rect img_roi = cv::Rect(x, y, size_x, size_y);
116 
117  // Extract FAST features for this part of the image
118  std::vector<cv::KeyPoint> pts_new;
119  cv::FAST(img(img_roi), pts_new, threshold, nonmaxSuppression);
120 
121  // Now lets get the top number from this
122  std::sort(pts_new.begin(), pts_new.end(), Grider_FAST::compare_response);
123 
124  // Append the "best" ones to our vector
125  // Note that we need to "correct" the point u,v since we extracted it in a ROI
126  // So we should append the location of that ROI in the image
127  for (size_t i = 0; i < (size_t)num_features_grid && i < pts_new.size(); i++) {
128 
129  // Create keypoint
130  cv::KeyPoint pt_cor = pts_new.at(i);
131  pt_cor.pt.x += (float)x;
132  pt_cor.pt.y += (float)y;
133 
134  // Reject if out of bounds (shouldn't be possible...)
135  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)
136  continue;
137 
138  // Check if it is in the mask region
139  // NOTE: mask has max value of 255 (white) if it should be removed
140  if (mask.at<uint8_t>((int)pt_cor.pt.y, (int)pt_cor.pt.x) > 127)
141  continue;
142  collection.at(r).push_back(pt_cor);
143  }
144  }
145  }));
146 
147  // Combine all the collections into our single vector
148  for (size_t r = 0; r < collection.size(); r++) {
149  pts.insert(pts.end(), collection.at(r).begin(), collection.at(r).end());
150  }
151 
152  // Return if no points
153  if (pts.empty())
154  return;
155 
156  // Sub-pixel refinement parameters
157  cv::Size win_size = cv::Size(5, 5);
158  cv::Size zero_zone = cv::Size(-1, -1);
159  cv::TermCriteria term_crit = cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 20, 0.001);
160 
161  // Get vector of points
162  std::vector<cv::Point2f> pts_refined;
163  for (size_t i = 0; i < pts.size(); i++) {
164  pts_refined.push_back(pts.at(i).pt);
165  }
166 
167  // Finally get sub-pixel for all extracted features
168  cv::cornerSubPix(img, pts_refined, win_size, zero_zone, term_crit);
169 
170  // Save the refined points!
171  for (size_t i = 0; i < pts.size(); i++) {
172  pts.at(i).pt = pts_refined.at(i);
173  }
174  }
175 };
176 
177 } // namespace ov_core
178 
179 #endif /* OV_CORE_GRIDER_FAST_H */
ov_core::Grider_FAST
Extracts FAST features in a grid pattern.
Definition: Grider_FAST.h:46
ov_core::Grider_FAST::perform_griding
static void perform_griding(const cv::Mat &img, const cv::Mat &mask, 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_FAST.h:73
ov_core::Grider_FAST::compare_response
static bool compare_response(cv::KeyPoint first, cv::KeyPoint second)
Compare keypoints based on their response value.
Definition: Grider_FAST.h:57
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