Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ExampleRectification.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  * @example ExampleRectification.cpp
27  @relates RectificationBase, PlanarRectification, CylindricalRectification, SphericalRectification
28  @brief Example for image rectification.
29  @ingroup g_examples
30  @author MIP
31 */
32 
33 #include <iostream>
34 #include <Base/Image/ImageIO.hh>
35 #include <Image/Camera.hh>
36 #include <Image/PlanarRectification.hh>
37 #include <Image/CylindricalRectification.hh>
38 #include <Image/SphericalRectification.hh>
39 #include <Image/RectificationBase.hh>
40 #include <Utils/Param.hh>
41 #include <Utils/ThreeDOut.hh>
42 #include <Base/Image/ImageConvert.hh>
43 
44 using namespace std;
45 using namespace BIAS;
46 
47 //#define OutStorageType float
48 #define OutStorageType unsigned char
49 
50 
51 int main(int argc, char* argv[])
52 {
53  Param params(true);
54  bool* vrml = params.AddParamBool("writeVrml",
55  "Write out VRML with rectified geometry?",
56  false);
57 
58  bool* pointsonly =
59  params.AddParamBool("pointsOnly",
60  "Do not use texture but colored vertices instead?",
61  false);
62 
63  bool* help = params.AddParamBool("help", "", false, 'h');
64 
65  enum {cylindrical = 0, spherical, planar}; // rectTypeID;
66 
67  vector<string> rectificationTypes;
68  rectificationTypes.push_back("cylindrical");//0
69  rectificationTypes.push_back("spherical"); //1
70  rectificationTypes.push_back("planar"); //2
71  int* rectType =
72  params.AddParamEnum("type",
73  "Specifies type of rectification to perform:"
74  " [cylindrical], spherical, planar",
75  rectificationTypes);
76 
77  enum {Trilinear = 0, Bilinear};
78  vector<string> interpolationType;
79  interpolationType.push_back("Trilinear"); // = 0
80  interpolationType.push_back("Bilinear"); // = 1
81  int* interType =
82  params.AddParamEnum("interpolation",
83  "Specifies type interpolation to use:"
84  " [Trilinear], Bilinear",
85  interpolationType);
86 
87  double* resolution =
88  params.AddParamDouble("resolution",
89  "Scales the resolution of rectified images",
90  0.8, 0.001);
91 
92  bool* useLUT =
93  params.AddParamBool("useLUT",
94  "Turn off usage of lookup tables", true);
95 
96  string* rectSetupName =
97  params.AddParamString("rectSetup", "File that contains or shall contain the"
98  " rectification setup", "", 0, -1);
99 
100  int fup = params.ParseCommandLine(argc, argv);
101 
102  if(argc<3 || *help) {
103  cout<<"Determines rectification and stores them in name."<<endl<<endl;
104  cout<<"Usage: "<<argv[0]<<" [options] <origImgA> <origImgB>"<<endl;
105  params.Usage();
106  return 0;
107  }
108 
109  BIAS::Camera<unsigned char> RGBcamA, camA, RGBcamB, camB;
110 
111  if(ImageIO::Load(argv[fup], camA)!=0) {
112  cerr<<"[ERROR] Unable to load first camera!"<<endl;
113  return -1;
114  }
115 
116  if(ImageIO::Load(argv[fup+1], camB)!=0) {
117  cerr<<"[ERROR] Unable to second first camera!"<<endl;
118  return -1;
119  }
120 
121  BIAS::Camera<float> rectSetup;
122  bool useSetup = false;
123  bool generateSetup = false;
124  if(rectSetupName->size()>0) {
125  useSetup = true;
126  if(ImageIO::Load(*rectSetupName, rectSetup)<0) {
127  cerr<<"[ERROR] Could not open rectification setup file "
128  <<*rectSetupName<<endl;
129  cerr<<" It will be created from given parameters."<<endl;
130  generateSetup = true;
131  }
132  }
133  //camA.ParseMetaData();
134  //camB.ParseMetaData();
135 
138  rectifierPM = NULL;
139 
140  // Choose different rectification methods here
141  switch(*rectType) {
142  case cylindrical :
143  rectifier = rectifierPM =
145  break;
146  case spherical :
147  rectifier = rectifierPM =
149  break;
150  case planar :
151  rectifier = rectifierPM =
153  break;
154  default:
155  cerr<<"[ERROR] Unknown rectification type "
156  <<*rectType<<" given!"<<endl;
157  return -1;
158  }
159 
160  // Choose different interpolation methods here
161  switch(*interType) {
162  case Trilinear:
163  rectifierPM->SetInterpolationMethod(MapTrilinear);
164  break;
165  case Bilinear:
166  rectifierPM->SetInterpolationMethod(MapBilinear);
167  break;
168  default:
169  cerr<<"[ERROR] Unknown interpolation method "
170  <<*interType<<" given!"<<endl;
171  return -1;
172  }
173  rectifierPM->UseLookUpTables(*useLUT);
174  rectifierPM->SetScale(*resolution);
175  rectifierPM->SetSecondFill(255);
176  if( rectifier->SetCameraA(camA) != 0 ) {
177  cerr<<"[ERROR] Invalid camera type for camera A!"<<endl;
178  delete rectifier;
179  return -1;
180  }
181 
182  if( rectifier->SetCameraB(camB) != 0 ) {
183  cerr<<"[ERROR] Invalid camera type for camera B!"<<endl;
184  delete rectifier;
185  return -1;
186  }
187 
188  if(useSetup) {
189  if(generateSetup) {
190  if(rectifierPM->GetRectificationSetup(rectSetup)<0) {
191  cerr<<"[ERROR] Failed to create rectification setup!"<<endl;
192  return -1;
193  }
194  //if(ImageIO::Save(*rectSetupName, rectSetup)<0) {
195  if(ImageIO::Save(*rectSetupName, rectSetup)<0) {
196  cerr<<"[ERROR] Failed to write rectification setup to "
197  <<*rectSetupName<<endl;
198  return -1;
199  }
200  } else {
201  if(rectifierPM->SetRectificationSetup(rectSetup)<0) {
202  cerr<<"[ERROR] Failed to load rectification setup!"<<endl;
203  return -1;
204  }
205  }
206  }
207 
208  ProjectionParametersBase* rectPPA;
209  ProjectionParametersBase* rectPPB;
210 
211  if(rectifierPM->GetClonesOfRectificationParameters(rectPPA, rectPPB) != 0) {
212  cerr<<"[ERROR] Failed to retrieve rectification parameters!"<<endl;
213  delete rectifier;
214  return -1;
215  }
216 
217  cerr<<"Found rectification parameters!"<<endl;
218  cerr<<"- Camera A rectification state: "<<*rectPPA<<endl;
219  cerr<<"- Camera B rectification state: "<<*rectPPB<<endl<<endl;
220 
221  cerr<<"Starting rectification... "<<flush;
222  if(rectifier->Rectify()!=0) {
223  cerr<<" failed!"<<endl;
224  delete rectifier;
225  delete rectPPA;
226  delete rectPPB;
227  return -1;
228  }
229  cerr<<" done!"<<endl;
230 
231  Camera<OutStorageType> rectA, rectB, RGBrectA, RGBrectB;
232 
233  rectifier->GetRectifiedImageA(rectA);
234  rectA.SetProj(Projection(*rectPPA));
235  rectA.UpdateMetaData();
236 
237  rectifier->GetRectifiedImageB(rectB);
238  rectB.SetProj(Projection(*rectPPB));
239  rectB.UpdateMetaData();
240 
241  string path1, basename1, suffix1;
242  string path2, basename2, suffix2;
243  FileHandling::SplitName(argv[fup], path1, basename1, suffix1);
244  FileHandling::SplitName(argv[fup+1], path2, basename2, suffix2);
245 
246  string firstName = basename1+"_rect";//+suffix1;
247  string secondName = basename2+"_rect";//+suffix2;
248 
249 
250  if(ImageIO::Save(firstName, rectA, ImageIO::FF_mip)!=0) {
251  cerr<<"[ERROR] Failed to write first rectified image!"<<endl;
252  }
253  if(ImageIO::Save(secondName, rectB, ImageIO::FF_mip)!=0) {
254  cerr<<"[ERROR] Failed to write second rectified image!"<<endl;
255  }
256 
257  if(*vrml) {
258  ThreeDOut tdo;
259  tdo.AddProjection(camA.GetProj(), RGBAuc(0, 255, 0, 255));
260  tdo.AddProjection(camB.GetProj(), RGBAuc(0, 255, 0, 255));
261 // tdo.AddProjection(Projection(*rectPPA), RGBAuc(255, 0, 0, 255));
262 // tdo.AddProjection(Projection(*rectPPB), RGBAuc(255, 0, 0, 255));
263 
264  cerr<<"Generating VRML models with rectification data:"<<endl;
265  cerr<<"- First VRML containing coordinate systems only... "<<flush;
266  tdo.AddLine(rectPPA->GetC(), rectPPB->GetC());
267  bool good = false;
268  if(tdo.VRMLOut("rectCoordinates.wrl")!=0) {
269  good = false;
270  } else {
271  good = true;
272  }
273  if(good) {
274  cerr<<"done!";
275  } else {
276  cerr<<"failed!";
277  }
278  cerr<<endl;
279 
280  cerr<<"- Generating VRML models containing projected images... "<<flush;
281  unsigned int width = 0, height = 0;
282  rectPPA->GetImageSize(width, height);
283  Image<float> depthmap(width, height, 1);
284  depthmap.SetZero();
285 
286  double scale = 3.0;
287  if (*pointsonly) {
288  for (unsigned int y=0; y<height; y++) {
289  for (unsigned int x=0; x<width; x++) {
290  HomgPoint2D p2(x,y);
291  HomgPoint3D p3 = rectPPA->UnProjectToImagePlane(p2, scale*0.99);
292  if (p3.NormL2()<0.1) continue;
293  OutStorageType color = rectA.GetImageDataArray()[y][x];
294  RGBAuc theColor((unsigned char)color,(unsigned char)color,
295  (unsigned char)color,255);
296  tdo.AddPoint(p3, theColor);
297  }
298  }
299  } else {
300  RGBrectA.Init(rectA.GetWidth(), rectA.GetHeight(), 3);
301  ImageConvert::ToRGB(rectA, RGBrectA);
302  TriangleMesh T;
304  ImageConvert::ConvertST(RGBrectA, tmp, ImageBase::ST_unsignedchar);
305  T.GenerateTexturedCamera(rectPPA, tmp, scale*0.99) ;
306  tdo.AddTriangleMesh(T, "textureA.png", "textureA.png");
307  }
308 
309  if (*pointsonly) {
310  rectPPB->GetImageSize(width, height);
311  for (unsigned int y=0; y<height; y++) {
312  for (unsigned int x=0; x<width; x++) {
313  HomgPoint2D p2(x,y);
314  HomgPoint3D p3 = rectPPB->UnProjectToImagePlane(p2, scale*1.01);
315  if (p3.NormL2()<0.1) continue;
316  unsigned char color =
317  (unsigned char)rint(rectB.GetImageDataArray()[y][x]);
318  RGBAuc theColor(color,color,color,255);
319  tdo.AddPoint(p3, theColor);
320  }
321  }
322  } else {
323  RGBrectB.Init(rectB.GetWidth(), rectB.GetHeight(), 3);
324  ImageConvert::ToRGB(rectB, RGBrectB);
325  TriangleMesh T;
327  ImageConvert::ConvertST(RGBrectB, tmp, ImageBase::ST_unsignedchar);
328  T.GenerateTexturedCamera(rectPPB, tmp, scale*1.01) ;
329  tdo.AddTriangleMesh(T, "textureB.png", "textureB.png");
330  }
331  Vector3<double> c= rectPPA->GetC() - rectPPB->GetC();
332  cerr<<"done!"<<endl<<flush;
333 
334  tdo.VRMLOut("rectCoordinates_image.wrl");
335  cerr<<"- Writing mipview3d animation file 'cylindersweep.anim'... "<<flush;
336  ofstream myanimfile("cylindersweep.anim");
337  myanimfile <<"[0] :43 0 0 0 0 1 0 0 0"<<endl
338  <<"[0] :43 1000 " <<c[0]<<" "<<c[1]<<" "<<c[2]
339  <<" 1 0 0 0"<<endl;
340  cerr<<"done!"<<endl;
341  cerr<<"- Generating VRML models with original cameras... "<<flush;
342 
343  ThreeDOut tdo2;
344  RGBcamA.Init(camA.GetWidth(), camA.GetHeight(), 3);
345  ImageConvert::ToRGB(camA, RGBcamA);
346  RGBcamB.Init(camB.GetWidth(), camB.GetHeight(), 3);
347  ImageConvert::ToRGB(camB, RGBcamB);
348 
349  TriangleMesh T1, T2;
350  T1.GenerateTexturedCamera(camA.GetProj().GetParameters(), RGBcamA, scale);
351  T2.GenerateTexturedCamera(camB.GetProj().GetParameters(), RGBcamB, scale);
352  tdo2.AddTriangleMesh(T1, "textureAorig.png", "textureAorig.png");
353  tdo2.AddTriangleMesh(T2, "textureBorig.png", "textureBorig.png");
354  tdo2.AddProjection(camA.GetProj(), RGBAuc(0, 255, 0, 255),
355  scale*0.1, scale);
356  tdo2.AddProjection(camB.GetProj(), RGBAuc(0, 255, 0, 255),
357  scale*0.1, scale);
358  tdo2.VRMLOut("orig.wrl");
359  cerr<<"done!"<<endl<<flush;
360  }
361 
362  delete rectPPA;
363  delete rectPPB;
364  delete rectifier;
365 
366  return 0;
367 }
virtual BIAS::Vector3< double > GetC() const
Get projection center.
unsigned int AddTriangleMesh(const TriangleMesh &mesh, const std::string &name="", const std::string &textureOutputName="", bool writeOutTexture=true, bool calcNormals=false)
Adds triangle mesh as IndexedFaceSet to ThreeDOut mem.
Definition: ThreeDOut.cpp:1104
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
Base class for rectification implementations that make use of projections to represent rectified stat...
int VRMLOut(const std::string &sFilename)
flush all 3d objects to a vrml file with name sFilename, this is the function most users would call ...
Definition: ThreeDOut.cpp:3670
void GenerateTexturedCamera(const ProjectionParametersBase *PPB, Image< unsigned char > &rgbtexture, const double &scale=1.0, const double &opacity=1.0, const double &resolution=1.0)
generates the sensor plane / cylinder / sphere in 3D space
void GetRectifiedImageA(Image< OutputStorageType > &rectImg)
class RGBAuc is asynonym for a Vector4 of corerct type
Unified output of 3D entities via OpenGL or VRML.
Definition: ThreeDOut.hh:349
bool * AddParamBool(const std::string &name, const std::string &help, bool deflt=false, char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:305
double * AddParamDouble(const std::string &name, const std::string &help, double deflt=0.0, double min=-DBL_MAX, double max=DBL_MAX, char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:351
base class for rectification implementations and wrappers
virtual int GetClonesOfRectificationParameters(ProjectionParametersBase *&rectPPA, ProjectionParametersBase *&rectPPB)
Tries to calculate the rectification parameters and returns clones of internal members.
int SetRectificationSetup(Camera< float > &rectSetup)
Loads rectification setup from Camera data.
int * AddParamEnum(const std::string &name, const std::string &help, const std::vector< std::string > &enums, const int deflt=0, const std::vector< int > *IDs=NULL, const char cmdshort=0, const int Group=GRP_NOSHOW)
Definition: Param.cpp:468
Class implements rectification by image projection onto a cylinder.
void SetScale(const double &scale)
Scale factor for isotropically scaling the rectified images (and rectified intrinsic parameters)...
unsigned int GetWidth() const
Definition: ImageBase.hh:312
int ParseCommandLine(int &argc, char *argv[])
scan command line arguments for valid parameters
Definition: Param.cpp:1028
double NormL2() const
Return the L2 norm: sqrt(a^2 + b^2 + c^2 + d^2)
Definition: Vector4.hh:510
unsigned int AddProjection(const Projection &p, const RGBAuc &colorSelection=RGBAuc_WHITE_OPAQUE, const double radius=0.1, const double scale=1.0, const std::string &identifier="", const int camera_type=-1)
Add a projection object to ThreeDOut mem.
Definition: ThreeDOut.cpp:1308
int GetRectificationSetup(Camera< float > &rectSetup)
Method returns the current rectification setup.
void Usage(std::ostream &os=std::cout)
print Help-Information to stdout
Definition: Param.cpp:176
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
void SetInterpolationMethod(InterpolationMethod interpolationType)
Determines the type of interpolation used when rectifying.
Create and represent a 3D triangle mesh.
Definition: TriangleMesh.hh:84
int SetProj(const Projection &Proj)
Definition: Camera.hh:106
unsigned int GetHeight() const
Definition: ImageBase.hh:319
Class implements rectification by image projection onto a sphere.
void UseLookUpTables(bool use)
Method allows to turn on or off the use of look up tables.
Rectification via perspective cameras, removes distortions.
unsigned int AddLine(const BIAS::Vector3< double > &Start, const BIAS::Vector3< double > &End, const BIAS::RGBAuc &Color=RGBAuc_WHITE_OPAQUE)
Definition: ThreeDOut.cpp:756
void SetSecondFill(OutputStorageType d)
fill color for second image (first is black)
virtual int SetCameraB(BIAS::Camera< InputStorageType > &cam)
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
virtual int Rectify()=0
Fundamental method which contains the rectification implementation.
virtual int GetImageSize(unsigned int &Width, unsigned int &Height) const
Obtain image dimensions.
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
Definition: Image.cpp:421
int UpdateMetaData()
copy P_ and co.
Definition: Camera.cpp:446
This class Param provides generic support for parameters.
Definition: Param.hh:231
void GetRectifiedImageB(Image< OutputStorageType > &rectImg)
virtual int SetCameraA(BIAS::Camera< InputStorageType > &cam)
unsigned int AddPoint(const BIAS::Vector3< double > &v, const BIAS::RGBAuc &Color=RGBAuc_WHITE_OPAQUE)
Definition: ThreeDOut.cpp:719
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
std::string * AddParamString(const std::string &name, const std::string &help, std::string deflt="", char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:327
virtual HomgPoint3D UnProjectToImagePlane(const HomgPoint2D &pos, const double &depth=1.0, bool IgnoreDistortion=false) const =0
map points from image onto unit diameter image plane in 3D.
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153