MRPT  2.0.2
CFeatureExtraction_spinImg.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 
12 #include <mrpt/math/ops_matrices.h>
14 #include <Eigen/Dense>
15 
16 using namespace mrpt;
17 using namespace mrpt::vision;
18 using namespace mrpt::img;
19 using namespace mrpt::img;
20 using namespace mrpt::system;
21 using namespace mrpt::math;
22 using namespace std;
23 
25  const CImage& in_img, CFeatureList& in_features)
26 {
29  profiler, "internal_computeSpinImageDescriptors");
30 
31  ASSERT_(options.SpinImagesOptions.radius > 1);
32 
33  // This is a C++ implementation of the descriptor "Intensity-domain spin
34  // images" as described
35  // in "A sparse texture representation using affine-invariant regions", S
36  // Lazebnik, C Schmid, J Ponce,
37  // 2003 IEEE Computer Society Conference on Computer Vision.
38 
39  const unsigned int HIST_N_INT =
40  options.SpinImagesOptions.hist_size_intensity;
41  const unsigned int HIST_N_DIS =
42  options.SpinImagesOptions.hist_size_distance;
43  const unsigned int R = options.SpinImagesOptions.radius;
44  const int img_w = static_cast<int>(in_img.getWidth());
45  const int img_h = static_cast<int>(in_img.getHeight());
46  const bool img_color = in_img.isColor();
47 
48  // constant for passing intensity [0,255] to histogram index
49  // [0,HIST_N_INT-1]:
50  const float k_int2idx = (HIST_N_INT - 1) / 255.0f;
51  const float k_idx2int = 1.0f / k_int2idx;
52 
53  // constant for passing distances in pixels [0,R] to histogram index
54  // [0,HIST_N_DIS-1]:
55  const float k_dis2idx = (HIST_N_DIS - 1) / d2f(R);
56  const float k_idx2dis = 1.0f / k_dis2idx;
57 
58  // The Gaussian kernel used below is approximated up to a given distance
59  // in pixels, given by 2 times the appropriate std. deviations:
60  const int STD_TIMES = 2;
61  const int kernel_size_dist = static_cast<int>(
62  ceil(k_dis2idx * STD_TIMES * options.SpinImagesOptions.std_dist));
63 
64  const float _2var_int =
65  -1.0f / (2 * square(options.SpinImagesOptions.std_intensity));
66  const float _2var_dist =
67  -1.0f / (2 * square(options.SpinImagesOptions.std_dist));
68 
69  // Create the 2D histogram:
70  CMatrixDouble hist2d(HIST_N_INT, HIST_N_DIS);
71 
72  // Compute intensity-domain spin images
73  for (auto& in_feature : in_features)
74  {
75  // Overwrite scale with the descriptor scale:
76  in_feature.keypoint.octave = options.SpinImagesOptions.radius;
77 
78  // Reset histogram to zeros:
79  hist2d.setZero();
80 
81  // Define the ROI around the interest point which counts for the
82  // histogram:
83  int px0 = round(in_feature.keypoint.pt.x - R);
84  int px1 = round(in_feature.keypoint.pt.x + R);
85  int py0 = round(in_feature.keypoint.pt.y - R);
86  int py1 = round(in_feature.keypoint.pt.y + R);
87 
88  // Clip at img borders:
89  px0 = max(0, px0);
90  px1 = min(img_w - 1, px1);
91  py0 = max(0, py0);
92  py1 = min(img_h - 1, py1);
93 
94  for (int px = px0; px <= px1; px++)
95  {
96  for (int py = py0; py <= py1; py++)
97  {
98  uint8_t pix_val;
99  // get the pixel color [0,255]
100  if (!img_color)
101  pix_val = in_img.at<uint8_t>(px, py);
102  else
103  {
104  auto aux_pix_ptr = in_img.ptr<uint8_t>(px, py);
105  pix_val =
106  (aux_pix_ptr[0] + aux_pix_ptr[1] + aux_pix_ptr[2]) / 3;
107  }
108 
109  const float pix_dist = hypot(
110  in_feature.keypoint.pt.x - px,
111  in_feature.keypoint.pt.y - py);
112  const int center_bin_dist = k_dis2idx * pix_dist;
113 
114  // A factor to correct the histogram due to the existence of
115  // more pixels at larger radius:
116  // Obtained as Area = PI ( R1^2 - R2^2 ) for R1,R2 being
117  // pix_dist +- Delta/2
118  // const double density_circular_area = 1.0/ (M_2PI *
119  // (center_bin_dist+0.5) * square(k_idx2dis) );
120 
121  // Apply a "soft-histogram", so each pixel counts into several
122  // bins,
123  // weighted by a exponential function to model a Gaussian
124  // kernel
125  const int bin_int_low =
126  max(0, static_cast<int>(ceil(
127  k_int2idx *
128  (pix_val -
129  STD_TIMES *
130  options.SpinImagesOptions.std_intensity))));
131  const int bin_int_hi =
132  min(static_cast<int>(HIST_N_INT - 1),
133  static_cast<int>(ceil(
134  k_int2idx *
135  (pix_val +
136  STD_TIMES *
137  options.SpinImagesOptions.std_intensity))));
138 
139  // cout << "d: " << pix_dist << "v: " << (int)pix_val << "\t";
140 
141  if (center_bin_dist <
142  static_cast<int>(HIST_N_DIS)) // this accounts for the
143  // "square" or "circle"
144  // shapes of the area to
145  // account for
146  {
147  const int bin_dist_low =
148  max(0, center_bin_dist - kernel_size_dist);
149  const int bin_dist_hi =
150  min(static_cast<int>(HIST_N_DIS - 1),
151  center_bin_dist + kernel_size_dist);
152 
153  int bin_dist, bin_int;
154  float pix_dist_cur_dist =
155  pix_dist - bin_dist_low * k_idx2dis;
156 
157  for (bin_dist = bin_dist_low; bin_dist <= bin_dist_hi;
158  bin_dist++, pix_dist_cur_dist -= k_idx2dis)
159  {
160  float pix_val_cur_val =
161  pix_val - (bin_int_low * k_idx2int);
162 
163  for (bin_int = bin_int_low; bin_int <= bin_int_hi;
164  bin_int++, pix_val_cur_val -= k_idx2int)
165  {
166  // Gaussian kernel:
167  double v = _2var_dist * square(pix_dist_cur_dist) +
168  _2var_int * square(pix_val_cur_val);
169 
170  hist2d(bin_int, bin_dist) += exp(v);
171  }
172  }
173  // hist2d(bin_int,bin_dist) *= ;
174  } // in range
175 
176  } // end py
177  } // end px
178 
179  // Normalize [0,1]
180  mrpt::math::normalize(hist2d, 0, 1);
181 
182  // Save the histogram as a vector:
183  unsigned idx = 0;
184  in_feature.descriptors.SpinImg.emplace();
185  std::vector<float>& ptr_trg = *in_feature.descriptors.SpinImg;
186  ptr_trg.resize(HIST_N_INT * HIST_N_DIS);
187 
188  for (unsigned i = 0; i < HIST_N_DIS; i++)
189  for (unsigned j = 0; j < HIST_N_INT; j++)
190  ptr_trg[idx++] = hist2d(j, i);
191 
192  in_feature.descriptors.SpinImg_range_rows = HIST_N_DIS;
193 
194  } // end for each feature
195 
196  MRPT_END
197 }
#define MRPT_START
Definition: exceptions.h:241
A safe way to call enter() and leave() of a mrpt::system::CTimeLogger upon construction and destructi...
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:849
This file implements miscelaneous matrix and matrix/vector operations, and internal functions in mrpt...
STL namespace.
const T & at(unsigned int col, unsigned int row, unsigned int channel=0) const
Access to pixels without checking boundaries, and doing a reinterpret_cast<> of the data as the given...
Definition: img/CImage.h:567
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:120
float d2f(const double d)
shortcut for static_cast<float>(double)
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:818
void normalize(CONTAINER &c, Scalar valMin, Scalar valMax)
Scales all elements such as the minimum & maximum values are shifted to the given values...
Classes for computer vision, detectors, features, etc.
Definition: CDifodo.h:17
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
Definition: CFeature.h:275
return_t square(const num_t x)
Inline function for the square of a number.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
Definition: CImage.cpp:859
const float R
#define MRPT_END
Definition: exceptions.h:245
const T * ptr(unsigned int col, unsigned int row, unsigned int channel=0) const
Returns a pointer to a given pixel, without checking for boundaries.
Definition: img/CImage.h:583
void internal_computeSpinImageDescriptors(const mrpt::img::CImage &in_img, CFeatureList &in_features)
Compute the intensity-domain spin images descriptor of the provided features into the input image...
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