Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ProjectionParametersGreatCircles.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 #include "Geometry/ProjectionParametersGreatCircles.hh"
27 #include <Base/Common/CompareFloatingPoint.hh>
28 #include <math.h>
29 
30 using namespace BIAS;
31 using namespace std;
32 
33 #define M_PI_TOL M_PI*1.1
34 #define M_PI_2_TOL M_PI_2*1.1
35 
36 
39 {
40  return focallengthTheta_;
41 }
42 
44 Distort(BIAS::HomgPoint2D& point2d) const
45 {
46  BIASERR("unfinished");
47  BIASABORT;
48  return false;
49 }
50 
53 {
54  BIASERR("unfinished");
55  BIASABORT;
56  return false;
57 }
58 
59 
62  double& phi,
63  double& theta)
64 {
65  //component x corresponds to H
66  const double x = euc[0];
67  //component y corresponds to V
68  const double y = euc[1];
69  //component z corresponds to A
70  const double z = euc[2];
71 
72  double l = euc.NormL2();
73  if((l<1e-12) || (fabs(z)<1e-12 && fabs(y)<1e-12)) {
74  phi = 0;
75  theta = 0;
76  return false;
77  }
78 
79  phi = atan2(y,z);
80  theta = acos(-x/l);
81  return true;
82 }
83 
86  const double theta,
88 {
89  //BIASASSERT(phi>=-M_PI && phi<=M_PI);
90  //BIASASSERT(theta=0 && theta<=M_PI);
91  ray.Set(0,0,0);
92  if(phi<-M_PI || phi>M_PI || theta<0 || theta>M_PI)
93  return false;
94 
95  if(theta<=0) {
96  ray.Set(-1, 0, 0);
97  return false; //result is not unique;
98  }
99  if(theta>=M_PI) {
100  ray.Set(1, 0, 0);
101  return false; //result is not unique;
102  }
103  ray[0] = -cos(theta);//the sign is correct! see above.
104  ray[1] = sin(theta)*sin(phi);
105  ray[2] = sin(theta)*cos(phi);
106  return true;
107 }
108 
110 Angle2Image(double phi, double theta, BIAS::HomgPoint2D& imgPoint) const
111 {
112  imgPoint[0] = theta*focallengthTheta_ + principalX_;
113  imgPoint[1] = phi*focallengthTheta_*aspectratio_ + principalY_;
114  imgPoint[2] = 1.0;
115 }
116 
119  double& phi, double& theta) const
120 {
121  theta = (imgPoint[0]-principalX_)/focallengthTheta_;
122  phi = (imgPoint[1]-principalY_)/(focallengthTheta_*aspectratio_);
123 }
124 
126 SetInternals(const double minPhi, const double maxPhi,
127  const double minTheta, const double maxTheta,
128  const unsigned int imgWidth, const unsigned int imgHeight)
129 {
130  BIASASSERT(minPhi>=-M_PI && minPhi<=M_PI);
131  BIASASSERT(minTheta>=0 && maxTheta<=M_PI);
132  BIASASSERT(maxTheta>minTheta);
133  BIASASSERT(maxTheta<=M_PI);
134 
135  BIASASSERT(maxPhi>minPhi);
136  BIASASSERT(maxPhi<=M_PI);
137 
138  //BIASASSERT(imgWidth>0);
139  //BIASASSERT(imgHeight>0);
140 
141  width_ = imgWidth;
142  height_ = imgHeight;
143 
144  focallengthTheta_ = width_/(maxTheta-minTheta);
145  principalX_ = -focallengthTheta_*minTheta-0.5;
146 
147  double focallengthPhi = height_/(maxPhi-minPhi);
148  if (width_ > 0)
149  aspectratio_ = focallengthPhi/focallengthTheta_;
150  else
151  aspectratio_ = 1.0;
152  //produce same rounding errors like in other methods:
153  principalY_ = -focallengthTheta_*aspectratio_*minPhi-0.5;
154 }
155 
156 
159 {
161  focallengthTheta_ = P.focallengthTheta_;
162  return *this;
163 }
164 
166 Rescale(double ratio, const double offset)
167 {
168  // attention - offset is being ignored
169 
170  double deltaTheta = width_/focallengthTheta_;
171  double deltaPhi = height_/(focallengthTheta_*aspectratio_);
172  principalX_+=0.5;
173  principalX_/=focallengthTheta_;
174  principalY_+=0.5;
175  principalY_/=(focallengthTheta_*aspectratio_);
176 
177  double widthTemp = (double)width_/ratio;
178  double heightTemp = (double)height_/ratio;
179  width_ = (int)rint(widthTemp);
180  height_ = (int)rint(heightTemp);
181  focallengthTheta_ = width_/deltaTheta;
182  double focallengthPhi = height_/deltaPhi;
183  aspectratio_ = focallengthPhi/focallengthTheta_;
184 
185  principalX_*=focallengthTheta_;
186  principalY_*=(focallengthTheta_*aspectratio_);
187  principalX_-=0.5;
188  principalY_-=0.5;
189 }
190 
191 
193 Rescale(unsigned int width, unsigned int height)
194 {
195  // attention - offset is being ignored
196 
197  double deltaTheta = width_/focallengthTheta_;
198  double deltaPhi = height_/(focallengthTheta_*aspectratio_);
199  principalX_+=0.5;
200  principalX_/=focallengthTheta_;
201  principalY_+=0.5;
202  principalY_/=(focallengthTheta_*aspectratio_);
203 
204  double widthTemp = (double)width_;
205  double heightTemp = (double)height_;
206  width_ = (int)rint(widthTemp);
207  height_ = (int)rint(heightTemp);
208  focallengthTheta_ = width_/deltaTheta;
209  double focallengthPhi = height_/deltaPhi;
210  aspectratio_ = focallengthPhi/focallengthTheta_;
211 
212  principalX_*=focallengthTheta_;
213  principalY_*=(focallengthTheta_*aspectratio_);
214  principalX_-=0.5;
215  principalY_-=0.5;
216 }
217 
218 
220 GetAngleInterval(const HomgPoint3D& worldPoint,
221  const double halfAngleRange,
222  double& thetaMin, double& thetaMax,
223  double& phiMin, double& phiMax) const
224 {
225  //first determine angles of worldPoint
226  Vector3<double> localEucPoint;
227  Pose_.GlobalToLocal(worldPoint).GetEuclidean(localEucPoint);
228  double phi, theta;
229  if(!LocalEuclideanCamCoordinates2SphericalAngles(localEucPoint,
230  phi, theta)) {
231  BIASERR("unable to transform given point into angle representation!");
232  return false;
233  }
234 
235  double thetaExtendedMin = theta - halfAngleRange;
236  double thetaExtendedMax = theta + halfAngleRange;
237 
238  //clamp to [0, M_PI]
239  thetaMin = (thetaExtendedMin<=0) ? 0 : thetaExtendedMin;
240  thetaMax = (thetaExtendedMax>=M_PI) ? M_PI : thetaExtendedMax;
241 
242  //if theta in [0,M_PI] is crossed consequently phi in [-M_PI, M_PI]
243  if((thetaExtendedMin<=0) || (thetaExtendedMax>=M_PI)) {
244  phiMin = -M_PI;
245  phiMax = M_PI;
246  return true;
247  }
248 
249  double phiExtendedMin = phi - halfAngleRange;
250  if(phiExtendedMin < -M_PI) {
251  phiMin = -M_PI;
252  phiMax = M_PI;
253  return true;
254  }
255 
256  double phiExtendedMax = phi + halfAngleRange;
257  if(phiExtendedMax > M_PI) {
258  phiMin = -M_PI;
259  phiMax = M_PI;
260  return true;
261  }
262 
263  phiMin = phiExtendedMin;
264  phiMax = phiExtendedMax;
265 
266  return true;
267 }
268 
270 SetAngleInterval(const HomgPoint3D& worldPoint,
271  const double& halfAngleRange)
272 {
273  bool result;
274  double thetaMin, thetaMax, phiMin, phiMax;
275  result = GetAngleInterval(worldPoint,
276  halfAngleRange,
277  thetaMin, thetaMax, phiMin, phiMax);
278  if(result) {
279  SetInternals(phiMin, phiMax,
280  thetaMin, thetaMax,
281  width_, height_);
282  }
283 
284  return result;
285 }
286 
287 
290 {
292  dynamic_cast<const ProjectionParametersGreatCircles*>(p);
293  if(ppbc == NULL)
294  return true;
295 
296  if(ppbc->focallengthTheta_ != focallengthTheta_)
297  return true;
298 
300  return true;
301 
302 
303 
304  return false;
305 }
306 
307 
310  HomgPoint2D& x,
311  bool IgnoreDistortion) const
312 {
313  //an ray intersects the image plane if it maps to
314 
315  if(localX[2] > 0.0) {
316  x = ProjectLocal(localX, IgnoreDistortion);
317  if(Equal(x[2], 0.0))
318  return false;
319  return (x[0]>=0.0 && x[1]>=0.0 &&
320  x[0]<=(double)(width_-1) && x[1]<=(double)(height_-1) );
321  }
322  return false;
323 }
324 
325 
327 ProjectLocal(const Vector3<double>& point, bool IgnoreDistortion) const
328 {
329  HomgPoint2D res(0,0,0);
330  double theta, phi;
331  if(LocalEuclideanCamCoordinates2SphericalAngles(point, phi, theta)) {
332  //successfull transformation to angles:
333  Angle2Image(phi, theta, res);
334  }
335  return res;
336 
337  /* if(CamCoordVectorToShiftedAngles_(point, theta, phi) != 0) {
338  return HomgPoint2D(0,0,0);
339  }
340 
341  return HomgPoint2D(ShiftedAnglesToImage(theta, phi)); */
342 
343 }
344 
347  bool IgnoreDistortion) const
348 {
349  BIASERR("unfinished\n");
350  BIASABORT;
351  return -1;
352 }
353 
354 
355 
358  const double& depth,
359  bool ignoreDistortion) const
360 {
361  Vector3<double> d, p;
362  UnProjectLocal(pos, p, d, ignoreDistortion);
363  double norm = d.NormL2();
364  if (Equal(norm, 0.0))
365  return HomgPoint3D(0,0,0,0);
366  HomgPoint3D local(d * (depth/norm));
367  local[3] = 1.0;
368  return Pose_.LocalToGlobal(local);
369 }
370 
371 
373 UnProjectLocal(const HomgPoint2D& cPos, Vector3<double>& pointOnRay,
374  Vector3<double>& direction, bool ignoreDistortion) const {
375  double theta, phi;
376  direction = Vector3<double>(0.0);
377  Image2Angle(cPos, phi, theta);
378  SphericalAngles2LocalEuclideanRay(phi, theta, direction);
379  pointOnRay = Vector3<double>(0.0);
380 }
381 
382 #ifdef BIAS_HAVE_XML2
383 
385  double& Version) const {
386  TopLevelTag = "ProjectionParametersGreatCircles";
387  Version = 0.1;
388  return 0;
389 }
390 
392  XMLIO& XMLObject) const {
393  xmlNodePtr theNode;
394  string TopLevelName;
395  double Version;
396  ProjectionParametersBase::XMLGetClassName(TopLevelName, Version);
397  theNode = XMLObject.addChildNode(Node, TopLevelName);
398  XMLObject.addAttribute(theNode, "Version", Version);
399  ProjectionParametersBase::XMLOut(theNode, XMLObject);
400 
401  XMLObject.addAttribute(Node,"focallengthTheta", focallengthTheta_);
402  return 0;
403  }
404 
405 
406 int ProjectionParametersGreatCircles::XMLIn(const xmlNodePtr Node,
407  XMLIO& XMLObject) {
408 
409  string TopLevelName;
410  double Version;
411  ProjectionParametersBase::XMLGetClassName(TopLevelName, Version);
412 
413  xmlNodePtr childNode;
414  if ((childNode = XMLObject.getChild(Node, TopLevelName))==NULL) {
415  BIASERR("Error in xml, no tag" << TopLevelName);
416  return -1;
417  }
418  if (ProjectionParametersBase::XMLIn(childNode, XMLObject)!=0) return -1;
419  focallengthTheta_ = XMLObject.getAttributeValueDouble(Node,
420  "focallengthTheta");
421  return 0;
422 }
423 
424 #endif // BIAS_HAVE_XML2
425 
426 
427 
void addAttribute(const xmlNodePtr Node, const std::string &AttributeName, bool AttributeValue)
Add an attribute to a node.
Definition: XMLIO.cpp:156
void Set(const T *pv)
copy the array of vectorsize beginning at *T to this-&gt;data_
Definition: Vector3.hh:532
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
void SetInternals(const double minPhi, const double maxPhi, const double minTheta, const double maxTheta, const unsigned int imgWidth, const unsigned int imgHeight)
Calculates and sets internal camera parameters.
virtual HomgPoint2D ProjectLocal(const Vector3< double > &point, bool IgnoreDistortion=false) const
calculates the projection of a point in the camera coordinate system to a pixel in the image plane of...
virtual int XMLOut(const xmlNodePtr Node, XMLIO &XMLObject) const
specialization of XML write function
virtual void UnProjectLocal(const HomgPoint2D &pos, Vector3< double > &pointOnRay, Vector3< double > &direction, bool ignoreDistortion=false) const
calculates the viewing ray from the camera center (in the camera coordinate system) which belongs to ...
virtual int XMLOut(const xmlNodePtr Node, XMLIO &XMLObject) const
Specialization of XML write function.
xmlNodePtr getChild(const xmlNodePtr ParentNode, const std::string &ChildName)
Get a child of a Parent node by specifying the childs name, NULL is returned if the ParentNode has no...
Definition: XMLIO.cpp:489
HomgPoint3D UnProjectToImagePlane(const HomgPoint2D &pos, const double &depth=1.0, bool IgnoreDistortion=false) const
map points from image onto unit diameter image plane in 3D.
virtual const bool DoIntrinsicsDiffer(const ProjectionParametersBase *p) const
ProjectionParametersGreatCircles & operator=(const ProjectionParametersGreatCircles &P)
virtual bool Undistort(BIAS::HomgPoint2D &point2d) const
Interface defintion for lens undistortion function, implemented by derived classes.
virtual int XMLIn(const xmlNodePtr Node, XMLIO &XMLObject)
Specialization of XML read function.
spherical camera that samples along big circles containig the H vector.
virtual const bool DoIntrinsicsDiffer(const ProjectionParametersBase *p) const
static bool SphericalAngles2LocalEuclideanRay(const double phi, const double theta, BIAS::Vector3< double > &ray)
Calculate euclidean ray direction in local camera frame from angles.
void Image2Angle(const BIAS::HomgPoint2D &imgPoint, double &phi, double &theta) const
Calculates local angle vectors from image coordinate.
virtual bool Distort(BIAS::HomgPoint2D &point2d) const
Interface defintion for lens distortion function, implemented by derived classes. ...
Wrapper class for reading and writing XML files based on the XML library libxml2. ...
Definition: XMLIO.hh:72
xmlNodePtr addChildNode(const xmlNodePtr ParentNode, const std::string &NewNodeName)
Add a child node to an incoming node with the given name.
Definition: XMLIO.cpp:131
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
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_...
virtual void Rescale(double ratio, const double offset=0.0)
double getAttributeValueDouble(const xmlAttrPtr Attribute) const
Definition: XMLIO.cpp:736
virtual int XMLGetClassName(std::string &TopLevelTag, double &Version) const
specialization of XML block name function
bool SetAngleInterval(const HomgPoint3D &worldPoint, const double &halfAngleRange)
Sets viewing volume of camera using GetAngleInterval().
virtual int XMLGetClassName(std::string &TopLevelTag, double &Version) const
Specialization of XML block name function.
bool GetAngleInterval(const HomgPoint3D &worldPoint, const double halfAngleRange, double &thetaMin, double &thetaMax, double &phiMin, double &phiMax) const
Determines angle intervalls for the camera from viewing cone.
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
virtual int XMLIn(const xmlNodePtr Node, XMLIO &XMLObject)
specialization of XML read function
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
Definition: Vector3.hh:633
bool DoesPointProjectIntoImageLocal(const Vector3< double > &localX, HomgPoint2D &x, bool IgnoreDistortion=false) const
Checks if 3D point projects into specified image and returns belonging 2D image point.
static bool LocalEuclideanCamCoordinates2SphericalAngles(const BIAS::Vector3< double > &euc, double &phi, double &theta)
Calculate spherical angles from local 3D point.
void Angle2Image(double phi, double theta, BIAS::HomgPoint2D &imgPoint) const
Calculates image coordinates from local angle vectors.
virtual ProjectionParametersBase & operator=(const ProjectionParametersBase &p)
class BIASGeometryBase_EXPORT HomgPoint3D