Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ExampleEstimateFisheyePolynomial.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 /**
26  @example ExampleEstimateFisheyePolynomial.cpp
27  @relates PolynomialSolve, ProjectionParametersSpherical
28  @brief Example for estimating the polynomial of a fisheye camera
29  @ingroup g_examples
30  @author MIP
31 */
32 
33 // BIAS
34 #include <Geometry/ProjectionParametersSpherical.hh>
35 #include <Geometry/Projection.hh>
36 #include "Base/Math/Random.hh"
37 #include "MathAlgo/PolynomialSolve.hh"
38 
39 using namespace BIAS;
40 using namespace std;
41 
42 
43 int main(int argc, char *argv[]) {
44 
45  // test distortion or undistortion parametrization
46  bool testDistortion = true;
47  bool skipLinearMonom = !testDistortion;
48  Projection P;
49 
50  if (argc<2) {
51  cout<<"error, no xml file given."<<endl;
52  return -2;
53  }
54  if (P.Load(argv[1])!=0) {
55  cout<<"error, could not load xml."<<endl;
56  return -2;
57  }
58 
60  dynamic_cast<ProjectionParametersSpherical *>(P.GetParameters());
61  if (ppS == NULL) {
62  cout<<"error, no spherical parameters."<<endl;
63  return -2;
64  }
65  unsigned int width, height;
66  ppS->GetImageSize(width,height);
67  cout<<"maxcamangle of loaded projection is "<< ppS->GetMaxCamAngle()<<endl;
68 
69  int degree = 4;
70  std::vector<double> coefficients;
71  coefficients.resize(degree+1);
72 
73  cout<<endl<<endl<<endl<<"now estimating polynomial"<<endl;
74  if (testDistortion) {
75  cout<<"distortion function is used ..."<<endl;
76  ppS->EstimateDistortionPolynomial(coefficients, degree, skipLinearMonom);
77  } else {
78  cout<<"undistortion function is used ..."<<endl;
79  ppS->EstimateUndistortionPolynomial(coefficients, degree, skipLinearMonom);
80  }
81  cout<<"coefficients are ";
82  for (unsigned int i=0; i<coefficients.size(); i++) {
83  cout<<coefficients[i]<<" ";
84  }
85  cout<<endl;
86 
87  // generate new parameters and test if it is the same
89  S2.SetImageSize(width,height);
90  S2.SetRadius(ppS->GetRadius());
91  double px=0, py=0;
92  ppS->GetPrincipal(px,py);
93  S2.SetPrincipal(px,py);
94  S2.SetPose(ppS->GetPose());
95  //S2 = *ppS;
96 
97 
98  cout<<endl<<endl<<endl<<"now initing with polynomial"<<endl;
99 
100  // S2.InitAngleCorrFromPoly(1.57079633e+00,
101  // -3.01118447e+02,
102  // 0.00000000,
103  // 1.29706584e-03,
104  // -1.07072253e-06,
105  // 2.34508181e-09);
106 
108  coefficients,
109  !testDistortion);
110 
111 
112  cout<<endl<<endl<<endl<<"now estimating polynomial again "<<endl;
113 
114 
115  if (testDistortion) {
116  cout<<"distortion function is used ..."<<endl;
117  ppS->EstimateDistortionPolynomial(coefficients, degree, skipLinearMonom);
118  } else {
119  cout<<"undistortion function is used ..."<<endl;
120  ppS->EstimateUndistortionPolynomial(coefficients, degree, skipLinearMonom);
121  }
122  cout<<"coefficients are ";
123 
124  for (unsigned int i=0; i<coefficients.size(); i++) {
125  cout<<coefficients[i]<<" ";
126  }
127  cout<<endl;
128 
129  cout<<"generating some 3D points with original projection .."<<endl;
130 
131  Random R;
132  vector<HomgPoint3D> points3D;
133  vector<HomgPoint2D> points2D;
134  for (unsigned int i=0; i<20; i++) {
135  HomgPoint2D x(R.GetUniformDistributed(width/4, width*3/4),
136  R.GetUniformDistributed(width/4, width*3/4));
137  HomgPoint3D X = ppS->UnProjectToPoint(x, 1.0);
138  if (X.NormL2()>0.1) {
139  points2D.push_back(x);
140  points3D.push_back(X);
141  }
142  }
143 
144 
145 
146 
147  BIAS::Pose thePose(ppS->GetPose());
148  PolynomialSolve PS;
149  double averageError = 0;
150  for (unsigned int i=0; i<points3D.size(); i++) {
151 
152 
153  Vector3<double> pRay, pos;
154  S2.UnProjectLocal(S2.Project(points3D[i]), pos, pRay);
155  //cout<<"perfect ray is "<<pRay<<endl;
156 
157  //cout<<"3D point is "<<X<<endl;
158 
159  // transform into camera coordinate system
160  HomgPoint3D XCCS(thePose.GlobalToLocal(points3D[i]));
161  Vector3<double> ProjectionRay(XCCS[0], XCCS[1], XCCS[2]);
162  ProjectionRay.Normalize();
163 
164 
165 
166 
167 
168 
169  if (testDistortion) {
170 
171  // we have a distortion polynomial,
172  Vector3<double> rPhiTheta = ProjectionRay.CoordEuclideanToSphere();
173  if(Equal(rPhiTheta[0], 0.0)) {
174  BIASERR("sphere coordinate transform failed for ray "
175  << ProjectionRay);
176  }
177 
178  double radius = PS.EvaluatePolynomial(rPhiTheta[2], coefficients);
179  HomgPoint2D result(0,0);
180  result[0] = radius * cos(rPhiTheta[1]) + px;
181  result[1] = radius * sin(rPhiTheta[1]) + py;
182  cout<<"projects to "<<result<<", measured at "<<points2D[i]
183  <<" diff is "<<(result-points2D[i]).NormL2()<<endl;
184 
185  averageError += (result-points2D[i]).NormL2();
186 
187  result = S2.Project(points3D[i]);
188  cout<<"Reconstructed projects to "<<result<<", measured at "<<points2D[i]
189  <<" diff is "<<(result-points2D[i]).NormL2()<<endl;
190 
191  } else {
192  //cout<<"projection ray is "<<ProjectionRay<<endl;
193  Vector3<double> ImageRay(points2D[i][0]-px,
194  points2D[i][1]-py,
195  0);
196  double radius = sqrt(ImageRay[0]*ImageRay[0] + ImageRay[1]*ImageRay[1]);
197  ImageRay[2] = -1.0*PS.EvaluatePolynomial(radius, coefficients);
198 
199  //cout<<"image ray is "<<ImageRay<<endl;
200  ImageRay.Normalize();
201  // cout<<"image ray normalized is "<<ImageRay<<endl;
202  if (ImageRay.ScalarProduct(ProjectionRay)<0.0)
203  ImageRay *= -1.0;
204  cout<<"ray error for manual polynomial projection in degree: ";
205  averageError += acos(ImageRay.ScalarProduct(ProjectionRay))*180.0/M_PI;
206  cout<<acos(ImageRay.ScalarProduct(ProjectionRay))*180.0/M_PI
207  <<" degree"<<endl;
208  cout<<"ray error for reconstructed interpolator projection in degree: ";
209  cout<<acos(ImageRay.ScalarProduct(pRay))*180.0/M_PI<<" degree"<<endl;
210  }
211 
212  Vector3<double> p, dir;
213  ppS->UnProjectLocal(points2D[i], p, dir);
215  testpoint1 = ppS->ProjectLocal(dir),
216  testpoint2 = points2D[i];
217  testpoint1.Normalize();
218  testpoint2.Normalize();
219  cout<<"ray error (inconsistency) for original project/unproject: ";
220  cout<<acos(testpoint1.ScalarProduct(testpoint2))*180.0/M_PI
221  <<" degree"<<endl;
222 
223 
224  //for (unsigned int i=0; i<3; i++) {
225  //cout<< ImageRay[i] - ProjectionRay[i] <<" ";
226  //}
227  cout<<endl;
228  }
229  averageError /= points3D.size();
230  cout<<"Average angular error (manual) is "<<averageError <<endl;
231 
232 
233  return 0;
234 }
235 
236 
237 
238 
239 
240 
241 
242 
243 
244 
245 
246 
247 
248 
249 
250 
virtual void SetPrincipal(const double x, const double y)
Set principal point (in pixels relative to top left corner).
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
BIAS::Vector3< T > CoordEuclideanToSphere() const
coordinate transform.
Definition: Vector3.cpp:113
virtual int Load(const std::string &filename)
convenience wrapper which tries to read different formats
Definition: Projection.cpp:62
virtual int GetPrincipal(double &PrincipalX, double &PrincipalY) const
Get principal point (in pixels relative to top left corner).
virtual HomgPoint3D UnProjectToPoint(const HomgPoint2D &pos, double depth, bool IgnoreDistortion=false) const
calculates a 3D point in the global (not the rig) coordinate system, which belongs to the image posit...
void ScalarProduct(const Vector3< T > &argvec, T &result) const
scalar product (=inner product) of two vectors, storing the result in result
Definition: Vector3.hh:603
virtual void SetImageSize(const unsigned int w, const unsigned int h)
Set image dimensions (in pixels).
int EstimateUndistortionPolynomial(std::vector< double > &coefficients, const unsigned int degree=4, bool LinearMonomialIsZero=true)
Estimates undistortion polynomial mapping z coordinates to radius according to Scaramuzza&#39;s Matlab to...
double GetUniformDistributed(const double min, const double max)
on succesive calls return uniform distributed random variable between min and max ...
Definition: Random.hh:84
base class for solving polynomial equations
virtual HomgPoint2D ProjectLocal(const Vector3< double > &point, bool IgnoreDistortion=false) const
calculates the projection of a point in the local camera coordinate system to a pixel in the image pl...
virtual HomgPoint2D Project(const HomgPoint3D &X, bool IgnoreDistortion=false) const
calculates the projection of a point in the world coordinate system to a pixel in the image plane of ...
void SetRadius(const double r)
Set radius of spherical image in pixels.
virtual void SetPose(const BIAS::Pose pose)
Set pose from pose object.
Represents 3d pose transformations, parametrized as Euclidean translation and unit quaternion orienta...
Definition: Pose.hh:73
const ProjectionParametersBase * GetParameters(unsigned int cam=0) const
const parameter access function
Definition: Projection.hh:194
This class hides the underlying projection model, like projection matrix, spherical camera...
Definition: Projection.hh:70
int InitAngleCorrFromPoly(const double maxCamAngle, const double acCoeff0, const double acCoeff1, const double acCoeff2, const double acCoeff3, const double acCoeff4)
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
virtual int GetImageSize(unsigned int &Width, unsigned int &Height) const
Obtain image dimensions.
bool Equal(const T left, const T right, const T eps)
comparison function for floating point values See http://www.boost.org/libs/test/doc/components/test_...
double GetRadius() const
Return radius of spherical image in pixels.
int EstimateDistortionPolynomial(std::vector< double > &coefficients, const unsigned int degree=4, bool LinearMonomialIsZero=false)
Estimates distortion polynomial mapping angle theta to radius according to Scaramuzza&#39;s Matlab toolbo...
virtual const BIAS::Pose & GetPose() const
Return complete pose object.
double GetMaxCamAngle() const
Get maximal camera angle (in rad), i.e.
Vector3< T > & Normalize()
normalize this vector to length 1
Definition: Vector3.hh:663
class for producing random numbers from different distributions
Definition: Random.hh:51
virtual void UnProjectLocal(const HomgPoint2D &pos, Vector3< double > &origin, Vector3< double > &direction, bool IgnoreDistortion=false) const
calculates the viewing ray from the camera center (in the camera coordinate system) which belongs to ...