Main MRPT website > C++ reference for MRPT 1.5.7
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 /************************************************************************************************
23 * computeSpinImageDescriptors *
24 ************************************************************************************************/
26  const CImage &in_img,
27  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 images" as described
34  // in "A sparse texture representation using affine-invariant regions", S Lazebnik, C Schmid, J Ponce,
35  // 2003 IEEE Computer Society Conference on Computer Vision.
36 
37  const unsigned int HIST_N_INT = options.SpinImagesOptions.hist_size_intensity;
38  const unsigned int HIST_N_DIS = options.SpinImagesOptions.hist_size_distance;
39  const unsigned int R = options.SpinImagesOptions.radius;
40  const int img_w = static_cast<int>( in_img.getWidth() );
41  const int img_h = static_cast<int>( in_img.getHeight() );
42  const bool img_color = in_img.isColor();
43 
44  // constant for passing intensity [0,255] to histogram index [0,HIST_N_INT-1]:
45  const float k_int2idx = (HIST_N_INT-1) / 255.0f;
46  const float k_idx2int = 1.0f/k_int2idx;
47 
48  // constant for passing distances in pixels [0,R] to histogram index [0,HIST_N_DIS-1]:
49  const float k_dis2idx = (HIST_N_DIS-1) / static_cast<float>(R);
50  const float k_idx2dis = 1.0f/k_dis2idx;
51 
52  // The Gaussian kernel used below is approximated up to a given distance
53  // in pixels, given by 2 times the appropriate std. deviations:
54  const int STD_TIMES = 2;
55  const int kernel_size_dist = static_cast<int>( ceil(k_dis2idx * STD_TIMES * options.SpinImagesOptions.std_dist) );
56 
57  const float _2var_int = -1.0f/(2*square( options.SpinImagesOptions.std_intensity ));
58  const float _2var_dist = -1.0f/(2*square( options.SpinImagesOptions.std_dist ));
59 
60 
61  // Create the 2D histogram:
62  CMatrixDouble hist2d(HIST_N_INT,HIST_N_DIS);
63 
64  // Compute intensity-domain spin images
65  for (CFeatureList::iterator it=in_features.begin();it!=in_features.end();++it)
66  {
67  // Overwrite scale with the descriptor scale:
68  (*it)->scale = options.SpinImagesOptions.radius;
69 
70  // Reset histogram to zeros:
71  hist2d.zeros();
72 
73  // Define the ROI around the interest point which counts for the histogram:
74  int px0 = round( (*it)->x - R );
75  int px1 = round( (*it)->x + R );
76  int py0 = round( (*it)->y - R );
77  int py1 = round( (*it)->y + R );
78 
79  // Clip at img borders:
80  px0=max(0,px0);
81  px1=min(img_w-1,px1);
82  py0=max(0,py0);
83  py1=min(img_h-1,py1);
84 
85  uint8_t pix_val;
86  uint8_t *aux_pix_ptr;
87 
88  for (int px=px0;px<=px1;px++)
89  {
90  for (int py=py0;py<=py1;py++)
91  {
92  // get the pixel color [0,255]
93  if (!img_color)
94  pix_val = *in_img.get_unsafe(px,py,0);
95  else
96  {
97  aux_pix_ptr = in_img.get_unsafe(px,py,0);
98  pix_val = (aux_pix_ptr[0] + aux_pix_ptr[1] + aux_pix_ptr[2]) / 3;
99  }
100 
101  const float pix_dist = hypot( (*it)->x - px, (*it)->y - py );
102  const int center_bin_dist = k_dis2idx * pix_dist;
103 
104  // A factor to correct the histogram due to the existence of more pixels at larger radius:
105  // Obtained as Area = PI ( R1^2 - R2^2 ) for R1,R2 being pix_dist +- Delta/2
106  //const double density_circular_area = 1.0/ (M_2PI * (center_bin_dist+0.5) * square(k_idx2dis) );
107 
108 #if 0
109  // "normal" histogram
110  const int bin_int = k_int2idx * pix_val;
111 
112  if (center_bin_dist<static_cast<int>(HIST_N_DIS)) // this accounts for the "square" or "circle" shapes of the area to account for
113  {
114  hist2d(bin_int,center_bin_dist) +=1; // * density_circular_area;
115  }
116 #else
117  // Apply a "soft-histogram", so each pixel counts into several bins,
118  // weighted by a exponential function to model a Gaussian kernel
119  const int bin_int_low = max(0, static_cast<int>(ceil(k_int2idx * ( pix_val - STD_TIMES * options.SpinImagesOptions.std_intensity ))) );
120  const int bin_int_hi = min(static_cast<int>(HIST_N_INT-1), static_cast<int>(ceil(k_int2idx * ( pix_val + STD_TIMES * options.SpinImagesOptions.std_intensity ))));
121 
122  //cout << "d: " << pix_dist << "v: " << (int)pix_val << "\t";
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  const int bin_dist_low = max(0, center_bin_dist-kernel_size_dist);
127  const int bin_dist_hi = min(static_cast<int>(HIST_N_DIS-1), center_bin_dist+kernel_size_dist);
128 
129  int bin_dist, bin_int;
130  float pix_dist_cur_dist = pix_dist - bin_dist_low*k_idx2dis;
131 
132  for (bin_dist = bin_dist_low;bin_dist<=bin_dist_hi;bin_dist++, pix_dist_cur_dist-=k_idx2dis)
133  {
134  float pix_val_cur_val = pix_val-(bin_int_low*k_idx2int);
135 
136  for (bin_int=bin_int_low;bin_int<=bin_int_hi;bin_int++, pix_val_cur_val-=k_idx2int)
137  {
138  // Gaussian kernel:
139  double v = _2var_dist * square(pix_dist_cur_dist) + _2var_int * square(pix_val_cur_val);
140 // _2var_dist * square(pix_dist - bin_dist*k_idx2dis ) +
141 // _2var_int * square(pix_val-(bin_int*k_idx2int));
142 
143  hist2d.get_unsafe(bin_int,bin_dist) += exp(v); // * density_circular_area;
144  }
145  }
146  //hist2d(bin_int,bin_dist) *= ;
147  } // in range
148 #endif
149 
150  } // end py
151  } // end px
152 
153  // Normalize:
154  hist2d.normalize(0,1); // [0,1]
155 
156 #if 0
157  { // Debug
158  static int n=0;
159  CMatrixDouble AA(hist2d);
160  AA.normalize(0,1);
161  CImage aux_img( AA );
162  aux_img.saveToFile( format("spin_feat_%04i.png",n) );
163  CImage aux_img2 = in_img;
164  aux_img2.drawCircle((*it)->x,(*it)->y,20,TColor(255,0,0));
165  aux_img2.saveToFile( format("spin_feat_%04i_map.png",n) );
166  n++;
167  }
168 #endif
169 
170  // Save the histogram as a vector:
171  unsigned idx=0;
172  std::vector<float> &ptr_trg = (*it)->descriptors.SpinImg;
173  ptr_trg.resize( HIST_N_INT * HIST_N_DIS );
174 
175  for (unsigned i=0;i<HIST_N_DIS;i++)
176  for (unsigned j=0;j<HIST_N_INT;j++)
177  ptr_trg[idx++] = hist2d.get_unsafe(j,i);
178 
179  (*it)->descriptors.SpinImg_range_rows = HIST_N_DIS;
180 
181  } // end for each feature
182 
183  MRPT_END
184 }
185 
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
Definition: zip.h:16
#define min(a, b)
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:29
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:101
void drawCircle(int x, int y, int radius, const mrpt::utils::TColor &color=mrpt::utils::TColor(255, 255, 255), unsigned int width=1) MRPT_OVERRIDE
Draws a circle of a given radius.
Definition: CImage.cpp:1323
GLenum GLsizei n
Definition: glext.h:4618
STL namespace.
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:52
unsigned char uint8_t
Definition: rptypes.h:43
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
#define MRPT_END
A RGB color - 8bit.
Definition: TColor.h:26
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:21
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:211
#define MRPT_START
const GLdouble * v
Definition: glext.h:3603
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:26
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:299
TInternalFeatList::iterator iterator
Definition: CFeature.h:261
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
Definition: CImage.cpp:898
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
size_t getWidth() const MRPT_OVERRIDE
Returns the width of the image in pixels.
Definition: CImage.cpp:855
hist1d FAR * hist2d
Definition: jquant2.cpp:143
size_t getHeight() const MRPT_OVERRIDE
Returns the height of the image in pixels.
Definition: CImage.cpp:884



Page generated by Doxygen 1.8.14 for MRPT 1.5.7 Git: 5902e14cc Wed Apr 24 15:04:01 2019 +0200 at lun oct 28 01:39:17 CET 2019