Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
biasVrmlOutCameraGeometry.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  * @file
27  * @brief takes a texture list, a projection list and an output filename
28  * and creates a vrml named with output filename with the cameras
29  * drawn, the textures as images in the camera pyramids, see biasVrmlOutCameraGeometry.cpp
30  * @ingroup g_tools
31  * @author MIP
32  */
33 
34 
35 #include <Base/Image/ImageIO.hh>
36 #include <Base/ImageUtils/ImageDraw.hh>
37 #include <Base/Image/ImageConvert.hh>
38 #include <Image/Camera.hh>
39 
40 #include <Utils/Param.hh>
41 #include <Utils/TriangleMesh.hh>
42 #include <GLviewer/ThreeDOutOpenSceneGraph.hh>
43 
44 #include <iostream>
45 
46 
47 
48 using namespace std;
49 using namespace BIAS;
50 
51 
52 
53 void Usage()
54 {
55  cout <<"Usage: biasVrmlOutCameraGeometry --projsList projs.lst --texList tex.lst --points3D points3D.txt --projectPoint true"<<endl
56  <<endl;
57  cout <<" The tool creates a vrml file with the projections drawn as mesh cameras. " << endl
58  <<" If specified, it can add textures as images into the cameras, add 3D points to the scene " << endl
59  <<" and project these 3D points into the images. If drawRays is set to true rays from cam center through 2D point" << endl
60  <<" to 3D point will be drawn. " << endl
61  <<" ATTENTION: if projections are set in texture meta data projection list will be ignored!!! " << endl
62  <<" In case the image should be just white instead of having a texture, set texList to WHITE." << endl
63  <<" If the image should be black, set texList to BLACK."<< endl
64  <<" If projsList is set to manualProjs.projection, a params file for projections can be given in the form: " << endl
65  <<" width height " << endl
66  <<" focalLength " << endl
67  <<" centerX_1 centerY_1 centerZ_1 phiX_1 phiY_1 phiZ_1 " << endl
68  <<" centerX_2 centerY_2 centerZ_2 phiX_2 phiY_2 phiZ_2 " << endl
69  <<" ... " << endl
70  <<" ATTENTION: in this case texList must either be set to WHITE or BLACK." << endl
71  <<" ATTENTION: angles are specified in degrees." << endl
72  <<" See bottom of tool implementation for example files with points and manual cams. " << endl
73  <<" ATTENTION: only works with unsigned char textures for now." << endl
74  <<endl<<endl;
75 }
76 
77 
78 void readPoints(string& pointsFile, vector<HomgPoint3D>& points3D){
79 
80  std::fstream filestr;
81  filestr.open(pointsFile.c_str(), std::fstream::in);
82 
83  points3D.clear();
84 
85  double x, y, z;
86 
87  while (!filestr.eof()) {
88  filestr >> x;
89  filestr >> y;
90  filestr >> z;
91  if(x != -100.0 && y !=-100.0 && z != -100.0){
92  cout << "read point " << x << " " << y << " " << z << endl;
93  points3D.push_back(HomgPoint3D(x, y, z));
94  x = -100.0;
95  y = -100.0;
96  z = -100.0;
97  }
98  }
99 
100  filestr.close();
101 }
102 
103 void parseManualProjections(vector<Projection>& projs){
104 
105  std::fstream filestr;
106  filestr.open(string("manualProjs.projection").c_str(), std::fstream::in);
107 
108  projs.clear();
109 
110  unsigned int width, height;
111  double focalLength;
112 
113  double x, y, z;
114  double phiX, phiY, phiZ;
115 
116  filestr >> width;
117  filestr >> height;
118  filestr >> focalLength;
119 
120  cout << "read width " << width << " height " << height << " focal length " << focalLength << endl;
121 
123  Projection projection;
124  ppp.SetImageSize(width, height);
125  ppp.SetFocalLengthAndAspect(focalLength, 1.0);
126  ppp.SetPrincipal(width/2, height/2);
127  ppp.SetSkew(0);
128 
129  projection.AddAbsoluteCamera(&ppp);
130 
131  Vector3<double> center;
133 
134  while (!filestr.eof()) {
135  filestr >> x;
136  filestr >> y;
137  filestr >> z;
138  filestr >> phiX;
139  filestr >> phiY;
140  filestr >> phiZ;
141  if(x != -100.0 && y !=-100.0 && z != -100.0){
142  cout << "read center " << x << " " << y << " " << z << endl;
143  cout << "read rotation " << phiX << " " << phiY << " " << phiZ << endl;
144 
145  center[0] = x;
146  center[1] = y;
147  center[2] = z;
148 
149  q.SetXYZ(phiX/180.0*M_PI, phiY/180.0*M_PI, phiZ/180.0*M_PI);
150 
151  projection.SetQ(q);
152  projection.SetC(center);
153 
154  cout << "finished projection " << projection << endl;
155  projs.push_back(projection);
156 
157  x = -100.0;
158  y = -100.0;
159  z = -100.0;
160 
161  }
162  }
163 
164  filestr.close();
165 
166 
167 }
168 
169 // due to different interfaces, the colors for the points need to be created this way
170 void createColors(vector<unsigned char>& reds, vector<unsigned char>& greens, vector<unsigned char>& blues){
171 
172  reds.clear();
173  greens.clear();
174  blues.clear();
175 
176  // red
177  reds.push_back((unsigned char)200);
178  greens.push_back((unsigned char)0);
179  blues.push_back((unsigned char)0);
180 
181  // green
182  reds.push_back((unsigned char)0);
183  greens.push_back((unsigned char)200);
184  blues.push_back((unsigned char)0);
185 
186  // blue
187  reds.push_back((unsigned char)0);
188  greens.push_back((unsigned char)0);
189  blues.push_back((unsigned char)200);
190 
191  // yellow
192  reds.push_back((unsigned char)200);
193  greens.push_back((unsigned char)200);
194  blues.push_back((unsigned char)0);
195 
196  // magenta
197  reds.push_back((unsigned char)200);
198  greens.push_back((unsigned char)0);
199  blues.push_back((unsigned char)200);
200 
201  // cyan
202  reds.push_back((unsigned char)0);
203  greens.push_back((unsigned char)200);
204  blues.push_back((unsigned char)200);
205 
206  // light grey
207  reds.push_back((unsigned char)150);
208  greens.push_back((unsigned char)150);
209  blues.push_back((unsigned char)150);
210 
211  // dark grey
212  reds.push_back((unsigned char)70);
213  greens.push_back((unsigned char)70);
214  blues.push_back((unsigned char)70);
215 
216  // purple
217  reds.push_back((unsigned char)130);
218  greens.push_back((unsigned char)0);
219  blues.push_back((unsigned char)170);
220 
221 
222  // orange
223  reds.push_back((unsigned char)255);
224  greens.push_back((unsigned char)150);
225  blues.push_back((unsigned char)0);
226 
227 }
228 
229 int main(int argc, char* argv[]){
230 
231  Param param;
232 
233 
234 
235  string *projsList = param.AddParamString("projsList", "list with projections", "");
236  string *texList = param.AddParamString("texList","list with projection files", "");
237  string *points3DFile = param.AddParamString("points3D","file with 3D points","");
238  bool *projectPoints = param.AddParamBool("projectPoints", "set to true if 3D points are to be projected", false);
239  string *outFile = param.AddParamString("outFile", "filename of resulting vrml file", "scene.wrl");
240  bool *foreGroundLineColorBlack = param.AddParamBool("foreGroundLineColorBlack", "should foreground line colors be black or white", false);
241  bool *drawRays = param.AddParamBool("drawRays", "should rays be drawn?", false);
242  bool *draw3Dpoints = param.AddParamBool("draw3Dpoints","should 3D points be drawn or not", true);
243 
244  // make color vectors for points
245  vector<unsigned char> reds;
246  vector<unsigned char> greens;
247  vector<unsigned char> blues;
248  createColors(reds, greens, blues);
249 
250 
251  // update parameters from file with arguments from command line
252  if (argc == 1){
253  Usage();
254  return -1;
255  }
256 
257  param.ParseCommandLine(argc, argv);
258 
259  param.ShowData(cout);
260 
261  // read lists if specified
262  vector<string> projFiles;
263  vector<Projection> projs;
264  Projection P;
265  if(*projsList != "" && *projsList != "manualProjs.projection"){
266  Param::ParseListFile(*projsList, projFiles);
267  for(unsigned int i=0; i < projFiles.size(); i++){
268  P.Load(projFiles[i]);
269  projs.push_back(P);
270  }
271  } else if(*projsList == "manualProjs.projection"){
272  parseManualProjections(projs);
273  }
274 
275  // read texture filenames if specified
276  vector<string> texFiles;
277  if(*texList != "" && *texList != "WHITE" && *texList != "BLACK"){
278  Param::ParseListFile(*texList, texFiles);
279  }
280 
281  // read 3D points if specified
282  vector<HomgPoint3D> points3D;
283  if(*points3DFile != ""){
284  readPoints(*points3DFile, points3D);
285  }
286 
287  // init 3D out
288  ThreeDOutParameters params3d;
289  params3d.WCSAxesLength = -1;
290  params3d.PointStyle = BIAS::Sphere;
291  ThreeDOutOpenSceneGraph vrmlOut(params3d);
292 
293  // find out how many textures or projections there are
294  unsigned int numImgs = projs.size();
295  if(numImgs == 0){
296  numImgs = texFiles.size();
297  }
298 
299  // image holding texture
300  Camera<unsigned char> texture;
301  Camera<float> textureFl;
302 
303  // take care of each projection of the projection file list
304  for(unsigned int i = 0; i < numImgs; i++){
305 
306  // state vars
307  bool foundProjection = false;
308  bool haveTex = false;
309 
310  // load texture
311  bool searchFl = false;
312  if(texFiles.size() == numImgs){ // texture files have been specified
313  cout << "loading image... " << texFiles[i] << endl;
314  if(ImageIO::Load(texFiles[i], texture)!=0) {
315  cout<<"texture could not be loaded, trying to load float" << texFiles[i] << endl;
316  if(ImageIO::Load(texFiles[i], textureFl)!=0){
317  cout << "texture could still not be loaded, aborting" << endl;
318  BIASABORT;
319  } else {
320  searchFl = true;
321  textureFl.ScaleShift(255.0, 0);
322  ImageConvert::ConvertST(textureFl, texture, ImageBase::ST_unsignedchar);
323  }
324  }
325 
326  haveTex = true;
327 
328  cout << "done ... parsing meta data..." << endl;
329  texture.ParseMetaData();
330 
331  if(searchFl == false){
332  if(texture.IsProjValid()){
333  P = texture.GetProj();
334  projs.push_back(P);
335  foundProjection = true;
336  }
337  cout<<"finished reading texture \n";
338  } else {
339  textureFl.ParseMetaData();
340  if(textureFl.IsProjValid()){
341  P = textureFl.GetProj();
342  projs.push_back(P);
343  foundProjection = true;
344  }
345  cout<<"finished reading texture from fl \n";
346 
347  }
348  }
349 
350 
351  // check if projection is present from projections list
352  if(!foundProjection && projs.size() == numImgs) {
353  foundProjection = true;
354  }
355 
356  // cast projection and add camera to vrml out
357  ProjectionParametersBase* ppb = NULL;
358  if(foundProjection == true){
359  ppb = projs[i].GetParameters(0);
360  unsigned int width, height;
361  ppb->GetImageSize(width, height);
363  if(ppp == NULL){
364  cout << "only implemented for perspective case for now, returning" << endl;
365  return -1;
366  }
367  PMatrix pmatrix = ppp->GetP();
368  if(*foreGroundLineColorBlack){
369  vrmlOut.AddPMatrix(pmatrix, width, height, RGBAuc(0, 0, 0, 128), 1, "cam"+i);
370  } else {
371  vrmlOut.AddPMatrix(pmatrix, width, height, RGBAuc(255, 255, 255, 128), 1, "cam"+i);
372  }
373  }
374 
375 
376  // make black or white image as texture if specified
377  if(foundProjection && (*texList == "WHITE" || *texList == "BLACK")){
378  unsigned int width=0, height=0;
379  ppb->GetImageSize(width, height);
380  texture.Init(width, height, 3, BIAS::ImageBase::ST_unsignedchar, true);
381  unsigned char constColor[3];
382  if(*texList == "BLACK"){
383  constColor[0] = 0;
384  constColor[1] = 0;
385  constColor[2] = 0;
386  }
387  if(*texList == "WHITE"){
388  constColor[0] = 255;
389  constColor[1] = 255;
390  constColor[2] = 255;
391  }
392  texture.FillImageWithConstValue(constColor);
393  // texFiles.push_back("const_" + i);
394  haveTex = true;
395  }
396 
397 
398  // project 2D points
399  if((*projectPoints) && haveTex && foundProjection){
400  unsigned char* col = new unsigned char[3];
401  for(unsigned int j=0; j < points3D.size(); j++){
402  HomgPoint2D point2D;
403  bool projected = projs[i].DoesPointProjectIntoImage(points3D[j], point2D);
404  point2D.Homogenize();
405  cout << "projected point " << point2D << " in image? " << projected << endl;
406  if(projected){
407  point2D.Homogenize();
408  col[0] = reds[j%10];
409  col[1] = greens[j%10];
410  col[2] = blues[j%10];
411  ImageDraw<unsigned char>::CircleCenterFilled(texture, (unsigned int)rint(point2D[0]), (unsigned int)rint(point2D[1]), (unsigned int)50, col);
412  cout << "drawing point with color " << (int)rint(point2D[0]) << " " << (int)rint(point2D[1]) << " color " << (int)reds[j%10] << " " << (int)greens[j%10] << " " << (int)blues[j%10] << endl;
413 
414  if(*drawRays){
415  vrmlOut.AddLine(HomgPoint3D(projs[i].GetC()), points3D[j], RGBAuc(reds[j%10], greens[j%10], blues[j%10], 128));
416  }
417  }
418 
419  }
420  cout << "might need to save texture now " << endl;
421 
422  delete col;
423  }
424 
425  if(*texList=="WHITE" || *texList=="BLACK"){ // in case there no textures, they need to be created at this point
426  stringstream texname;
427  texname << "projImg_" << i << ".png";
428  cout << "saving texture " << texname.str() << endl;
429  texFiles.push_back(texname.str());
430  ImageIO::Save(texFiles.back(), texture);
431  }
432 
433 
434  // create mes of texture
435  if(haveTex){
436  cout<<"meshing..."; cout.flush();
437  TriangleMesh mesh(0.0,180.0);
438  // make one quad in 3d space
439  mesh.GenerateImagePlane(projs[i], texture);
440 
441 
442  vrmlOut.AddTriangleMesh(mesh, "mesh_from_"+string(texFiles[i]),
443  texFiles[i], true);
444 
445  }
446 
447  } // end of for loop projections/ images
448 
449 
450  if(*draw3Dpoints){
451  for(unsigned int i=0; i < points3D.size(); i++){
452  cout << "adding point with color " << reds[i%10] << " " << greens[i%10] << " " << blues[i%10] << endl;
453  vrmlOut.AddPoint(points3D[i], RGBAuc(reds[i%10], greens[i%10], blues[i%10], 128));
454  }
455  }
456 
457  cout<<"Writing osg to " << *outFile;
458 
459  vrmlOut.OpenSceneGraphOut(*outFile);
460 
461  cout<<" finished\n";
462 
463  return 0;
464 }
465 
466 /* Example file for manual cameras
467  * It depicts for cameras facing each other in a way that it works for making slides
468  *
469  * 1200 900
470  * 1000
471  * 0 0 1 30 140 0
472  * 4 0 1 40 220 0
473  * 3 0 -4 -20 -20 0
474  * 0 0 -4 -20 20 0
475  *
476 */
477 
478 /* 3D point list with points that are seen in the cam list above
479  * 2 0.5 -0.5
480  * 1.5 1.2 -1.2
481  * 1 0.9 -1.6
482  * 1.3 1.3 -1.4
483  * 0.8 1.5 -2
484  * 1.5 1 -2.1
485  *
486  */
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
virtual int Load(const std::string &filename)
convenience wrapper which tries to read different formats
Definition: Projection.cpp:62
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
virtual void SetPrincipal(const double x, const double y)
Set principal point in pixels relative to top left corner, virtual overload to recalculate K_...
class RGBAuc is asynonym for a Vector4 of corerct type
virtual void SetImageSize(const unsigned int w, const unsigned int h)
Set image dimensions (in pixels).
HomgPoint2D & Homogenize()
homogenize class data member elements to W==1 by divison by W
Definition: HomgPoint2D.hh:215
bool * AddParamBool(const std::string &name, const std::string &help, bool deflt=false, char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:305
configuration struct for drawing styles of various 3d objects
Definition: ThreeDOut.hh:309
int ScaleShift(double Scale, double Shift)
scales and shifts image (all channels simultanously)
Definition: Image.cpp:1064
double WCSAxesLength
&lt;=0 means no visual coordinate axes
Definition: ThreeDOut.hh:321
int SetXYZ(QUAT_TYPE radX, QUAT_TYPE radY, QUAT_TYPE radZ)
Sets quaternion as concatenated rotations around x,y,z-axis; this = q_x * q_y * q_z (BIAS-RMatrix con...
int ParseCommandLine(int &argc, char *argv[])
scan command line arguments for valid parameters
Definition: Param.cpp:1028
virtual void SetC(const Vector3< double > &C, unsigned int cam=0)
Set center of camera with index cam.
Definition: Projection.hh:331
void SetSkew(double skew)
Set the current camera skew factor.
This class hides the underlying projection model, like projection matrix, spherical camera...
Definition: Projection.hh:70
Create and represent a 3D triangle mesh.
Definition: TriangleMesh.hh:84
void FillImageWithConstValue(StorageType Value)
fill grey images
Definition: Image.cpp:456
void AddAbsoluteCamera(ProjectionParametersBase *ppb)
Add a camera to the projection,the coordinates of the pose are given in absolute Coordinates, they are transformed to relative coordinates to the first camera internally.
Definition: Projection.cpp:199
a class for exporting ThreeDOut objects to OSG scene graphs
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
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
This class Param provides generic support for parameters.
Definition: Param.hh:231
bool IsProjValid() const
Definition: Camera.hh:221
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
virtual void SetQ(const Quaternion< double > &Q, unsigned int cam=0)
Set rotation quaternion of camera with index cam.
Definition: Projection.hh:338
void ShowData(std::ostream &os=std::cout, int grp=GRP_ALL, bool showenhanced=true)
print all data in group grp including current values to os if grp = GRP_ALL, print all values if show...
Definition: Param.cpp:121
describes a projective 3D -&gt; 2D mapping in homogenous coordinates
Definition: PMatrix.hh:88
void SetFocalLengthAndAspect(double f, double AspectRatio)
Set the current camera focal length in pixel and the a spect ratio.
PointDrawingStyle PointStyle
Definition: ThreeDOut.hh:312
drawing simple entities into the image like rectangles or lines As all functions are static they have...
Definition: ImageDraw.hh:72
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
int ParseMetaData(bool bUse2x64bitTS=true)
After ImageIO::Load() operated on AppData_, this method fills P_, Timestamp, DC_*, ...
Definition: Camera.cpp:154