15 #include <mrpt/otherlibs/do_opencv_includes.h> 27 void CFeatureExtraction::extractFeaturesORB(
29 const unsigned int init_ID,
const unsigned int nDesiredFeatures,
36 #if MRPT_OPENCV_VERSION_NUM < 0x240 42 vector<KeyPoint> cv_feats;
45 const bool use_precomputed_feats = feats.
size() > 0;
47 if (use_precomputed_feats)
49 cv_feats.resize(feats.
size());
50 for (
size_t k = 0; k < cv_feats.size(); ++k)
52 cv_feats[k].pt.x = feats[k]->x;
53 cv_feats[k].pt.y = feats[k]->y;
59 const Mat cvImg = cv::cvarrToMat(inImg_gray.
getAs<IplImage>());
62 #if MRPT_OPENCV_VERSION_NUM < 0x300 63 Ptr<Feature2D> orb = Algorithm::create<Feature2D>(
"Feature2D.ORB");
64 orb->operator()(cvImg, Mat(), cv_feats, cv_descs, use_precomputed_feats);
66 const size_t n_feats_2_extract =
67 nDesiredFeatures == 0 ? 1000 : 3 * nDesiredFeatures;
68 Ptr<cv::ORB> orb = cv::ORB::create(
69 n_feats_2_extract, options.ORBOptions.scale_factor,
70 options.ORBOptions.n_levels);
71 orb->detectAndCompute(
72 cvImg, Mat(), cv_feats, cv_descs, use_precomputed_feats);
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] =
87 cv_descs.at<uchar>(k, m);
97 if (options.ORBOptions.extract_patch && options.patchSize > 0)
100 feats[k]->patch,
round(feats[k]->
x) - patch_size_2,
101 round(feats[k]->
y) - patch_size_2, 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.
fillAll(
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 size_t section_idx_x =
180 size_t(kp.pt.x * occupied_grid_cell_size_inv);
181 const size_t section_idx_y =
182 size_t(kp.pt.y * occupied_grid_cell_size_inv);
184 if (occupied_sections(section_idx_x, section_idx_y))
188 occupied_sections.
set_unsafe(section_idx_x, section_idx_y,
true);
189 if (section_idx_x > 0)
191 section_idx_x - 1, section_idx_y,
true);
192 if (section_idx_y > 0)
194 section_idx_x, section_idx_y - 1,
true);
195 if (section_idx_x < grid_lx - 1)
197 section_idx_x + 1, section_idx_y,
true);
198 if (section_idx_y < grid_ly - 1)
200 section_idx_x, section_idx_y + 1,
true);
209 ft->response = kp.response;
210 ft->orientation = kp.angle;
211 ft->scale = kp.octave;
215 ft->descriptors.ORB.resize(cv_descs.cols);
216 for (
int m = 0; m < cv_descs.cols; ++m)
217 ft->descriptors.ORB[m] = cv_descs.at<uchar>(idx, m);
219 if (options.ORBOptions.extract_patch && options.patchSize > 0)
221 ft->patchSize = options.patchSize;
224 ft->patch,
round(ft->x) - patch_size_2,
225 round(ft->y) - patch_size_2, options.patchSize,
237 void CFeatureExtraction::internal_computeORBDescriptors(
241 #if MRPT_OPENCV_VERSION_NUM < 0x240 246 const size_t n_feats = in_features.
size();
250 vector<KeyPoint> cv_feats(n_feats);
251 for (
size_t k = 0; k < n_feats; ++k)
253 KeyPoint& kp = cv_feats[k];
254 kp.pt.x = in_features[k]->x;
255 kp.pt.y = in_features[k]->y;
256 kp.angle = in_features[k]->orientation;
257 kp.
size = in_features[k]->scale;
260 Mat cvImg(cv::cvarrToMat(inImg_gray.
getAs<IplImage>()));
263 #if MRPT_OPENCV_VERSION_NUM < 0x300 264 Ptr<Feature2D> orb = Algorithm::create<Feature2D>(
"Feature2D.ORB");
266 cvImg, Mat(), cv_feats, cv_descs,
true );
268 Ptr<cv::ORB> orb = cv::ORB::create(
269 n_feats, options.ORBOptions.scale_factor, options.ORBOptions.n_levels);
270 orb->detectAndCompute(
271 cvImg, Mat(), cv_feats, cv_descs,
true );
275 for (
size_t k = 0; k < n_feats; ++k)
277 in_features[k]->descriptors.ORB.
resize(cv_descs.cols);
278 for (
int i = 0; i < cv_descs.cols; ++i)
279 in_features[k]->descriptors.ORB[i] = cv_descs.at<uchar>(k, i);
std::shared_ptr< CFeature > Ptr
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
Declares a matrix of booleans (non serializable).
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
A class for storing images as grayscale or RGB bitmaps.
#define THROW_EXCEPTION(msg)
const T * getAs() const
Returns a pointer to a const T* containing the image - the idea is to call like "img.getAs<IplImage>()" so we can avoid here including OpenCV's headers.
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.
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
size_t getHeight() const override
Returns the height of the image in pixels.
Classes for computer vision, detectors, features, etc.
void set_unsafe(size_t row, size_t col, const T &v)
Fast but unsafe method to write a value in the matrix.
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
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)...
int round(const T value)
Returns the closer integer (int) to x.
ORB detector and descriptor, OpenCV's implementation ("ORB: an efficient alternative to SIFT o...
void push_back(const CFeature::Ptr &f)
void fillAll(const T &val)