Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ProjectionParametersPerspective.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_ProjectionParametersPerspective_hh__
27 #define __BIAS_ProjectionParametersPerspective_hh__
28 #include "bias_config.h"
29 
30 #include <Base/Common/BIASpragmaStart.hh>
31 #include <Geometry/ProjectionParametersBase.hh>
32 #include <Base/Geometry/KMatrix.hh>
33 #include <Geometry/PMatrix.hh>
34 #include <Base/Image/Image.hh>
35 
36 #define LUT_RES 10
37 #define UNDISTORT_ITERS 20
38 
39 namespace BIAS {
40 
42  {
43  DISTYPE_RADIAL = 0, // standard distortion, only radial parameters
44  DISTYPE_DEF=1, // standard distortion
45  DISTYPE_BROWN=2, // brown distortion
46  DISTYPE_NONE=3, // No radial distortion
47  DISTYPE_INVERSE_RAD=4, // like radial distortion, but applied inversely
48  DISTYPE_RAD3=5, // radial distortion with 3 coefficients
49  DISTYPE_INVRAD3=6 // inverse radial distortion with 3 coefficients
50  };
51 
52  /** @class ProjectionParametersPerspective
53  * @ingroup g_geometry
54  * @brief camera parameters which define the mapping between rays in the
55  * camera coordinate system and pixels in the image as well as external pose
56  * @author koeser/evers/streckel */
57  class BIASGeometry_EXPORT ProjectionParametersPerspective
58  : public ProjectionParametersBase {
59  public:
60 
61  ProjectionParametersPerspective(const unsigned int width = 0,
62  const unsigned int height = 0)
63  : ProjectionParametersBase(width, height)
64  {
65  InitParams_();
66  }
67 
69  const unsigned int width = 10000,
70  const unsigned int height = 10000)
71  : ProjectionParametersBase(width, height)
72  {
73  InitParams_();
74  SetP(P);
75  }
76 
78  *this = P;
79  };
80 
84  this->K_ = P.K_;
85  this->invK_ = P.invK_;
86  this->focallength_= P.focallength_;
87  this->skew_=P.skew_;
88  this->kc1_= P.kc1_;
89  this->kc2_= P.kc2_;
90  this->kc3_= P.kc3_;
91  this->kc4_= P.kc4_;
92  this->r0_ = P.r0_;
93  this->distType_ = P.distType_;
94  this->idealImageWidth_ = P.idealImageWidth_;
95  this->idealImageHeight_ = P.idealImageHeight_;
96  this->minZlocal_ = P.minZlocal_;
97  return *this;
98  };
99 
100 
101  /** Method calculates K-Matrix and image size from specified angles.
102  * Angle phi is determining the opening angle and the principle point shift in y direction,
103  * while theta is determining the opening angle and the principle point shift in x direction.
104  * angleStep is used to derive the resolution, hence the focallength and the aspectratio.
105  * The K-Matrix is free of skew.
106  *
107  * Valid values for phi are (-M_PI/2, M_PI/2), while theta must lie within (0,M_PI).
108  * Phi's reference direction is the A-Vector, theta's is the -H-Vector (negated H-Vector).
109  * The extrinsics are left unchanged (which you certainly guessed already).
110  *
111  * \returns -1 if angle values made no sense to the method.
112  *
113  * \author bartczak 10/2007
114  **/
115  int SetIntrinsics(double minPhi, double maxPhi,
116  double minTheta, double maxTheta,
117  double angleStep, double aspectratio = 1.0);
118 
119  int SetIntrinsics(Vector3<double>& p, Vector3<double>& q,
120  unsigned int width, unsigned int height);
121 
123 
124  virtual int GetMinimalAngularSamplingStep(double& minAngleStep);
125 
126  virtual const bool DoIntrinsicsDiffer(const ProjectionParametersBase* p) const;
127 
128 
129  bool DoesPointProjectIntoImageLocal(const Vector3<double>& localX,
130  HomgPoint2D& x,
131  bool IgnoreDistortion = false) const;
132 
133 
134  /** @brief calculates the projection of a point
135  in the camera coordinate system
136  to a pixel in the image plane of the camera
137  with lens distortion
138  In the simplest case perspective pinhole projection x = K * y
139  where y is the projection of X using y = (R^T | -R^T C) X
140  */
141  virtual HomgPoint2D ProjectLocal(const Vector3<double>& point,
142  bool IgnoreDistortion = false) const;
143 
144  /** @brief calculates the projection of a point in the local camera
145  coordinate system to a pixel in the image plane of the camera. The
146  only case when this function may not compute the 2d point is when the
147  camera center and the 3d point coincide. This case must be indicated
148  by a negative return value. In all other cases, a 2d point must be
149  computed, *particularily* when the 3d point is behind the camera
150  or when the resulting 2d point is at infinity.
151 
152  In the simplest case perspective pinhole projection x = K * point
153  where point is transformed of X using point = (R^T | -R^T C) X
154  @author woelk 08/2008 (c) www.vision-n.de */
155  virtual int ProjectLocal(const Vector3<double>& point, HomgPoint2D &p2d,
156  bool IgnoreDistortion = false) const;
157 
158  /** @brief map points from image onto unit diameter image plane in 3D.
159  * Chosen is the image plane with distance of one from the image center.
160  */
161  HomgPoint3D UnProjectToImagePlane(const HomgPoint2D& pos,
162  const double& depth = 1.0,
163  bool IgnoreDistortion = false) const;
164 
165 
166  /** @brief calculates the viewing ray from the camera center (in the
167  camera coordinate system) which belongs to the image position pos
168  with lens distortion
169  e.g. (0,0,1) means optical axis
170  */
171  virtual void UnProjectLocal(const HomgPoint2D& pos,
172  Vector3<double>& pointOnRay,
173  Vector3<double>& direction,
174  bool IgnoreDistortion = false)const;
175 
176  /** @brief unprojects the covariance matrices to K=Identity camera
177  Fast implementation for IgnorDistortion = true and Normalize = false
178  @author woelk 11/2007 */
179  virtual Matrix3x3<double>
180  UnProjectCovLocal(const HomgPoint2D& pos, const Matrix3x3<double>& cov2D,
181  bool IgnoreDistortion = false, bool Normalize = false);
182 
183 
184  /** **/
185  virtual HomgPoint3D UnProjectToPointByZ(const HomgPoint2D& pos,
186  const double& zDistance,
187  bool IgnoreDistortion = false) const;
188 
189  /** @brief Using the Matlab camera calibration toolbox parameters
190  for an undistortion of distorted coordinates.
191  TODO: faster implementation via Lookup-table
192  @author streckel 06/2004 */
193  virtual bool Undistort(BIAS::HomgPoint2D& point2d) const;
194 
195  /** @brief Using the Matlab camera calibration toolbox parameters
196  for a distortion of undistorted coordinates. Inverse to the
197  undistort function.
198  TODO: faster implementation via Lookup-table
199  @author streckel 06/2004 */
200  virtual bool Distort(BIAS::HomgPoint2D& point2d) const;
201 
202  /** @brief Undistort distorted coordinates using the
203  standard distortion parameters and the parameter describing the
204  second constant root of the distortion polynomial of the
205  radial symmetric distortion.
206  In contrast to the the bouguet way of calculating the radial symmetric
207  distortion by using the polynomial
208  raddist = 1 + kc1 * r^2 + kc2 * r^4
209  the "brown" way uses a modyfied polynomial which has a second
210  root. the second constant root of the polynomial is implemented by
211  subtracting the constant term rc from raddist with
212  rc = kc1 * r0^2 + kc2 * r0^4
213  r0 is the parameter describing the root of the polynomial.
214  (For details see: Luhmann, Nahbereichsphotogrammetrie. page. 121 )
215  @author grauel 09/2007 */
216  //void UndistortBrown(HomgPoint2D& point2d) const;
217 
218  /** @brief Distort undistorted coordinates using the
219 
220  @author grauel 09/2007 */
221  //void DistortBrown(HomgPoint2D& point2d) const;
222 
223  /** @brief distortion of a normalized point
224  @author woelk 11/2006 */
225  int DistortNormalized(BIAS::HomgPoint2D& point2d) const;
226 
227  /** @brief covariant virtual copy constructor for use in Projection */
229  return new ProjectionParametersPerspective(*this);
230  }
231 
232  /** Shifts the principle point so that imagePoint-(halfWidth, halfHeight)
233  * is mapped to (0,0). Image size is adapted to halfWidth*2+1 and
234  * halfHeight*2+1. Distortion parameters are applied in normalized coords
235  * hence they keep their validity.
236  * \returns true only if whole cutout lies in image.
237  */
238  bool GetCutOutParameters(const Vector2<int>& centerPoint,
239  const unsigned int halfWidth,
240  const unsigned int halfHeight,
241  ProjectionParametersPerspective& cutOutParams)
242  const;
243 
244  /** @brief Get the current camera focal length.
245  @author buck */
246  inline void GetFocalLength(double& f) const {
247  f = focallength_;
248  }
249 
250  /**
251  * @brief Returns the focal length.
252  * @author rwulff
253  * @date 07/2010
254  */
255  inline double GetFocalLength() const {
256  return focallength_;
257  }
258 
259  inline void GetUndistortion(double& kc1, double& kc2,
260  double& kc3, double& kc4) const
261  {
262  kc1 = kc1_;
263  kc2 = kc2_;
264  kc3 = kc3_;
265  kc4 = kc4_;
266  }
267 
268  inline void GetUndistortion(double& kc1, double& kc2,
269  double& kc3, double& kc4,
270  double r0) const
271  {
272  kc1 = kc1_;
273  kc2 = kc2_;
274  kc3 = kc3_;
275  kc4 = kc4_;
276  r0 = r0_;
277  }
278 
279  inline bool IsDistorted() const {
280  return ((kc1_!=0.0) || (kc2_!=0.0) || (kc3_!=0.0) || (kc4_!=0.0));
281  }
282 
283  /** @brief Sets the parameters for a simple perspective camera with
284  imagesize 512x512, focal length 512 (fov = 90 deg.),
285  princ.point (255.5,255.5) and without distortion.
286  */
287  inline void SetSimplePerspective(const double FoV = M_PI/2,
288  const unsigned int width = 512,
289  const unsigned int height = 512) {
290  SetImageSize(width, height);
291  focallength_ = double(width)/(2.0*tan(FoV/2.0));
292  aspectratio_ = 1.0;
293  principalX_ = 0.5*double(width-1);
294  principalY_ = 0.5*double(height-1);
295  //K_.SetIdentity();
296  ////set focal length
297  //K_[0][0] = K_[1][1] = 512.0;
298  //set princ. point
299  // K_[0][2] = K_[1][2] = 255.5;
300  //invK_ = K_.Invert();
301  //focallength_=512.0;
302  skew_=0;
303  kc1_=0;
304  kc2_=0;
305  kc3_=0;
306  kc4_=0;
307  r0_=0;
308  distType_=DISTYPE_DEF;
309  minZlocal_ = 0.1;
310  ComputeK_();
311  }
312 
313  /** @brief Set the current camera focal length in pixel and the a
314  spect ratio */
315  inline void SetFocalLengthAndAspect(double f,
316  double AspectRatio) {
317  focallength_ = f;
319  ComputeK_();
320  }
321 
322  /** @brief Set the current camera skew factor */
323  inline void SetSkew(double skew) {
324  skew_ = skew;
325  ComputeK_();
326  }
327 
328  /** @brief Obtain the current camera skew factor */
329  inline double GetSkew() const {
330  return skew_;
331  }
332 
333  /** @brief Set principal point in pixels relative to top left corner,
334  virtual overload to recalculate K_
335  @author streckel */
336  virtual void SetPrincipal(const double x, const double y) {
338  ComputeK_();
339  }
340 
341  /** @brief Set CCD cell-size in meter, virtual overload to
342  recalculate K_.
343  @author streckel */
344  virtual void SetAspectratio(const double AspectRatio) {
346  ComputeK_();
347  }
348 
349  /** @brief Set type of distortion parameters
350  @author grauel */
352  {
353  distType_ = distype;
354  }
355 
356  /** @brief Get type of distortion parameters
357  @author grauel */
359  {
360  return(distType_);
361  }
362 
363 
364  inline void SetUndistortion(double kc1, double kc2){
365  kc1_ = kc1;
366  kc2_ = kc2;
367  kc3_ = 0;
368  kc4_ = 0;
369  distType_ = DISTYPE_RADIAL;
370  }
371 
372  /** @brief Set the lens undistortion parameters*/
373  inline void SetUndistortion(double kc1, double kc2,
374  double kc3, double kc4)
375  {
376  kc1_ = kc1;
377  kc2_ = kc2;
378  kc3_ = kc3;
379  kc4_ = kc4;
380  distType_ = DISTYPE_DEF; //reset to default distortion
381  }
382 
383  /** @brief Set the lens undistortion parameters including the root of
384  the polynomial.
385  @author grauel 9/2007 */
386  inline void SetUndistortionBrown(double kc1, double kc2,
387  double kc3, double kc4,
388  double r0)
389  {
390  kc1_ = kc1;
391  kc2_ = kc2;
392  kc3_ = kc3;
393  kc4_ = kc4;
394  r0_ = r0;
395  distType_ = DISTYPE_BROWN;
396  }
397 
398  inline void SetUndistortionInverseRad(double kc1, double kc2,
399  double kc3, double kc4){
400 
401  kc1_ = kc1;
402  kc2_ = kc2;
403  kc3_ = kc3;
404  kc4_ = kc4;
405  distType_ = DISTYPE_INVERSE_RAD;
406  }
407 
408  inline void SetUndistortionRad3(double kc1, double kc2, double kc3){
409  kc1_ = kc1;
410  kc2_ = kc2;
411  kc3_ = kc3;
412  kc4_ = 0;
413  distType_ = DISTYPE_RAD3;
414  }
415 
416  inline void SetUndistortionInverseRad3(double kc1, double kc2, double kc3){
417  kc1_ = kc1;
418  kc2_ = kc2;
419  kc3_ = kc3;
420  kc4_ = 0;
421  distType_ = DISTYPE_INVRAD3;
422  }
423 
424 
425  inline void GetUndistortionInverseRad(double& kc1, double& kc2,
426  double& kc3, double& kc4) const {
427 
428  if(distType_ != DISTYPE_INVERSE_RAD){
429  BIASWARN("Distortion type is not inverse, parameters might be invalid");
430  BIASABORT;
431  }
432  kc1 = kc1_;
433  kc2 = kc2_;
434  kc3 = kc3_;
435  kc4 = kc4_;
436  }
437 
438  /** @brief Get the lens undistortion parameters including the parameter
439  describing root of the polynomial
440  @author grauel 9/2007 */
441  inline void GetUndistortionBrown(double& kc1, double& kc2,
442  double& kc3, double& kc4,
443  double& r0) const
444  {
445  if(distType_ != DISTYPE_BROWN)
446  {
447  BIASWARN("Distortion type is not DISTYPE_BROWN. the parameters might not be valid.")
448  }
449  kc1 = kc1_;
450  kc2 = kc2_;
451  kc3 = kc3_;
452  kc4 = kc4_;
453  r0 = r0_;
454 
455  }
456 
457  inline void GetUndistortionRad3(double& kc1, double& kc2, double& kc3){
458 
459  if(distType_ != DISTYPE_RAD3){
460  BIASWARN("Distortion type is not DistypeRAD3, the parameters might be invalid." << distType_);
461  }
462 
463  kc1 = kc1_;
464  kc2 = kc2_;
465  kc3 = kc3_;
466  }
467 
468  inline void GetUndistortionInvRad3(double& kc1, double& kc2, double& kc3){
469 
470  if(distType_ != DISTYPE_INVRAD3){
471  BIASWARN("Distortion type is not DistypeINVRAD3, the parameters might be invalid.");
472  }
473 
474  kc1 = kc1_;
475  kc2 = kc2_;
476  kc3 = kc3_;
477  }
478 
479 
480  /* @brief get the PMatrix composed from the projection object
481  */
482  inline virtual BIAS::PMatrix GetP() const {
483  return PMatrix(K_, GetR(), GetC());
484  }
485 
486  /* @brief get cached KMatrix
487  */
488  inline virtual BIAS::KMatrix GetK() const {
489  return K_;
490  };
491 
492  /* @brief get cached inverted KMatrix
493  */
494  inline virtual BIAS::KMatrix GetKinv() const {
495  return invK_;
496  };
497 
498  /** @brief sets the internal parameters from a given KMatrix
499  and updates the cached K and its inverse */
500  virtual void SetK(const KMatrix& K) {
501  BIASASSERT(K[0][0]!=0);
502  focallength_ = K[0][0];
503  skew_ = K[0][1];
505  double aspectratio = K[1][1]/K[0][0];
507  K_ = K; invK_ = K.Invert();
508  };
509 
510  /** @brief set from P */
511  virtual void SetP(const PMatrix& P) {
512  PMatrix p(P); // de-const
513  SetK(p.GetK());
514  SetC(p.GetC());
515  SetR(p.GetR());
516  ComputeK_();
517  };
518 
519  /** @brief Adapt internal parameters to resampled image.
520  @param ratio 2.0 = downsample by 2, 0.5 = upsample by 2
521  @param offset Offset for principal point (applied before down/upsampling!)
522  \attention Delivers only correct results if ratio is chosen
523  to rescale image size to integral image dimensions
524  in both directions. Image size is rounded!
525  */
526  virtual void Rescale(double ratio, const double offset = 0.0) {
527  ProjectionParametersBase::Rescale(ratio, offset);
528  focallength_ /= ratio;
529  skew_ /= ratio;
530  ComputeK_();
531  // dont have to update radial/tangential distortion coefficients
532  // because we measure in normalize space
533  }
534 
535  /** @brief Adapt internal parameters to resampled image. Allows to rescale to different aspect ratio.
536  @param width new image width
537  @param height new image height
538  */
539  virtual void Rescale(unsigned int width, unsigned int height){
540  unsigned int oldwidth = width_;
541  unsigned int oldheight = height_;
542  ProjectionParametersBase::Rescale(width, height);
543  double ratio = (double)oldwidth/(double)width_;
544  focallength_ /= ratio;
545  skew_ /= ratio;
546  aspectratio_ /= ((double)oldheight/(double)height_) / ((double)oldwidth/(double)width_);
547  ComputeK_();
548 
549  }
550 
551  /** @brief compute scalar dissimilarity between two cameras based upon
552  rough approximation of field of view overlap for pure rotation and
553  penalty term for translation: 0=identical */
554  virtual double ViewDifference(const ProjectionParametersBase* pPPB) const;
555 
556  void GetIdealK(KMatrix& K) const;
557  void SetIdealImageSize(unsigned int width, unsigned int height);
558  void GetIdealImageSize(unsigned int& width, unsigned int& height) const;
559 
560  /** \brief transforms an image from polar coordinates to cartesian coordinates
561  * \author ischiller
562  * \date 06/2010 */
563  int TransformPolarToCartesianCoordinates(const BIAS::Image<float>& polarDepth,
564  BIAS::Image<float>& cartesianDepth);
565  /** \brief transforms a depth value from polar coodinates to cartesian coordinates
566  * \return the transformed depth in cartesian coordinates
567  * \author ischiller
568  * \date 06/2010 */
569  float TransformPolarToCartesianCoordinates(const HomgPoint2D& pos, const float depthPolar);
570  /** \brief transforms an image from cartesian coordinates to polar coordinates
571  * \author ischiller
572  * \date 06/2010 */
573  int TransformCartesianToPolarCoordinates(const BIAS::Image<float>& cartesianDepth,
574  BIAS::Image<float>& polarDepth);
575  /** \brief transforms a depth value from cartesian coordinates to polar coordinates
576  * \return the transformed depth in polar coordinates
577  * \author ischiller
578  * \date 06/2010 */
579  float TransformCartesianToPolarCoordinates(const HomgPoint2D& pos, const float depthCartesian);
580 
581 
582  /** @brief sets minimum z value of unit-ray in local CCS to be accepted
583  as in front of camera (e.g. DoesPointProjectIntoImage) */
584  void SetMinZLocal(const double& minz) {
585  minZlocal_ = minz;
586  }
587 
588  /** @get minimum z value of ray in image (if computed already) */
589  double GetMinZLocal() const { return minZlocal_; }
590 
591  /** @brief run along image border and compute maximum field of view,
592  save in minzlocal */
593  void UpdateMinZLocal();
594 
595  /** Calculates an ModelViewProjection matrix useable in OpenGL.
596  \param zNear defines the near z-clipping plane.
597  \param zFar defines the far z-clipping plane.
598  \param flip reading out the framebuffer into a bias image implicitly flips the image,
599  when this can be remedied by (pre)flipping in the projection matrix - however when rendering
600  onscreen, the visible image will be flipped then.
601  **/
602  Matrix4x4<double> GetGLModelviewProjectionMatrix(const double zNear,
603  const double zFar,
604  const bool flip,
605  const bool transpose=false);
606 
607  /** Calculates an projection matrix useable in OpenGL.
608  \param zNear defines the near z-clipping plane.
609  \param zFar defines the far z-clipping plane.
610  \param flip reading out the framebuffer into a bias image implicitly flips the image,
611  when this can be remedied by (pre)flipping in the projection matrix - however when rendering
612  onscreen, the visible image will be flipped then.
613  **/
614  Matrix4x4<double> GetGLProjectionMatrix(const double zNear,
615  const double zFar,
616  const bool flip,
617  const bool transpose=false);
618 
619  /** Calculates an projection matrix useable in OpenGL.
620  The viewing frustum encloses the image all optical rays passing through the image region
621  specified by the parameters upperLeft, width and height.
622  \param zNear defines the near z-clipping plane.
623  \param zFar defines the far z-clipping plane.
624  \param upperLeft specifies the image positions of the upper left "visible" optical ray.
625  \param width specifies the x-component of the image position of the lower right "visible" optical ray.
626  \param height specifies the y-component of the image position of the lower right "visible" optical ray.
627  \param flip reading out the framebuffer into a bias image implicitly flips the image,
628  when this can be remedied by (pre)flipping in the projection matrix - however when rendering
629  onscreen, the visible image will be flipped then.
630  **/
631  Matrix4x4<double> GetGLProjectionMatrix(const double zNear,
632  const double zFar,
633  const Vector2<unsigned int> upperLeft,
634  const unsigned int width,
635  const unsigned int height,
636  const bool flip,
637  const bool transpose=false);
638 
639  static std::string GetRadialDistModelString(BIAS_ProjParaPersp_DISTORTION_TYPE model);
640 
641 #ifdef BIAS_HAVE_XML2
642  /** @brief specialization of XML block name function */
643  virtual int XMLGetClassName(std::string& TopLevelTag,
644  double& Version) const;
645 
646  /** @brief specialization of XML write function */
647  virtual int XMLOut(const xmlNodePtr Node, XMLIO& XMLObject) const;
648 
649  /** @brief specialization of XML read function */
650  virtual int XMLIn(const xmlNodePtr Node, XMLIO& XMLObject);
651 #endif
652 
653  friend std::ostream&
654  operator<<(std::ostream &os, const ProjectionParametersPerspective& p);
655 
656  protected:
657  /** @brief called from constructors to set zeros to most values */
658  void InitParams_() {
659  K_.SetIdentity();
660  invK_.SetIdentity();
661  focallength_=1.0;
662  skew_=0;
663  kc1_=0;
664  kc2_=0;
665  kc3_=0;
666  kc4_=0;
667  r0_=0;
668  distType_=DISTYPE_DEF;
669  idealImageWidth_ = 512; //width_;
670  idealImageHeight_ = 512; //height_;
671  minZlocal_ = 0.1;
672  }
673 
674  /** @brief computes the cached KMatrix and its inverse
675  call after every parameter change */
676  void ComputeK_();
677 
678  /// focal length, aspect ratio, principal point in K_, inverse in invK_
679  KMatrix K_, invK_;
680 
681  /// focal length is stored in pixel for cellSizeX
682  double focallength_;
683  /// lens undistortion parameters after Bouquet
684  /// also used as parameters for distortion after Brown(?)
685  double kc1_,kc2_,kc3_,kc4_;
686 
687  // additional lens undistortion parameter after Brown(?)
688  // describing the constant root of the polynomial
689  double r0_;
690 
691  // distortion type parameter
693 
694  /// skew calibration parameter
695  double skew_;
696 
697  /// ideal image size
698  unsigned int idealImageWidth_, idealImageHeight_;
699 
700  /// rigorously clip unit rays in CCS with z smaller than this values
701  double minZlocal_;
702 
703  /** Helper function for minimal angle step calculation. **/
704  int GetMinimalAngleInCorner_(const HomgPoint2D& corner, double& minAngle);
705 
706 
707  inline void Distort_(const double x, const double y,
708  double& dist_x, double& dist_y) const;
709 
710  inline bool Undistort_(const double dist_x, const double dist_y,
711  double& x, double& y) const;
712  };
713 
714 
715  //////////// inline code //////////////////
716  inline std::ostream& operator<<(std::ostream &os,
718  {
719  os << "ProjectionParametersPerspective:" << std::endl;
720  os << "Pose " << p.GetPose() << std::endl;
721  unsigned int cx, cy;
722  p.GetImageSize(cx, cy);
723  os<<"ImageSize: " << cx << " " << cy << std::endl;
724  os<<"Skew: "<<p.skew_<<std::endl;
725  os<<"K:"<<p.GetK()<<std::endl;
726  std::string dist_model;
727  bool brown = false;
728  if(p.distType_ == DISTYPE_BROWN){
729  dist_model = "Browns distortion model";
730  brown = true;
731  }
733  dist_model = "Default distortion model";
734  }
736  dist_model = "Inverse rad distorion model";
737  }
738  if(p.distType_ == DISTYPE_NONE){
739  dist_model = "no distortion model";
740  }
741  if(p.distType_ == DISTYPE_RAD3){
742  dist_model = "radial distortion, 3 coeffs";
743  }
744  if(p.distType_ == DISTYPE_INVRAD3){
745  dist_model = "inverse radial distortion, 3 coeffs";
746  }
747  os<<dist_model<<": ";
748  os<< " kc1_: " <<p.kc1_<< " kc2_: "<<p.kc2_<<" kc3_: "
749  <<p.kc3_<<" kc4_: "<<p.kc4_;
750  if (brown)
751  os <<" r0_: "<< p.r0_;
752  os << "\nminZlocal: "<<p.minZlocal_<<std::endl;
753  os<<std::endl;
754  return os;
755  }
756 
758  Distort_(const double x, const double y,
759  double& dist_x, double& dist_y) const
760  {
761  double twoxy, xx, yy;
762  double rc;
763  double tmpx, tmpy;
764  double r0squared;
765  double rsquared;
766  double raddist;
767  xx = x*x;
768  yy = y*y;
769  rsquared = xx + yy;
770 
771  switch(distType_){
772  case DISTYPE_NONE:
773  raddist = 1.0;
774  break;
775  case DISTYPE_BROWN:
776  //todo why is here no iteration of UNDISTORT_ITERS ??? ischiller
777  //todo and the tangential factors are missing too!!
778 
779  // r0 is the distance of polynomial root from the distortion center
780  // since the x and y are normalized r0 must be normalized too.
781  r0squared = (r0_)*(r0_);
782  //"constant root of polynomial"
783  rc = kc1_ * r0squared + kc2_* r0squared*r0squared;
784  // radial distortion:
785  raddist = 1 + kc1_*rsquared + kc2_*rsquared*rsquared - rc;
786  break;
787  case DISTYPE_DEF:
788  // radial distortion:
789  raddist = 1 + kc1_*rsquared + kc2_*rsquared*rsquared;
790  if (kc3_!=0.0 || kc4_!=0.0){
791  twoxy = 2.0*x*y;
792  // apply radial and tangential distortion:
793  dist_x = raddist * x + kc3_*twoxy + kc4_ * (rsquared + 2.0*xx);
794  dist_y = raddist * y + kc4_*twoxy + kc3_ * (rsquared + 2.0*yy);
795  } else {
796  // apply only radial distortion:
797  dist_x = raddist * x;
798  dist_y = raddist * y;
799  }
800  break;
801  case DISTYPE_RADIAL:
802  // radial distortion:
803  raddist = 1 + kc1_*rsquared + kc2_*rsquared*rsquared;
804  dist_x = raddist * x;
805  dist_y = raddist * y;
806  break;
807  case DISTYPE_INVERSE_RAD:
808  BIASWARNONCE("distorting with dist inverse ");
809  // inverse radial distortion - the iterative technique is applied here
810  double tandistx, tandisty;
811  dist_x = x;
812  dist_y = y;
813  for (unsigned int i = 0; i < UNDISTORT_ITERS; i++){
814  twoxy = 2 * dist_x*dist_y;
815  rsquared = dist_x*dist_x + dist_y*dist_y;
816 
817  // radial distortion:
818  raddist = 1.0 + (kc1_ + kc2_*rsquared)*rsquared;
819  // tangential distortion:
820  tandistx = kc3_*twoxy + kc4_ * (rsquared + 2*dist_x*dist_x);
821  tandisty = kc4_*twoxy + kc3_ * (rsquared + 2*dist_y*dist_y);
822 
823  // apply distortion:
824  tmpx = raddist * dist_x + tandistx;
825  tmpy = raddist * dist_y + tandisty;
826 
827  // subtract distortion from distorted coordinates
828  dist_x = x - (tmpx-dist_x);
829  dist_y = y - (tmpy-dist_y);
830 
831  // prevent NaN in next iteration step
832  if (fabs(dist_x)>1e10 || fabs(dist_y)>1e10) {
833  dist_x = -1;
834  dist_y = -1;
835  return;
836  }
837  }
838  break;
839  case DISTYPE_RAD3:
840  // radial distortion with 3 coefficients:
841  raddist = 1 + kc1_*rsquared + kc2_*rsquared*rsquared + kc3_*rsquared*rsquared*rsquared;
842  dist_x = raddist * x;
843  dist_y = raddist * y;
844  break;
845 
846  case DISTYPE_INVRAD3:
847  // radial distortion with 3 coefficients, but inversed, hence the iteration is applied here
848  BIASWARNONCE("distorting with dist inverse ");
849  dist_x = x;
850  dist_y = y;
851  for (unsigned int i = 0; i < UNDISTORT_ITERS; i++){
852  twoxy = 2 * dist_x*dist_y;
853  rsquared = dist_x*dist_x + dist_y*dist_y;
854 
855  // radial distortion:
856  raddist = 1.0 + (kc1_ + kc2_*rsquared+kc3_*rsquared*rsquared)*rsquared;
857 
858  // apply distortion:
859  tmpx = raddist * dist_x;
860  tmpy = raddist * dist_y;
861 
862  // subtract distortion from distorted coordinates
863  dist_x = x - (tmpx-dist_x);
864  dist_y = y - (tmpy-dist_y);
865 
866  // prevent NaN in next iteration step
867  if (fabs(dist_x)>1e10 || fabs(dist_y)>1e10) {
868  dist_x = -1;
869  dist_y = -1;
870  return;
871  }
872  }
873  break;
874  default:
875  BIASERR("unknown distortion type");
876  BIASABORT
877  break;
878  }
879 
880  }
881 
883  Undistort_(const double dist_x, const double dist_y,
884  double& x, double& y) const
885  {
886  double twoxy;
887  double tmpx, tmpy;
888  double rsquared;
889  double raddist;
890  double tandistx, tandisty;
891  double distx, disty;
892  double rc, r0squared;
893 
894  x = dist_x;
895  y = dist_y;
896  switch (distType_){
897  case DISTYPE_NONE:
898  x = dist_x;
899  y = dist_y;
900  return true;
901  case DISTYPE_BROWN:
902  // r0 is the distance of polynomial root from the distortion center
903  r0squared = (r0_)*(r0_);
904 
905  //"constant root of polynomial"
906  rc = kc1_ * r0squared + kc2_* r0squared* r0squared;
907 
908  for (unsigned int i = 0; i < UNDISTORT_ITERS; i++){
909  twoxy = 2 * x*y;
910  rsquared = x*x + y*y;
911 
912  // radial distortion:
913  raddist = 1.0 + (kc1_ + kc2_*rsquared)*rsquared - rc;
914  // tangential distortion:
915  tandistx = kc3_*twoxy + kc4_ * (rsquared + 2*x*x);
916  tandisty = kc4_*twoxy + kc3_ * (rsquared + 2*y*y);
917 
918  // subtract distortion from distorted coordinates
919  x = (dist_x - tandistx)/raddist;
920  y = (dist_y - tandisty)/raddist;
921 
922  // prevent NaN in next iteration step
923  if (fabs(x)>1e10 || fabs(y)>1e10) {
924  return false;
925  }
926  }
927  break;
928  case DISTYPE_DEF:
929  for (unsigned int i = 0; i < UNDISTORT_ITERS; i++){
930  twoxy = 2 * x*y;
931  rsquared = x*x + y*y;
932 
933  // radial distortion:
934  raddist = 1.0 + (kc1_ + kc2_*rsquared)*rsquared;
935  // tangential distortion:
936  tandistx = kc3_*twoxy + kc4_ * (rsquared + 2*x*x);
937  tandisty = kc4_*twoxy + kc3_ * (rsquared + 2*y*y);
938 
939  // apply distortion:
940  distx = raddist * x + tandistx;
941  disty = raddist * y + tandisty;
942 
943  // subtract distortion from distorted coordinates
944  x = dist_x - (distx-x);
945  y = dist_y - (disty-y);
946 
947  // prevent NaN in next iteration step
948  if (fabs(x)>1e10 || fabs(y)>1e10) {
949  return false;
950  }
951  }
952  break;
953  case DISTYPE_RADIAL:
954 
955  for (unsigned int i = 0; i < UNDISTORT_ITERS; i++){
956  rsquared = x*x + y*y;
957 
958  // radial distortion:
959  raddist = 1.0 + (kc1_ + kc2_*rsquared)*rsquared;
960 
961  // apply distortion:
962  distx = raddist * x;
963  disty = raddist * y;
964 
965  // subtract distortion from distorted coordinates
966  x = dist_x - (distx-x);
967  y = dist_y - (disty-y);
968 
969  // prevent NaN in next iteration step
970  if (fabs(x)>1e10 || fabs(y)>1e10) {
971  return false;
972  }
973  }
974  break;
975  case DISTYPE_INVERSE_RAD:
976  BIASWARNONCE("undistorting with dist inverse ")
977  // radial distortion:
978  rsquared = dist_x*dist_x + dist_y*dist_y;
979  raddist = 1 + kc1_*rsquared + kc2_*rsquared*rsquared;
980  if (kc3_!=0.0 || kc4_!=0.0){
981  twoxy = 2.0*dist_x*dist_y;
982  // apply radial and tangential distortion:
983  x = raddist * dist_x + kc3_*twoxy + kc4_ * (rsquared + 2.0*dist_x*dist_x);
984  y = raddist * dist_y + kc4_*twoxy + kc3_ * (rsquared + 2.0*dist_y*dist_y);
985  } else {
986  // apply only radial distortion:
987  x = raddist * dist_x;
988  y = raddist * dist_y;
989  }
990  break;
991  case DISTYPE_RAD3:
992  // radial distortion with 3 coefficients, this is undistort, so iteration needs to be applied
993  x = dist_x;
994  y = dist_y;
995  for (unsigned int i = 0; i < UNDISTORT_ITERS; i++){
996  twoxy = 2 * x*y;
997  rsquared = x*x + y*y;
998 
999  // radial distortion:
1000  raddist = 1.0 + (kc1_ + kc2_*rsquared+kc3_*rsquared*rsquared)*rsquared;
1001 
1002  // apply distortion:
1003  tmpx = raddist * x;
1004  tmpy = raddist * y;
1005 
1006  // subtract distortion from distorted coordinates
1007  x = dist_x - (tmpx-x);
1008  y = dist_y - (tmpy-y);
1009 
1010  // prevent NaN in next iteration step
1011  if (fabs(x)>1e10 || fabs(y)>1e10) {
1012  x = -1;
1013  y = -1;
1014  return false;
1015  }
1016  }
1017  break;
1018 
1019  case DISTYPE_INVRAD3:
1020  // radial distortion with 3 coefficients:
1021  rsquared = dist_x*dist_x + dist_y*dist_y;
1022  raddist = 1 + kc1_*rsquared + kc2_*rsquared*rsquared + kc3_*rsquared*rsquared*rsquared;
1023  x = raddist * dist_x;
1024  y = raddist * dist_y;
1025 
1026  break;
1027  default:
1028  BIASERR("unknown distortion type");
1029  BIASABORT
1030  break;
1031  }
1032  return true;
1033  }
1034 
1035 } // end namespace
1036 
1037 
1038 #include <Base/Common/BIASpragmaEnd.hh>
1039 
1040 #endif
1041 
bool Undistort_(const double dist_x, const double dist_y, double &x, double &y) const
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
void SetDistortionType(BIAS_ProjParaPersp_DISTORTION_TYPE distype)
Set type of distortion parameters.
void GetUndistortionRad3(double &kc1, double &kc2, double &kc3)
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
void GetUndistortionBrown(double &kc1, double &kc2, double &kc3, double &kc4, double &r0) const
Get the lens undistortion parameters including the parameter describing root of the polynomial...
virtual void SetPrincipal(const double x, const double y)
Set principal point in pixels relative to top left corner, virtual overload to recalculate K_...
virtual void Rescale(double ratio, const double offset=0.0)
Adapt internal parameters to resampled image.
void Distort_(const double x, const double y, double &dist_x, double &dist_y) const
void SetMinZLocal(const double &minz)
sets minimum z value of unit-ray in local CCS to be accepted as in front of camera (e...
virtual void SetP(const PMatrix &P)
set from P
int GetR(Matrix3x3< double > &R)
Definition: PMatrix.cpp:204
void GetUndistortion(double &kc1, double &kc2, double &kc3, double &kc4) const
double minZlocal_
rigorously clip unit rays in CCS with z smaller than this values
void InitParams_()
called from constructors to set zeros to most values
void SetSkew(double skew)
Set the current camera skew factor.
KMatrix K_
focal length, aspect ratio, principal point in K_, inverse in invK_
double GetMinZLocal() const
minimum z value of ray in image (if computed already)
Wrapper class for reading and writing XML files based on the XML library libxml2. ...
Definition: XMLIO.hh:72
ProjectionParametersPerspective(const ProjectionParametersPerspective &P)
void SetUndistortionInverseRad(double kc1, double kc2, double kc3, double kc4)
virtual ProjectionParametersPerspective * Clone() const
covariant virtual copy constructor for use in Projection
void SetUndistortionInverseRad3(double kc1, double kc2, double kc3)
void GetFocalLength(double &f) const
Get the current camera focal length.
class BIASGeometry_EXPORT PMatrix
void GetUndistortionInvRad3(double &kc1, double &kc2, double &kc3)
virtual void SetAspectratio(const double AspectRatio)
Set CCD cell-size in meter, virtual overload to recalculate K_.
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
ProjectionParametersPerspective(const BIAS::PMatrix &P, const unsigned int width=10000, const unsigned int height=10000)
virtual int GetImageSize(unsigned int &Width, unsigned int &Height) const
Obtain image dimensions.
void SetUndistortionRad3(double kc1, double kc2, double kc3)
double focallength_
focal length is stored in pixel for cellSizeX
int GetC(Vector3< double > &C)
computes translation vector origin world coo -&gt; origin camera coo (center), uses decomposition, which is cached
Definition: PMatrix.cpp:165
void SetUndistortionBrown(double kc1, double kc2, double kc3, double kc4, double r0)
Set the lens undistortion parameters including the root of the polynomial.
double GetFocalLength() const
Returns the focal length.
void GetUndistortionInverseRad(double &kc1, double &kc2, double &kc3, double &kc4) const
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
Definition: KMatrix.hh:48
ProjectionParametersPerspective(const unsigned int width=0, const unsigned int height=0)
virtual void SetAspectratio(const double AspectRatio)
Set CCD aspect ratio (i.e.
ProjectionParametersPerspective & operator=(const ProjectionParametersPerspective &P)
describes a projective 3D -&gt; 2D mapping in homogenous coordinates
Definition: PMatrix.hh:88
virtual void Rescale(unsigned int width, unsigned int height)
Adapt internal parameters to resampled image.
void SetFocalLengthAndAspect(double f, double AspectRatio)
Set the current camera focal length in pixel and the a spect ratio.
void SetSimplePerspective(const double FoV=M_PI/2, const unsigned int width=512, const unsigned int height=512)
Sets the parameters for a simple perspective camera with imagesize 512x512, focal length 512 (fov = 9...
virtual void Rescale(double ratio, const double offset=0.0)
Adapt internal parameters to resampled image.
KMatrix Invert() const
returns analyticaly inverted matrix
Definition: KMatrix.cpp:31
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
void SetUndistortion(double kc1, double kc2, double kc3, double kc4)
Set the lens undistortion parameters.
virtual const BIAS::Pose & GetPose() const
Return complete pose object.
virtual void SetK(const KMatrix &K)
sets the internal parameters from a given KMatrix and updates the cached K and its inverse ...
void GetUndistortion(double &kc1, double &kc2, double &kc3, double &kc4, double r0) const
double GetSkew() const
Obtain the current camera skew factor.
double kc1_
lens undistortion parameters after Bouquet also used as parameters for distortion after Brown(...
virtual ProjectionParametersBase & operator=(const ProjectionParametersBase &p)
BIAS_ProjParaPersp_DISTORTION_TYPE GetDistortionType() const
Get type of distortion parameters.
int GetK(KMatrix &K)
calibration matrix
Definition: PMatrix.cpp:220