MRPT  1.9.9
CFeatureExtraction_LSD_BLD.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 /*---------------------------------------------------------------
11  CLASS: CFeatureExtraction
12  FILE: CFeatureExtraction_LSD_BLD.cpp
13  AUTHOR: Raghavender Sahdev <raghavendersahdev@gmail.com>
14  ---------------------------------------------------------------*/
15 
16 #include "vision-precomp.h" // Precompiled headers
17 #include <mrpt/system/os.h>
18 #include <mrpt/vision/CFeatureExtraction.h> // important import
19 #include <mrpt/io/CMemoryStream.h>
20 #include <mrpt/otherlibs/do_opencv_includes.h>
21 
22 #ifdef HAVE_OPENCV_XFEATURES2D
23 #include <opencv2/xfeatures2d.hpp>
24 #endif
25 #ifdef HAVE_OPENCV_LINE_DESCRIPTOR
26 #include <opencv2/line_descriptor.hpp>
27 using namespace cv::line_descriptor;
28 #endif
29 
30 using namespace mrpt::vision;
31 using namespace mrpt::img;
32 using namespace mrpt::math;
33 using namespace mrpt::img;
34 using namespace mrpt;
35 using namespace std;
36 
37 #if defined(HAVE_OPENCV_XFEATURES2D) && defined(HAVE_OPENCV_LINE_DESCRIPTOR)
38 #define HAVE_OPENCV_WITH_LSD 1
39 #else
40 #define HAVE_OPENCV_WITH_LSD 0
41 #endif
42 
43 void CFeatureExtraction::extractFeaturesLSD(
44  const mrpt::img::CImage& inImg, CFeatureList& feats, unsigned int init_ID,
45  unsigned int nDesiredFeatures, const TImageROI& ROI) const
46 {
48 #if (!HAVE_OPENCV_WITH_LSD)
50  "This function requires OpenCV modules: xfeatures2d, line_descriptor");
51 #else
52  using namespace cv;
53 
54  vector<KeyPoint> cv_feats; // The opencv keypoint output vector
55  vector<KeyLine> cv_line;
56 
57  // Make sure we operate on a gray-scale version of the image:
58  const CImage inImg_gray(inImg, FAST_REF_OR_CONVERT_TO_GRAY);
59 
60  const Mat theImg = cvarrToMat(inImg_gray.getAs<IplImage>());
61  /* create a random binary mask */
62  cv::Mat mask = Mat::ones(theImg.size(), CV_8UC1);
63 
64  Ptr<LSDDetector> bd = LSDDetector::createLSDDetector();
65 
66  /* extract lines */
67  cv::Mat output = theImg.clone();
68  bd->detect(
69  theImg, cv_line, options.LSDOptions.scale, options.LSDOptions.nOctaves,
70  mask);
71 
72  // *All* the features have been extracted.
73  const size_t N = cv_line.size();
74 
75  // Now:
76  // 1) Sort them by "response":
77  // sort the LSD features by line length
78  for (size_t i = 0; i < N; i++)
79  {
80  for (size_t j = i + 1; j < N; j++)
81  {
82  if (cv_line.at(j).lineLength > cv_line.at(i).lineLength)
83  {
84  KeyLine temp_line = cv_line.at(i);
85  cv_line.at(i) = cv_line.at(j);
86  cv_line.at(j) = temp_line;
87  }
88  }
89  }
90 
91  // 2) Filter by "min-distance" (in options.FASTOptions.min_distance) //
92  // NOT REQUIRED FOR LSD Features
93  // 3) Convert to MRPT CFeatureList format.
94  // Steps 2 & 3 are done together in the while() below.
95  // The "min-distance" filter is done by means of a 2D binary matrix where
96  // each cell is marked when one
97  // feature falls within it. This is not exactly the same than a pure
98  // "min-distance" but is pretty close
99  // and for large numbers of features is much faster than brute force search
100  // of kd-trees.
101  // (An intermediate approach would be the creation of a mask image updated
102  // for each accepted feature, etc.)
103 
104  unsigned int nMax =
105  (nDesiredFeatures != 0 && N > nDesiredFeatures) ? nDesiredFeatures : N;
106  const int offset = (int)this->options.patchSize / 2 + 1;
107  const size_t size_2 = options.patchSize / 2;
108  const size_t imgH = inImg.getHeight();
109  const size_t imgW = inImg.getWidth();
110  unsigned int i = 0;
111  unsigned int cont = 0;
112  TFeatureID nextID = init_ID;
113 
114  if (!options.addNewFeatures) feats.clear();
115 
116  /* draw lines extracted from octave 0 */
117  if (output.channels() == 1) cvtColor(output, output, COLOR_GRAY2BGR);
118 
119  while (cont != nMax && i != N)
120  {
121  KeyLine kl = cv_line[i];
122  KeyPoint kp;
123 
124  if (kl.octave == 0)
125  {
126  Point pt1 = Point2f(kl.startPointX, kl.startPointY);
127  Point pt2 = Point2f(kl.endPointX, kl.endPointY);
128 
129  kp.pt.x = (pt1.x + pt2.x) / 2;
130  kp.pt.y = (pt1.y + pt2.y) / 2;
131  i++;
132  // Patch out of the image??
133  const int xBorderInf = (int)floor(kp.pt.x - size_2);
134  const int xBorderSup = (int)floor(kp.pt.x + size_2);
135  const int yBorderInf = (int)floor(kp.pt.y - size_2);
136  const int yBorderSup = (int)floor(kp.pt.y + size_2);
137 
138  if (!(xBorderSup < (int)imgW && xBorderInf > 0 &&
139  yBorderSup < (int)imgH && yBorderInf > 0))
140  continue; // nope, skip.
141 
142  // All tests passed: add new feature:
143  CFeature::Ptr ft = std::make_shared<CFeature>();
144  ft->type = featLSD;
145  ft->ID = nextID++;
146  ft->x = kp.pt.x;
147  ft->y = kp.pt.y;
148  ft->x2[0] = pt1.x;
149  ft->x2[1] = pt2.x;
150  ft->y2[0] = pt1.y;
151  ft->y2[1] = pt2.y;
152  ft->response = kl.response;
153  // ft->orientation = kp.angle;
154  ft->scale = kl.octave;
155  // ft->patchSize = options.patchSize; // The size of
156  // the
157  // feature
158  // patch
159 
160  if (options.patchSize > 0)
161  {
162  inImg.extract_patch(
163  ft->patch, round(ft->x) - offset, round(ft->y) - offset,
164  options.patchSize,
165  options.patchSize); // Image patch surronding the feature
166  }
167  feats.push_back(ft);
168  }
169  ++cont;
170  // cout << ft->x << " " << ft->y << endl;
171  }
172 
173 #endif
174  MRPT_END
175 }
176 
177 /************************************************************************************************
178 * internal_computeBLDDescriptors
179 ************************************************************************************************/
180 void CFeatureExtraction::internal_computeBLDLineDescriptors(
181  const mrpt::img::CImage& in_img, CFeatureList& in_features) const
182 {
183 #if (!HAVE_OPENCV_WITH_LSD)
185  "This function requires OpenCV modules: xfeatures2d, line_descriptor");
186 #else
187  using namespace cv;
188 
189  if (in_features.empty()) return;
190 
191  const CImage img_grayscale(in_img, FAST_REF_OR_CONVERT_TO_GRAY);
192  const Mat img = cvarrToMat(img_grayscale.getAs<IplImage>());
193 
194  vector<KeyPoint> cv_feats; // OpenCV keypoint output vector
195  Mat cv_descs; // OpenCV descriptor output
196 
197  cv::Mat mask = Mat::ones(img.size(), CV_8UC1);
198 
199  BinaryDescriptor::Params params;
200  params.ksize_ = options.BLDOptions.ksize_;
201  params.reductionRatio = options.BLDOptions.reductionRatio;
202  params.numOfOctave_ = options.BLDOptions.numOfOctave;
203  params.widthOfBand_ = options.BLDOptions.widthOfBand;
204 
205  Ptr<BinaryDescriptor> bd2 =
206  BinaryDescriptor::createBinaryDescriptor(params);
207  /* compute lines */
208  std::vector<KeyLine> keylines;
209 
210  bd2->detect(img, keylines, mask);
211 
212  /* compute descriptors */
213  bd2->compute(img, keylines, cv_descs);
214  keylines.resize(in_features.size());
215 
216  // -----------------------------------------------------------------
217  // MRPT Wrapping
218  // -----------------------------------------------------------------
219  CFeatureList::iterator itList;
220  int i;
221  for (i = 0, itList = in_features.begin(); itList != in_features.end();
222  itList++, i++)
223  {
224  CFeature::Ptr ft = *itList;
225 
226  // Get the BLD descriptor
227  ft->descriptors.BLD.resize(cv_descs.cols);
228  for (int m = 0; m < cv_descs.cols; ++m)
229  ft->descriptors.BLD[m] =
230  cv_descs.at<int>(i, m); // Get the SURF descriptor
231  } // end for
232 
233 #endif // end of opencv3 version check
234 } // end internal_computeBLDDescriptors
GLenum GLint GLuint mask
Definition: glext.h:4050
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&#39;s headers.
Definition: img/CImage.h:599
#define MRPT_START
Definition: exceptions.h:262
uint64_t TFeatureID
Definition of a feature ID.
TInternalFeatList::iterator iterator
Definition: CFeature.h:365
LSD detector, OpenCV&#39;s implementation.
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
size_t size() const
Definition: CFeature.h:386
GLintptr offset
Definition: glext.h:3925
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:892
STL namespace.
A structure for defining a ROI within an image.
This base provides a set of functions for maths stuff.
size_t getWidth() const override
Returns the width of the image in pixels.
Definition: CImage.cpp:864
GLint GLvoid * img
Definition: glext.h:3763
Classes for computer vision, detectors, features, etc.
Definition: CCamModel.h:18
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
Definition: CFeature.h:304
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define MRPT_END
Definition: exceptions.h:266
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:1359
EIGEN_STRONG_INLINE void ones(const size_t row, const size_t col)
Resize matrix and set all elements to one.
Definition: eigen_plugins.h:82
GLenum const GLfloat * params
Definition: glext.h:3534
void push_back(const CFeature::Ptr &f)
Definition: CFeature.h:398
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:130
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:23



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020