Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
biasextract.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 <Image/Camera.hh>
27 #include <Image/CameraParam.hh>
28 #include <Base/Image/ImageIO.hh>
29 #include <Base/Image/ImageAttributes.hh>
30 #include <iostream>
31 #include <fstream>
32 
33 #ifdef WIN32
34 #include "Base/Common/getopt_W32.h"
35 #else //not WIN32
36 #include <unistd.h>
37 #endif //WIN32
38 
39 #include <Utils/Param.hh>
40 
41 using namespace std;
42 using namespace BIAS;
43 
44 
45 /**
46  * @file
47  * @ingroup g_tools
48  * @brief extract header data from image files: uid, time stamp orientation, KMatrix from EXIF data, see biasextract.cpp
49  * @author evers */
50 void usage()
51 {
52  cout <<"Usage: biasextract [options] Image ..."<<endl
53  <<" Options: "<<endl
54  <<"-a : extract ascii string"<<endl
55  <<"-t : extract timestamp as [sec usec]"<<endl
56  <<"-T : extract timestamp as [msec]"<<endl
57  <<"-s : suppress current filename in output"<<endl
58  <<"-P : extract P-Matrix"<<endl
59  <<"-p : Decompose P-Matrix and extract axis-angle orientation"
60  <<endl
61  <<"-x file : extract pmatrix as xml data"<<endl
62  <<"-K : extract internal parameter matrix"<<endl
63  <<"-R : extract rotation matrix"<<endl
64  <<"-r : extract axis-angle orientation"<<endl
65  <<"-C : extract camera center position"<<endl
66  <<"-A : extract viewing direction"<<endl
67  <<"-V : extract 'down' vector"<<endl
68  <<"-H : extract 'right' vector"<<endl
69  <<"-e : compute K from EXIF data"<<endl
70  <<"-c : compute CameraParam from KMatrix in header"<<endl
71  <<"-E : compute CameraParam from EXIF data"<<endl
72  <<"-u : extract UID"<<endl
73  <<"-O : extract orientation"<<endl
74  <<"-o file : write output to file"<<endl;
75 }
76 
77 
78 int main(int argc,char *argv[])
79 {
80  Param params(true);
81  /**** GENERAL PARAMS *****/
82  int generalGroupID = params.GetFreeGroupID();
83  bool* help = params.AddParamBool("help",
84  "print out help",
85  false, 'h',
86  generalGroupID);
87  params.SetGroupName(generalGroupID, "general");
88  /**** ADDITIONAL METADATA PARAMS *****/
89  int additionalDataGroupID = params.GetFreeGroupID();
90  bool* GetASCIIString = params.AddParamBool("GetASCIIString",
91  "extract ascii string",
92  false, 'a',
93  additionalDataGroupID);
94  bool* GetTimeStamp = params.AddParamBool("GetTimeStamp",
95  "extract timestamp as [sec usec]",
96  false, 't',
97  additionalDataGroupID);
98  bool* GetTimeMsec = params.AddParamBool("GetTimeMsec",
99  "extract timestamp as [msec]",
100  false, 'T',
101  additionalDataGroupID);
102  bool* GetUID = params.AddParamBool("GetUID",
103  "extract UID",
104  false, 'u',
105  additionalDataGroupID);
106  params.SetGroupName(additionalDataGroupID, "extract additional data");
107 
108  /**** CAMERA METADATA PARAMS *****/
109  int camParamGroupID = params.GetFreeGroupID();
110 
111  bool* GetPMatrix = params.AddParamBool("GetPMatrix",
112  "Decompose P-Matrix",
113  false, 'P',
114  camParamGroupID);
115  bool* GetPandDecomposition =
116  params.AddParamBool("GetPMatrixAndDecompose",
117  "Decompose P-Matrix and "
118  "extract axis-angle orientation",
119  false, 'p',
120  camParamGroupID);
121 
122  bool* GetR = params.AddParamBool("GetR",
123  "extract axis-angle orientation",
124  false, 'R',
125  camParamGroupID);
126  bool* GetAxisAngle = params.AddParamBool("GetAxisAngle",
127  "extract axis-angle orientation",
128  false, 'r',
129  camParamGroupID);
130 
131  bool* GetOri = params.AddParamBool("GetOri",
132  "extract orientation as yaw, pitch, roll",
133  false, 'O',
134  camParamGroupID);
135 
136 
137  bool* GetC = params.AddParamBool("GetC",
138  "extract camera center position",
139  false, 'C',
140  camParamGroupID);
141  bool* GetK = params.AddParamBool("GetK",
142  "extract internal parameter matrix",
143  false, 'K',
144  camParamGroupID);
145 
146  bool* GetKFromEXIF = params.AddParamBool("GetKFromEXIF",
147  "compute K from EXIF data",
148  false, 'e',
149  camParamGroupID);
150  bool* GetCameraParamFromEXIF =
151  params.AddParamBool("GetCameraParamFromEXIF",
152  "compute CameraParam from EXIF data",
153  false, 'E',
154  camParamGroupID);
155  bool* GetCameraParamFromK =
156  params.AddParamBool("GetCameraParamFromK",
157  "compute CameraParam from KMatrix in header",
158  false, 'c',
159  camParamGroupID);
160 
161 
162  bool* GetA = params.AddParamBool("GetA",
163  "extract viewing direction",
164  false, 'A',
165  camParamGroupID);
166  bool* GetH = params.AddParamBool("GetH",
167  "extract 'right' vector",
168  false, 'H',
169  camParamGroupID);
170  bool* GetV = params.AddParamBool("GetV",
171  "extract 'down' vector",
172  false, 'V',
173  camParamGroupID);
174 #ifdef BIAS_HAVE_XML2
175  string* PXMLName =
176  params.AddParamString("PXMLName",
177  "write out pmatrix as xml data"
178  " into this file",
179  "", 'x',
180  camParamGroupID);
181 
182 
183  string* GetProjection =
184  params.AddParamString("GetProjection",
185  "extract projection and write into this file",
186  "", 0,
187  camParamGroupID);
188 #endif
189 
190  params.SetGroupName(camParamGroupID, "extract camera parameters");
191 
192  /**** OUTPUT PARAMS *****/
193  int outputGroupID = params.GetFreeGroupID();
194 
195  bool* SuppressFilename =
196  params.AddParamBool("SuppressFilename",
197  "suppress current filename in output",
198  false, 's',
199  outputGroupID);
200 
201  string* Outfile = params.AddParamString("Outfile",
202  "write results into this file",
203  "", 'o',
204  outputGroupID);
205 
206  params.SetGroupName(outputGroupID, "output");
207 
208  int fup = params.ParseCommandLine(argc, argv);
209 
210  if(*help) {
211  usage();
212  params.Usage();
213  return 0;
214  }
215 
216 
217  if(*GetTimeMsec) *GetTimeStamp = true;
218  if(*GetPandDecomposition) {
219  *GetPMatrix = true;
220  *GetK = true;
221  *GetR = true;
222  *GetAxisAngle = true;
223  *GetC = true;
224  }
225 
226  bool GetPXML = false;
227 #ifdef BIAS_HAVE_XML2
228  if(PXMLName->size()>0) GetPXML = true;
229 #endif
230 
231  // //int c;
232  // int c=1;
233  // while(c >0) {
234  // c = getopt(argc,argv,"aceo:ptrsux:ETPKRCAHVO");
235  // if (c>0){
236  // switch(c) {
237  // // case 'a': GetASCIIString =true;
238  // // break;
239  // // case 't': GetTimeStamp = true;
240  // // break;
241  // // case 'e': GetKFromEXIF = true;
242  // // break;
243  // // case 'E': GetCameraParamFromEXIF = true;
244  // // break;
245  // // case 'c': GetCameraParamFromK = true;
246  // // break;
247  // // case 'T':
248  // // GetTimeStamp = true;
249  // // GetTimeMsec = true;
250  // // break;
251  // // case 'P': GetPMatrix = true;
252  // // break;
253  // // case 'p':
254  // // GetPMatrix = true;
255  // // GetK = true;
256  // // GetR = true;
257  // // GetAxisAngle = true;
258  // // GetC = true;
259  // // break;
260  // // case 'R': GetR = true;
261  // // break;
262  // // case 'r': GetAxisAngle = true;
263  // // break;
264  // // case 'C': GetC = true;
265  // // break;
266  // // case 'A': GetA = true;
267  // // break;
268  // // case 'H': GetH = true;
269  // // break;
270  // // case 'V': GetV = true;
271  // // break;
272  // // case 'K': GetK = true;
273  // // break;
274  // // case 'u': GetUID = true;
275  // // break;
276  // // case 'O': GetOri = true;
277  // // break;
278  // case 'o': Outfile = optarg;
279  // break;
280  // // case 's': SuppressFilename = true;
281  // // break;
282  // // case 'x': GetPXML = true;
283  // // PXMLName = optarg;
284  // // break;
285  // default:
286  // usage();
287  // //exit(1);
288  // return 0; // for Dart testing
289  // }
290  // }
291  // }
292 
293 
294  if (argc-fup < 1) {
295  cout <<"==> To few arguments."<<endl;
296  params.Usage();
297  usage();
298  exit(1);
299  }
300  ofstream ofs;
301  if (Outfile->size()>0) {
302  ofs.open(Outfile->c_str());
303  if (!ofs) {
304  perror(Outfile->c_str());
305  exit(1);
306  }
307  // cout <<"Writing to file: "<<*Outfile<<endl;
308  cout.rdbuf(ofs.rdbuf());
309  } else {
310  ;
311  // ofs = cout;
312  // if (!(*SuppressFilename))
313  // cout <<"Writing to stdout "<<endl;
314  }
315 
316  // Image<unsigned char> tmp;
317  ImageBase tmp;
318 
319  for ( int i=fup; i<argc;i++) {
320  // ImageIO::Load(argv[i],pic);
321  // ImageIO::Load(argv[i],pic);
322  ImageIO::Load(argv[i],tmp);
324  pic.SetMetaData(*tmp.GetMetaData());
325  pic.ParseMetaData();
326  if(*GetASCIIString) {
327  cerr<<"ASCII: "<<pic.GetASCIIString()<<endl;
328  }
329 
330  if (*GetKFromEXIF) {
331  ImageAttributes Att;
332  Att.InitExifTags();
333  if (Att.Read(argv[i])!=BIAS_IMAGEATTRIBUTES_SUCCESS) {
334  cerr<<"error reading exif tags ..."<<endl;
335  } else {
336  KMatrix KExif;
337  KExif.SetIdentity();
338  bool success = true;
339  success = success && (Att.GetFocalLengthXPixel(KExif[0][0])>=0);
340  success = success && (Att.GetFocalLengthYPixel(KExif[1][1])>=0);
341  success = success && (Att.GetPrincipalPoint(KExif[0][2],
342  KExif[1][2] )>=0);
343  if (success) {
344  cerr<<"K: ";
345  cout<<KExif<<endl;
346  } else {
347  cerr<<"Error, not enough EXIF data to get K:"<<KExif<<endl;
348  }
349  }
350  }
351  if (*GetCameraParamFromEXIF) {
352 #ifdef BIAS_HAVE_XML2
353  CameraParam cp;
354  if (cp.ReadFromEXIF(argv[i])==0) {
355  stringstream cpfilename;
356  cpfilename <<argv[i]<<".cameraparam.xml";
357  cp.WriteCameraData(cpfilename.str());
358  } else {
359  cerr<<"Error, not enough EXIF data to construct cameraparam"<<endl;
360  }
361 #else
362  cerr<<"Missing XML2 support led to missing class BIAS::CameraParam, "
363  <<"cant extract EXIF."<<endl;
364 #endif
365  }
366  pic.ParseMetaData();
367  if (!(*SuppressFilename)) cout <<argv[i]<<"\t"<<endl;
368  if (*GetUID) cout<<pic.GetUID()<<" ";
369  if (*GetTimeStamp) {
370  //long sec,usec;
371  unsigned long long int sec,usec;
372  pic.GetTime(sec,usec);
373  // cout <<"true msec: "<<pic.GetTime()<<endl;
374  if (GetTimeMsec) cout<< (sec % 1000) * 1000 + (usec / 1000);
375  else cout<<sec<<" "<<usec;
376  }
377  if (*GetOri) {
378  float y,p,r;
379  pic.GetOrientation(y,p,r);
380  cout<<y<<" "<<p<<" "<<r;
381  }
382  if (*GetPMatrix || GetPXML) {
383  //pic.PrintAppData(std::cout);
384  PMatrix P;
385  P.SetZero();
386  if (pic.IsPValid()) {
387  // read composed P directly, ignore possibel decomposition
388  P=pic.GetP();
389  };
390  // otherwise copose form K,R,C
391  // compose, if P is zero, too
392  if (!pic.IsPValid() || P.IsZero() ){
393  KMatrix K;
394  RMatrix R;
395  K.SetIdentity();
396  R.SetIdentity();
397  BIAS::Vector3<double> C(0,0,0);
398 
399  // check if valid Pose in meta data
400  if (pic.IsRValid())
401  R=pic.GetR();
402  else
403  BIASERR("could not read R, assuming identity");
404 
405  if (pic.IsCValid())
406  C=pic.GetC();
407  else
408  BIASERR("could not read C, assuming zero");
409 
410  if (pic.IsKValid())
411  K=pic.GetK();
412  else
413  BIASERR("could not read K, assuming identity");
414 
415  // compose from separation:
416  P.Compose(K, R, C);
417  }
418  if (*GetPMatrix)
419  cout<< P<<endl;
420  if (GetPXML) {
421 #ifdef BIAS_HAVE_XML2
422  P.XMLWrite(*PXMLName);
423 #else
424  cerr<<"No XML support found, so no writing of P as xml !"<<endl;
425 #endif
426  }
427  }
428  if (*GetK) {
429  KMatrix K;
430  if (pic.IsKValid()) {
431  K = pic.GetK();
432  } else {
433  PMatrix mytempP = pic.GetP();
434  K = mytempP.GetK();
435  }
436  cout<<"K: "<<K<<endl;
437  }
438  if (*GetR){
439  PMatrix P = pic.GetP();
440  cout<<"R: "<<P.GetR()<<endl;
441  }
442  if (*GetAxisAngle){
443  PMatrix P = pic.GetP();
444  Vector3<double> axis;
445  double angle;
446  RMatrix R;
447  R = P.GetR();
448  R.GetRotationAxisAngle(axis, angle);
449  cout<<"r[axis, angle]: "<<axis[0]<<" "<<axis[1]
450  <<" "<<axis[2]<<" "<<angle<<endl;
451  cout<<"|axis|= "<<axis.NormL2()<<endl;
452  cout<<"R: "<<R<<endl;
453  RMatrix temp;
454  temp.Set(axis, angle);
455  cout<<"R-axisAngle:\n "<<R-temp<<endl;
456 
457  }
458  if (*GetC){
459  PMatrix P = pic.GetP();
460  cout<<"C: "<<P.GetC()<<endl;
461  }
462  if (*GetA){
463  PMatrix P = pic.GetP();
464  cout<<"A: "<<P.GetA()<<endl;
465  }
466  if (*GetH){
467  PMatrix P = pic.GetP();
468  cout<<"H: "<<P.GetH()<<endl;
469  }
470  if (*GetV){
471  PMatrix P = pic.GetP();
472  cout<<"V: "<<P.GetV()<<endl;
473  }
474 
475  if (*GetCameraParamFromK) {
476 #ifdef BIAS_HAVE_XML2
477  KMatrix K;
478  bool HaveK = true;
479  if (pic.IsKValid()) {
480  K = pic.GetK();
481  } else if (pic.IsPValid()) {
482  PMatrix myp = pic.GetP();
483  K = myp.GetK();
484  } else {
485  HaveK = false;
486  }
487  if (HaveK) {
488  CameraParam cp(K, pic.GetWidth(), pic.GetHeight());
489  stringstream cpfilename;
490  cpfilename <<argv[i]<<".cameraparam.xml";
491  cp.WriteCameraData(cpfilename.str());
492  } else {
493  cerr<<"Error, no K to construct cameraparam"<<endl;
494  }
495 #else
496  cerr<<"Missing XML2 support led to missing class BIAS::CameraParam, "
497  <<"cant extract EXIF."<<endl;
498 #endif
499  }
500  cout<<endl;
501 #ifdef BIAS_HAVE_XML2
502  if(GetProjection->size() > 0) {
503  Projection proj = pic.GetProj();
504  if(proj.XMLWrite(*GetProjection)!=0) {
505  BIASERR("error writing projection");
506  }
507  }
508 #endif
509 
510  }//end of for
511 
512  if (Outfile->size() > 0)
513  ofs.close();
514 
515 
516  return 0;
517 }
void GetTime(unsigned long long int &sec, unsigned long long int &usec)
Definition: Camera.hh:139
bool IsZero(double eps=0.0) const
Checks if the matrix is a null matrix.
Definition: Matrix.cpp:638
const Vector3< double > & GetC() const
Definition: Camera.hh:168
bool IsCValid() const
Is field of data valid or unknown ? if false, the return value of the Get...()-function is undefined...
Definition: Camera.hh:213
bool IsKValid() const
Is field of data valid or unknown ? if false, the return value of the Get...()-function is undefined...
Definition: Camera.hh:207
void GetOrientation(float &o0, float &o1, float &o2) const
Definition: Camera.hh:160
MetaData * GetMetaData()
Definition: ImageBase.hh:456
bool * AddParamBool(const std::string &name, const std::string &help, bool deflt=false, char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:305
int GetPrincipalPoint(double &x, double &y)
look up principal point
int ReadFromEXIF(const std::string &filename)
read jpeg EXIF header and set camera parameter
int GetR(Matrix3x3< double > &R)
Definition: PMatrix.cpp:204
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
const BIAS::UUID & GetUID() const
returns the UUID of the image
Definition: ImageBase.hh:449
3D rotation matrix
Definition: RMatrix.hh:49
void Usage(std::ostream &os=std::cout)
print Help-Information to stdout
Definition: Param.cpp:176
void Set(const Vector3< ROTATION_MATRIX_TYPE > &w, const ROTATION_MATRIX_TYPE phi)
Set from rotation axis w and angle phi (in rad)
void SetZero()
Sets all values to zero.
Definition: Matrix.hh:856
This class hides the underlying projection model, like projection matrix, spherical camera...
Definition: Projection.hh:70
int XMLWrite(const std::string &Filename, int CompressionLevel=0, bool AutoAddCompressionSuffix=true, std::string encoding="UTF-8") const
call this to add the class to a new xml tree and write it to the file Filename.
Definition: XMLBase.cpp:40
int GetH(Vector3< double > &H)
returns the unit vector H0, while H0 and V0 span the camera coordinate system in world coordinates ...
Definition: PMatrix.cpp:237
unsigned int GetHeight() const
Definition: ImageBase.hh:319
int GetFreeGroupID()
returns unused group id
Definition: Param.cpp:1421
std::string GetASCIIString()
Definition: Camera.hh:117
int Read(const std::string &filename)
main entry routine to read all EXIF tags from the header of image file.
const BIAS::PMatrix & GetP() const
Definition: Camera.hh:104
int GetFocalLengthXPixel(double &fp)
compute focallength in pixels
int GetC(Vector3< double > &C)
computes translation vector origin world coo -&gt; origin camera coo (center), uses decomposition, which is cached
Definition: PMatrix.cpp:165
This class Param provides generic support for parameters.
Definition: Param.hh:231
int SetGroupName(const int group_id, const std::string &name)
sets the name for a group
Definition: Param.cpp:1448
contains all atribute info and values of e.g. a file.
void InitExifTags()
initialize me vector with all known EXIF tags
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
Definition: KMatrix.hh:48
int GetA(Vector3< double > &A)
returns the unit vector A which is the normal vector to the image plane in world coordinates.
Definition: PMatrix.cpp:287
bool IsRValid() const
Is field of data valid or unknown ? if false, the return value of the Get...()-function is undefined...
Definition: Camera.hh:210
int GetRotationAxisAngle(Vector3< ROTATION_MATRIX_TYPE > &axis, ROTATION_MATRIX_TYPE &angle) const
Calculates angle and rotation axis representation for this rotation matrix.
describes a projective 3D -&gt; 2D mapping in homogenous coordinates
Definition: PMatrix.hh:88
const RMatrix & GetR() const
Definition: Camera.hh:171
int WriteCameraData(const std::string &Filename) const
Write all data to a camera data parameter file )
void SetMetaData(const MetaData &m)
Definition: ImageBase.hh:470
bool IsPValid() const
Is field of data valid or unknown ? if false, the return value of the Get...()-function is undefined...
Definition: Camera.hh:204
const BIAS::Projection & GetProj() const
Definition: Camera.hh:109
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
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
int ParseMetaData(bool bUse2x64bitTS=true)
After ImageIO::Load() operated on AppData_, this method fills P_, Timestamp, DC_*, ...
Definition: Camera.cpp:154
int GetFocalLengthYPixel(double &fp)
compute focallength in pixels
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
Definition: Vector3.hh:633
const KMatrix & GetK() const
Definition: Camera.hh:174
int GetV(Vector3< double > &V)
This is not the cam.# standard CAHV, but the unit vector H0.
Definition: PMatrix.cpp:264
void Compose(const Matrix3x3< double > &K, const Matrix3x3< double > &R, const Vector3< double > &C)
composes this from K, R and C using P = [ K R&#39; | -K R&#39; C ] with R&#39; = transpose(R) ...
Definition: PMatrix.cpp:581
void SetIdentity()
set the elements of this matrix to the identity matrix (possibly overriding the inherited method) ...
Definition: Matrix3x3.hh:429
int GetK(KMatrix &K)
calibration matrix
Definition: PMatrix.cpp:220