Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
PlanarRectification.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 <Image/PlanarRectification.hh>
27 #include <Geometry/ProjectionParametersPerspective.hh>
28 
29 using namespace BIAS;
30 using namespace std;
31 
32 #define SUPERPARENT RectificationBase<InputStorageType, OutputStorageType>
33 #define PARENT RectificationViaProjectionMappingBase<InputStorageType, OutputStorageType>
34 
35 
36 template <class InputStorageType, class OutputStorageType>
39  PARENT::RectificationViaProjectionMappingBase("PlanarRectification"),
40  rectOrientationGiven_(false),
41  fixedIntrinsicsGiven_(false)
42 { }
43 
44 template <class InputStorageType, class OutputStorageType>
47 { }
48 
49 template <class InputStorageType, class OutputStorageType>
53 {
55  dynamic_cast<const ProjectionParametersPerspective*>(proj);
56 
57  if (ppp == NULL) {
58  return false;
59  }
60 
61  return true;
62 }
63 
64 template <class InputStorageType, class OutputStorageType>
67 {
68  rectOrientation_ = orientation;
69  rectOrientationGiven_ = true;
70  PARENT::rectificationParamsAreValid_ = false;
71 }
72 
73 template <class InputStorageType, class OutputStorageType>
76 {
77  fixedIntrinsicsA_ = fixedIntrinsicsB_ = ppp;
78  fixedIntrinsicsGiven_ = true;
79  PARENT::rectificationParamsAreValid_ = false;
80 }
81 
82 template <class InputStorageType, class OutputStorageType>
86 {
87  fixedIntrinsicsA_ = pppA;
88  fixedIntrinsicsB_ = pppB;
89  fixedIntrinsicsGiven_ = true;
90  PARENT::rectificationParamsAreValid_ = false;
91 }
92 
93 template <class InputStorageType, class OutputStorageType>
96 {
97 
98  Pose rectPoseA, rectPoseB;//, relativeTransformA, relativeTransformB;
99 
100  // simple test if rectification is necessary. fkellner
101  if (!SUPERPARENT::ppBA_->DoIntrinsicsDiffer(SUPERPARENT::ppBB_)) {
102  if (SUPERPARENT::ppBA_->GetQ().Dist(SUPERPARENT::ppBB_->GetQ()) == 0.0f) {
103  BIASWARN("The camera parameters look like the image pair is already "
104  "rectified! Parameters are cloned.");
105  PARENT::rectPPA_ = SUPERPARENT::ppBA_->Clone();
106  PARENT::rectPPB_ = SUPERPARENT::ppBB_->Clone();
107  return 0;
108  }
109  }
110 
111  if(!rectOrientationGiven_) {
112  BIASASSERT((SUPERPARENT::ppBA_)!=NULL);
113  BIASASSERT((SUPERPARENT::ppBB_)!=NULL);
114  if (SUPERPARENT::CalculateRectifiedBases(SUPERPARENT::ppBA_->GetPose(),
115  SUPERPARENT::ppBB_->GetPose(),
116  rectPoseA, rectPoseB, true) != 0) {
117  BIASERR("Failed to compute rectified base! Is epipole in any image?");
118  return -1;
119  }
120  } else {
121  Vector3<double> cA = SUPERPARENT::ppBA_->GetC();
122  Vector3<double> cB = SUPERPARENT::ppBB_->GetC();
123  rectPoseA.Set(rectOrientation_,cA);
124  rectPoseB.Set(rectOrientation_, cB);
125  }
126 
127  delete PARENT::rectPPA_;
128  delete PARENT::rectPPB_;
129  PARENT::rectPPA_ = new ProjectionParametersPerspective();
130  PARENT::rectPPB_ = new ProjectionParametersPerspective();
131 
133  dynamic_cast<ProjectionParametersPerspective*> (SUPERPARENT::ppBA_);
134  BIASASSERT(ppPA_ != NULL);
136  dynamic_cast<ProjectionParametersPerspective*> (SUPERPARENT::ppBB_);
137  BIASASSERT(ppPB_ != NULL);
138 
140  dynamic_cast<ProjectionParametersPerspective*> (PARENT::rectPPA_);
142  dynamic_cast<ProjectionParametersPerspective*> (PARENT::rectPPB_);
143 
144 
145  if(!fixedIntrinsicsGiven_) {
146  //the whole thing should be optimized/corrected! :
147  //KMatrix Ka = ppPA_->GetK();
148  //Ka[0][1] = 0;
149 
150  ////assume that images have very low roll component relative to each other
151  //// and that baseline direction is basically in direction of image width:
152  //unsigned int widthA, heightA;
153  //ppPA_->GetImageSize(widthA, heightA);
154  //unsigned int widthB, heightB;
155  //ppPB_->GetImageSize(widthB, heightB);
156  //int numSamplesOnEpiLine = (widthA>widthB) ? widthA : widthB;
157  //int numEpiLines = (heightA>heightB) ? heightA : heightB;
158 
159  //PARENT::rectPPA_->SetImageSize((unsigned int)numSamplesOnEpiLine,
160  // (unsigned int)numEpiLines);
161  //PARENT::rectPPB_->SetImageSize((unsigned int)numSamplesOnEpiLine,
162  // (unsigned int)numEpiLines);
163 
164  //rectPPPA_->SetK(Ka);
165  //rectPPPB_->SetK(Ka);
166 
167 
168 // cout<<"orig R A: "<<ppPA_->GetR()<<endl;
169 // cout<<"rect R A: "<<rectPoseA.GetR()<<endl;
170 // cout<<"orig R B: "<<ppPB_->GetR()<<endl;
171 // cout<<"rect R B: "<<rectPoseB.GetR()<<endl;
172 
173  //It can be assumed that the epipoles are not in the images!
174  //Determine the spherical angles in rectified frames.
175  CoordinateTransform3D spherePoseA = rectPoseA;
176  spherePoseA.RotateLocalFrame(Quaternion<double>(0, -sin(M_PI_4),
177  0, cos(M_PI_4)));
178  CoordinateTransform3D spherePoseB = rectPoseB;
179  spherePoseB.RotateLocalFrame(Quaternion<double>(0, -sin(M_PI_4),
180  0, cos(M_PI_4)));
181 
182  double anglesA[5];
183  double stepSizeA;
184  ppPA_->GetSphericalViewingRange(spherePoseA, anglesA[0], anglesA[1],
185  anglesA[2], anglesA[3], anglesA[4]);
186  ppPA_->GetMinimalAngularSamplingStep(stepSizeA);
187 
188 // for (unsigned int i = 0; i < 5; i++) {
189 // cout << "- anglesA[" << i << "] = " << anglesA[i]*180.0/M_PI
190 // << " degree" << endl;
191 // }
192 
193 
194  double anglesB[5];
195  double stepSizeB;
196  ppPB_->GetSphericalViewingRange(spherePoseB, anglesB[0], anglesB[1],
197  anglesB[2], anglesB[3], anglesB[4]);
198  ppPB_->GetMinimalAngularSamplingStep(stepSizeB);
199 
200 // for(unsigned int i = 0; i < 5; i++) {
201 // cout << "- anglesB[" << i << "] = " << anglesB[i]*180.0/M_PI
202 // << " degree" << endl;
203 // }
204 
205 
206 
207 
208  //find common viewing field, exploit that B lies in positive x direction
209  double minPhi = (anglesA[0]<anglesB[0]) ? anglesB[0] : anglesA[0];
210  double maxPhi = (anglesA[1]>anglesB[1]) ? anglesB[1] : anglesA[1];
211  //is the one we should always choose for the smaller angle
212  double minTheta = anglesB[3];
213  //is the one we should always choose for the larger angle
214  double maxTheta = anglesA[4];
215  //find resolution
216  double minAngleStep = (stepSizeA<stepSizeB) ? stepSizeA : stepSizeB;
217 
218  double aspectratio = 1.0;
219 
220  if(retainAspectRatio_) {
221  //calculate the means aspect ratio of original images:
222  double aspectratio =
223  ppPA_->GetAspectratio() +
224  ppPB_->GetAspectratio();
225  aspectratio /= 2.0;
226  if(aspectratio<1.0) {
227  minAngleStep *= aspectratio;
228  //do this to keep the minimal sampling step overall
229  }
230 
231  }
232 
233 // spherePoseA = ppPA_->GetPose();
234 // spherePoseA.RotateLocalFrame(Quaternion<double>(0, -sin(M_PI_4),
235 // 0, cos(M_PI_4)));
236 // spherePoseB = ppPB_->GetPose();
237 // spherePoseB.RotateLocalFrame(Quaternion<double>(0, -sin(M_PI_4),
238 // 0, cos(M_PI_4)));
239 // ppPA_->GetSphericalViewingRange(spherePoseA, anglesA[0], anglesA[1],
240 // anglesA[2], anglesA[3], anglesA[4]);
241 // ppPA_->GetMinimalAngularSamplingStep(stepSizeA);
242 
243 // for (unsigned int i = 0; i < 5; i++) {
244 // cout << "- orig anglesA[" << i << "] = " << anglesA[i]*180.0/M_PI
245 // << " degree" << endl;
246 // }
247 // ppPB_->GetSphericalViewingRange(spherePoseB, anglesB[0], anglesB[1],
248 // anglesB[2], anglesB[3], anglesB[4]);
249 // ppPB_->GetMinimalAngularSamplingStep(stepSizeB);
250 
251 // for(unsigned int i = 0; i < 5; i++) {
252 // cout << "- orig anglesB[" << i << "] = " << anglesB[i]*180.0/M_PI
253 // << " degree" << endl;
254 // }
255 
256 
257 
258 
259  //set intrinsics
260  rectPPPA_->SetIntrinsics(minPhi, maxPhi, minTheta, maxTheta,
261  minAngleStep, aspectratio);
262  rectPPPB_->SetIntrinsics(minPhi, maxPhi, minTheta, maxTheta,
263  minAngleStep, aspectratio);
264 
265  } else {
266  (*rectPPPA_) = fixedIntrinsicsA_;
267  (*rectPPPB_) = fixedIntrinsicsB_;
268  }
269 
270  rectPPPA_->SetPose(rectPoseA);
271  rectPPPB_->SetPose(rectPoseB);
272 
273 
274  return 0;
275 }
276 
277 
278 template <class InputStorageType, class OutputStorageType>
281 {
282  retainAspectRatio_ = retain;
283 }
284 
285 
286 namespace BIAS{
288 template class BIASImage_EXPORT PlanarRectification<float, float>;
289 template class BIASImage_EXPORT PlanarRectification<unsigned char, float>;
290 template class BIASImage_EXPORT PlanarRectification<float, unsigned char>;
291 
292 #if defined(BUILD_IMAGE_CHAR)
293 template class BIASImage_EXPORT PlanarRectification<unsigned char, char>;
294 template class BIASImage_EXPORT PlanarRectification<char, char>;
295 #endif
296 
297 #if defined(BUILD_IMAGE_USHORT)
299 #endif
300 
301 #if defined(BUILD_IMAGE_SHORT)
302 template class BIASImage_EXPORT PlanarRectification<short, short>;
303 #endif
304 
305 #if defined(BUILD_IMAGE_SHORT)&&defined(BUILD_IMAGE_USHORT)
306 template class BIASImage_EXPORT PlanarRectification<unsigned short, short>;
307 #endif
308 
309 #if defined(BUILD_IMAGE_INT)
310 template class BIASImage_EXPORT PlanarRectification<int,int>;
311 #endif
312 
313 #if defined(BUILD_IMAGE_USHORT)
314 template class BIASImage_EXPORT PlanarRectification<unsigned short,float>;
315 #endif
316 
317 #if defined(BUILD_IMAGE_USHORT) && defined(BUILD_IMAGE_INT)
318 template class BIASImage_EXPORT PlanarRectification<unsigned short,int>;
319 #endif
320 
321 #if defined(BUILD_IMAGE_DOUBLE)
322 template class BIASImage_EXPORT PlanarRectification<double,double>;
323 #endif
324 }
325 
void RetainOriginalApectRatio(bool retain=true)
If this is set to true, the rectification will use the mean of the input pixel aspect ratios for the ...
int SetIntrinsics(double minPhi, double maxPhi, double minTheta, double maxTheta, double angleStep, double aspectratio=1.0)
Method calculates K-Matrix and image size from specified angles.
virtual int DetermineRectificationParameters_()
current implementation is suboptimal, a beter way for the choise of internal parameters must be found...
Base class for rectification implementations that make use of projections to represent rectified stat...
int Set(const PoseParametrization &pose)
Set pose from pose parametrization.
Definition: Pose.cpp:140
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
void RotateLocalFrame(const Quaternion< double > &Q)
Applies the passed rotation to the orientation of the local frame.
virtual int GetSphericalViewingRange(const CoordinateTransform3D &sphericalReferenceFrame, double &minPhi, double &maxPhi, double &centerPhi, double &minTheta, double &maxTheta)
Determines the maximal and minimal viewing range in means of spherical coordinates.
virtual int GetMinimalAngularSamplingStep(double &minAngleStep)
Delivers the assumed minimal angular distance between two optical rays belonging to integer image coo...
virtual void SetPose(const BIAS::Pose pose)
Set pose from pose object.
Represents 3d pose transformations, parametrized as Euclidean translation and unit quaternion orienta...
Definition: Pose.hh:73
virtual double GetAspectratio() const
Return aspectratio (i.e.
void FixateIntrinsics(const ProjectionParametersPerspective &ppp)
Rectification via perspective cameras, removes distortions.
Transforms 3d points between two different coodinate systems, e.g.
void FixateRectOrientation(const Quaternion< double > &rectOrientation)
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
virtual bool IsInputCameraValid(const BIAS::Image< InputStorageType > &img, const BIAS::ProjectionParametersBase *proj)
Only works with perspective cameras.