Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PanoToolsInterface.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
27 #include <hugin_config.h>
28 
29 #include <stdlib.h>
30 
31 #include "PanoToolsInterface.h"
32 
33 #include <vector>
34 #include <set>
35 #include <hugin_utils/utils.h>
36 #include <hugin_utils/stl_utils.h>
37 #include <panodata/PanoramaData.h>
39 
40 namespace HuginBase { namespace PTools {
41 
43 {
44  if (!m_initialized) {
47  }
48 }
49 
50 void Transform::updatePTData(const vigra::Diff2D &srcSize,
51  const VariableMap & srcVars,
53  const vigra::Diff2D & destSize,
55  const std::vector<double> & destProjParam,
56  double destHFOV)
57 {
58  if (m_initialized) {
61  }
62 
63  // fill our data into the Pano Tools structures.
64  setFullImage(m_srcImage, srcSize, 0,
65  srcVars, srcProj, true);
66  setDestImage(m_dstImage, destSize, 0, destProj, destProjParam, destHFOV);
67 }
68 
69 
70 void Transform::createTransform(const PanoramaData & pano, unsigned int imgNr,
71  const PanoramaOptions & dest, vigra::Diff2D srcSize)
72 {
73  const SrcPanoImage & img = pano.getImage(imgNr);
74  if (srcSize.x == 0 && srcSize.y == 0) {
75  srcSize.x = img.getWidth();
76  srcSize.y = img.getHeight();
77  }
78  createTransform(srcSize,
79  pano.getImageVariables(imgNr),
80  (Lens::LensProjectionFormat)pano.getImage(imgNr).getProjection(),
81  vigra::Diff2D(dest.getWidth(), dest.getHeight()),
82  dest.getProjection(),
84  dest.getHFOV(),
85  vigra::Diff2D(img.getWidth(), img.getHeight()));
86 }
87 
89 {
90  VariableMap vars;
91  // not very nice, but I don't like to change all the stuff in this file..
92  vars.insert(make_pair(std::string("v"), Variable(std::string("v"), src.getHFOV())));
93  vars.insert(make_pair(std::string("a"), Variable("a", src.getRadialDistortion()[0])));
94  vars.insert(make_pair(std::string("b"), Variable("b", src.getRadialDistortion()[1])));
95  vars.insert(make_pair(std::string("c"), Variable("c", src.getRadialDistortion()[2])));
96  vars.insert(make_pair(std::string("d"), Variable("d", src.getRadialDistortionCenterShift().x)));
97  vars.insert(make_pair(std::string("e"), Variable("e", src.getRadialDistortionCenterShift().y)));
98  vars.insert(make_pair(std::string("g"), Variable("g", src.getShear().x)));
99  vars.insert(make_pair(std::string("t"), Variable("t", src.getShear().y)));
100 
101  vars.insert(make_pair(std::string("r"), Variable("r", src.getRoll())));
102  vars.insert(make_pair(std::string("p"), Variable("p", src.getPitch())));
103  vars.insert(make_pair(std::string("y"), Variable("y", src.getYaw())));
104 
105  vars.insert(make_pair(std::string("TrX"), Variable("TrX", src.getX())));
106  vars.insert(make_pair(std::string("TrY"), Variable("TrY", src.getY())));
107  vars.insert(make_pair(std::string("TrZ"), Variable("TrZ", src.getZ())));
108 
109  vars.insert(make_pair(std::string("Tpy"), Variable("Tpy", src.getTranslationPlaneYaw())));
110  vars.insert(make_pair(std::string("Tpp"), Variable("Tpp", src.getTranslationPlanePitch())));
111 
112  createInvTransform(src.getSize(),
113  vars,
114  (Lens::LensProjectionFormat) src.getProjection(),
115  dest.getSize(),
116  dest.getProjection(),
118  dest.getHFOV(),
119  src.getSize());
120 }
121 
123 {
124 
125  VariableMap vars;
126  // not very nice, but I don't like to change all the stuff in this file..
127  vars.insert(make_pair(std::string("v"), Variable(std::string("v"), src.getHFOV())));
128  vars.insert(make_pair(std::string("a"), Variable("a", src.getRadialDistortion()[0])));
129  vars.insert(make_pair(std::string("b"), Variable("b", src.getRadialDistortion()[1])));
130  vars.insert(make_pair(std::string("c"), Variable("c", src.getRadialDistortion()[2])));
131  vars.insert(make_pair(std::string("d"), Variable("d", src.getRadialDistortionCenterShift().x)));
132  vars.insert(make_pair(std::string("e"), Variable("e", src.getRadialDistortionCenterShift().y)));
133  vars.insert(make_pair(std::string("g"), Variable("g", src.getShear().x)));
134  vars.insert(make_pair(std::string("t"), Variable("t", src.getShear().y)));
135 
136  vars.insert(make_pair(std::string("r"), Variable("r", src.getRoll())));
137  vars.insert(make_pair(std::string("p"), Variable("p", src.getPitch())));
138  vars.insert(make_pair(std::string("y"), Variable("y", src.getYaw())));
139 
140  vars.insert(make_pair(std::string("TrX"), Variable("TrX", src.getX())));
141  vars.insert(make_pair(std::string("TrY"), Variable("TrY", src.getY())));
142  vars.insert(make_pair(std::string("TrZ"), Variable("TrZ", src.getZ())));
143 
144  vars.insert(make_pair(std::string("Tpy"), Variable("Tpy", src.getTranslationPlaneYaw())));
145  vars.insert(make_pair(std::string("Tpp"), Variable("Tpp", src.getTranslationPlanePitch())));
146 
147  createTransform(src.getSize(),
148  vars,
149  (Lens::LensProjectionFormat) src.getProjection(),
150  dest.getSize(),
151  dest.getProjection(),
153  dest.getHFOV(),
154  src.getSize());
155 }
156 
157 
158 void Transform::createTransform(const vigra::Diff2D & srcSize,
159  VariableMap srcVars,
161  const vigra::Diff2D &destSize,
163  const std::vector<double> & destProjParam,
164  double destHFOV,
165  const vigra::Diff2D & originalSrcSize)
166 {
167  m_srcTX = destSize.x/2.0;
168  m_srcTY = destSize.y/2.0;
169 
170  m_destTX = srcSize.x/2.0;
171  m_destTY = srcSize.y/2.0;
172 
173  // adjust parameters dependant on the image size.
174  if (originalSrcSize.x != 0 && originalSrcSize.y != 0) {
175  double rx = srcSize.x / (double)originalSrcSize.x;
176  double ry = srcSize.y / (double)originalSrcSize.y;
177  map_get(srcVars,"d").setValue( map_get(srcVars,"d").getValue() * rx );
178  map_get(srcVars,"e").setValue( map_get(srcVars,"e").getValue() * ry );
179  }
180 
181  updatePTData(srcSize, srcVars, srcProj,
182  destSize, destProj, destProjParam, destHFOV);
183  // create the actual stack
184  SetMakeParams( m_stack, &m_mp, &m_srcImage , &m_dstImage, 0 );
185 }
186 
187 
188 void Transform::createInvTransform(const PanoramaData & pano, unsigned int imgNr,
189  const PanoramaOptions & dest, vigra::Diff2D srcSize)
190 {
191  const SrcPanoImage & img = pano.getImage(imgNr);
192  if (srcSize.x == 0 && srcSize.y == 0) {
193  srcSize.x = img.getWidth();
194  srcSize.y = img.getHeight();
195  }
196  createInvTransform(srcSize,
197  pano.getImageVariables(imgNr),
198  (Lens::LensProjectionFormat)pano.getImage(imgNr).getProjection(),
199  vigra::Diff2D(dest.getWidth(), dest.getHeight()),
200  dest.getProjection(),
202  dest.getHFOV(),
203  vigra::Diff2D(img.getWidth(), img.getHeight()));
204 }
205 
206 void Transform::createInvTransform(const vigra::Diff2D & srcSize,
207  VariableMap srcVars,
209  const vigra::Diff2D & destSize,
211  const std::vector<double> & destProjParam,
212  double destHFOV,
213  const vigra::Diff2D & originalSrcSize)
214 {
215  m_srcTX = srcSize.x/2.0;
216  m_srcTY = srcSize.y/2.0;
217 
218  m_destTX = destSize.x/2.0;
219  m_destTY = destSize.y/2.0;
220 
221  // adjust parameters dependant on the image size.
222  if (originalSrcSize.x != 0 && originalSrcSize.y != 0) {
223  double rx = srcSize.x / (double)originalSrcSize.x;
224  double ry = srcSize.y / (double)originalSrcSize.y;
225  map_get(srcVars,"d").setValue( map_get(srcVars,"d").getValue() * rx );
226  map_get(srcVars,"e").setValue( map_get(srcVars,"e").getValue() * ry );
227  }
228 
229  updatePTData(srcSize, srcVars, srcProj,
230  destSize, destProj,
231  destProjParam,
232  destHFOV);
233  // create the actual stack
234  SetInvMakeParams( m_stack, &m_mp, &m_srcImage , &m_dstImage, 0 );
235 }
236 
237 
238 bool Transform::transform(double & x_dest, double & y_dest,
239  double x_src, double y_src) const
240 {
241  void * params= (void *) (&m_stack);
242  return execute_stack_new(x_src, y_src, &x_dest, &y_dest, params) != 0;
243 }
244 
247 {
248  double x_dest, y_dest;
249  void * params= (void *) (&m_stack);
250  bool ok = execute_stack_new(src.x, src.y, &x_dest, &y_dest, params) != 0;
251  dest.x = x_dest;
252  dest.y = y_dest;
253  return ok;
254 }
255 
259 bool Transform::transformImgCoord(double & x_dest, double & y_dest,
260  double x_src, double y_src) const
261 {
262  x_src -= m_srcTX - 0.5 ;
263  y_src -= m_srcTY - 0.5;
264 
265  void * params= (void *) (&m_stack);
266  bool ok = execute_stack_new(x_src, y_src, &x_dest, &y_dest, params) != 0;
267  if(ok)
268  {
269  x_dest += m_destTX - 0.5;
270  y_dest += m_destTY - 0.5;
271  }
272  else
273  {
274  // if the image coordinates could not transformed, e.g. this can happen
275  // with non-zero translation parameters, set the result to a point
276  // outside the image (-1,-1)
277  // better solution would be to evaluate the return value of transformImgCoord
278  x_dest = -1;
279  y_dest = -1;
280  };
281  return ok;
282 }
283 
284 
286 {
287  VariableMapVector res;
288  if (gl.im) {
289  for (int i = 0; i < gl.numIm; i++) {
290  VariableMap vars;
291  vars.insert(make_pair(std::string("TrX"), Variable("TrX", gl.im[i].cP.trans_x)));
292  vars.insert(make_pair(std::string("TrY"), Variable("TrY", gl.im[i].cP.trans_y)));
293  vars.insert(make_pair(std::string("TrZ"), Variable("TrZ", gl.im[i].cP.trans_z)));
294  vars.insert(make_pair(std::string("Tpy"), Variable("Tpy", gl.im[i].cP.trans_yaw)));
295  vars.insert(make_pair(std::string("Tpp"), Variable("Tpp", gl.im[i].cP.trans_pitch)));
296 
297  vars.insert(make_pair(std::string("v"), Variable("v", gl.im[i].hfov)));
298  vars.insert(make_pair(std::string("y"), Variable("y", gl.im[i].yaw)));
299  vars.insert(make_pair(std::string("r"), Variable("r", gl.im[i].roll)));
300  vars.insert(make_pair(std::string("p"), Variable("p", gl.im[i].pitch)));
301  vars.insert(make_pair(std::string("a"), Variable("a", gl.im[i].cP.radial_params[0][3])));
302  vars.insert(make_pair(std::string("b"), Variable("b", gl.im[i].cP.radial_params[0][2])));
303  vars.insert(make_pair(std::string("c"), Variable("c", gl.im[i].cP.radial_params[0][1])));
304 
305  vars.insert(make_pair(std::string("e"), Variable("e", gl.im[i].cP.vertical_params[0])));
306  vars.insert(make_pair(std::string("d"), Variable("d", gl.im[i].cP.horizontal_params[0])));
307 
308  //Modified by Dev
309  vars.insert(make_pair(std::string("g"), Variable("g", gl.im[i].cP.shear_x)));
310  vars.insert(make_pair(std::string("t"), Variable("t", gl.im[i].cP.shear_y)));
311 
312 
313  res.push_back(vars);
314  }
315  }
316  return res;
317 }
318 
319 CPVector GetAlignInfoCtrlPoints(const AlignInfo& gl)
320 {
321  CPVector result;
322  if (gl.cpt) {
323  for (int i = 0; i < gl.numPts; i++) {
324  ControlPoint pnt(gl.cpt[i].num[0], gl.cpt[i].x[0], gl.cpt[i].y[0],
325  gl.cpt[i].num[1], gl.cpt[i].x[1], gl.cpt[i].y[1], (ControlPoint::OptimizeMode) gl.cpt[i].type);
326  pnt.error = sqrt(distSquared(i));
327  result.push_back(pnt);
328  }
329  }
330  return result;
331 }
332 
333 
334 void setDestImage(Image & image, vigra::Diff2D size,
335  unsigned char * imageData,
336  const PanoramaOptions::ProjectionFormat & format,
337  const std::vector<double> & projParams,
338  double destHFOV)
339 {
340  SetImageDefaults(&image);
341  image.width = size.x;
342  image.height = size.y;
343  image.bytesPerLine = image.width*3;
344  image.bitsPerPixel = 24;
345  image.dataSize = image.height * image.bytesPerLine;
346  // Allocate memory for pointer to pointer to image data
347 // image.data = (unsigned char**)malloc( sizeof(unsigned char*) );
348 // if(image.data == NULL) {
349 // DEBUG_FATAL("Out of memory");
350 // }
351  image.data = 0;
352  pano_projection_features projd;
353  if (panoProjectionFeaturesQuery((int) format, &projd)) {
354  image.format = projd.internalFormat;
355  } else {
356  image.format = _equirectangular;
357  DEBUG_ERROR("unsupported projection");
358  }
359  image.formatParamCount = projd.numberOfParameters;
360  assert(image.formatParamCount == (int) projParams.size());
361  for (int i=0; i < projd.numberOfParameters; i++) {
362  image.formatParam[i] = projParams[i];
363  DEBUG_DEBUG("projection parameter " << i << ": " << image.formatParam[i]);
364  }
365  image.hfov = destHFOV;
366 }
367 
368 
369 // internal function, used by setFullImage() to set the distortion parameters
370 void initCPrefs(cPrefs & p, const VariableMap &vars)
371 {
372  SetCorrectDefaults(&p);
373 
374  double val;
375  double a = const_map_get(vars,"a").getValue();
376  double b = const_map_get(vars,"b").getValue();
377  double c = const_map_get(vars,"c").getValue();
378  if (a != 0.0 || b != 0.0 || c != 0) {
379  p.radial = 1;
380  p.radial_params[0][3] = p.radial_params[1][3] = p.radial_params[2][3] = a;
381  p.radial_params[0][2] = p.radial_params[1][2] = p.radial_params[2][2] = b;
382  p.radial_params[0][1] = p.radial_params[1][1] = p.radial_params[2][1] = c;
383  double d = 1.0 - (a+b+c);
384  p.radial_params[0][0] = p.radial_params[1][0] = p.radial_params[2][0] = d;
385  } else {
386  p.radial = 0;
387  }
388 
389  val = const_map_get(vars,"e").getValue();
390  if (val != 0.0) {
391  p.vertical = TRUE;
392  p.vertical_params[0] = p.vertical_params[1] = p.vertical_params[2] = val;
393  } else {
394  p.vertical = FALSE;
395  p.vertical_params[0] = p.vertical_params[1] = p.vertical_params[2] = 0;
396  }
397 
398  val = const_map_get(vars,"d").getValue();
399  if (val != 0.0) {
400  p.horizontal = TRUE;
401  p.horizontal_params[0] = p.horizontal_params[1] = p.horizontal_params[2] = val;
402  } else {
403  p.horizontal = FALSE;
404  p.horizontal_params[0] = p.horizontal_params[1] = p.horizontal_params[2] = 0;
405  }
406 
407  p.trans_x = const_map_get(vars,"TrX").getValue();
408  p.trans_y = const_map_get(vars,"TrY").getValue();
409  p.trans_z = const_map_get(vars,"TrZ").getValue();
410  if (p.trans_x != 0 || p.trans_y != 0 || p.trans_z != 0)
411  {
412  p.trans = TRUE;
413  p.trans_yaw = const_map_get(vars,"Tpy").getValue();
414  p.trans_pitch = const_map_get(vars,"Tpp").getValue();
415  }
416  else
417  {
418  p.trans = FALSE;
419  p.trans_yaw = 0;
420  p.trans_pitch = 0;
421  }
422 
423 
424  // FIXME add shear parameters
425  val = const_map_get(vars, "g").getValue();
426  double val2 = const_map_get(vars, "t").getValue();
427  if (val2 != 0.0 || val != 0.0) {
428  p.shear = TRUE;
429  p.shear_x = val;
430  p.shear_y = val2;
431  } else {
432  p.shear = FALSE;
433  }
434  p.resize = FALSE;
435  p.luminance = FALSE;
436  p.cutFrame = FALSE;
437  p.fourier = FALSE;
438 
439  // calculate correction radius
440  SetCorrectionRadius(&p);
441 
442 }
443 
444 void setFullImage(Image & image, vigra::Diff2D size,
445  unsigned char * imageData, const VariableMap & vars,
446  const Lens::LensProjectionFormat format,
447  bool correctDistortions)
448 {
449  SetImageDefaults(&image);
450  image.width = size.x;
451  image.height = size.y;
452  image.bytesPerLine = image.width*3;
453  image.bitsPerPixel = 24;
454  image.dataSize = image.height * image.bytesPerLine;
455 
456 #if 0
457  // Allocate memory for pointer to pointer to image data
458  image.data = (unsigned char**)malloc( sizeof(unsigned char*) );
459  if(image.data == NULL) {
460  DEBUG_FATAL("Out of memory");
461  }
462  *(image.data) = imageData;
463 #else
464  image.data = 0;
465 #endif
466 
467  image.dataformat = _RGB;
468  switch (format) {
470  image.format = _rectilinear;
471  break;
473  image.format = _panorama;
474  break;
476  image.format = _fisheye_circ;
477  break;
479  image.format = _fisheye_ff;
480  break;
482  image.format = _equirectangular;
483  break;
485  image.format = _orthographic;
486  break;
488  image.format = _stereographic;
489  break;
491  image.format = _equisolid;
492  break;
494  image.format = _thoby;
495  }
496  image.hfov = const_map_get(vars,"v").getValue();
497  image.yaw = const_map_get(vars,"y").getValue();
498  image.pitch = const_map_get(vars,"p").getValue();
499  image.roll = const_map_get(vars,"r").getValue();
500 
501  //fill cPrefs struct
502  if (correctDistortions) {
503  initCPrefs(image.cP,vars);
504  }
505 
506  // no name
507  image.name[0]=0;
508 
509  image.selection.top = 0;
510  image.selection.left = 0;
511  image.selection.right = image.width;
512  image.selection.bottom = image.height;
513 }
514 
515 // ===========================================================================
516 // ===========================================================================
517 
518 
519 // prepare a Trform struct for the adjust operation, image -> pano
520 void createAdjustTrform(TrformStr & trf)
521 {
522  trf.src = (Image *) malloc(sizeof(Image));
523  SetImageDefaults(trf.src);
524  trf.dest = (Image *) malloc(sizeof(Image));
525  SetImageDefaults(trf.dest);
526  trf.success = TRUE;
527  trf.tool = _adjust;
528  trf.mode = _destSupplied | _honor_valid;
529  trf.data = 0;
530  trf.interpolator = _nn;
531  trf.gamma = 1.0;
532 }
533 
534 
535 void freeImage(Image &img)
536 {
537  if (img.data) {
538  myfree((void**)img.data);
539  }
540 }
541 
542 }} // namespace
PanoramaOptions::ProjectionFormat getProjection() const
VariableMapVector GetAlignInfoVariables(const AlignInfo &gl)
virtual const VariableMap getImageVariables(unsigned int imgNr) const =0
get variables of an image
Somewhere to specify what variables belong to what.
unsigned int getHeight() const
get panorama height
a variable has a value and a name.
int getHeight() const
Get the height of the image in pixels.
Definition: SrcPanoImage.h:276
represents a control point
Definition: ControlPoint.h:38
const Map::mapped_type & const_map_get(const Map &m, const typename Map::key_type &key)
Definition: stl_utils.h:110
bool transform(double &x_dest, double &y_dest, double x_src, double y_src) const
excecute transform
#define DEBUG_FATAL(msg)
Definition: utils.h:78
std::vector< VariableMap > VariableMapVector
void initCPrefs(cPrefs &p, const VariableMap &vars)
void createInvTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
create image-&gt;pano transformation
Map::mapped_type & map_get(Map &m, const typename Map::key_type &key)
get a map element.
Definition: stl_utils.h:98
int getWidth() const
Get the width of the image in pixels.
Definition: SrcPanoImage.h:266
void freeImage(Image &img)
free the pointer storage needed by Image
OptimizeMode
minimize x,y or both.
Definition: ControlPoint.h:45
Model for a panorama.
Definition: PanoramaData.h:81
virtual const SrcPanoImage & getImage(std::size_t nr) const =0
get a panorama image, counting starts with 0
void setDestImage(Image &image, vigra::Diff2D size, unsigned char *imageData, const PanoramaOptions::ProjectionFormat &format, const std::vector< double > &projParams, double destHFOV)
set an output image, with properties from opts, that points to the bitmap data of imgData ...
#define DEBUG_ERROR(msg)
Definition: utils.h:76
std::map< std::string, Variable > VariableMap
unsigned int getWidth() const
CPVector GetAlignInfoCtrlPoints(const AlignInfo &gl)
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
void updatePTData(const vigra::Diff2D &srcSize, const VariableMap &srcVars, Lens::LensProjectionFormat &srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat &destProj, const std::vector< double > &destProjParam, double destHFOV)
const std::vector< double > & getProjectionParameters() const
Get the optional projection parameters.
void createAdjustTrform(TrformStr &trf)
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
std::vector< ControlPoint > CPVector
Definition: ControlPoint.h:99
ProjectionFormat
Projection of final panorama.
All variables of a source image.
Definition: SrcPanoImage.h:194
Panorama image options.
vigra::Size2D getSize() const
get size of output image
void setFullImage(Image &image, vigra::Diff2D size, unsigned char *imageData, const VariableMap &vars, const Lens::LensProjectionFormat format, bool correctDistortions)
fills image with a complete input image, including distortion correction parameters if correctDistort...
void createTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
initialize pano-&gt;image transformation
BaseSrcPanoImage::Projection LensProjectionFormat
Definition: Lens.h:47