Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
biasmerge.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 <Base/Common/BIASpragma.hh>
26 
27 #include <Base/Image/ImageBase.hh>
28 #include <Base/Image/ImageIO.hh>
29 #include <stdio.h>
30 #include <map>
31 #include <string>
32 #include "Geometry/PMatrix.hh"
33 #include "Image/HomographyMapping.hh"
34 #include "Image/Camera.hh"
35 
36 using namespace BIAS;
37 using namespace std;
38 
39 /**
40  @file
41  @ingroup g_tools
42  @brief Merge a projection matrix and an image and write header data to image.
43  See biasmerge.cpp.
44  @author koeser
45 */
46 void usage()
47 {
48  cout << "Usage: biasmerge [options] files"<<endl;
49  cout <<" Options: "<< endl
50  <<" -s : search next smaller(string compare) PMatrix file"<<endl
51  <<" -b : assume bbc camera file format"<<endl
52  <<" -a : enforce aspect ratio 1, adapt P and image"<<endl
53  <<" -p : force principal point=image center, adapt P and image"
54  << endl
55  << endl;
56  cout <<"This program opens the image files given by the command line, "
57  <<"e.g. image037.pgm, looks at the command line for a file "
58  <<"image037.pgm.mat and attaches the pmatrix to the pgm header."<<endl
59  <<"With special options, you can enforce constraints on the KMatrix."
60  <<endl
61  <<"Returns: 0 on success, 1 if errors occured."<<endl<<endl
62  <<"e.g. biasmerge *.ppm *.ppm.mat"<<endl<<endl;
63 }
64 
65 int DetermineFiletype(const string &fn, ImageIO::TFileFormat &thetype)
66 {
67  int EndOfPrefix;
68  string suffix;
69 
70  EndOfPrefix = fn.rfind('.');
71 
72  suffix = fn.substr(EndOfPrefix+1,fn.length());
73  if (suffix == "pnm") thetype = ImageIO::FF_ppm;
74  else if (suffix == "ppm") thetype = ImageIO::FF_ppm;
75  else if (suffix == "pgm") thetype = ImageIO::FF_pgm;
76  else if (suffix == "mip") thetype = ImageIO::FF_mip;
77  else return -1;
78 
79  return 0;
80 }
81 
82 
83 int main (int argc, char *argv[])
84 {
85  bool Nearest = false, BBC = false, EnforceAspect = false,
86  EnforcePP = false;
87  double ShrinkFactor = 1.0;
88  int i = 1;
89  bool param = true;
90  while ((i<argc) && (param)) {
91  param = false;
92  if (!strcmp("-s",argv[i])) {
93  std::cout << "Using nearest P from command line also."<<endl;
94  Nearest = true;
95  i++;
96  param = true;
97  continue;
98  }
99  if (!strcmp("-b",argv[i])) {
100  std::cout << "Trying to load BBC camera data."<<endl;
101  BBC = true;
102  i++;
103  param = true;
104  continue;
105  }
106  if (!strcmp("-a",argv[i])) {
107  std::cout << "Enforcing aspect ratio 1."<<endl;
108  EnforceAspect = true;
109  i++;
110  param = true;
111  continue;
112  }
113  if (!strcmp("-p",argv[i])) {
114  std::cout << "Enforcing principal point to image center."<<endl;
115  EnforcePP = true;
116  i++;
117  param = true;
118  continue;
119  }
120  if (!strcmp("-h",argv[i])) {
121  std::cout << "Half image width and height."<<endl;
122  ShrinkFactor = 0.5;
123  i++;
124  param = true;
125  continue;
126  }
127  }
128 
129  if (i>=argc) {
130  usage();
131  return -1;
132  }
133 
134  ImageIO::TFileFormat FileType;
135  bool ErrorFlag = false;
136  int IOResult = 0;
137  BIAS::ImageBase CurImage;
138 
139  PMatrix P;
140  BIAS::UUID CurrUID;
141  map<string, PMatrix> mapP;
142  map<string, BIAS::UUID> mapPUIDs;
143 
144  for (int j=i; j<argc; j++) {
145  if (strstr(argv[j], ".mat")!=NULL) {
146  cout<<"arg "<<j<<" is .mat";
147  PMatrix P;
148  BIAS::UUID Puid;
149  char ctmp;
150  P.SetZero();
151  if (!BBC) {
152  // check for UID in PMatrix
153  std::ifstream fs( argv[j] );
154  fs>>P;
155  do {
156  fs.get(ctmp);
157  } while (!fs.eof() && ctmp!='#');
158  if (!fs.eof()){
159  fs.get(ctmp);
160  fs >> Puid;
161  fs.close();
162  mapPUIDs[argv[j]] =Puid;
163  };
164  } else {
165  P.LoadBBC(argv[j]);
166  }
167  cout << "P is "<<P<<endl;
168  mapP[argv[j]] = P;
169  }
170  }
171  if (mapP.size()==0) {
172  BIASERR("No matrices found !");
173  return -1;
174  }
175 
176 
177 
178 
179  for (;i<argc;i++) {
180  if (strstr(argv[i], ".mat")!=NULL) continue;
181  cout<< "Trying "<<argv[i]<<endl;
182  if (DetermineFiletype(argv[i], FileType)!=0) {
183  BIASERR("Skipping current file because of unknown/unsuported format: "
184  <<argv[i]<<endl<<"PMatrix can be written to mip,pgm,ppm,pnm");
185  ErrorFlag = true;
186  continue;
187  }
188 
189  IOResult = ImageIO::Load(argv[i], CurImage);
190  if (IOResult!=0) {
191  ErrorFlag = true;
192  BIASERR("Error "<<IOResult <<" reading "<< argv[i]);
193  continue;
194  }
195 
196  stringstream ss, filename;
197  filename << argv[i];
198  ss << argv[i] <<".mat";
199  if (mapP.find(ss.str())!=mapP.end()) {
200  cout<<"Found a mat file for "<< filename.str() <<endl;
201  P = mapP[ss.str()];
202  if (mapPUIDs.find(ss.str())!=mapPUIDs.end()) {
203  cout<<"Found a UID in P-mat file "<< filename.str() << " UID "
204  << mapPUIDs[ss.str()] << endl;
205  CurrUID = mapPUIDs[ss.str()];
206  }
207  } else {
208  if (!Nearest) {
209  cout <<"Found NO mat file for "<< filename.str()
210  <<" !!!!! SKIPPING"<<endl;
211  continue;
212  }
213  map<string,PMatrix>::iterator it = mapP.lower_bound(ss.str());
214  if (it != mapP.begin()) it--;
215  else cout<<"First element, cant use smaller, must use larger !";
216  P = it->second;
217  cout <<"Found next mat file for "<< filename.str()
218  <<": "<<it->first<<endl;
219  }
220 
221  if (EnforceAspect || EnforcePP || (ShrinkFactor!=1.0)) {
222  bool SkipWarping = true;
223  // check KMatrix, which components to adapt ?
224  KMatrix K = P.GetK();
225  int newimsizex = CurImage.GetWidth(),
226  newimsizey = CurImage.GetHeight();
227 
228  // check if aspect ratio is one and adapt if desired
229  if (EnforceAspect) {
230  if (K[0][0]>K[1][1]) {
231  newimsizey = (int)rint(double(newimsizey) * double(K[0][0]/K[1][1]));
232  K[1][2] *= double(K[0][0]/K[1][1]);
233  K[1][1] = K[0][0];
234  SkipWarping = false;
235  } else if (K[0][0]<K[1][1]) {
236  newimsizex = (int)rint(double(newimsizex) * double(K[1][1]/K[0][0]));
237  K[0][2] *= double(K[1][1]/K[0][0]);
238  K[0][0] = K[1][1];
239  SkipWarping = false;
240  }
241  }
242  // check if principal point is in image center and adapt if desired
243  if (EnforcePP) {
244  if (rint(K[0][2]*2.0)!=(newimsizex-1)) {
245  cout<<"changing ppx from "<<K[0][2];
246  SkipWarping = false;
247  K[0][2] = double(newimsizex-1) / 2.0;
248  cout<<" to "<<K[0][2]<<endl;
249  }
250  if (rint(K[1][2]*2.0)!=(newimsizey-1)) {
251  cout<<"changing ppy from "<<K[1][2];
252  SkipWarping = false;
253  K[1][2] = double(newimsizey-1) / 2.0;
254  cout<<" to "<<K[1][2]<<endl;
255  }
256  }
257  if (ShrinkFactor != 1.0) {
258  K[0][0] *= ShrinkFactor;
259  K[1][1] *= ShrinkFactor;
260  K[0][2] *= ShrinkFactor;
261  K[1][2] *= ShrinkFactor;
262  newimsizex = int(rint(double(newimsizex)*ShrinkFactor));
263  newimsizey = int(rint(double(newimsizey)*ShrinkFactor));
264  SkipWarping = false;
265  }
266 
267  // do we have any changes for the image data ?
268  if (!SkipWarping) {
269  // compose new P
270  RMatrix R;
271  Vector3<double> C;
272  P.GetR(R);
273  P.GetC(C);
274  PMatrix PCorrected(K, R, C);
275 
276  // compute homography for backward mapping and transform image
277  HMatrix H = P.GetK() * K.Invert();
278 
279  cout<<"Warping image from "<<CurImage.GetWidth()<<"x"
280  <<CurImage.GetHeight()<<" pixels to "<<newimsizex<<"x"
281  <<newimsizey<<" pixels."<<endl;
282  cout<<" K was "<<P.GetK()<<endl;
283  cout<<" K new "<<K<<endl;
284  cout<<"Warping homography is "<<H<<endl;
285  switch (CurImage.GetStorageType()) {
288  Image<unsigned char> origtemplated,
289  aspect1(newimsizex, newimsizey, CurImage.GetChannelCount());
290  aspect1.SetColorModel(CurImage.GetColorModel());
291  origtemplated.StealImage(CurImage);
292  Mapper.SetHomography(H);
293  Mapper.Map(origtemplated, aspect1);
294  CurImage.StealImage(aspect1);
295  P = PCorrected;
296  break;
297  }
298  default:BIASERR("storagetype "<<int(CurImage.GetStorageType())
299  <<" not implemented, please add the bit of code here");
300 
301  }
302  filename << "_warped";
303  }
304  }
305 
306  // just a dummy class to do the metadata job for us
308  c.SetP(P);
309  if (P.IsMetric()) {
310  c.SetK(P.GetK());
311  c.SetR(RMatrix(P.GetR()));
312  c.SetC(P.GetC());
313  }
314  c.UpdateMetaData();
315  CurImage.SetMetaData(*c.GetMetaData());
316  // if the image does not have a valid UID check for a UID in the PMatrix
317  if (!(CurImage.GetUID().IsValid()) && CurrUID.IsValid()){
318  CurImage.SetUID(CurrUID);
319  cout << "set UID from P matrix because image doesn't have a valid UID"
320  << endl;
321  }
322  /*
323  if (FileType==ImageIO::FF_mip) {
324  IOResult = ImageIO::Save(filename.str(), CurImage, false, false );
325  } else {
326  IOResult = ImageIO::Save(filename.str(), CurImage,
327  FileType, false,
328  0, false);
329  } */
330  IOResult = ImageIO::Save(filename.str(),
331  CurImage,
332  FileType,
333  false,
334  0,
335  false);
336 
337  if (IOResult!=0) {
338  ErrorFlag = true;
339  BIASERR("Error writing "<< filename.str());
340  continue;
341  } else cout<<filename.str()<<endl;
342 
343  }
344  if (ErrorFlag) cout << "There were errors." <<endl;
345  if (ErrorFlag) return 1;
346  return 0;
347 }
348 
349 
a 3x3 Matrix describing projective transformations between planes
Definition: HMatrix.hh:39
Maps image src to image sink with homography H (software implementation)
void SetColorModel(EColorModel Model)
Definition: ImageBase.hh:561
MetaData * GetMetaData()
Definition: ImageBase.hh:456
int SetP(const PMatrix &matP)
Definition: Camera.hh:102
unsigned int GetWidth() const
Definition: ImageBase.hh:312
const BIAS::UUID & GetUID() const
returns the UUID of the image
Definition: ImageBase.hh:449
3D rotation matrix
Definition: RMatrix.hh:49
void SetZero()
Sets all values to zero.
Definition: Matrix.hh:856
int StealImage(ImageBase &source)
steals the image data array from source, after releasing the actual image data and sets source image ...
Definition: ImageBase.cpp:395
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
TFileFormat
format specifier when writing an image to a file Do NOT change order or associated enum value because...
Definition: ImageIO.hh:76
unsigned int GetHeight() const
Definition: ImageBase.hh:319
void SetC(const Vector3< double > &C)
Definition: Camera.hh:167
int Map(const Image< InputStorageType > &src, Image< OutputStorageType > &sink, InterpolationMethod=MapTrilinear, bool newSink=false, double SuperSampling=1.0)
backward mapping with various interpolations
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
void SetUID(const BIAS::UUID &id)
Definition: ImageBase.hh:589
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
int UpdateMetaData()
copy P_ and co.
Definition: Camera.cpp:446
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
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
Definition: KMatrix.hh:48
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
describes a projective 3D -&gt; 2D mapping in homogenous coordinates
Definition: PMatrix.hh:88
void SetK(const KMatrix &K)
Definition: Camera.hh:173
interface class for producing/storing Universally Unique IDentifiers
Definition: UUID.hh:98
void SetMetaData(const MetaData &m)
Definition: ImageBase.hh:470
KMatrix Invert() const
returns analyticaly inverted matrix
Definition: KMatrix.cpp:31
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
void SetHomography(const HMatrix &H)
set your homography H (source = H * sink) before calling Map()
void SetR(const RMatrix &R)
Definition: Camera.hh:170
bool IsValid() const
checks whether this uuid is valid(true) or unitialized(false)
Definition: UUID.hh:210