Main MRPT website > C++ reference for MRPT 1.9.9
CFeatureExtraction_spinImg.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 #include "vision-precomp.h" // Precompiled headers
11 
13 
14 using namespace mrpt;
15 using namespace mrpt::vision;
16 using namespace mrpt::img;
17 using namespace mrpt::img;
18 using namespace mrpt::system;
19 using namespace mrpt::math;
20 using namespace std;
21 
22 /************************************************************************************************
23 * computeSpinImageDescriptors
24 **
25 ************************************************************************************************/
27  const CImage& in_img, CFeatureList& in_features) const
28 {
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) / static_cast<float>(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 (CFeatureList::iterator it = in_features.begin();
74  it != in_features.end(); ++it)
75  {
76  // Overwrite scale with the descriptor scale:
77  (*it)->scale = options.SpinImagesOptions.radius;
78 
79  // Reset histogram to zeros:
80  hist2d.zeros();
81 
82  // Define the ROI around the interest point which counts for the
83  // histogram:
84  int px0 = round((*it)->x - R);
85  int px1 = round((*it)->x + R);
86  int py0 = round((*it)->y - R);
87  int py1 = round((*it)->y + R);
88 
89  // Clip at img borders:
90  px0 = max(0, px0);
91  px1 = min(img_w - 1, px1);
92  py0 = max(0, py0);
93  py1 = min(img_h - 1, py1);
94 
95  uint8_t pix_val;
96  uint8_t* aux_pix_ptr;
97 
98  for (int px = px0; px <= px1; px++)
99  {
100  for (int py = py0; py <= py1; py++)
101  {
102  // get the pixel color [0,255]
103  if (!img_color)
104  pix_val = *in_img.get_unsafe(px, py, 0);
105  else
106  {
107  aux_pix_ptr = in_img.get_unsafe(px, py, 0);
108  pix_val =
109  (aux_pix_ptr[0] + aux_pix_ptr[1] + aux_pix_ptr[2]) / 3;
110  }
111 
112  const float pix_dist = hypot((*it)->x - px, (*it)->y - py);
113  const int center_bin_dist = k_dis2idx * pix_dist;
114 
115 // A factor to correct the histogram due to the existence of more pixels at
116 // larger radius:
117 // Obtained as Area = PI ( R1^2 - R2^2 ) for R1,R2 being pix_dist +- Delta/2
118 // const double density_circular_area = 1.0/ (M_2PI * (center_bin_dist+0.5) *
119 // square(k_idx2dis) );
120 
121 #if 0
122  // "normal" histogram
123  const int bin_int = k_int2idx * pix_val;
124 
125  if (center_bin_dist<static_cast<int>(HIST_N_DIS)) // this accounts for the "square" or "circle" shapes of the area to account for
126  {
127  hist2d(bin_int,center_bin_dist) +=1; // * density_circular_area;
128  }
129 #else
130  // Apply a "soft-histogram", so each pixel counts into several
131  // bins,
132  // weighted by a exponential function to model a Gaussian
133  // kernel
134  const int bin_int_low = max(
135  0, static_cast<int>(
136  ceil(
137  k_int2idx *
138  (pix_val -
139  STD_TIMES *
140  options.SpinImagesOptions.std_intensity))));
141  const int bin_int_hi = min(
142  static_cast<int>(HIST_N_INT - 1),
143  static_cast<int>(
144  ceil(
145  k_int2idx *
146  (pix_val +
147  STD_TIMES *
148  options.SpinImagesOptions.std_intensity))));
149 
150  // cout << "d: " << pix_dist << "v: " << (int)pix_val << "\t";
151 
152  if (center_bin_dist <
153  static_cast<int>(HIST_N_DIS)) // this accounts for the
154  // "square" or "circle"
155  // shapes of the area to
156  // account for
157  {
158  const int bin_dist_low =
159  max(0, center_bin_dist - kernel_size_dist);
160  const int bin_dist_hi =
161  min(static_cast<int>(HIST_N_DIS - 1),
162  center_bin_dist + kernel_size_dist);
163 
164  int bin_dist, bin_int;
165  float pix_dist_cur_dist =
166  pix_dist - bin_dist_low * k_idx2dis;
167 
168  for (bin_dist = bin_dist_low; bin_dist <= bin_dist_hi;
169  bin_dist++, pix_dist_cur_dist -= k_idx2dis)
170  {
171  float pix_val_cur_val =
172  pix_val - (bin_int_low * k_idx2int);
173 
174  for (bin_int = bin_int_low; bin_int <= bin_int_hi;
175  bin_int++, pix_val_cur_val -= k_idx2int)
176  {
177  // Gaussian kernel:
178  double v = _2var_dist * square(pix_dist_cur_dist) +
179  _2var_int * square(pix_val_cur_val);
180  // _2var_dist *
181  // square(pix_dist
182  //-
183  // bin_dist*k_idx2dis ) +
184  // _2var_int *
185  // square(pix_val-(bin_int*k_idx2int));
186 
187  hist2d.get_unsafe(bin_int, bin_dist) +=
188  exp(v); // * density_circular_area;
189  }
190  }
191  // hist2d(bin_int,bin_dist) *= ;
192  } // in range
193 #endif
194 
195  } // end py
196  } // end px
197 
198  // Normalize:
199  hist2d.normalize(0, 1); // [0,1]
200 
201 #if 0
202  { // Debug
203  static int n=0;
204  CMatrixDouble AA(hist2d);
205  AA.normalize(0,1);
206  CImage aux_img( AA );
207  aux_img.saveToFile( format("spin_feat_%04i.png",n) );
208  CImage aux_img2 = in_img;
209  aux_img2.drawCircle((*it)->x,(*it)->y,20,TColor(255,0,0));
210  aux_img2.saveToFile( format("spin_feat_%04i_map.png",n) );
211  n++;
212  }
213 #endif
214 
215  // Save the histogram as a vector:
216  unsigned idx = 0;
217  std::vector<float>& ptr_trg = (*it)->descriptors.SpinImg;
218  ptr_trg.resize(HIST_N_INT * HIST_N_DIS);
219 
220  for (unsigned i = 0; i < HIST_N_DIS; i++)
221  for (unsigned j = 0; j < HIST_N_INT; j++)
222  ptr_trg[idx++] = hist2d.get_unsafe(j, i);
223 
224  (*it)->descriptors.SpinImg_range_rows = HIST_N_DIS;
225 
226  } // end for each feature
227 
228  MRPT_END
229 }
void drawCircle(int x, int y, int radius, const mrpt::img::TColor &color=mrpt::img::TColor(255, 255, 255), unsigned int width=1) override
Draws a circle of a given radius.
Definition: CImage.cpp:1315
#define MRPT_START
Definition: exceptions.h:262
#define min(a, b)
TInternalFeatList::iterator iterator
Definition: CFeature.h:365
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:25
GLenum GLsizei n
Definition: glext.h:5074
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:892
STL namespace.
unsigned char uint8_t
Definition: rptypes.h:41
T square(const T x)
Inline function for the square of a number.
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
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
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
Classes for computer vision, detectors, features, etc.
Definition: CCamModel.h:20
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
Definition: CFeature.h:304
const GLdouble * v
Definition: glext.h:3678
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:906
const float R
#define MRPT_END
Definition: exceptions.h:266
bool saveToFile(const std::string &fileName, int jpeg_quality=95) const
Save the image to a file, whose format is determined from the extension (internally uses OpenCV)...
Definition: CImage.cpp:296
A RGB color - 8bit.
Definition: TColor.h:22
void internal_computeSpinImageDescriptors(const mrpt::img::CImage &in_img, CFeatureList &in_features) const
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:130
unsigned char * get_unsafe(unsigned int col, unsigned int row, unsigned int channel=0) const
Access to pixels without checking boundaries - Use normally the () operator better, which checks the coordinates.
Definition: CImage.cpp:491
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: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at lun oct 28 00:14:14 CET 2019