PICCANTE  0.4
The hottest HDR imaging library!
iterative_closest_point_2D.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_COMPUTER_VISION_ITERATIVE_CLOSEST_POINT_2D_HPP
19 #define PIC_COMPUTER_VISION_ITERATIVE_CLOSEST_POINT_2D_HPP
20 
21 #include <vector>
22 #include <random>
23 #include <stdlib.h>
24 
25 #include "../base.hpp"
26 
27 #include "../util/math.hpp"
28 
29 #include "../features_matching/brief_descriptor.hpp"
30 
31 #include "../util/eigen_util.hpp"
32 
33 #ifndef PIC_DISABLE_EIGEN
34  #ifndef PIC_EIGEN_NOT_BUNDLED
35  #include "../externals/Eigen/Dense"
36  #include "../externals/Eigen/SVD"
37  #include "../externals/Eigen/Geometry"
38  #else
39  #include <Eigen/Dense>
40  #include <Eigen/SVD>
41  #include <Eigen/Geometry>
42  #endif
43 #endif
44 
45 namespace pic {
46 #ifndef PIC_DISABLE_EIGEN
47 
53 PIC_INLINE Eigen::Vector2f getMeanVector2f(std::vector< Eigen::Vector2f > &p)
54 {
55  auto c = p[0];
56  for(unsigned int i = 1; i < p.size(); i++) {
57  c += p[i];
58  }
59  c /= float(p.size());
60 
61  return c;
62 }
63 
69 PIC_INLINE Eigen::Vector2f getMedianVector2f(std::vector< Eigen::Vector2f > &p)
70 {
71  auto n = p.size();
72  float *x = new float[n];
73  float *y = new float[n];
74 
75  for(unsigned int i = 0; i < n; i++) {
76  x[i] = p[i][0];
77  y[i] = p[i][1];
78  }
79 
80  std::sort(x, x + n);
81  std::sort(y, y + n);
82 
83  Eigen::Vector2f med;
84 
85  med[0] = x[n >> 1];
86  med[1] = y[n >> 1];
87 
88 #ifdef PIC_DEBUG
89  printf("%f %f\n", med[0], med[1]);
90 #endif
91 
92  delete[] x;
93  delete[] y;
94  return med;
95 }
96 
98 {
99 public:
100  Eigen::Matrix2f R;
101  Eigen::Vector2f t;
102  float scale;
103 
105  {
106  R.setIdentity();
107 
108  t.setZero();
109 
110  scale = 1.0f;
111  }
112 
113  ICP2DTransform(float tx, float ty, float angle, float scale)
114  {
115  this->scale = scale;
116  t[0] = tx;
117  t[1] = ty;
118 
119  float cos_a = cosf(angle);
120  float sin_a = sinf(angle);
121 
122  R(0, 0) = cos_a;
123  R(0, 1) = -sin_a;
124  R(1, 0) = sin_a;
125  R(1, 1) = cos_a;
126  }
127 
128  void print()
129  {
130  printf("R:\n %f %f\n %f %f\n", R(0,0), R(0,1), R(1,0), R(1,1));
131 
132  printf("T: %f %f\n", t[0], t[1]);
133 
134  printf("S: %f\n\n", scale);
135  }
136 
137  void apply(std::vector< Eigen::Vector2f > &points) {
138  //apply transform
139  for(unsigned int i = 0; i < points.size(); i++) {
140  Eigen::Vector2f tmp = points[i];
141  points[i] = ((R * tmp) + t) * scale;
142  }
143  }
144 
145  void apply(std::vector< Eigen::Vector2f > &points,
146  std::vector< Eigen::Vector2f > &out) {
147  //apply transform
148  for(unsigned int i = 0; i < points.size(); i++) {
149  Eigen::Vector2f tmp = ((R * points[i]) + t) * scale;
150  out.push_back(tmp);
151  }
152  }
153 
154  //
155  //
156  //
157 
158  void applyC(std::vector< Eigen::Vector2f > &points) {
159 
160  //compute centroid to points
161  Eigen::Vector2f c = getMeanVector2f(points);
162  auto shift = c + t;
163 
164  //apply transform
165  for(unsigned int i = 0; i < points.size(); i++) {
166  Eigen::Vector2f tmp = points[i] - c;
167  points[i] = (R * tmp) * scale + shift;
168  }
169  }
170 
171  void applyC(std::vector< Eigen::Vector2f > &points,
172  std::vector< Eigen::Vector2f > &out) {
173 
174  //compute centroid to points
175  Eigen::Vector2f c = getMeanVector2f(points);
176  auto shift = c + t;
177 
178  //apply transform
179  for(unsigned int i = 0; i < points.size(); i++) {
180  Eigen::Vector2f tmp = points[i] - c;
181  Eigen::Vector2f tmp2 = (R * tmp) * scale + shift;
182  out.push_back(tmp2);
183  }
184  }
185 };
186 
197  std::vector< Eigen::Vector2f > &p1,
198  std::vector< unsigned int *> &p0_descs,
199  std::vector< unsigned int *> &p1_descs,
200  int size_descs,
201  int *ind = NULL)
202 {
203  ICP2DTransform ret;
204 
205  if(p0.size() < 2 || p1.size() < 2) {
206  return ret;
207  }
208 
209  bool bFlag = false;
210  if(ind == NULL) {
211  ind = new int[p1.size()];
212  bFlag = true;
213  }
214 
215  //compute c0
216  Eigen::Vector2f c1 = getMeanVector2f(p1);
217 
218  //compute c1
219  Eigen::Vector2f c0;
220  c0.setZero();
221  int n = 0;
222 
223 #ifdef PIC_DEBUG
224  printf("Size: %d\n", size_descs);
225 #endif
226 
227  for(int i = 0; i < p1.size(); i++) {
228  auto p_i = p1[i];
229 
230  float d_min = FLT_MAX;
231  int index = -1;
232  for(int j = 0; j < p0.size(); j++) {
233  auto delta_ij = p_i - p0[j];
234  float d_tmp = delta_ij.norm();
235 
236  int value = BRIEFDescriptor::match(p0_descs[j], p1_descs[i], size_descs);
237  d_tmp += float(size_descs * 32) - float(value);
238 
239  if(d_tmp < d_min) {
240  d_min = d_tmp;
241  index = j;
242  }
243 
244  }
245 
246  if(index > -1) {
247  ind[i] = index;
248  c0 += p0[index];
249  n++;
250  }
251  }
252  c0 /= float(n);
253 
254 
255  //compute R
256  Eigen::Matrix2f H;
257  H.setZero();
258 
259  for(unsigned int i = 0; i < p1.size(); i++) {
260  int j = ind[i];
261 
262  auto t0 = p0[j] - c0;
263  auto t1 = p1[i] - c1;
264 
265  Eigen::RowVector2f t1r = t1;
266  Eigen::Matrix2f tmp = t0 * t1r;
267 
268 /* tmp(0, 0) = t0(0) * t1(0);
269  tmp(0, 1) = t0(0) * t1(1);
270  tmp(1, 0) = t0(1) * t1(0);
271  tmp(1, 1) = t0(1) * t1(1);*/
272  H += tmp;
273  }
274 
275  //SVD decomposition
276  Eigen::JacobiSVD< Eigen::Matrix2f > svd(H, Eigen::ComputeFullV | Eigen::ComputeFullU);
277  Eigen::Matrix2f U = svd.matrixU();
278  Eigen::Matrix2f V = svd.matrixV();
279 
280  Eigen::Matrix2f U_t = U.transpose();
281  Eigen::Matrix2f R = V * U_t;
282 
283  if(R.determinant() < 0.0f) {
284  for(unsigned int i = 0; i < V.rows(); i++) {
285  V(i, 1) = -V(i, 1);
286  }
287 
288  R = V * U_t;
289  }
290 
291  ret.R = R;
292  ret.t = c0 - (ret.R * c1);
293 
294  if(bFlag) {
295  delete[] ind;
296  }
297 
298  return ret;
299 }
300 
307 PIC_INLINE float getErrorPointsList(std::vector< Eigen::Vector2f > &p0,
308  std::vector< Eigen::Vector2f > &p1)
309 {
310  float err = 0.0f;
311  for(unsigned int i = 0; i < p0.size(); i++) {
312  auto p_i = p0[i];
313 
314  float tmp_err = FLT_MAX;
315  for(unsigned int j = 0; j < p1.size(); j++) {
316  auto delta_ij = p_i - p1[j];
317  float dist = delta_ij.norm();
318 
319  if(dist < tmp_err) {
320  tmp_err = dist;
321  }
322  }
323 
324  err += tmp_err;
325  }
326 
327  return err / float(p0.size());
328 }
329 
339 PIC_INLINE void iterativeClosestPoints2D(std::vector<Eigen::Vector2f> &points_pattern,
340  std::vector<Eigen::Vector2f> &points,
341  std::vector< unsigned int *> &points_pattern_descs,
342  std::vector< unsigned int *> &points_descs,
343  int size_descs,
344  int maxIterations = 1000)
345 {
346  ICP2DTransform t_init;
347  t_init.t = getMedianVector2f(points) - getMeanVector2f(points_pattern);
348  t_init.apply(points_pattern);
349 
350  float err = getErrorPointsList(points_pattern, points);;
351  float prev_err = 1e32f;
352  int iter = 0;
353  while(iter < maxIterations) {
354  prev_err = err;
355  ICP2DTransform t = estimateRotatioMatrixAndTranslation(points, points_pattern,
356  points_descs, points_pattern_descs,
357  size_descs);
358 
359 #ifdef PIC_DEBUG
360  t.print();
361 #endif
362 
363 // std::vector< Eigen::Vector2f > points_pattern_tmp;
364  t.apply(points_pattern);
365 
366  err = getErrorPointsList(points_pattern, points);
367 
368  /*
369  if(err < prev_err) {
370  points_pattern.clear();
371  std::copy(points_pattern_tmp.begin(), points_pattern_tmp.end(),
372  std::back_inserter(points_pattern));
373  } else {
374  iter = maxIterations;
375  }
376  */
377 
378  #ifdef PIC_DEBUG
379  printf("Error: %f %f\n", err, prev_err);
380  #endif
381 
382  iter++;
383  }
384 }
385 
386 #endif
387 } // end namespace pic
388 
389 #endif // PIC_COMPUTER_VISION_ITERATIVE_CLOSEST_POINT_2D_HPP
ICP2DTransform()
Definition: iterative_closest_point_2D.hpp:104
PIC_INLINE float getErrorPointsList(std::vector< Eigen::Vector2f > &p0, std::vector< Eigen::Vector2f > &p1)
getErrorPointsList
Definition: iterative_closest_point_2D.hpp:307
float scale
Definition: iterative_closest_point_2D.hpp:102
void print()
Definition: iterative_closest_point_2D.hpp:128
PIC_INLINE ICP2DTransform estimateRotatioMatrixAndTranslation(std::vector< Eigen::Vector2f > &p0, std::vector< Eigen::Vector2f > &p1, std::vector< unsigned int *> &p0_descs, std::vector< unsigned int *> &p1_descs, int size_descs, int *ind=NULL)
estimateRotatioMatrixAndTranslation
Definition: iterative_closest_point_2D.hpp:196
void apply(std::vector< Eigen::Vector2f > &points, std::vector< Eigen::Vector2f > &out)
Definition: iterative_closest_point_2D.hpp:145
void applyC(std::vector< Eigen::Vector2f > &points)
Definition: iterative_closest_point_2D.hpp:158
void apply(std::vector< Eigen::Vector2f > &points)
Definition: iterative_closest_point_2D.hpp:137
#define PIC_INLINE
Definition: base.hpp:33
static uint match(uint *fv0, uint *fv1, uint nfv)
match matches two descriptors. Note: Higher scores means better matching.
Definition: brief_descriptor.hpp:255
PIC_INLINE Eigen::Vector2f getMedianVector2f(std::vector< Eigen::Vector2f > &p)
getMedianVector2f
Definition: iterative_closest_point_2D.hpp:69
PIC_INLINE Eigen::Vector2f getMeanVector2f(std::vector< Eigen::Vector2f > &p)
getMean
Definition: iterative_closest_point_2D.hpp:53
ICP2DTransform(float tx, float ty, float angle, float scale)
Definition: iterative_closest_point_2D.hpp:113
Definition: bilateral_separation.hpp:25
PIC_INLINE void iterativeClosestPoints2D(std::vector< Eigen::Vector2f > &points_pattern, std::vector< Eigen::Vector2f > &points, std::vector< unsigned int *> &points_pattern_descs, std::vector< unsigned int *> &points_descs, int size_descs, int maxIterations=1000)
iterativeClosestPoints2D
Definition: iterative_closest_point_2D.hpp:339
Definition: iterative_closest_point_2D.hpp:97
Eigen::Vector2f t
Definition: iterative_closest_point_2D.hpp:101
void applyC(std::vector< Eigen::Vector2f > &points, std::vector< Eigen::Vector2f > &out)
Definition: iterative_closest_point_2D.hpp:171
Eigen::Matrix2f R
Definition: iterative_closest_point_2D.hpp:100