Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ProjectionParametersSpherical.hh
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 #ifndef __BIAS_ProjectionParametersSpherical_hh__
27 #define __BIAS_ProjectionParametersSpherical_hh__
28 #include "bias_config.h"
29 
30 #include <Base/Common/BIASpragmaStart.hh>
31 #include <Geometry/ProjectionParametersBase.hh>
32 #include <Geometry/ProjectionParametersPerspective.hh>
33 #include <MathAlgo/Interpolator.hh>
34 #include <Base/ImageUtils/BresenhamCircle.hh>
35 
36 namespace BIAS {
37 
38  /** @class ProjectionParametersSpherical
39  * @ingroup g_geometry
40  @brief camera parameters which define the mapping between rays in the
41  camera coordinate system and pixels in the image as well as external pose
42  @author koeser/evers/streckel
43  */
44  class BIASGeometry_EXPORT ProjectionParametersSpherical:
46  public:
47 
48  ProjectionParametersSpherical(const unsigned int width = 0,
49  const unsigned int height = 0)
50  : ProjectionParametersBase(width, height)
51  {
52  radius_=0;
53  MaxCamAngle_=0;
54  interpolatorInit_ = false;
55  };
56 
57  ProjectionParametersSpherical(const double radius,
58  const double maxAngle,
59  const unsigned int width,
60  const unsigned int height)
61  : ProjectionParametersBase(width, height)
62  {
63  radius_=radius;
64  MaxCamAngle_=maxAngle;
65  interpolatorInit_ = false;
66  }
67 
69  *this = P;
70  }
71 
74  {
76  radius_ = P.radius_;
77  MaxCamAngle_ = P.MaxCamAngle_;
78  interpolatorAngle_ = P.interpolatorAngle_;
79  interpolatorAngleBack_ = P.interpolatorAngleBack_;
80  interpolatorInit_ = P.interpolatorInit_;
81  acCoeff_ = P.acCoeff_;
82  return *this;
83  }
84 
86 
87  /** @brief call this to start a run at the outer boundary of an image.
88  *
89  * You get the first boundary position in it, e.g. (0,0) for a perspective
90  * image. Feed this into GetNextBorderPixel to get the next position.
91  * Special implmentation here, because we need to run around the FOV
92  * circle. NOT YET IMPLEMENTED, PLEASE DO !
93  */
94  virtual void GetFirstBorderPixel(PixelIterator& it);
95 
96  /** @brief call this iteratively to run at the outer boundary of an image.
97  *
98  * All returned coordinates must have valid local rays in the camera
99  * coordinate system (e.g. in fisheye cams, we run at the fov circle) and
100  * must be in the image. Two subsequent coordinates must not be more
101  * distant than 1 pixel. NOT YET IMPLEMENTED, PLEASE DO !
102  * @param it must be initialized by GetFirstBorderPixel
103  * @return false if the returned position closes the loop around the image
104  */
105  virtual bool GetNextBorderPixel(PixelIterator& it);
106 
107 
108  virtual const bool
109  DoIntrinsicsDiffer(const ProjectionParametersBase* p) const;
110 
111  virtual bool Distort(BIAS::HomgPoint2D& point2d) const;
112 
113  virtual bool Undistort(BIAS::HomgPoint2D& point2d) const;
114 
115 
116 
117  bool DoesPointProjectIntoImageLocal(const BIAS::Vector3<double>& localX,
118  HomgPoint2D& x,
119  bool IgnoreDistortion = false) const;
120 
121  /** @brief calculates the projection of a point in the local camera
122  coordinate system to a pixel in the image plane of the camera. The
123  only case when this function may not compute the 2d point is when the
124  camera center and the 3d point coincide. This case is indicated
125  by a return value of (0, 0, 0). In all other cases, a 2d point must be
126  computed, *particularily* when the 3d point is behind the camera
127  or when the resulting 2d point is at infinity.*/
129  bool IgnoreDistortion = false) const {
130  HomgPoint2D retVal_hom2D;
131  ProjectionParametersSpherical::ProjectLocal(point, retVal_hom2D, IgnoreDistortion);
132  return retVal_hom2D;
133  }
134 
135  /** @brief calculates the projection of a point in the local camera
136  coordinate system to a pixel in the image plane of the camera. The
137  only case when this function may not compute the 2d point is when the
138  camera center and the 3d point coincide. This case is indicated
139  by a return value of zero. In all other cases, a 2d point must be
140  computed, *particularily* when the 3d point is behind the camera
141  or when the resulting 2d point is at infinity.
142 
143  In the simplest case perspective pinhole projection x = K * point
144  where point is transformed of X using point = (R^T | -R^T C) X
145  @author woelk 08/2008 (c) www.vision-n.de */
146  virtual int ProjectLocal(const Vector3<double>& point, HomgPoint2D &p2d,
147  bool IgnoreDistortion = false) const;
148 
149  /** @brief map points from image onto unit diameter image plane in 3D.
150  * Chosen is the spherical image plane with radius of one from the
151  * image center.
152  */
153  HomgPoint3D UnProjectToImagePlane(const HomgPoint2D& pos,
154  const double& depth = 1.0,
155  bool IgnoreDistortion = false) const;
156 
157 
158  /** @brief calculates the viewing ray from the camera center (in the
159  camera coordinate system) which belongs to the image position pos
160  e.g. (0,0,1) means optical axis
161  */
162  virtual void
163  UnProjectLocal(const HomgPoint2D& pos, Vector3<double>& origin,
164  Vector3<double>& direction, bool IgnoreDistortion = false) const;
165 
166  /** @brief covariant virtual copy constructor for use in Projection */
168  return new ProjectionParametersSpherical(*this);
169  }
170 
171  /** @brief Return radius of spherical image in pixels. */
172  inline double GetRadius() const {
173  return radius_;
174  }
175 
176  /** @brief Set radius of spherical image in pixels. */
177  inline void SetRadius(const double r) {
178  radius_ = r;
179  }
180 
181  /** @brief Get maximal camera angle (in rad), i.e. azimuth angle of rays
182  corresponding to the outer rim of the image. */
183  inline double GetMaxCamAngle() const {
184  return MaxCamAngle_;
185  }
186 
187  /** @brief Set maximal camera angle (in rad), i.e. azimuth angle of rays
188  corresponding to the outer rim of the image.
189  @param[in] maxCamAngle New maximal camera angle to set (in rad)
190  @attention If undistortion polynomial is set, it will be recalculated
191  with default sampling. Use RecalculateUndistortion instead
192  if you want to reset undistortion and max. camera angle
193  by yourself.
194  */
195  void SetMaxCamAngle(const double maxCamAngle);
196 
197  /** @brief Recalculate undistortion polynomial for new maximal camera angle.
198  @param[in] maxCamAngle New maximal camera angle to set (in rad)
199  @attention If new max. camera angle is larger than former, the
200  undistortion polynomial is extrapolated linearly beyond the
201  former range which may result in strange behaviour!
202  */
203  void RecalculateUndistortion(const double maxCamAngle);
204 
205  /** @brief Set undistortion polynomial from corresponding undistorted and
206  distorted azimuth angles (in rad) and image radius (in pixels).
207  @param[in] undistAngles Vector of undistorted azimuth angles (in rad)
208  @param[in] distAngles Vector of corresponding distorted angles
209  @param[in] radius Radius of spherical image to set (in pixels)
210  */
211  int SetUndistortion(const std::vector<double>& undistAngles,
212  const std::vector<double>& distAngles,
213  const double radius);
214 
215  /** @deprecated Use vector interface for #InitAngleCorrFromPoly! */
216  inline int InitAngleCorrFromPoly(const double maxCamAngle, const double acCoeff0,
217  const double acCoeff1, const double acCoeff2,
218  const double acCoeff3, const double acCoeff4)
219  {
220  std::vector<double> coefficients;
221  coefficients.reserve(5);
222  coefficients.push_back(acCoeff0);
223  coefficients.push_back(acCoeff1);
224  coefficients.push_back(acCoeff2);
225  coefficients.push_back(acCoeff3);
226  coefficients.push_back(acCoeff4);
227  return InitAngleCorrFromPoly(maxCamAngle, coefficients);
228  }
229 
230  /** @brief Set undistortion polynomial from from polynomial coefficients
231  of undistortion (mapping radius to z coordinate) or distortion
232  (mapping theta to radius) function.
233  @param[in] maxCamAngle Maximal azimuth angle corresponding to the
234  outer rim of the spherical image
235  @param[in] coefficients Vector of polynomial coefficients to
236  estimate the undistortion polynomial from
237  @param[in] mapsRadiusToZ Specifies if the given polynomial coefficients
238  describe the undistortion (mapping radius to
239  z cooordinate), or distortion (mapping theta
240  to radius).
241  */
242  int InitAngleCorrFromPoly(const double maxCamAngle,
243  const std::vector<double>& coefficients,
244  const bool mapsRadiusToZ = true);
245 
246  /** @brief Adapt internal parameters to resampled image.
247  @param ratio 2.0 = downsample by 2, 0.5 = upsample by 2
248  @param offset Offset for principal point (applied before down/upsampling!)
249  \attention Delivers only correct results if ratio is chosen
250  to rescale image size to integral image dimensions
251  in both directions. Image size is rounded!
252  */
253  virtual void Rescale(double ratio, const double offset = 0.0) {
254  ProjectionParametersBase::Rescale(ratio, offset);
255  radius_ /= ratio;
256  }
257 
258  virtual void Rescale(unsigned int width, unsigned int height){
259  unsigned int oldwidth = width_;
260  ProjectionParametersBase::Rescale(width, height);
261  radius_ /= ((double)oldwidth/(double)width_);
262  }
263 
264  virtual double ViewDifference(const ProjectionParametersBase* pPPB) const;
265 
266  /** @brief Returns a fake KMatrix for the fisheye camera.
267 
268  Uses MaxAngle_ to limit maxangle, then calls PPB::GetFakeK.
269  The FoV of the KMatrix is specified by maxangle (PI*80/180 for 160deg)
270  or the max fisheye angle, if this is <160deg.
271  @param resolution The resolution parameter influences the
272  Resolution of the perspective image that is represented by the camera.
273  0 - The perspective image has the same size as the fisheye image
274  1 - The perspective image has the same resolution as the fisheye
275  image in the center (highest resolution)
276  2 - The perspective image has the same resolution as the fisheye
277  image near the border (lowest resolution)
278  @param imgsize returns the image size
279  @param maxangle maximum theta in rad, e.g. (PI*80/180 for 160deg fov)
280  @author streckel 05/2006
281  */
282  virtual BIAS::KMatrix GetFakeKMatrix(double& imgsize, int resolution=0,
283  const double& maxangle = 1.4) const;
284 
285  /** @brief stupid reimplementation since this class does not inherit
286  function from base class (gcc) */
287  virtual BIAS::KMatrix GetFakeKMatrix(int resolution=0,
288  const double& maxangle = 1.4) const {
289  return ProjectionParametersBase::GetFakeKMatrix(resolution, maxangle);
290  }
291 
292  /** Calculates perspective camera with specified viewing angle and
293  * optical axis aligned with the optical ray corresponding to viewCenter
294  * in spherical camera.
295  * @param viewCenter pixel position in spherical image that is the
296  * center of the perspective cutout.
297  * @param perspHalfViewingAngle half field of view of the cutout in Degree
298  * @pp returning cutout parameters
299  * \returns false if perspective cut out could not be calculated.
300  * @author streckel 08/2006
301  */
302  bool GetPerspectiveCutOutParameters(const BIAS::HomgPoint2D& viewCenter,
303  const double perspHalfViewingAngleDEG,
305  const;
306 
307  /** @brief calculates a 3D point in
308  a local camera coordinate system specified by camSystem, which
309  belongs to the image position pos in cam with distance depth to the
310  camera center cam. Overload to habe return value (0,0,0)
311  for undefined or out of image radius pixels.
312  @author streckel */
313  virtual Vector3<double> UnProjectToPointLocal(const HomgPoint2D& pos,
314  const double& depth,
315  bool IgnoreDistortion = false) const;
316 
317 
318  /** @brief Estimates undistortion polynomial mapping z coordinates to
319  radius according to Scaramuzza's Matlab toolbox.
320 
321  Scaramuzza's undistortion polynomial is a function z(radius) which
322  typically has a local extremum at radius = 0 and therefore can not
323  have a linear monomial.
324  @author koeser 04/2007
325  */
326  int EstimateUndistortionPolynomial(std::vector<double>& coefficients,
327  const unsigned int degree = 4,
328  bool LinearMonomialIsZero = true);
329 
330  /** @brief Estimates distortion polynomial mapping angle theta to radius
331  according to Scaramuzza's Matlab toolbox.
332 
333  Scaramuzza's distortion polynomial is a function radius(theta) which
334  is usually close to linear for fisheye cameras and SHOULD therefore
335  have a linear monomial.
336  @author koeser 04/2007
337  */
338  int EstimateDistortionPolynomial(std::vector<double>& coefficients,
339  const unsigned int degree = 4,
340  bool LinearMonomialIsZero = false);
341 
342  /** @brief Returns polynomial coefficients of angle correction polynomial
343  (aka undistortion polynomial) mapping distorted to undistorted
344  azimuth angles.
345  @param[out] coeffs Returns coefficients of undistortion polynomial
346  */
347  inline void GetAngleCorrCoefficients(std::vector<double> &coeffs) const {
348  coeffs.clear();
349  for (unsigned i = 0; i < acCoeff_.size(); i++)
350  coeffs.push_back(acCoeff_[i]);
351  }
352 
353  /** @brief Returns samples for undistorted and distorted angles from
354  which the angle correction polynomial (aka undistortion
355  polynomial) has been interpolated.
356  @param[out] undistAngles Returns knot points of distortion interpolator,
357  i.e. samples of undistorted azimuth angles
358  @param[out] distAngles Returns control points of distortion interpolator,
359  i.e. samples of distorted azimuth angles
360  */
361  inline void GetAngleCorr(std::vector<double>& undistAngles,
362  std::vector<double>& distAngles) const {
363  interpolatorAngle_.GetKnotPoints(undistAngles);
364  interpolatorAngle_.GetControlPoints(distAngles);
365  }
366 
367  /** @brief Returns samples for distorted and unddistorted angles from
368  which the angleback correction polynomial (aka distortion
369  polynomial) has been interpolated.
370  @param[out] distAngles Returns knot points of undistortion interpolator,
371  i.e. samples of distorted azimuth angles
372  @param[out] undistAngles Returns control points of undistortion interpolator,
373  i.e. samples of undistorted azimuth angles
374  */
375  inline void GetAngleCorrBack(std::vector<double>& distAngles,
376  std::vector<double>& undistAngles) const{
377  interpolatorAngleBack_.GetKnotPoints(distAngles);
378  interpolatorAngleBack_.GetControlPoints(undistAngles);
379  }
380 
381 
382 #ifdef BIAS_HAVE_XML2
383  /** @brief specialization of XML block name function */
384  virtual int XMLGetClassName(std::string& TopLevelTag,
385  double& Version) const;
386 
387  /** @brief specialization of XML write function */
388  virtual int XMLOut(const xmlNodePtr Node, XMLIO& XMLObject) const;
389 
390  /** @brief specialization of XML read function */
391  virtual int XMLIn(const xmlNodePtr Node, XMLIO& XMLObject);
392 #endif
393 
394  friend std::ostream& operator<<(std::ostream &os,
396 
397 
398  // long names to avoid global symbol clashes
401 
402  protected:
403 
404  /** \brief helper function for EstimateUndistortionPolynomial */
405  int FitPolynomialWithoutLinearMonomial_(const unsigned int degree,
406  const std::vector<double>& x,
407  const std::vector<double>& y,
408  std::vector<double> &coefficients);
409 
410  /** @brief Transforms a coordinate pair of image coordinates x, y in the
411  uncalibrated spherical image, to a calibrated pair of polar coordinates
412  phi, theta.
413  @author Birger Streckel */
414  void TransfCoordImage2Sphere_ (const HomgPoint2D& Source,
415  double &theta, double &phi) const;
416 
417  /** @brief Transforms a coordinate pair of image coordinates x, y in the
418  calibrated spherical image, to a calibrated pair of polar coordinates
419  phi, theta.
420  @author Birger Streckel */
421  void TransfCoordCalibImage2Sphere_ (const HomgPoint2D& Source,
422  double &theta, double &phi) const;
423 
424  /** @brief Transforms a calibrated pair of polar coordinates phi, theta
425  to a coordinate pair of image coordinates x, y in the uncalibrated
426  spherical image.
427  @author Birger Streckel */
428  void TransfCoordSphere2Image_ (double theta, double phi,
429  HomgPoint2D &Source) const;
430 
431  /** @brief Transforms a calibrated pair of polar coordinates phi, theta
432  to a coordinate pair of image coordinates x, y in the uncalibrated
433  spherical image.
434  @author Birger Streckel */
435  int TransfCoordRotateSphere2Image_ (double theta, double phi,
436  double viewCenterX,
437  double viewCenterY,
438  HomgPoint2D &Source) const;
439 
440  /** @brief Transforms a calibrated pair of polar coordinates phi, theta
441  to a coordinate pair of image coordinates x, y in an equidistant
442  spherical image.
443  @author Birger Streckel */
444  void TransfCoordSphere2CalibImage_ (double theta, double phi,
445  HomgPoint2D &Source) const;
446 
447  /** @brief theta and phi are periodic in 2*M_PI, if they are out of a
448  suitable range, try to find best equivalent angle by adding 2*l*M_PI
449  @return 0 on success, <0 indicates that at least one angle is invalid
450  @author koeser 10/2004 */
451  void EnforceNormalRange_(double& theta, double& phi) const;
452 
453 
454 
455  // image radius if image is spherical
456  double radius_;
457 
458  // Maximum image angle of the fisheye camera
459  double MaxCamAngle_;
460  // these are the polynom coefficients
461  std::vector<double> acCoeff_;
462 
463  // Spline interpolators y(x) for image distortion
464  // x : angle in an undistorted image
465  // y : distorted angle
466  // Example: x = pi, y = 0.8*pi means that the image at angle pi is
467  // distorted with factor 0.8
469 
470  // back transformation
472 
473  // determine if interpolator has been initialized
475 
476  //bresenham-circle for running allong fov area
478  //projects pixels outside the image onto the image border
479  void ProjectOutsidePositions_(int& posX, int& posY);
480 
481 
482  };
483 
484  /////////////// inline code ///////////////////////
485  inline std::ostream& operator<<(std::ostream &os,
487  {
488  os<<"ProjectionParametersSpherical:"<<std::endl;
489  os<<"Principal: "<<p.principalX_<< " " <<p.principalY_<<std::endl;
490  os<<"Radius: "<<p.radius_<<std::endl;
491  os<<"MaxCamAngle: "<<p.MaxCamAngle_<<std::endl;
492  os<<"Coefficients:"<<std::endl;
493  std::vector<double> controlpoints, knotpoints;
494  p.interpolatorAngle_.GetControlPoints(controlpoints);
495  p.interpolatorAngle_.GetKnotPoints(knotpoints);
496  for (unsigned int i=0; i<controlpoints.size(); i++) {
497  os<< knotpoints[i]<<" "<< controlpoints[i]<<std::endl;
498  }
499  return os;
500  }
501 
502 } // end namespace
503 
504 
505 #include <Base/Common/BIASpragmaEnd.hh>
506 
507 #endif
508 
virtual BIAS::KMatrix GetFakeKMatrix(double &imgsize, int resolution=0, const double &maxangle=1.4) const
Returns a fake KMatrix for the camera.
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
virtual ProjectionParametersSpherical * Clone() const
covariant virtual copy constructor for use in Projection
Scans a circle using Bresenham&#39;s integer arithmetic algorithm.
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
std::vector< double > myvaluesPolynomialWithoutLinearMonomialError
virtual void Rescale(double ratio, const double offset=0.0)
Adapt internal parameters to resampled image.
ProjectionParametersSpherical(const unsigned int width=0, const unsigned int height=0)
void GetAngleCorrBack(std::vector< double > &distAngles, std::vector< double > &undistAngles) const
Returns samples for distorted and unddistorted angles from which the angleback correction polynomial ...
void GetKnotPoints(std::vector< double > &kPnt) const
virtual void Rescale(unsigned int width, unsigned int height)
adapt internal parameters to new image size
std::vector< double > mylocationsPolynomialWithoutLinearMonomialError
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...
void SetRadius(const double r)
Set radius of spherical image in pixels.
this class interpolates a function y=f(t) between given control points (the y-values) ...
Definition: Interpolator.hh:71
Wrapper class for reading and writing XML files based on the XML library libxml2. ...
Definition: XMLIO.hh:72
int InitAngleCorrFromPoly(const double maxCamAngle, const double acCoeff0, const double acCoeff1, const double acCoeff2, const double acCoeff3, const double acCoeff4)
ProjectionParametersSpherical(const double radius, const double maxAngle, const unsigned int width, const unsigned int height)
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
ProjectionParametersSpherical(const ProjectionParametersSpherical &P)
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
std::ostream & operator<<(std::ostream &os, const Array2D< T > &arg)
Definition: Array2D.hh:260
virtual BIAS::KMatrix GetFakeKMatrix(int resolution=0, const double &maxangle=1.4) const
stupid reimplementation since this class does not inherit function from base class (gcc) ...
Can be used to run along the image border.
ProjectionParametersSpherical & operator=(const ProjectionParametersSpherical &P)
void GetAngleCorr(std::vector< double > &undistAngles, std::vector< double > &distAngles) const
Returns samples for undistorted and distorted angles from which the angle correction polynomial (aka ...
void GetAngleCorrCoefficients(std::vector< double > &coeffs) const
Returns polynomial coefficients of angle correction polynomial (aka undistortion polynomial) mapping ...
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
Definition: KMatrix.hh:48
double principalX_
principal point in pixel coordinates (one for all zoom settings)
void GetControlPoints(std::vector< double > &cPnt) const
Definition: Interpolator.hh:91
double GetRadius() const
Return radius of spherical image in pixels.
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
virtual void Rescale(double ratio, const double offset=0.0)
Adapt internal parameters to resampled image.
double GetMaxCamAngle() const
Get maximal camera angle (in rad), i.e.
virtual ProjectionParametersBase & operator=(const ProjectionParametersBase &p)