Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
RectificationBase.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 #include <Image/RectificationBase.hh>
26 #include <Geometry/Projection.hh>
27 
28 using namespace BIAS;
29 using namespace std;
30 
31 template <class InputStorageType, class OutputStorageType>
34 {
35  delete ppBA_;
36  delete ppBB_;
37 }
38 
39 template <class InputStorageType, class OutputStorageType>
41 RectificationBase() : ppBA_(NULL), ppBB_(NULL)
42 { }
43 
44 template <class InputStorageType, class OutputStorageType>
47 {
48  cam.ParseMetaData();
49  return IsInputCameraValid(cam, cam.GetProj().GetParameters());
50 }
51 
52 
53 template <class InputStorageType, class OutputStorageType>
56 {
57  /* if (!IsInputCameraValid(cam)) {
58  return -1;
59  }*/
60 
61  cam.ParseMetaData();
62  //Projection P = cam.GetProj();
63  return SetCameraA(cam, cam.GetProj().GetParameters());
64 
65  /*delete ppBA_;
66  ppBA_ = NULL;
67 
68  if (P.GetParameters() == NULL) {
69  return -1;
70  } else {
71  ppBA_ = P.GetParameters()->Clone();
72  }
73 
74  if (cam.IsEmpty()) {
75  return -1;
76  }
77 
78  imageA_ = cam;
79 
80  return 0;*/
81 }
82 
83 
84 template <class InputStorageType, class OutputStorageType>
87  const BIAS::ProjectionParametersBase* proj)
88 {
89  if (!IsInputCameraValid(img, proj)) {
90  BIASERR("input camera is invalid!");
91  return -1;
92  }
93  int res = 0;
94 
95  bool setProjection = false;
96  if(ppBA_ == NULL) {
97  setProjection = true;
98  } else {
99  setProjection = (ppBA_->DoExtrinsicsDiffer(proj) || ppBA_->DoIntrinsicsDiffer(proj));
100  }
101 
102  if(setProjection)
103  {
104  delete ppBA_;
105  ppBA_ = NULL;
106 
107  if (proj == NULL) {
108  BIASERR("given projection is empty!")
109  return -1;
110  }
111 
112  ppBA_ = proj->Clone();
113  } else {
114  res = 1;
115  }
116 
117  if (img.IsEmpty()) {
118  return -1;
119  }
120 
121  imageA_ = Camera<InputStorageType>(img);
122 
123  return res;
124 }
125 
126 
127 template <class InputStorageType, class OutputStorageType>
130 {
131 
132  cam.ParseMetaData();
133  Projection P = cam.GetProj();
134  return SetCameraB(cam, P.GetParameters());
135 
136 // if (!IsInputCameraValid(cam)) {
137 // return -1;
138 // }
139 //
140 ////cam.ParseMetaData();
141 // Projection P = cam.GetProj();
142 //
143 // delete ppBB_;
144 // ppBB_ = NULL;
145 //
146 // if (P.GetParameters() == NULL) {
147 // return -1;
148 // } else {
149 // ppBB_ = P.GetParameters()->Clone();
150 // }
151 //
152 // if (cam.IsEmpty()) {
153 // return -1;
154 // }
155 //
156 // imageB_ = cam;
157 //
158 // return 0;
159 }
160 
161 
162 template <class InputStorageType, class OutputStorageType>
165  const BIAS::ProjectionParametersBase* proj)
166 {
167  if (!IsInputCameraValid(img, proj)) {
168  return -1;
169  }
170 
171  int res = 0;
172 
173  bool setProjection = false;
174  if(ppBB_ == NULL) {
175  setProjection = true;
176  } else {
177  setProjection = (ppBB_->DoExtrinsicsDiffer(proj) || ppBB_->DoIntrinsicsDiffer(proj));
178  }
179 
180  if(setProjection)
181  {
182  delete ppBB_;
183  ppBB_ = NULL;
184 
185  if (proj == NULL) {
186  return -1;
187  }
188 
189  ppBB_ = proj->Clone();
190  } else {
191  res = 1;
192  }
193 
194  if (img.IsEmpty()) {
195  return -1;
196  }
197 
198  imageB_ = Camera<InputStorageType>(img);
199 
200  return res;
201 }
202 
203 template <class InputStorageType, class OutputStorageType>
206 {
207  rectImg = rectImageA_;
208 }
209 
210 template <class InputStorageType, class OutputStorageType>
213 {
214  rectImg = rectImageB_;
215 }
216 
217 
218 template <class InputStorageType, class OutputStorageType>
220  OutputStorageType>::
221 GetImagePointerA()
222 {
223  return &imageA_;
224 }
225 
226 template <class InputStorageType, class OutputStorageType>
228  OutputStorageType>::
229 GetImagePointerB()
230 {
231  return &imageB_;
232 }
233 
234 template <class InputStorageType, class OutputStorageType>
235 const Image<OutputStorageType>* BIAS::RectificationBase<InputStorageType,
236  OutputStorageType>::
237 GetRectifiedImagePointerA()
238 {
239  return &rectImageA_;
240 }
241 
242 
243 template <class InputStorageType, class OutputStorageType>
244 const Image<OutputStorageType>* BIAS::RectificationBase<InputStorageType,
245  OutputStorageType>::
246 GetRectifiedImagePointerB()
247 {
248  return &rectImageB_;
249 }
250 
251 //=========================== STATIC UTILS ===============================
252 template <class InputStorageType, class OutputStorageType>
255  const Pose& poseCenter,
256  const Pose& poseRight,
257  Quaternion<double>& orientation)
258 {
259  Vector3<double> cL = poseLeft.GetC();
260  Vector3<double> cR = poseRight.GetC();
261  Vector3<double> cC = poseCenter.GetC();
262  if (Equal((cL-cR).NormL2(), 0.0)) {
263  return -1;
264  }
265  if (Equal((cL-cC).NormL2(), 0.0)) {
266  return -1;
267  }
268  if (Equal((cR-cC).NormL2(), 0.0)) {
269  return -1;
270  }
271 
272  //calculate mean baseline vector
273  Vector3<double> baseline = (cC-cL)+(cR-cL);
274  baseline.Normalize();
275  // baseline/=3.0;
276  // Vector3<double> baselineNormalized = baseline;
277  // baselineNormalized.
278 
279  //calcaulte mean optical axis
280  Vector3<double> meanOA;
281  //first determine the components orthogonal to the baseline
282  Vector3<double> z[3];
283  enum {left=0, center, right};
284  z[left] = poseLeft.GetZAxis();
285  z[right] = poseRight.GetZAxis();
286  z[center] = poseCenter.GetZAxis();
287  Vector3<double> baselineParallel[3]; //the zAxis part parallel to the baseline
288  baselineParallel[left] = baseline.ScalarProduct(z[left])*baseline;
289  baselineParallel[right] = baseline.ScalarProduct(z[right])*baseline;
290  baselineParallel[center] = baseline.ScalarProduct(z[center])*baseline;
291 
292  Vector3<double> baselineOrtho[3]; //the zAxis part parallel to the baseline
293  baselineOrtho[left] = z[left]-baselineParallel[left];
294  baselineOrtho[right] = z[right]-baselineParallel[right];
295  baselineOrtho[center] = z[center]-baselineParallel[center];
296 
297  meanOA = baselineOrtho[left]+baselineOrtho[right]+baselineOrtho[center];
298  meanOA.Normalize();
299  cerr<<"ortho? = "<<meanOA.ScalarProduct(baseline)<<endl;
300  Vector3<double> newYAxis = meanOA.CrossProduct(baseline);
301  // newYAxis.Normalize();//unneccessary !
302  RMatrix resOrientation;
303  for(unsigned int i=0; i<3; i++) {
304  resOrientation[i][0] = baseline[i];
305  resOrientation[i][1] = newYAxis[i];
306  resOrientation[i][2] = meanOA[i];
307  }
308  cerr<<resOrientation.GetDeterminant()<<endl;
309  cerr<<resOrientation<<endl;
310  resOrientation.GetQuaternion(orientation);
311 
312  return 0;
313 }
314 
315 template <class InputStorageType, class OutputStorageType>
318  const Pose& poseB,
319  Pose& poseResA,
320  Pose& poseResB,
321  bool failIfForwardMove)
322 {
323  if (Equal((poseA.GetC() - poseB.GetC()).NormL2(), 0.0)) {
324  BIASERR("poses for rectification have equal C" << endl)
325  return -1;
326  }
327 
328  Vector3<double> C[2], A[2]; // decomposed original cams
329  RMatrix R1,R2;
330  Vector3<double> Ap[2]; // decomposed virtual planar cams
331  Vector3<double> B; // Baseline vector
332  Vector3<double> Ac, Hc, Vc;
333 
334  R1 = poseA.GetR();
335  C[0] = poseA.GetC();
336  A[0].Set(R1[0][2], R1[1][2], R1[2][2]);
337 
338  R2 = poseB.GetR();
339  C[1] = poseB.GetC();
340  A[1].Set(R2[0][2], R2[1][2], R2[2][2]);
341 
342  B = C[1] - C[0];
343  B.Normalize();
344 
345  double scalarProduct[2];
346 
347  for (unsigned int i=0;i<2;i++){
348  //Project A onto B. Compute vector in direction of B and appropiate length.
349  //Redirect the imageplane normal A to Ap.
350  // Resulting Ap is orthonormal to B.
351 
352  scalarProduct[i] = A[i].ScalarProduct(B);
353  Ap[i] = A[i] - B * (scalarProduct[i]);
354  if(fabs(scalarProduct[i]) != 1.0)
355  Ap[i].Normalize();
356  else { //one camera is viewing along the baseline => forward move
357  if(failIfForwardMove){
358  BIASERR("no cylindrical rectification in case of forwar move" << endl)
359  return -2;
360  }
361  }
362 
363  }
364 
365  bool first = Equal(fabs(scalarProduct[0]), 1.0);
366  bool second = Equal(fabs(scalarProduct[1]), 1.0);
367 
368  if( first || second) {
369  //this case takes place when one of two cameras is viewing along
370  //the baseline
371  //multiplication by scalarProduct explained:
372  //if both cameras are facing each other or are rolled against each other
373  // then the following operation of taking the half vector can fail so
374  // both rectifying vectors Ap should lie in the same halfspace
375  //choose basevector perpendicular to viewing direction
376  if(first) {
377  Ap[0].Set(R1[0][0], R1[1][0], R1[2][0]);
378  Ap[0]*= -scalarProduct[0];
379  }
380  if(second) {
381  Ap[1].Set(R2[0][0], R2[1][0], R2[2][0]);
382  Ap[1]*= -scalarProduct[1];
383  }
384  }
385 
386  //normal vector of plane lies inbetween redirected imageplane normals
387  Ac = Ap[0] + Ap[1];
388  if(Equal(Ac.NormL2(), 0.0)) {
389  //if only one camera was viewing in direction of the baseline it might
390  // happen that the chosen direction of Ap is parallel to the other.
391  // decide for the other so that at least one rect image is close to
392  // viewing direction.
393  if(second)
394  Ac = Ap[0];
395  if(first)
396  Ac = Ap[1];
397  }
398  Ac.Normalize();
399  Hc = B;
400  Vc = Ac.CrossProduct(Hc);
401 
402 
403  RMatrix resR;
404  for(unsigned int i=0; i<3; i++) {
405  resR[i][0] = Hc[i];
406  resR[i][1] = Vc[i];
407  resR[i][2] = Ac[i];
408  }
409 
411  resR.GetQuaternion(Q);
412  poseResA.Set(Q, C[0]);
413  poseResB.Set(Q, C[1]);
414  return 0;
415 }
416 
417 
418 
419 namespace BIAS{
420 // TODO FIXME win32 template instantiation problem (JW)
422 template class RectificationBase<float, float>;
425 
426 #if defined(BUILD_IMAGE_CHAR)
427 // TODO FIXME win32 template instantiation problem (JW)
429 template class RectificationBase<char, char>;
430 #endif
431 
432 #if defined(BUILD_IMAGE_USHORT)
434 #endif
435 
436 #if defined(BUILD_IMAGE_SHORT)
437 template class RectificationBase<short, short>;
438 #endif
439 
440 #if defined(BUILD_IMAGE_SHORT)&&defined(BUILD_IMAGE_USHORT)
442 #endif
443 
444 #if defined(BUILD_IMAGE_INT)
445 template class RectificationBase<int,int>;
446 #endif
447 
448 #if defined(BUILD_IMAGE_USHORT)
450 #endif
451 
452 #if defined(BUILD_IMAGE_USHORT) && defined(BUILD_IMAGE_INT)
454 #endif
455 
456 #if defined(BUILD_IMAGE_DOUBLE)
457 template class RectificationBase<double,double>;
458 #endif
459 }
BIAS::RMatrixBase GetR() const
Get orientation of local coordinate system as rotation matrix mapping from local coordinates to globa...
void Set(const T *pv)
copy the array of vectorsize beginning at *T to this-&gt;data_
Definition: Vector3.hh:532
int Set(const PoseParametrization &pose)
Set pose from pose parametrization.
Definition: Pose.cpp:140
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
void GetRectifiedImageA(Image< OutputStorageType > &rectImg)
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
const Vector3< double > & GetC() const
Set origin of local coordinate system in global coordinates.
virtual ProjectionParametersBase * Clone() const =0
Covariant virtual copy constructor used in BIAS::Projection.
Vector3< double > GetZAxis() const
Definition: Pose.cpp:331
base class for rectification implementations and wrappers
int GetQuaternion(Quaternion< ROTATION_MATRIX_TYPE > &quat) const
Calculates quaternion representation for this rotation matrix.
static int CalculateRectifiedBases(const Pose &poseA, const Pose &poseB, Pose &poseResA, Pose &poseResB, bool failIfForwardMove=false)
Method determines two orthonormal bases suitable for rectification.
3D rotation matrix
Definition: RMatrix.hh:49
Represents 3d pose transformations, parametrized as Euclidean translation and unit quaternion orienta...
Definition: Pose.hh:73
bool IsInputCameraValid(BIAS::Camera< InputStorageType > &cam)
Method calls two parameteric pure virtual method.
void CrossProduct(const Vector3< T > &argvec, Vector3< T > &destvec) const
cross product of two vectors destvec = this x argvec
Definition: Vector3.hh:594
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
static int CalculateMeanOrientation(const Pose &poseLeft, const Pose &poseCenter, const Pose &poseRight, Quaternion< double > &orientation)
Method calculates an intermediate orientation for rectification from all three poses.
virtual int SetCameraB(BIAS::Camera< InputStorageType > &cam)
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_...
void GetRectifiedImageB(Image< OutputStorageType > &rectImg)
T GetDeterminant() const
returns the Determinant |A| of this
Definition: Matrix3x3.cpp:347
virtual int SetCameraA(BIAS::Camera< InputStorageType > &cam)
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
const BIAS::Projection & GetProj() const
Definition: Camera.hh:109
int ParseMetaData(bool bUse2x64bitTS=true)
After ImageIO::Load() operated on AppData_, this method fills P_, Timestamp, DC_*, ...
Definition: Camera.cpp:154
Vector3< T > & Normalize()
normalize this vector to length 1
Definition: Vector3.hh:663
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
Definition: Vector3.hh:633