15 #include <mrpt/3rdparty/do_opencv_includes.h> 26 const unsigned int init_ID,
const unsigned int nDesiredFeatures,
36 vector<KeyPoint> cv_feats;
39 const bool use_precomputed_feats = feats.
size() > 0;
41 if (use_precomputed_feats)
43 cv_feats.resize(feats.
size());
44 for (
size_t k = 0; k < cv_feats.size(); ++k)
46 cv_feats[k].pt.x = feats[k].keypoint.pt.x;
47 cv_feats[k].pt.y = feats[k].keypoint.pt.y;
56 profiler.enter(
"extractFeaturesORB.openCV_detectAndCompute");
58 #if MRPT_OPENCV_VERSION_NUM < 0x300 59 Ptr<Feature2D> orb = Algorithm::create<Feature2D>(
"Feature2D.ORB");
60 orb->operator()(cvImg, Mat(), cv_feats, cv_descs, use_precomputed_feats);
62 const size_t n_feats_2_extract =
63 nDesiredFeatures == 0 ? 1000 : 3 * nDesiredFeatures;
64 Ptr<cv::ORB> orb = cv::ORB::create(
65 n_feats_2_extract, options.ORBOptions.scale_factor,
66 options.ORBOptions.n_levels);
67 orb->detectAndCompute(
68 cvImg, Mat(), cv_feats, cv_descs, use_precomputed_feats);
70 profiler.leave(
"extractFeaturesORB.openCV_detectAndCompute");
74 const size_t n_feats = cv_feats.size();
77 const unsigned int patch_size_2 = options.patchSize / 2;
78 unsigned int f_id = init_ID;
79 if (use_precomputed_feats)
81 for (
size_t k = 0; k < n_feats; ++k)
83 feats[k].descriptors.ORB->
resize(cv_descs.cols);
84 for (
int m = 0; m < cv_descs.cols; ++m)
85 (*feats[k].descriptors.ORB)[m] = cv_descs.at<uchar>(k, m);
95 if (options.ORBOptions.extract_patch && options.patchSize > 0)
99 round(feats[k].keypoint.pt.x) - patch_size_2,
100 round(feats[k].keypoint.pt.y) - patch_size_2,
101 options.patchSize, options.patchSize);
111 std::vector<size_t> sorted_indices(n_feats);
112 for (
size_t i = 0; i < n_feats; i++) sorted_indices[i] = i;
114 sorted_indices.begin(), sorted_indices.end(),
129 const bool do_filter_min_dist = options.ORBOptions.min_distance > 1;
130 const unsigned int occupied_grid_cell_size =
131 options.ORBOptions.min_distance / 2;
132 const float occupied_grid_cell_size_inv = 1.0f / occupied_grid_cell_size;
134 unsigned int grid_lx =
137 : (
unsigned int)(1 + inImg.
getWidth() * occupied_grid_cell_size_inv);
138 unsigned int grid_ly =
141 : (
unsigned int)(1 + inImg.
getHeight() * occupied_grid_cell_size_inv);
145 occupied_sections.
fill(
false);
147 const size_t n_max_feats = nDesiredFeatures > 0
148 ? std::min(
size_t(nDesiredFeatures), n_feats)
151 if (!options.addNewFeatures) feats.
clear();
155 const size_t imgW = inImg.
getWidth();
158 while (c_feats < n_max_feats && k < n_feats)
160 const size_t idx = sorted_indices[k++];
161 const KeyPoint& kp = cv_feats[idx];
162 if (options.ORBOptions.extract_patch && options.patchSize > 0)
165 const int xBorderInf = (int)floor(kp.pt.x - patch_size_2);
166 const int xBorderSup = (int)floor(kp.pt.x + patch_size_2);
167 const int yBorderInf = (int)floor(kp.pt.y - patch_size_2);
168 const int yBorderSup = (int)floor(kp.pt.y + patch_size_2);
170 if (!(xBorderSup < (
int)imgW && xBorderInf > 0 &&
171 yBorderSup < (int)imgH && yBorderInf > 0))
175 if (do_filter_min_dist)
178 const auto sect_ix = size_t(kp.pt.x * occupied_grid_cell_size_inv);
179 const auto sect_iy = size_t(kp.pt.y * occupied_grid_cell_size_inv);
181 if (occupied_sections(sect_ix, sect_iy))
185 occupied_sections(sect_ix, sect_iy) =
true;
186 if (sect_ix > 0) occupied_sections(sect_ix - 1, sect_iy) =
true;
187 if (sect_iy > 0) occupied_sections(sect_ix, sect_iy - 1) =
true;
188 if (sect_ix < grid_lx - 1)
189 occupied_sections(sect_ix + 1, sect_iy) =
true;
190 if (sect_iy < grid_ly - 1)
191 occupied_sections(sect_ix, sect_iy + 1) =
true;
208 for (
int m = 0; m < cv_descs.cols; ++m)
211 if (options.ORBOptions.extract_patch && options.patchSize > 0)
218 round(kp.pt.y) - patch_size_2, options.patchSize,
235 profiler,
"internal_computeORBDescriptors");
237 const size_t n_feats = in_features.
size();
241 vector<KeyPoint> cv_feats(n_feats);
242 for (
size_t k = 0; k < n_feats; ++k)
244 KeyPoint& kp = cv_feats[k];
245 kp.pt.x = in_features[k].keypoint.pt.x;
246 kp.pt.y = in_features[k].keypoint.pt.y;
247 kp.angle = in_features[k].orientation;
248 kp.
size = in_features[k].keypoint.octave;
254 #if MRPT_OPENCV_VERSION_NUM < 0x300 255 Ptr<Feature2D> orb = Algorithm::create<Feature2D>(
"Feature2D.ORB");
257 cvImg, cv::noArray(), cv_feats, cv_descs,
260 Ptr<cv::ORB> orb = cv::ORB::create(
261 n_feats, options.ORBOptions.scale_factor, options.ORBOptions.n_levels);
262 orb->detectAndCompute(
263 cvImg, cv::noArray(), cv_feats, cv_descs,
268 for (
size_t k = 0; k < n_feats; ++k)
270 in_features[k].descriptors.ORB.emplace();
271 auto& orb_desc = *in_features[k].descriptors.ORB;
272 orb_desc.
resize(cv_descs.cols);
273 for (
int i = 0; i < cv_descs.cols; ++i)
274 orb_desc[i] = cv_descs.at<uchar>(k, i);
std::optional< std::vector< uint8_t > > ORB
ORB feature descriptor.
A safe way to call enter() and leave() of a mrpt::system::CTimeLogger upon construction and destructi...
TKeyPointMethod type
Keypoint method used to detect this feature.
void fill(const Scalar &val)
cv::Mat & asCvMatRef()
Get a reference to the internal cv::Mat, which can be resized, etc.
size_t getHeight() const override
Returns the height of the image in pixels.
TFeatureID ID
ID of the feature.
A helper struct to sort keypoints by their response: It can be used with these types: ...
A structure for defining a ROI within an image.
size_t getWidth() const override
Returns the width of the image in pixels.
std::optional< mrpt::img::CImage > patch
A patch of the image surrounding the feature.
Classes for computer vision, detectors, features, etc.
A generic 2D feature from an image, extracted with CFeatureExtraction Each feature may have one or mo...
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
float response
A measure of the "goodness" of the feature.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
uint8_t octave
The image octave the image was found in: 0=original image, 1=1/2 image, 2=1/4 image, etc.
void extract_patch(CImage &patch, const unsigned int col=0, const unsigned int row=0, const unsigned int width=1, const unsigned int height=1) const
Extract a patch from this image, saveing it into "patch" (its previous contents will be overwritten)...
float orientation
Main orientation of the feature.
This template class provides the basic functionality for a general 2D any-size, resizable container o...
uint16_t patchSize
Size of the patch (patchSize x patchSize) (it must be an odd number)
void emplace_back(CFeature &&f)
ORB detector and descriptor, OpenCV's implementation.
pixel_coords_t pt
Coordinates in the image.
A class for storing images as grayscale or RGB bitmaps.
int round(const T value)
Returns the closer integer (int) to x.