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-2017, 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::system;
17 using namespace mrpt::utils;
18 using namespace mrpt::math;
19 using namespace std;
20 
21 /************************************************************************************************
22 * computeSpinImageDescriptors
23 **
24 ************************************************************************************************/
26  const CImage& in_img, CFeatureList& in_features) const
27 {
29 
30  ASSERT_(options.SpinImagesOptions.radius > 1)
31 
32  // This is a C++ implementation of the descriptor "Intensity-domain spin
33  // images" as described
34  // in "A sparse texture representation using affine-invariant regions", S
35  // Lazebnik, C Schmid, J Ponce,
36  // 2003 IEEE Computer Society Conference on Computer Vision.
37 
38  const unsigned int HIST_N_INT =
39  options.SpinImagesOptions.hist_size_intensity;
40  const unsigned int HIST_N_DIS =
41  options.SpinImagesOptions.hist_size_distance;
42  const unsigned int R = options.SpinImagesOptions.radius;
43  const int img_w = static_cast<int>(in_img.getWidth());
44  const int img_h = static_cast<int>(in_img.getHeight());
45  const bool img_color = in_img.isColor();
46 
47  // constant for passing intensity [0,255] to histogram index
48  // [0,HIST_N_INT-1]:
49  const float k_int2idx = (HIST_N_INT - 1) / 255.0f;
50  const float k_idx2int = 1.0f / k_int2idx;
51 
52  // constant for passing distances in pixels [0,R] to histogram index
53  // [0,HIST_N_DIS-1]:
54  const float k_dis2idx = (HIST_N_DIS - 1) / static_cast<float>(R);
55  const float k_idx2dis = 1.0f / k_dis2idx;
56 
57  // The Gaussian kernel used below is approximated up to a given distance
58  // in pixels, given by 2 times the appropriate std. deviations:
59  const int STD_TIMES = 2;
60  const int kernel_size_dist = static_cast<int>(
61  ceil(k_dis2idx * STD_TIMES * options.SpinImagesOptions.std_dist));
62 
63  const float _2var_int =
64  -1.0f / (2 * square(options.SpinImagesOptions.std_intensity));
65  const float _2var_dist =
66  -1.0f / (2 * square(options.SpinImagesOptions.std_dist));
67 
68  // Create the 2D histogram:
69  CMatrixDouble hist2d(HIST_N_INT, HIST_N_DIS);
70 
71  // Compute intensity-domain spin images
72  for (CFeatureList::iterator it = in_features.begin();
73  it != in_features.end(); ++it)
74  {
75  // Overwrite scale with the descriptor scale:
76  (*it)->scale = options.SpinImagesOptions.radius;
77 
78  // Reset histogram to zeros:
79  hist2d.zeros();
80 
81  // Define the ROI around the interest point which counts for the
82  // histogram:
83  int px0 = round((*it)->x - R);
84  int px1 = round((*it)->x + R);
85  int py0 = round((*it)->y - R);
86  int py1 = round((*it)->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  uint8_t pix_val;
95  uint8_t* aux_pix_ptr;
96 
97  for (int px = px0; px <= px1; px++)
98  {
99  for (int py = py0; py <= py1; py++)
100  {
101  // get the pixel color [0,255]
102  if (!img_color)
103  pix_val = *in_img.get_unsafe(px, py, 0);
104  else
105  {
106  aux_pix_ptr = in_img.get_unsafe(px, py, 0);
107  pix_val =
108  (aux_pix_ptr[0] + aux_pix_ptr[1] + aux_pix_ptr[2]) / 3;
109  }
110 
111  const float pix_dist = hypot((*it)->x - px, (*it)->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 more pixels at
115 // larger radius:
116 // Obtained as Area = PI ( R1^2 - R2^2 ) for R1,R2 being pix_dist +- Delta/2
117 // const double density_circular_area = 1.0/ (M_2PI * (center_bin_dist+0.5) *
118 // square(k_idx2dis) );
119 
120 #if 0
121  // "normal" histogram
122  const int bin_int = k_int2idx * pix_val;
123 
124  if (center_bin_dist<static_cast<int>(HIST_N_DIS)) // this accounts for the "square" or "circle" shapes of the area to account for
125  {
126  hist2d(bin_int,center_bin_dist) +=1; // * density_circular_area;
127  }
128 #else
129  // Apply a "soft-histogram", so each pixel counts into several
130  // bins,
131  // weighted by a exponential function to model a Gaussian
132  // kernel
133  const int bin_int_low = max(
134  0, static_cast<int>(
135  ceil(
136  k_int2idx *
137  (pix_val -
138  STD_TIMES *
139  options.SpinImagesOptions.std_intensity))));
140  const int bin_int_hi = min(
141  static_cast<int>(HIST_N_INT - 1),
142  static_cast<int>(
143  ceil(
144  k_int2idx *
145  (pix_val +
146  STD_TIMES *
147  options.SpinImagesOptions.std_intensity))));
148 
149  // cout << "d: " << pix_dist << "v: " << (int)pix_val << "\t";
150 
151  if (center_bin_dist <
152  static_cast<int>(HIST_N_DIS)) // this accounts for the
153  // "square" or "circle"
154  // shapes of the area to
155  // account for
156  {
157  const int bin_dist_low =
158  max(0, center_bin_dist - kernel_size_dist);
159  const int bin_dist_hi =
160  min(static_cast<int>(HIST_N_DIS - 1),
161  center_bin_dist + kernel_size_dist);
162 
163  int bin_dist, bin_int;
164  float pix_dist_cur_dist =
165  pix_dist - bin_dist_low * k_idx2dis;
166 
167  for (bin_dist = bin_dist_low; bin_dist <= bin_dist_hi;
168  bin_dist++, pix_dist_cur_dist -= k_idx2dis)
169  {
170  float pix_val_cur_val =
171  pix_val - (bin_int_low * k_idx2int);
172 
173  for (bin_int = bin_int_low; bin_int <= bin_int_hi;
174  bin_int++, pix_val_cur_val -= k_idx2int)
175  {
176  // Gaussian kernel:
177  double v = _2var_dist * square(pix_dist_cur_dist) +
178  _2var_int * square(pix_val_cur_val);
179  // _2var_dist *
180  // square(pix_dist
181  //-
182  // bin_dist*k_idx2dis ) +
183  // _2var_int *
184  // square(pix_val-(bin_int*k_idx2int));
185 
186  hist2d.get_unsafe(bin_int, bin_dist) +=
187  exp(v); // * density_circular_area;
188  }
189  }
190  // hist2d(bin_int,bin_dist) *= ;
191  } // in range
192 #endif
193 
194  } // end py
195  } // end px
196 
197  // Normalize:
198  hist2d.normalize(0, 1); // [0,1]
199 
200 #if 0
201  { // Debug
202  static int n=0;
203  CMatrixDouble AA(hist2d);
204  AA.normalize(0,1);
205  CImage aux_img( AA );
206  aux_img.saveToFile( format("spin_feat_%04i.png",n) );
207  CImage aux_img2 = in_img;
208  aux_img2.drawCircle((*it)->x,(*it)->y,20,TColor(255,0,0));
209  aux_img2.saveToFile( format("spin_feat_%04i_map.png",n) );
210  n++;
211  }
212 #endif
213 
214  // Save the histogram as a vector:
215  unsigned idx = 0;
216  std::vector<float>& ptr_trg = (*it)->descriptors.SpinImg;
217  ptr_trg.resize(HIST_N_INT * HIST_N_DIS);
218 
219  for (unsigned i = 0; i < HIST_N_DIS; i++)
220  for (unsigned j = 0; j < HIST_N_INT; j++)
221  ptr_trg[idx++] = hist2d.get_unsafe(j, i);
222 
223  (*it)->descriptors.SpinImg_range_rows = HIST_N_DIS;
224 
225  } // end for each feature
226 
227  MRPT_END
228 }
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
#define min(a, b)
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:30
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:118
GLenum GLsizei n
Definition: glext.h:5074
STL namespace.
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
unsigned char uint8_t
Definition: rptypes.h:41
void internal_computeSpinImageDescriptors(const mrpt::utils::CImage &in_img, CFeatureList &in_features) const
Compute the intensity-domain spin images descriptor of the provided features into the input image...
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
size_t getWidth() const override
Returns the width of the image in pixels.
Definition: CImage.cpp:869
#define MRPT_END
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:897
A RGB color - 8bit.
Definition: TColor.h:25
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
Classes for computer vision, detectors, features, etc.
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
Definition: CFeature.h:305
#define MRPT_START
const GLdouble * v
Definition: glext.h:3678
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
const float R
#define ASSERT_(f)
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:25
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:301
TInternalFeatList::iterator iterator
Definition: CFeature.h:366
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
Definition: CImage.cpp:911
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:496
void drawCircle(int x, int y, int radius, const mrpt::utils::TColor &color=mrpt::utils::TColor(255, 255, 255), unsigned int width=1) override
Draws a circle of a given radius.
Definition: CImage.cpp:1323
hist1d FAR * hist2d
Definition: jquant2.cpp:140



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019