SLIP  1.4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DistortionCamera.hpp
Go to the documentation of this file.
1 /*
2  * Copyright(c):
3  * Signal Image and Communications (SIC) Department
4  * http://www.sic.sp2mi.univ-poitiers.fr/
5  * - University of Poitiers, France http://www.univ-poitiers.fr
6  * - XLIM Institute UMR CNRS 7252 http://www.xlim.fr/
7  *
8  * and
9  *
10  * D2 Fluid, Thermic and Combustion
11  * - University of Poitiers, France http://www.univ-poitiers.fr
12  * - PPRIME Institute - UPR CNRS 3346 http://www.pprime.fr
13  * - ISAE-ENSMA http://www.ensma.fr
14  *
15  * Contributor(s):
16  * The SLIP team,
17  * Benoit Tremblais <tremblais_AT_sic.univ-poitiers.fr>,
18  * Laurent David <laurent.david_AT_lea.univ-poitiers.fr>,
19  * Ludovic Chatellier <ludovic.chatellier_AT_univ-poitiers.fr>,
20  * Lionel Thomas <lionel.thomas_AT_univ-poitiers.fr>,
21  * Denis Arrivault <arrivault_AT_sic.univ-poitiers.fr>,
22  * Julien Dombre <julien.dombre_AT_univ-poitiers.fr>.
23  *
24  * Description:
25  * The Simple Library of Image Processing (SLIP) is a new image processing
26  * library. It is written in the C++ language following as much as possible
27  * the ISO/ANSI C++ standard. It is consequently compatible with any system
28  * satisfying the ANSI C++ complience. It works on different Unix , Linux ,
29  * Mircrosoft Windows and Mac OS X plateforms. SLIP is a research library that
30  * was created by the Signal, Image and Communications (SIC) departement of
31  * the XLIM, UMR 7252 CNRS Institute in collaboration with the Fluids, Thermic
32  * and Combustion departement of the P', UPR 3346 CNRS Institute of the
33  * University of Poitiers.
34  *
35  * The SLIP Library source code has been registered to the APP (French Agency
36  * for the Protection of Programs) by the University of Poitiers and CNRS,
37  * under registration number IDDN.FR.001.300034.000.S.P.2010.000.21000.
38 
39  * http://www.sic.sp2mi.univ-poitiers.fr/slip/
40  *
41  * This software is governed by the CeCILL-C license under French law and
42  * abiding by the rules of distribution of free software. You can use,
43  * modify and/ or redistribute the software under the terms of the CeCILL-C
44  * license as circulated by CEA, CNRS and INRIA at the following URL
45  * http://www.cecill.info.
46  * As a counterpart to the access to the source code and rights to copy,
47  * modify and redistribute granted by the license, users are provided only
48  * with a limited warranty and the software's author, the holder of the
49  * economic rights, and the successive licensors have only limited
50  * liability.
51  *
52  * In this respect, the user's attention is drawn to the risks associated
53  * with loading, using, modifying and/or developing or reproducing the
54  * software by the user in light of its specific status of free software,
55  * that may mean that it is complicated to manipulate, and that also
56  * therefore means that it is reserved for developers and experienced
57  * professionals having in-depth computer knowledge. Users are therefore
58  * encouraged to load and test the software's suitability as regards their
59  * requirements in conditions enabling the security of their systems and/or
60  * data to be ensured and, more generally, to use and operate it in the
61  * same conditions as regards security.
62  *
63  * The fact that you are presently reading this means that you have had
64  * knowledge of the CeCILL-C license and that you accept its terms.
65  */
66 
67 
75 #ifndef SLIP_DISTORTIONCAMERA_HPP
76 #define SLIP_DISTORTIONCAMERA_HPP
77 
78 #include <iostream>
79 #include <cassert>
80 #include "Point2d.hpp"
81 #include "Point3d.hpp"
82 #include "Matrix.hpp"
83 #include "io_tools.hpp"
84 
85 #include "CameraModel.hpp"
86 #include "camera_algo.hpp"
87 #include "levenberg_marquardt.hpp"
88 
89 #include <boost/serialization/access.hpp>
90 #include <boost/serialization/split_member.hpp>
91 #include <boost/serialization/version.hpp>
92 #include <boost/serialization/base_object.hpp>
93 
94 namespace slip
95 {
96  template <typename Type>
97  struct DistStruct
98  {
100  R1(0),
101  R2(0),
102  R3(0),
103  d1(0),
104  d2(0),
105  p1(0),
106  p2(0)
107  {
108  }
109 
111  R1(rhs.R1),
112  R2(rhs.R2),
113  R3(rhs.R3),
114  d1(rhs.d1),
115  d2(rhs.d2),
116  p1(rhs.p1),
117  p2(rhs.p2)
118  {}
119 
120  Type R1;
121  Type R2;
122  Type R3;
123  Type d1;
124  Type d2;
125  Type p1;
126  Type p2;
127 
128  private:
130  template<class Archive>
131  void save(Archive & ar, const unsigned int version) const
132  {
133  ar & R1 & R2 & R3 & d1 & d2 & p1 & p2;
134  }
135  template<class Archive>
136  void load(Archive & ar, const unsigned int version)
137  {
138  ar & R1 & R2 & R3 & d1 & d2 & p1 & p2;
139  }
140  BOOST_SERIALIZATION_SPLIT_MEMBER()
141  };
142 }
143 
144 namespace slip
145 {
146  template <typename Type>
148 
149  template <typename Type>
150  std::ostream& operator<<(std::ostream & out, const DistortionCamera<Type>& c);
151 
163  template <typename Type>
164  class DistortionCamera: public CameraModel<Type>
165  {
166  typedef DistortionCamera<Type> self;
168  public:
173 
178  calibration_matrix_(new slip::Matrix<Type>(3,4)),
179  calibration_distortions_(new slip::DistStruct<Type>()),
180  calibration_vector_(new slip::Vector<Type>(21))
181  {}
182 
188  calibration_matrix_(new slip::Matrix<Type>(3,4)),
189  calibration_distortions_(dist_struct),
190  calibration_vector_(new slip::Vector<Type>(21))
191  {}
192 
197  DistortionCamera(const self& rhs):
198  base(rhs),
199  calibration_matrix_(new slip::Matrix<Type>(*(rhs.calibration_matrix_))),
201  calibration_vector_(new slip::Vector<Type>(*(rhs.calibration_vector_)))
202  {}
203 
208  {
209  delete calibration_matrix_;
211  delete calibration_vector_;
212  }
220 
226  friend std::ostream& operator<< <>(std::ostream & out, const self& c);
240  void read(const std::string& file)
241  {
243  }
244 
252  void write(const std::string& file)
253  {
254  slip::write_ascii_1d<typename slip::Vector<Type>::iterator,Type>((*calibration_vector_).begin(),(*calibration_vector_).end(),file);
255  }
271  self& operator=(const self & rhs)
272  {
273  if(this != &rhs)
274  {
275  this->base::operator=(rhs);
276  if(this->calibration_matrix_ != 0)
277  {
278  delete this->calibration_matrix_;
279  }
280  this->calibration_matrix_ = new slip::Matrix<Type>(*(rhs.calibration_matrix_));
281 
282  if(this->calibration_distortions_ != 0)
283  {
284  delete this->calibration_distortions_;
285  }
286  this->calibration_distortions_ = new slip::DistStruct<Type>(*(rhs.calibration_distortions_));
287 
288  if(this->calibration_vector_ != 0)
289  {
290  delete this->calibration_vector_;
291  }
292  this->calibration_vector_ = new slip::Vector<Type>(*(rhs.calibration_vector_));
293  }
294  return *this;
295  }
309  {
310  //Type X=p[0]; Type Y=p[1]; Type Z=p[2];
311  Type den = ((*calibration_vector_)[6]*p[0] + (*calibration_vector_)[7]*p[1] + (*calibration_vector_)[8]*p[2] + (*calibration_vector_)[11]);
312  Type xr = ((*calibration_vector_)[0]*p[0] + (*calibration_vector_)[1]*p[1] + (*calibration_vector_)[2]*p[2] + (*calibration_vector_)[9])/den;
313  Type yr = ((*calibration_vector_)[3]*p[0] + (*calibration_vector_)[4]*p[1] + (*calibration_vector_)[5]*p[2] + (*calibration_vector_)[10])/den;
314  Type xr_p = xr-(*calibration_vector_)[12];
315  Type yr_p = yr-(*calibration_vector_)[13];
316  Type xr_p_2 = xr_p*xr_p;
317  Type yr_p_2 = yr_p*yr_p;
318  Type xr_p_yr_p = xr_p *yr_p;
319  Type rhoi2 = xr_p_2 + yr_p_2;
320  Type rhoi2_2 = rhoi2*rhoi2;
321  Type rhoi2_3 = rhoi2_2*rhoi2;
322  Type rad = ((*calibration_vector_)[14]*rhoi2 + (*calibration_vector_)[15]*rhoi2_2 + (*calibration_vector_)[16]*rhoi2_3);
323  Type u = xr
324  + xr_p*rad
325  + static_cast<Type>(2.0)*(*calibration_vector_)[17]*xr_p_yr_p
326  + (*calibration_vector_)[18]*(static_cast<Type>(3.0)*xr_p_2 + yr_p_2)
327  + (*calibration_vector_)[19]*rhoi2;
328  Type v = yr
329  + yr_p*rad
330  + static_cast<Type>(2.0)*(*calibration_vector_)[18]*xr_p*yr_p
331  + (*calibration_vector_)[17]*(static_cast<Type>(3.0)*yr_p_2 + xr_p_2)
332  + (*calibration_vector_)[20]*rhoi2;
333  return slip::Point2d<Type>(u,v);
334  }
335 
344  {
345  //data --> attributes
346  slip::Vector<Type> data(24);
348 
349  data(21) = p2[0];
350  data(22) = p2[1];
351  data(23) = z;
352  //TO OPTIMIZE
353  slip::funLM_bp<Type> h(data);
354 
355  slip:: Vector<Type> r(2);
356  slip:: Vector<Type> p(2);
357 
359  double chisq = 0.0;
360  slip::marquardt(h,dh,p,r,chisq);
361 
362  return slip::Point3d<Type>(p[0],p[1],z);
363  }
382  void compute(const slip::Matrix<Type>& P)
383  {
384  // 1.) get initial parameters
385  slip::Vector<Type> y(21,static_cast<Type>(0.0));
386  slip::Vector<Type> p9(9,static_cast<Type>(0.0));
387  slip::Matrix<Type> M(3,4);
388  typename slip::Vector<Type>::iterator y_begin = y.begin();
389  typename slip::Vector<Type>::iterator y_begin12 = y.begin() + 12;
390  typename slip::Vector<Type>::iterator y_end = y.end();
391  typename slip::Vector<Type>::iterator p9_begin = p9.begin();
392  typename slip::Vector<Type>::iterator p9_end = p9.end();
393  typename slip::Vector<Type>::iterator calibration_vector_begin = calibration_vector_->begin();
394  typename slip::Vector<Type>::iterator calibration_vector_begin12 = calibration_vector_->begin() + 12;
395 
396  getpars_DLT_norm(P,M);
397 
398  y(0)=M[0][0]; y(1)=M[0][1]; y(2)=M[0][2]; y(9)=M[0][3];
399  y(3)=M[1][0]; y(4)=M[1][1]; y(5)=M[1][2]; y(10)=M[1][3];
400  y(6)=M[2][0]; y(7)=M[2][1]; y(8)=M[2][2]; y(11)=M[2][3];
401  std::fill(y_begin12,y_end,static_cast<Type>(0.0));
402  // 2.) put all data in one vector
403  const std::size_t N = P.rows();
404  const std::size_t _5N = 5 * N;
405  const std::size_t _5N_p_19 = _5N+19;
406  const std::size_t _5N_p_7 = _5N+7;
407  slip::Vector<Type> adatad (_5N_p_19);
408  typename slip::Vector<Type>::iterator adatad_begin_5N_p_7 = adatad.begin()+_5N_p_7;
409  for(std::size_t i = 0; i<N; ++i)
410  {
411  adatad[i]=P[i][0]; // u_i
412  adatad[N+i]=P[i][1]; // v_i
413  adatad[2*N+i]=P[i][2]; // X_i
414  adatad[3*N+i]=P[i][3]; // Y_i
415  adatad[4*N+i]=P[i][4]; // Z_i
416  }
417 
418  adatad[_5N] = calibration_distortions_->R1;
419  adatad[_5N+1] = calibration_distortions_->R2;
420  adatad[_5N+2] = calibration_distortions_->R3;
421  adatad[_5N+3] = calibration_distortions_->d1;
422  adatad[_5N+4] = calibration_distortions_->d2;
423  adatad[_5N+5] = calibration_distortions_->p1;
424  adatad[_5N+6] = calibration_distortions_->p2;
425 
426  std::copy(y_begin,y_begin12,adatad_begin_5N_p_7);
427  //3.) Calcul param�tres
428  std::copy(y_begin12,y_end,p9_begin);
429  slip::Matrix<Type> Q(P);
430  // Q=P;
431  slip:: Vector<Type> r(2*N);
432  double chisq = 1000.0;
433  double new_chisq = 0.0;
434  bool done = 0;
435  int iter = 0;
436  double eps = 10e-5;
437 
438  //main loop
439  while(!done)
440  {
441  slip::funLM_DLT<Type> f(adatad);
442  // slip::LMDerivFunctor<funLM_DLT<Type>, Type> df(f,adatad.size(),p9.size());
443  slip::LMDerivFunctor<funLM_DLT<Type>, Type> df(f,r.size(),p9.size());
444 
445  slip::marquardt (f, df,p9, r,new_chisq);
446  std::copy(y_begin,y_begin12,calibration_vector_begin);
447  std::copy(p9_begin,p9_end,calibration_vector_begin12);
448  //estimation nouvelle matrice lin�aire
449  undistort(P,Q);
450  getpars_DLT_norm(Q,M);
451 
452  y(0)=M[0][0]; y(1)=M[0][1]; y(2)=M[0][2]; y(9)=M[0][3];
453  y(3)=M[1][0]; y(4)=M[1][1]; y(5)=M[1][2]; y(10)=M[1][3];
454  y(6)=M[2][0]; y(7)=M[2][1]; y(8)=M[2][2]; y(11)=M[2][3];
455 
456  std::copy(y_begin,y_begin12,adatad_begin_5N_p_7);
457 
458  if (std::abs(((chisq - new_chisq)/chisq)) < eps)
459  {
460  done = 1;
461  }
462  if (new_chisq>chisq)
463  {
464  done = 1;
465  }
466  if (iter>1000)
467  {
468  done = 1;
469  }
470  chisq=new_chisq;
471  iter++;
472  }
473  std::cout<<" Chisq final = "<<new_chisq<<" iteration = "<<iter<<std::endl;
474 
475  // 4.) Ecriture mod�le distorsion
476  std::copy(y_begin,y_begin12,calibration_vector_begin);
477  std::copy(p9_begin,p9_end,calibration_vector_begin12);
478  }
479 
480 
481 
499  {
500 
501  Q.resize(P.rows(),P.cols());
504  const std::size_t P_rows = P.rows();
505  for(std::size_t i = 0; i < P_rows; ++i)
506  {
507  pd[0] = P[i][0];
508  pd[1] = P[i][1];
510  Q[i][0] = pr[0];
511  Q[i][1] = pr[1];
512  Q[i][2] = P[i][2];
513  Q[i][3] = P[i][3];
514  Q[i][4] = P[i][4];
515  }
516  }
517 
524  {
525  Type U0=(*calibration_vector_)[12];Type V0=(*calibration_vector_)[13];
526  Type R1=(*calibration_vector_)[14];Type R2=(*calibration_vector_)[15];Type R3=(*calibration_vector_)[16];
527  Type D1=(*calibration_vector_)[17];Type D2=(*calibration_vector_)[18];
528  Type P1=(*calibration_vector_)[19];Type P2=(*calibration_vector_)[20];
529  Type x = p[0];
530  Type y = p[1];
531  Type x_p = x-U0;
532  Type y_p = y-V0;
533  Type x_p2 = x_p*x_p;
534  Type y_p2 = y_p*y_p;
535  Type two_x_p_y_p = static_cast<Type>(2.0)*x_p * y_p;
536  Type rhoi2 = x_p2 + y_p2;
537  Type rhoi2_2 = rhoi2*rhoi2;
538  Type rhoi2_3 = rhoi2_2*rhoi2;
539  Type rad=(R1*rhoi2 + R2*rhoi2_2 + R3*rhoi2_3);
540  Type xd = x + x_p*rad + D1*two_x_p_y_p + D2*(static_cast<Type>(3.0)*x_p2+y_p2) + P1*rhoi2;
541  Type yd = y + y_p*rad + D2*two_x_p_y_p + D1*(static_cast<Type>(3.0)*y_p2+x_p2) + P2*rhoi2;
542  pd[0]=xd;
543  pd[1]=yd;
544  }
545 
546 
549  //protected:
553 
554  private:
556  template<class Archive>
557  void save(Archive & ar, const unsigned int version) const
558  {
559  ar & boost::serialization::base_object<slip::CameraModel<Type> >(*this);
560  ar & calibration_matrix_;
562  ar & calibration_vector_;
563  }
564  template<class Archive>
565  void load(Archive & ar, const unsigned int version)
566  {
567  ar & boost::serialization::base_object<slip::CameraModel<Type> >(*this);
568  ar & calibration_matrix_;
570  ar & calibration_vector_;
571  }
572  BOOST_SERIALIZATION_SPLIT_MEMBER()
573  };
574 
575 }//slip::
576 
577 
578 namespace slip
579 {
580 
581  template<typename Type>
582  std::ostream& operator<<(std::ostream & out, const DistortionCamera<Type>& c)
583  {
584  out<<*c.calibration_matrix_<<std::endl;
585  out<<c.calibration_distortions_->R1<<std::endl;
586  out<<c.calibration_distortions_->R2<<std::endl;
587  out<<c.calibration_distortions_->R3<<std::endl;
588  out<<c.calibration_distortions_->d1<<std::endl;
589  out<<c.calibration_distortions_->d2<<std::endl;
590  out<<c.calibration_distortions_->p1<<std::endl;
591  out<<c.calibration_distortions_->p2<<std::endl;
592  out<<*c.calibration_vector_;
593  return out;
594  }
595 
596 
597 }//slip::
598 #endif //SLIP_DISTORTIONCAMERA_HPP
599 
Provides a class to modelize 3d points.
void read_ascii_1d(const std::string &file_path_name, Container1d &container)
Read a Container1d from an ASCII file.
Definition: io_tools.hpp:2518
self & operator=(const self &other)
Assign a CameraModel.
friend class boost::serialization::access
slip::Point2d< Type > invert_distortion_model(const slip::Point2d< Type > &pd, const slip::Vector< Type > &p)
Inverts distortion model using the Newton-method.
DistortionCamera(const self &rhs)
Constructs a copy of the DistortionCamera rhs.
iterator end()
Returns a read/write iterator that points one past the last element in the Vector. Iteration is done in ordinary element order.
Definition: Vector.hpp:1481
void distort(const slip::Point2d< Type > &p, slip::Point2d< Type > &pd)
Distorts a image point using the parameters of the distortion camera model.
Provides a camera algorithms.
void undistort(const slip::Matrix< Type > &P, slip::Matrix< Type > &Q)
undistorts a vector list using the parameters of the distortion camera model
size_type cols() const
Returns the number of columns (second dimension size) in the Matrix.
Definition: Matrix.hpp:3512
DistortionCamera(slip::DistStruct< Type > *dist_struct)
Constructor of DistortionCamera.
generic derivative functor
void write(const std::string &file)
Write a calibration matrix to an ASCII file.
HyperVolume< T > abs(const HyperVolume< T > &M)
~DistortionCamera()
Destructor of the DistortionCamera.
Function to compute the backprojection of the 3d world point corresponding to the backprojection of a...
void marquardt(Function &fun, DerivativeFunction &df, slip::Vector< Real > &par, slip::Vector< Real > &r, Real &calchi2, const int maxiter=10000, const Real eps=static_cast< Real >(1e-6))
Optimization of function using the Levenberg-Marquardt algorithm.
This is a point2d class, a specialized version of Point<CoordType,DIM> with DIM = 2...
Definition: Array2d.hpp:132
Define a DistortionCamera class.
slip::Point2d< Type > projection(const slip::Point3d< Type > &p)
Computes the projection of a 3d world point onto the image plane.
self & operator=(const self &rhs)
Assign a DistortionCamera.
pointer iterator
Definition: Vector.hpp:169
size_type size() const
Returns the number of elements in the Vector.
Definition: Vector.hpp:1743
Provides a simple implementation of the Levendberg-Marquardt algorithm.
void copy(_II first, _II last, _OI output_first)
Copy algorithm optimized for slip iterators.
Definition: copy_ext.hpp:177
DistortionCamera()
Default constructor of DistortionCamera.
slip::Vector< Type > * calibration_vector_
Numerical Vector class. This container statisfies the RandomAccessContainer concepts of the Standard ...
Definition: Vector.hpp:104
Provides an abstract class to model cameras.
slip::DistStruct< Type > * calibration_distortions_
Provides some input/ouput algorithms.
Numerical matrix class. This container statisfies the BidirectionnalContainer concepts of the STL...
slip::Matrix< Type > * calibration_matrix_
friend class boost::serialization::access
void read(const std::string &file)
Read a calibration matrix from an ASCII file.
size_type rows() const
Returns the number of rows (first dimension size) in the Matrix.
Definition: Matrix.hpp:3499
Function to compute the camera model of distortion using the Levenberg-Marquadt algorithm.
void resize(const size_type d1, const size_type d2, const T &val=T())
Resizes a Matrix.
Definition: Matrix.hpp:2779
void getpars_DLT_norm(const slip::Matrix< Type > &P, slip::Matrix< Type > &Mat)
Get calibration parameters using the DLT.
Provides a class to manipulate Numerical Matrix.
Provides a class to modelize 2d points.
void compute(const slip::Matrix< Type > &P)
Computes the parameters of the distortion camera model.
DistStruct(const DistStruct< Type > &rhs)
slip::Point3d< Type > backprojection(const slip::Point2d< Type > &p2, const Type &z)
Computes the 3d world point corresponding to the backprojection of an image point.
iterator begin()
Returns a read/write iterator that points to the first element in the Vector. Iteration is done in or...
Definition: Vector.hpp:1474
Define an abstract CameraModel class.
Definition: CameraModel.hpp:93
This is a point3d class, a specialized version of Point<CoordType,DIM> with DIM = 3...