MRPT  2.0.2
CFeatureExtraction_SURF.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "vision-precomp.h" // Precompiled headers
11 
13 
14 // Universal include for all versions of OpenCV
15 #include <mrpt/3rdparty/do_opencv_includes.h>
16 
17 #ifdef HAVE_OPENCV_NONFREE // MRPT_HAS_OPENCV_NONFREE
18 #include <opencv2/nonfree/nonfree.hpp>
19 #endif
20 #ifdef HAVE_OPENCV_FEATURES2D
21 #include <opencv2/features2d/features2d.hpp>
22 #endif
23 #ifdef HAVE_OPENCV_XFEATURES2D
24 #include <opencv2/xfeatures2d.hpp>
25 #endif
26 
27 using namespace mrpt;
28 using namespace mrpt::vision;
29 using namespace mrpt::img;
30 using namespace mrpt::img;
31 using namespace mrpt::system;
32 using namespace std;
33 
34 // Was: MRPT_HAS_OPENCV_NONFREE
35 #if defined(HAVE_OPENCV_XFEATURES2D) || \
36  (MRPT_OPENCV_VERSION_NUM < 0x300 && MRPT_OPENCV_VERSION_NUM >= 0x240)
37 #define HAVE_OPENCV_WITH_SURF 1
38 #else
39 #define HAVE_OPENCV_WITH_SURF 0
40 #endif
41 
43  const mrpt::img::CImage& inImg, CFeatureList& feats, unsigned int init_ID,
44  unsigned int nDesiredFeatures, const TImageROI& ROI)
45 {
46 #if HAVE_OPENCV_WITH_SURF
47  mrpt::system::CTimeLoggerEntry tle(profiler, "extractFeaturesSURF");
48 
49  using namespace cv;
50 
51  const CImage img_grayscale(inImg, FAST_REF_OR_CONVERT_TO_GRAY);
52  const Mat& img = img_grayscale.asCvMatRef();
53 
54  vector<KeyPoint> cv_feats; // OpenCV keypoint output vector
55  Mat cv_descs; // OpenCV descriptor output
56 
57 // gb redesign start -make sure that the Algorithm::create is used only for
58 // older openCV versions
59 #if MRPT_OPENCV_VERSION_NUM < 0x300 && MRPT_OPENCV_VERSION_NUM >= 0x240
60 
61  Ptr<Feature2D> surf = Algorithm::create<Feature2D>("Feature2D.SURF");
62  if (surf.empty())
63  CV_Error(
64  CV_StsNotImplemented,
65  "OpenCV <v3.0 was built without SURF support");
66 
67  surf->set("hessianThreshold", options.SURFOptions.hessianThreshold);
68  surf->set("nOctaves", options.SURFOptions.nOctaves);
69  surf->set("nOctaveLayers", options.SURFOptions.nLayersPerOctave);
70  // surf->set("upright", params.upright != 0);
71  surf->set("extended", options.SURFOptions.rotation_invariant);
72 
73  surf->operator()(img, Mat(), cv_feats, cv_descs);
74 
75 #else
76  Ptr<xfeatures2d::SURF> surf =
77  xfeatures2d::SURF::create(100.0, 4, 3, 0, 0); // gb
78 
79  if (surf.empty())
80  CV_Error(
81  CV_StsNotImplemented, "OpenCV 3.0 was built without SURF support");
82  surf->setHessianThreshold(options.SURFOptions.hessianThreshold);
83  surf->setNOctaves(options.SURFOptions.nOctaves);
84  surf->setNOctaveLayers(options.SURFOptions.nLayersPerOctave);
85  // surf->setUpright(params.upright != 0);
86  surf->setExtended(options.SURFOptions.rotation_invariant);
87  // gb redesign end
88  surf->detectAndCompute(img, Mat(), cv_feats, cv_descs);
89 #endif
90 
91  // -----------------------------------------------------------------
92  // MRPT Wrapping
93  // -----------------------------------------------------------------
94  feats.clear();
95  unsigned int nCFeats = init_ID;
96  int offset = (int)this->options.patchSize / 2 + 1;
97  unsigned int imgH = inImg.getHeight();
98  unsigned int imgW = inImg.getWidth();
99 
100  const size_t n_feats =
101  (nDesiredFeatures == 0)
102  ? cv_feats.size()
103  : std::min((size_t)nDesiredFeatures, cv_feats.size());
104 
105  for (size_t i = 0; i < n_feats; i++)
106  {
107  // Get the OpenCV SURF point
108  CFeature ft;
109  const KeyPoint& point = cv_feats[i];
110 
111  const int xBorderInf = (int)floor(point.pt.x - options.patchSize / 2);
112  const int xBorderSup = (int)floor(point.pt.x + options.patchSize / 2);
113  const int yBorderInf = (int)floor(point.pt.y - options.patchSize / 2);
114  const int yBorderSup = (int)floor(point.pt.y + options.patchSize / 2);
115 
116  if (options.patchSize == 0 ||
117  ((xBorderSup < (int)imgW) && (xBorderInf > 0) &&
118  (yBorderSup < (int)imgH) && (yBorderInf > 0)))
119  {
120  ft.type = featSURF;
121  ft.keypoint.pt.x = point.pt.x; // X position
122  ft.keypoint.pt.y = point.pt.y; // Y position
123  ft.orientation = point.angle; // Orientation
124  ft.keypoint.octave = point.size * 1.2 / 9; // Scale
125  ft.keypoint.ID = nCFeats++; // Feature ID into extraction
126  ft.patchSize = options.patchSize; // The size of the feature patch
127 
128  // Image patch?
129  if (options.patchSize > 0)
130  {
132  inImg.extract_patch(
133  p, round(point.pt.x) - offset, round(point.pt.y) - offset,
134  options.patchSize, options.patchSize);
135 
136  ft.patch = std::move(p);
137  }
138 
139  // Get the SURF descriptor
140  ft.descriptors.SURF.emplace();
141  auto& desc = ft.descriptors.SURF.value();
142  desc.resize(cv_descs.cols);
143  for (int m = 0; m < cv_descs.cols; ++m)
144  desc[m] = cv_descs.at<float>(i, m);
145 
146  feats.emplace_back(std::move(ft));
147 
148  } // end if
149  } // end for
150 
151 #else
153  "Method not available: MRPT compiled without OpenCV, or against a "
154  "version of OpenCV without SURF");
155 #endif // MRPT_HAS_OPENCV
156 } // end extractFeaturesSURF
157 
159  const mrpt::img::CImage& inImg, CFeatureList& in_features)
160 {
161 #if HAVE_OPENCV_WITH_SURF
162  using namespace cv;
164  profiler, "internal_computeSurfDescriptors");
165 
166  if (in_features.empty()) return;
167 
168  const CImage img_grayscale(inImg, FAST_REF_OR_CONVERT_TO_GRAY);
169  const Mat& img = img_grayscale.asCvMatRef();
170 
171  vector<KeyPoint> cv_feats; // OpenCV keypoint output vector
172  Mat cv_descs; // OpenCV descriptor output
173 
174  // Fill in the desired key-points:
175  cv_feats.resize(in_features.size());
176  for (size_t i = 0; i < in_features.size(); ++i)
177  {
178  cv_feats[i].pt.x = in_features[i].keypoint.pt.x;
179  cv_feats[i].pt.y = in_features[i].keypoint.pt.y;
180  cv_feats[i].size = 1 << in_features[i].keypoint.octave;
181  }
182 
183 // Only computes the descriptors:
184 // gb redesign
185 #if MRPT_OPENCV_VERSION_NUM < 0x300 && MRPT_OPENCV_VERSION_NUM >= 0x240
186 
187  Ptr<Feature2D> surf = Algorithm::create<Feature2D>("Feature2D.SURF");
188  if (surf.empty())
189  CV_Error(CV_StsNotImplemented, "OpenCV was built without SURF support");
190  surf->set("hessianThreshold", options.SURFOptions.hessianThreshold);
191  surf->set("nOctaves", options.SURFOptions.nOctaves);
192  surf->set("nOctaveLayers", options.SURFOptions.nLayersPerOctave);
193  // surf->set("upright", params.upright != 0);
194  surf->set("extended", options.SURFOptions.rotation_invariant);
195 
196  surf->compute(
197  img, cv_feats,
198  cv_descs); // is that correct? the version from above is:
199 // surf->operator()(img, Mat(), cv_feats, cv_descs);
200 #else
201 
202  Ptr<xfeatures2d::SURF> surf =
203  xfeatures2d::SURF::create(100.0, 4, 3, 0, 0); // gb
204 
205  if (surf.empty())
206  CV_Error(CV_StsNotImplemented, "OpenCV was built without SURF support");
207  surf->setHessianThreshold(options.SURFOptions.hessianThreshold);
208  surf->setNOctaves(options.SURFOptions.nOctaves);
209  surf->setNOctaveLayers(options.SURFOptions.nLayersPerOctave);
210  // surf->setUpright(params.upright != 0);
211  surf->setExtended(options.SURFOptions.rotation_invariant);
212 
213  surf->detectAndCompute(img, Mat(), cv_feats, cv_descs);
214 #endif
215  // gb redesign end
216  // -----------------------------------------------------------------
217  // MRPT Wrapping
218  // -----------------------------------------------------------------
219  int i = 0;
220  for (auto& ft : in_features)
221  {
222  // Get the OpenCV SURF point
223  const KeyPoint& point = cv_feats[i];
224 
225  ft.orientation = point.angle;
226  ft.keypoint.octave = point.octave;
227 
228  // Get the SURF descriptor
229  ft.descriptors.SURF.emplace();
230  auto& desc = ft.descriptors.SURF.value();
231  desc.resize(cv_descs.cols);
232  for (int m = 0; m < cv_descs.cols; ++m)
233  desc[m] = cv_descs.at<float>(i, m);
234 
235  i++;
236  }
237 
238 #else
240  "Method not available: MRPT compiled without OpenCV, or against a "
241  "version of OpenCV without SURF");
242 #endif // MRPT_HAS_OPENCV
243 } // end internal_computeSurfDescriptors
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
A safe way to call enter() and leave() of a mrpt::system::CTimeLogger upon construction and destructi...
void extractFeaturesSURF(const mrpt::img::CImage &img, CFeatureList &feats, unsigned int init_ID=0, unsigned int nDesiredFeatures=0, const TImageROI &ROI=TImageROI())
Extract features from the image based on the SURF method.
TKeyPointMethod type
Keypoint method used to detect this feature.
Definition: CFeature.h:73
size_t size() const
Definition: CFeature.h:352
cv::Mat & asCvMatRef()
Get a reference to the internal cv::Mat, which can be resized, etc.
Definition: CImage.cpp:227
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:849
STL namespace.
TFeatureID ID
ID of the feature.
Definition: TKeyPoint.h:39
Definition: img/CImage.h:23
void internal_computeSurfDescriptors(const mrpt::img::CImage &in_img, CFeatureList &in_features)
Compute the SURF descriptor of the provided features into the input image.
A structure for defining a ROI within an image.
size_t getWidth() const override
Returns the width of the image in pixels.
Definition: CImage.cpp:818
TKeyPointf keypoint
Definition: CFeature.h:64
std::optional< mrpt::img::CImage > patch
A patch of the image surrounding the feature.
Definition: CFeature.h:67
Classes for computer vision, detectors, features, etc.
Definition: CDifodo.h:17
A generic 2D feature from an image, extracted with CFeatureExtraction Each feature may have one or mo...
Definition: CFeature.h:53
Speeded Up Robust Feature [BAY&#39;06].
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
Definition: CFeature.h:275
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
TDescriptors descriptors
Definition: CFeature.h:157
std::optional< std::vector< float > > SURF
SURF feature descriptor.
Definition: CFeature.h:113
uint8_t octave
The image octave the image was found in: 0=original image, 1=1/2 image, 2=1/4 image, etc.
Definition: TKeyPoint.h:49
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)...
Definition: CImage.cpp:1166
float orientation
Main orientation of the feature.
Definition: CFeature.h:81
uint16_t patchSize
Size of the patch (patchSize x patchSize) (it must be an odd number)
Definition: CFeature.h:70
void emplace_back(CFeature &&f)
Definition: CFeature.h:364
pixel_coords_t pt
Coordinates in the image.
Definition: TKeyPoint.h:36
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:148
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:24



Page generated by Doxygen 1.8.14 for MRPT 2.0.2 Git: 9b4fd2465 Mon May 4 16:59:08 2020 +0200 at lun may 4 17:26:07 CEST 2020