15 #include <mrpt/otherlibs/do_opencv_includes.h> 26 const unsigned int init_ID,
const unsigned int nDesiredFeatures,
37 vector<KeyPoint> cv_feats;
40 const bool use_precomputed_feats = feats.
size() > 0;
42 if (use_precomputed_feats)
44 cv_feats.resize(feats.
size());
45 for (
size_t k = 0; k < cv_feats.size(); ++k)
47 cv_feats[k].pt.x = feats[k].keypoint.pt.x;
48 cv_feats[k].pt.y = feats[k].keypoint.pt.y;
57 profiler.enter(
"extractFeaturesORB.openCV_detectAndCompute");
59 #if MRPT_OPENCV_VERSION_NUM < 0x300 60 Ptr<Feature2D> orb = Algorithm::create<Feature2D>(
"Feature2D.ORB");
61 orb->operator()(cvImg, Mat(), cv_feats, cv_descs, use_precomputed_feats);
63 const size_t n_feats_2_extract =
64 nDesiredFeatures == 0 ? 1000 : 3 * nDesiredFeatures;
65 Ptr<cv::ORB> orb = cv::ORB::create(
66 n_feats_2_extract, options.ORBOptions.scale_factor,
67 options.ORBOptions.n_levels);
68 orb->detectAndCompute(
69 cvImg, Mat(), cv_feats, cv_descs, use_precomputed_feats);
71 profiler.leave(
"extractFeaturesORB.openCV_detectAndCompute");
75 const size_t n_feats = cv_feats.size();
78 const unsigned int patch_size_2 = options.patchSize / 2;
79 unsigned int f_id = init_ID;
80 if (use_precomputed_feats)
82 for (
size_t k = 0; k < n_feats; ++k)
84 feats[k].descriptors.ORB->
resize(cv_descs.cols);
85 for (
int m = 0; m < cv_descs.cols; ++m)
86 (*feats[k].descriptors.ORB)[m] = cv_descs.at<uchar>(k, m);
96 if (options.ORBOptions.extract_patch && options.patchSize > 0)
100 round(feats[k].keypoint.pt.x) - patch_size_2,
101 round(feats[k].keypoint.pt.y) - patch_size_2,
102 options.patchSize, options.patchSize);
112 std::vector<size_t> sorted_indices(n_feats);
113 for (
size_t i = 0; i < n_feats; i++) sorted_indices[i] = i;
115 sorted_indices.begin(), sorted_indices.end(),
130 const bool do_filter_min_dist = options.ORBOptions.min_distance > 1;
131 const unsigned int occupied_grid_cell_size =
132 options.ORBOptions.min_distance / 2.0;
133 const float occupied_grid_cell_size_inv = 1.0f / occupied_grid_cell_size;
135 unsigned int grid_lx =
138 : (
unsigned int)(1 + inImg.
getWidth() * occupied_grid_cell_size_inv);
139 unsigned int grid_ly =
142 : (
unsigned int)(1 + inImg.
getHeight() * occupied_grid_cell_size_inv);
146 occupied_sections.
fill(
false);
148 const size_t n_max_feats = nDesiredFeatures > 0
149 ?
std::min(
size_t(nDesiredFeatures), n_feats)
152 if (!options.addNewFeatures) feats.
clear();
156 const size_t imgW = inImg.
getWidth();
159 while (c_feats < n_max_feats && k < n_feats)
161 const size_t idx = sorted_indices[k++];
162 const KeyPoint& kp = cv_feats[idx];
163 if (options.ORBOptions.extract_patch && options.patchSize > 0)
166 const int xBorderInf = (int)floor(kp.pt.x - patch_size_2);
167 const int xBorderSup = (int)floor(kp.pt.x + patch_size_2);
168 const int yBorderInf = (int)floor(kp.pt.y - patch_size_2);
169 const int yBorderSup = (int)floor(kp.pt.y + patch_size_2);
171 if (!(xBorderSup < (
int)imgW && xBorderInf > 0 &&
172 yBorderSup < (int)imgH && yBorderInf > 0))
176 if (do_filter_min_dist)
179 const auto sect_ix = size_t(kp.pt.x * occupied_grid_cell_size_inv);
180 const auto sect_iy = size_t(kp.pt.y * occupied_grid_cell_size_inv);
182 if (occupied_sections(sect_ix, sect_iy))
186 occupied_sections(sect_ix, sect_iy) =
true;
187 if (sect_ix > 0) occupied_sections(sect_ix - 1, sect_iy) =
true;
188 if (sect_iy > 0) occupied_sections(sect_ix, sect_iy - 1) =
true;
189 if (sect_ix < grid_lx - 1)
190 occupied_sections(sect_ix + 1, sect_iy) =
true;
191 if (sect_iy < grid_ly - 1)
192 occupied_sections(sect_ix, sect_iy + 1) =
true;
209 for (
int m = 0; m < cv_descs.cols; ++m)
212 if (options.ORBOptions.extract_patch && options.patchSize > 0)
219 round(kp.pt.y) - patch_size_2, options.patchSize,
236 profiler,
"internal_computeORBDescriptors");
238 const size_t n_feats = in_features.
size();
242 vector<KeyPoint> cv_feats(n_feats);
243 for (
size_t k = 0; k < n_feats; ++k)
245 KeyPoint& kp = cv_feats[k];
246 kp.pt.x = in_features[k].keypoint.pt.x;
247 kp.pt.y = in_features[k].keypoint.pt.y;
248 kp.angle = in_features[k].orientation;
249 kp.
size = in_features[k].keypoint.octave;
255 #if MRPT_OPENCV_VERSION_NUM < 0x300 256 Ptr<Feature2D> orb = Algorithm::create<Feature2D>(
"Feature2D.ORB");
258 cvImg, cv::noArray(), cv_feats, cv_descs,
261 Ptr<cv::ORB> orb = cv::ORB::create(
262 n_feats, options.ORBOptions.scale_factor, options.ORBOptions.n_levels);
263 orb->detectAndCompute(
264 cvImg, cv::noArray(), cv_feats, cv_descs,
269 for (
size_t k = 0; k < n_feats; ++k)
271 in_features[k].descriptors.ORB.emplace();
272 auto& orb_desc = *in_features[k].descriptors.ORB;
273 orb_desc.
resize(cv_descs.cols);
274 for (
int i = 0; i < cv_descs.cols; ++i)
275 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.
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
int round(const T value)
Returns the closer integer (int) to x.