Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ExampleProjectionMapping.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 ExampleProjectionMapping.cpp
27 * @relates ProjectionMapping
28 * @brief example for mapping images according to projection parameters
29 * @ingroup g_examples
30 * @author oniemann
31 */
32 
33 #include <Image/ProjectionMapping.hh>
34 #include <Base/Image/ImageIO.hh>
35 #include <Base/Image/ImageConvert.hh>
36 #include <Base/Image/Image.hh>
37 #include <Base/Debug/TimeMeasure.hh>
38 #include <Base/Math/Vector3.hh>
39 #include <Base/Math/Vector.hh>
40 #include <Utils/Param.hh>
41 #include <Utils/ThreeDOut.hh>
42 #include <Geometry/ProjectionParametersSpherical.hh>
43 #include <Image/Camera.hh>
44 
45 using namespace BIAS;
46 using namespace std;
47 
48 // Calculates rotationAngle for sequence steps in x or y (yaxis = true)
49 // direction.
50 void GetSequenceAngle(unsigned int & sequence ,Projection p1,
51  Projection p2, const bool yaxis, double & rotationAngle)
52 {
53  unsigned int width1,height1,width2,height2;
54  double angle1, angle2,focalLength;
55 
57  dynamic_cast<ProjectionParametersPerspective * >(p1.GetParameters());
59  dynamic_cast<ProjectionParametersSpherical * >(p1.GetParameters());
60  if (pPPP!=NULL){
61  pPPP->GetImageSize(width1,height1);
62  pPPP->GetFocalLength(focalLength);
63  if(!yaxis) angle1 = 2*atan(width1/(2*focalLength));
64  else angle1 = 2*atan(height1/(2*focalLength));
65  }
66  else if (pPPS!=NULL) angle1 = 1.7*pPPS->GetMaxCamAngle();
67  else{
68  cout<<"Hat nicht geklappt. Kamera 1 ist weder Perspektivisch, noch Spherisch.";
69  return;
70  }
71  pPPP = dynamic_cast<ProjectionParametersPerspective * >(p2.GetParameters());
72  pPPS = dynamic_cast<ProjectionParametersSpherical * >(p2.GetParameters());
73  if (pPPP!=NULL){
74  pPPP->GetImageSize(width2,height2);
75  pPPP->GetFocalLength(focalLength);
76  if(!yaxis) angle2 = 2*atan(width2/(2*focalLength));
77  else angle2 = 2*atan(height2/(2*focalLength));
78  }
79  else if (pPPS!=NULL) angle2 = 1.7*pPPS->GetMaxCamAngle();
80  else{
81  cout<<"Hat nicht geklappt. Kamera 2 ist weder Perspektivisch, noch Spherisch.";
82  return;
83  }
84  if(sequence == 0){
85  sequence =(unsigned int)(angle1/angle2);
86  rotationAngle = angle2;
87  }
88  else{
89  rotationAngle = (angle1-angle2)/((double)sequence-1);
90  }
91 
92  cout << "Abgedeckter Winkel: " << (rotationAngle*(sequence-1)*180/M_PI) << " Winkel der OriginalKamera: " << (angle1*180/M_PI) << " Winkel der ZielKamera: " << (angle2*180/M_PI) << endl;
93 }
94 
95 //Set a rotation of angle a around vector v for projection p.
96 void SetRotation(Projection & p,Vector3< ROTATION_MATRIX_TYPE > v,double a)
97 {
98  RMatrix R (v, a);
99  p.GetParameters()->SetR(R);
100 }
101 
102 //default sink projection
103 void GenerateProjection(Projection & p)
104 {
106 
107  pBase.SetImageSize(640,480);
108  pBase.SetFocalLengthAndAspect(800.0,1.0);
109  pBase.SetPrincipal(320,240);
110  p = Projection(pBase);
111  SetRotation(p,Vector3< ROTATION_MATRIX_TYPE > (0,1,0),0.5);
112 }
113 
114 int main(int argc, char *argv[])
115 {
116 
117  Param *param = new Param();
118  string sourceImage,sourceCam,sinkCam;
119  unsigned int sequence;
120  Vector< double > rotationVector;
121  double rotationAngle;
122  MetaData metaData;
123 
124  param->AddParamString("SourceImage",
125  "Absolute path to the source Image",
126  "",
127  'i');
128 
129  param->AddParamString("SinkImage",
130  "Absolute path to the sink Image",
131  "image_projection_trilinear",
132  'o');
133 
134  param->AddParamString("SourceCam",
135  "Absolute path to the source Camera calibration XML",
136  "",
137  'c');
138  param->AddParamDouble("RotationAngle",
139  "Angle to rotate around v in RAD (e.g. 0.1)",
140  0.0,
141  0.0,
142  2*M_PI,
143  'w');
144  param->AddParamString("SinkCam",
145  "Absolute path to the sink Camera calibration XML",
146  "",
147  's');
148  param->AddParamVecDbl("RotationVector",
149  "A Vector to rotate (e.g. 0.0 1.0 0.0)",
150  "0.0 1.0 0.0",
151  'v');
152  param->AddParamInt("Sequence",
153  "Give a number of images to create a sequence",
154  1,
155  1,
156  1000,
157  'S');
158  param->AddParamBool("Mosaic",
159  "Create a mosaic from Image?",
160  false,
161  'm');
162  param->ParseCommandLine(argc,argv);
163 
164  //Read and load source image and projection from parameters
165  sourceImage = *param->GetParamString("SourceImage");
166  sourceCam = *param->GetParamString("SourceCam");
167  if(sourceImage == "" || sourceCam == "")
168  {
169  BIASERR(argv[0]<<" -i<image-file> -c<SourceCamera-file>" <<
170  "-vaSs[Rotation-Vector Rotation-Angle] [Sequence] [SinkCamera-file]");
171  return -1;
172  }
173 
174 
176  if (ImageIO::Load(sourceImage, im)!=0){
177  BIASERR("error loading "<<sourceImage);
178  return -2;
179  }
181 
183  Projection p1,p2;
184 
185  if (p1.XMLRead(sourceCam)!=0) {
186  if (p1.ReadFromCamParamFile(sourceCam)!=0) {
187  BIASERR("Error reading "<<sourceCam);
188  return -3;
189  }
190  }
191  BIASASSERT(p1.GetParameters()!=NULL);
192  mapper.SetSourceCam(p1);
193 
194  //use default sink projection or load specified one
195  sinkCam = *param->GetParamString("SinkCam");
196  if(sinkCam == "") {
197  GenerateProjection(p2);
198  } else {
199  if (p2.XMLRead(sinkCam)!=0) {
200  if (p2.ReadFromCamParamFile(sinkCam)!=0) {
201  BIASERR("Error reading "<<sinkCam);
202  return -3;
203  }
204  }
205  }
206  BIASASSERT(p2.GetParameters()!=NULL);
207  //set the rotation for sink projection, default none
208  rotationVector = *param->GetParamVecDbl("RotationVector");
209  rotationVector.MultiplyIP(1.0/rotationVector.NormL2());
210  rotationAngle = *param->GetParamDouble("RotationAngle");
211  Vector3<ROTATION_MATRIX_TYPE> v(rotationVector);
212  SetRotation(p2,v,rotationAngle);
213  cout << rotationVector.Length() << endl;
214 
215  unsigned int width, height;
216 
217  sequence = *param->GetParamInt("Sequence");
218  bool mosaic = *param->GetParamBool("Mosaic");
219  //calculate the sequence angle if wanted
220  if(sequence > 1 && !mosaic)
221  {
222  GetSequenceAngle(sequence,p1,p2,false,rotationAngle);
223  }
224  p2.GetParameters()->GetImageSize(width,height);
225  cout<<"ROI of source image is "<<*im.GetROI()
226  <<" while image size is "<<width<<" x "<<height<<endl;
227  Camera<unsigned char> imrestrilinear;
228  imrestrilinear.Init(width,height,im.GetChannelCount());
229  // imrestrilinear(width,height, im.GetChannelCount());
230  //imrestrilinear.SetColorModel(im.GetColorModel());
231  cout<<"timing ..."<<endl<<flush;
232  mapper.SetPyramidSize(20);
233  TimeMeasure t1;
234  stringstream filename;
235  //ThreeDOut vrml;
236  //vrml.SetParamsCameraStyle(PyramidMesh);
237  //if(sequence>1) vrml.AddProjection(p1);
238  //calculate the image for given rotation angle or sequence
239 
240  for(unsigned int i=0;i<50;i++){
241  cout<<"Run: "<<i<<"/50"<<endl;
242  SetRotation(p2,v,(0.03*((double)i-(49.0/2.0))));
243  // vrml.AddProjection(p2);
244  mapper.SetSinkCam(p2);
245  mapper.Map(im, imrestrilinear, MapTrilinear);
246  imrestrilinear.SetProj(p2);
247  imrestrilinear.UpdateMetaData();
248  filename.str("");
249  char tmpStr[8];
250  sprintf(tmpStr, "%03i", i);
251  filename << "/datapc/sieg/oniemann/data/images/find/find_image_"<<tmpStr<<".mip";
252  //if (ImageIO::Save(filename.str(), imrestrilinear)!=0){
253  if (ImageIO::Save(filename.str(), imrestrilinear)!=0){
254  BIASERR("error image");
255  }
256  }
257 
258  if(!mosaic)
259  {
260  for (unsigned int i=0; i<sequence; i++) {
261  if(sequence > 1){
262  v[0] = 0.0;
263  v[1] = 1.0;
264  v[2] = 0.0;
265  cout << "Run "<<i<<endl;
266  cout << "RotationAngle: " << rotationAngle*((double)i-(((double)sequence-1)/2.0))*180/M_PI << endl;
267  SetRotation(p2,v,(rotationAngle*((double)i-(((double)sequence-1)/2.0))));
268  // vrml.AddProjection(p2);
269  }
270  else{
271  cout << "Angle: " << (rotationAngle*180/M_PI) << endl;
272  }
273  mapper.SetSinkCam(p2);
274  t1.Start();
275  // trilinear mapping with automatic scale and pyramid size selection
276  mapper.Map(im, imrestrilinear, MapTrilinear);
277  imrestrilinear.SetProj(p2);
278  imrestrilinear.UpdateMetaData();
279  t1.Stop();
280  filename.str("");
281  char tmpStr[8];
282  sprintf(tmpStr, "%03i", i);
283  filename << "/datapc/sieg/oniemann/data/images/reference/reference_image_000_"<<tmpStr<<".mip";
284  //if (ImageIO::Save(filename.str(), imrestrilinear)!=0){
285  if (ImageIO::Save(filename.str(), imrestrilinear)!=0){
286  BIASERR("error image");
287  }
288  }
289  }
290  //calculate mosaic image
291  else
292  {
293  double rotationAngle2;
294  unsigned int sequence2;
295  Vector3<ROTATION_MATRIX_TYPE> v2(1, 0, 0);
296  RMatrix R, R2, R3;
297 
298  sequence = 0;
299  sequence2 = 0;
300  GetSequenceAngle(sequence,p1,p2,false,rotationAngle);
301  GetSequenceAngle(sequence2,p1,p2,true,rotationAngle2);
302  //Run through ImageHeight
303  for ( unsigned int j=0; j<sequence2; j++) {
304  R3= RMatrix(v2, (rotationAngle2*((double)j-(((double)sequence2-1.0)/2.0))));
305  for (unsigned int i=0; i<sequence; i++) {
306  if(j%2==0){
307  R2= RMatrix(v, (rotationAngle*((double)i-(((double)sequence-1.0)/2.0))));
308  }
309  else{
310  R2= RMatrix(v, (rotationAngle*((double)i+0.5-(((double)sequence-1.0)/2.0))));
311  }
312  //Run through ImageWidth
313  cout << "Run " << i <<" " << j <<endl;
314 
315  R2.Mult(R3,R);
316  p2.GetParameters()->SetR(R);
317  mapper.SetSinkCam(p2);
318  t1.Start();
319  // trilinear mapping with automatic scale and pyramid size selection
320  imrestrilinear.FillImageWithConstValue((unsigned char)0);
321  mapper.Map(im, imrestrilinear, MapTrilinear);
322  imrestrilinear.SetProj(p2);
323  imrestrilinear.UpdateMetaData();
324  t1.Stop();
325  filename.str("");
326  char tmpStr[8];
327  sprintf(tmpStr, "%03i_%03i", j, i);
328  filename << "/datapc/sieg/oniemann/data/images/reference/reference_image_"<<tmpStr<<".mip";
329  //if (ImageIO::Save(filename.str(), imrestrilinear)!=0){
330  if (ImageIO::Save(filename.str(), imrestrilinear)!=0){
331  BIASERR("error image");
332  }
333  }
334  }
335  }
336 
337  //create vrml file
338  //vrml.VRMLOut("myVRML.wrl");
339 
340  cout <<"Trilinear mapping took "
341  <<t1.GetUserTime()/double(sequence)
342  <<" ms,"<<endl;
343 
344  return 0;
345 }
double * GetParamDouble(const std::string &name) const
Definition: Param.cpp:665
int XMLRead(const std::string &Filename)
derived classes must implement the function XMLIn which is called by this function XMLRead to read ev...
Definition: XMLBase.cpp:78
gray values, 1 channel
Definition: ImageBase.hh:130
virtual void SetR(const BIAS::RMatrix &R)
Set orientation from rotation matrix R.
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
void SetSinkCam(const Projection &P, const Image< float > *sinkdepth=NULL)
Set your sink projection before calling Map(),.
virtual void SetPrincipal(const double x, const double y)
Set principal point in pixels relative to top left corner, virtual overload to recalculate K_...
void SetSourceCam(const Projection &P)
Set your source projection before calling Map()
virtual void SetImageSize(const unsigned int w, const unsigned int h)
Set image dimensions (in pixels).
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
void SetPyramidSize(const int newsize)
sets pyramid size to pyramid and updates if neccessary
int ParseCommandLine(int &argc, char *argv[])
scan command line arguments for valid parameters
Definition: Param.cpp:1028
bool * GetParamBool(const std::string &name) const
Definition: Param.cpp:633
3D rotation matrix
Definition: RMatrix.hh:49
const ProjectionParametersBase * GetParameters(unsigned int cam=0) const
const parameter access function
Definition: Projection.hh:194
ROI * GetROI()
Returns a pointer to the roi object.
Definition: ImageBase.hh:615
void Mult(const Vector3< T > &argvec, Vector3< T > &destvec) const
matrix - vector multiplicate this matrix with Vector3, storing the result in destvec calculates: dest...
Definition: Matrix3x3.hh:302
This class hides the underlying projection model, like projection matrix, spherical camera...
Definition: Projection.hh:70
std::string * GetParamString(const std::string &name) const
Definition: Param.cpp:649
BIAS::Vector< double > * GetParamVecDbl(const std::string &name) const
Definition: Param.cpp:680
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
int SetProj(const Projection &Proj)
Definition: Camera.hh:106
void GetFocalLength(double &f) const
Get the current camera focal length.
int * GetParamInt(const std::string &name) const
Definition: Param.cpp:618
int Map(const Image< InputStorageType > &src, Image< OutputStorageType > &sink, InterpolationMethod=MapTrilinear, bool newSink=false, double SuperSampling=1.0)
backward mapping with various interpolations
void FillImageWithConstValue(StorageType Value)
fill grey images
Definition: Image.cpp:456
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
Definition: ImageIO.cpp:725
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
class Vector3 contains a Vector of fixed dim.
Definition: Matrix.hh:53
BIAS::Vector< double > * AddParamVecDbl(const std::string &name, const std::string &help, const BIAS::Vector< double > &deflt, char cmdshort=0, int Group=GRP_NOSHOW)
Add a parameter that expects a string on command line like &quot;&lt;value0&gt; &lt;value1&gt; &lt;value2&gt; ...
Definition: Param.cpp:378
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
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
int UpdateMetaData()
copy P_ and co.
Definition: Camera.cpp:446
This class Param provides generic support for parameters.
Definition: Param.hh:231
static int Load(const std::string &FileName, ImageBase &img)
first tries a call to Read MIP image and if that fails, tries to Import Image with all other availabl...
Definition: ImageIO.cpp:141
this class collects all additional data chunks of type AppData to be written into/read from an image ...
Definition: MetaData.hh:121
int * AddParamInt(const std::string &name, const std::string &help, int deflt=0, int min=std::numeric_limits< int >::min(), int max=std::numeric_limits< int >::max(), char cmdshort=0, int Group=GRP_NOSHOW)
For all adding routines:
Definition: Param.cpp:276
void SetFocalLengthAndAspect(double f, double AspectRatio)
Set the current camera focal length in pixel and the a spect ratio.
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
double GetMaxCamAngle() const
Get maximal camera angle (in rad), i.e.
double GetUserTime() const
return user time (=system usage time) in msec JW For Win32: user-time is the sum over all processes o...
class TimeMeasure contains functions for timing real time and cpu time.
Definition: TimeMeasure.hh:111
void MultiplyIP(const T &scalar)
in place multiplication with scalar
Definition: Vector.hh:202
int ReadFromCamParamFile(const std::string &filename, const bool silent=false)
Reads a camera data XML file and constructs the ProjectionParametersBase-pointer, using the Projectio...
Definition: Projection.cpp:99
static int ToGrey(const ImageBase &source, ImageBase &dest)
wrapper for the templated function ToGrey