Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImageTransformsGPU.h
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
27 #ifndef _VIGRA_EXT_IMAGETRANSFORMSGPU_H
28 #define _VIGRA_EXT_IMAGETRANSFORMSGPU_H
29 
30 #include <fstream>
31 #include <iostream>
32 #include <iomanip>
33 
34 #include <hugin_shared.h>
35 #include <vigra/basicimage.hxx>
36 #include <vigra_ext/ROIImage.h>
38 #include <vigra/accessor.hxx>
40 
41 #include <hugin_math/hugin_math.h>
42 #include <hugin_utils/utils.h>
44 
45 using vigra::NumericTraits;
46 
47 namespace vigra_ext
48 {
49 
50 IMPEX void SetGPUDebugMessages(const bool doPrint);
51 
52 bool IMPEX transformImageGPUIntern(const std::string& coordXformGLSL,
53  const std::string& interpolatorGLSL,
54  const int interpolatorSize,
55  const std::string& photometricGLSL,
56  const std::vector<double>& invLut,
57  const std::vector<double>& destLut,
58  const vigra::Diff2D srcSize,
59  const void* const srcBuffer,
60  const int srcGLInternalFormat, const int srcGLTransferFormat, const int srcGLFormat, const int srcGLType,
61  const void* const srcAlphaBuffer,
62  const int srcAlphaGLType,
63  const vigra::Diff2D destUL,
64  const vigra::Diff2D destSize,
65  void* const destBuffer,
66  const int destGLInternalFormat, const int destGLTransferFormat, const int destGLFormat, const int destGLType,
67  void* const destAlphaBuffer,
68  const int destAlphaGLType,
69  const bool warparound);
70 
71 // This is to avoid including GL headers in this file.
72 enum {
73  // gltypes
75  // Internalformats
78  // formats
80 };
81 
83 
84 template <class A>
87  enum {NumBands = 0};
90  enum {ImageGLFormat = 0};
92 };
93 
94 #define DEFINE_GPUNUMERICTRAITS(IMAGECOMPONENT, GLFORMAT, GLFORMATRGB, GLTRANSFER, GLTRANSFERRGB, GLTYPE) \
95 template<> \
96 struct GpuNumericTraits<IMAGECOMPONENT> { \
97  typedef IMAGECOMPONENT ImagePixelComponentType; \
98  enum {NumBands = 1}; \
99  enum {ImageGLInternalFormat = GLFORMAT}; \
100  enum {ImageGLTransferFormat = GLTRANSFER}; \
101  enum {ImageGLFormat = XGL_LUMINANCE}; \
102  enum {ImagePixelComponentGLType = GLTYPE}; \
103 }; \
104 template<> \
105 struct GpuNumericTraits<vigra::RGBValue<IMAGECOMPONENT, 0, 1, 2> > { \
106  typedef IMAGECOMPONENT ImagePixelComponentType; \
107  enum {NumBands = 3}; \
108  enum {ImageGLInternalFormat = GLFORMATRGB}; \
109  enum {ImageGLTransferFormat = GLTRANSFERRGB}; \
110  enum {ImageGLFormat = XGL_RGB}; \
111  enum {ImagePixelComponentGLType = GLTYPE}; \
112 }; \
113 template<> \
114 struct GpuNumericTraits<vigra::TinyVector<IMAGECOMPONENT, 2> > { \
115  typedef IMAGECOMPONENT ImagePixelComponentType; \
116  enum {NumBands = 2}; \
117  enum {ImageGLInternalFormat = GLFORMAT}; \
118  enum {ImageGLTransferFormat = GLFORMAT}; \
119  enum {ImageGLFormat = XGL_LUMINANCE_ALPHA}; \
120  enum {ImagePixelComponentGLType = GLTYPE}; \
121 }; \
122 template<> \
123 struct GpuNumericTraits<vigra::TinyVector<IMAGECOMPONENT, 4> > { \
124  typedef IMAGECOMPONENT ImagePixelComponentType; \
125  enum {NumBands = 4}; \
126  enum {ImageGLInternalFormat = GLFORMATRGB}; \
127  enum {ImageGLTransferFormat = GLFORMATRGB}; \
128  enum {ImageGLFormat = XGL_RGBA}; \
129  enum {ImagePixelComponentGLType = GLTYPE}; \
130 };
131 
139 
140 // FIXME ACM this is wrong, there is no GL_DOUBLE for transfering doubles.
142 
143 
170 template <class SrcImageIterator, class SrcAccessor,
171  class DestImageIterator, class DestAccessor,
172  class TRANSFORM,
173  class PixelTransform,
174  class AlphaImageIterator, class AlphaAccessor,
175  class Interpolator>
176 void transformImageGPUIntern(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
177  vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
178  std::pair<AlphaImageIterator, AlphaAccessor> alpha,
179  TRANSFORM & transform,
180  PixelTransform & pixelTransform,
181  vigra::Diff2D destUL,
182  Interpolator interp,
183  bool warparound,
184  AppBase::ProgressDisplay* progress)
185 {
186  typedef typename SrcAccessor::value_type SrcValueType;
187  typedef typename DestAccessor::value_type DestValueType;
188  typedef typename AlphaAccessor::value_type AlphaValueType;
189 
190  vigra::Diff2D srcSize = src.second - src.first;
191  vigra::Diff2D destSize = dest.second - dest.first;
192 
194  interpol (src, interp, warparound);
195 
196  // Emit coordinate transform and interpolator as GLSL shader program.
197 
198  std::ostringstream coordXformOss;
199  coordXformOss << std::setprecision(20) << std::showpoint;
200  transform.emitGLSL(coordXformOss);
201 
202  std::ostringstream interpolatorOss;
203  interpolatorOss << std::setprecision(20) << std::showpoint;
204  interpol.emitGLSL(interpolatorOss);
205 
206  std::ostringstream photometricOss;
207  std::vector<double> invLut;
208  std::vector<double> destLut;
209  photometricOss << std::setprecision(20) << std::showpoint;
210  pixelTransform.emitGLSL(photometricOss, invLut, destLut);
211 
212  // Do remapping.
213  // Give the GPU pointers directly to the image data, bypassing the vigra iterators and accessors.
214  // This is cheating. It will not work if the iterators describe subsets of the images or if
215  // the accessors perform computation.
216  transformImageGPUIntern(coordXformOss.str(),
217  interpolatorOss.str(),
218  interp.size,
219  photometricOss.str(),
220  invLut,
221  destLut,
222  srcSize,
223  src.first[0],
228  NULL, /* no alpha buffer */
229  XGL_BYTE,
230  destUL,
231  destSize,
232  dest.first[0],
237  alpha.first[0],
239  warparound);
240 
241 }
242 
243 
245 template <class SrcImageIterator, class SrcAccessor,
246  class SrcAlphaIterator, class SrcAlphaAccessor,
247  class DestImageIterator, class DestAccessor,
248  class TRANSFORM,
249  class PixelTransform,
250  class AlphaImageIterator, class AlphaAccessor,
251  class Interpolator>
252 void transformImageAlphaGPUIntern(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
253  std::pair<SrcAlphaIterator, SrcAlphaAccessor> srcAlpha,
254  vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
255  std::pair<AlphaImageIterator, AlphaAccessor> alpha,
256  TRANSFORM & transform,
257  PixelTransform & pixelTransform,
258  vigra::Diff2D destUL,
259  Interpolator interp,
260  bool warparound,
261  AppBase::ProgressDisplay* progress)
262 {
263  typedef typename SrcAccessor::value_type SrcValueType;
264  typedef typename SrcAlphaAccessor::value_type SrcAlphaType;
265  typedef typename DestAccessor::value_type DestValueType;
266  typedef typename AlphaAccessor::value_type DestAlphaType;
267 
268  vigra::Diff2D srcSize = src.second - src.first;
269  vigra::Diff2D destSize = dest.second - dest.first;
270 
271  // Note that GPU interpolators are the same for source images with and without alpha channels.
273  interpol (src, interp, warparound);
274 
275  // Emit coordinate transform and interpolator as GLSL shader program.
276 
277  std::ostringstream coordXformOss;
278  coordXformOss << std::setprecision(20) << std::showpoint;
279  if(!transform.emitGLSL(coordXformOss))
280  {
281  std::cerr << "nona: Found unsupported transformation in stack." << std::endl
282  << " This geometric transformation is not supported by GPU." << std::endl
283  << " Remove -g switch and try with CPU transformation." << std::endl;
284  exit(1);
285  };
286 
287  std::ostringstream interpolatorOss;
288  interpolatorOss << std::setprecision(20) << std::showpoint;
289  interpol.emitGLSL(interpolatorOss);
290 
291  std::ostringstream photometricOss;
292  std::vector<double> invLut;
293  std::vector<double> destLut;
294  photometricOss << std::setprecision(20) << std::showpoint;
295  pixelTransform.emitGLSL(photometricOss, invLut, destLut);
296 
297 /*
298  // Experiment: measure speedup with TinyVector4 source images.
299  typedef typename GpuNumericTraits<SrcValueType>::ImagePixelComponentType SrcImagePixelComponentType;
300  typedef vigra::TinyVector<SrcImagePixelComponentType, 4> SrcVectorValueType;
301  //class SrcVectorPixelType : public SrcVectorValueType {
302  //public:
303  // SrcVectorPixelType() : SrcVectorValueType() { }
304  // SrcVectorPixelType(const SrcImagePixelComponentType & s) : SrcVectorValueType(s) { }
305  // SrcVectorPixelType(const vigra::RGBValue<SrcImagePixelComponentType> & s) : SrcVectorValueType(s.red(), s.green(), s.blue(), 0) { }
306  //};
307  //std::allocator<SrcVectorPixelType> al;
308  //vigra::BasicImage<SrcVectorPixelType, std::allocator<SrcVectorPixelType> > srcVectorImage(srcSize, al);
309  vigra::BasicImage<SrcVectorValueType> srcVectorImage(srcSize);
310  //vigra::copyImage(src, destImage(srcVectorImage));
311  vigra::copyImage(srcAlpha.first, srcAlpha.first + (src.second - src.first), srcAlpha.second, srcVectorImage.upperLeft(), vigra::VectorComponentAccessor<SrcVectorValueType>(3));
312 
313  transformImageGPUIntern(coordXformOss.str(),
314  interpolatorOss.str(),
315  interp.size,
316  srcSize,
317  srcVectorImage[0],
318  GpuNumericTraits<SrcVectorValueType>::ImageGLInternalFormat,
319  GpuNumericTraits<SrcVectorValueType>::ImageGLTransferFormat,
320  GpuNumericTraits<SrcVectorValueType>::ImageGLFormat,
321  GpuNumericTraits<SrcVectorValueType>::ImagePixelComponentGLType,
322  NULL,
323  XGL_BYTE,
324  destUL,
325  destSize,
326  dest.first[0],
327  GpuNumericTraits<DestValueType>::ImageGLInternalFormat,
328  GpuNumericTraits<DestValueType>::ImageGLTransferFormat,
329  GpuNumericTraits<DestValueType>::ImageGLFormat,
330  GpuNumericTraits<DestValueType>::ImagePixelComponentGLType,
331  alpha.first[0],
332  GpuNumericTraits<DestAlphaType>::ImagePixelComponentGLType,
333  warparound);
334 */
335  // Do remapping.
336  // Give the GPU pointers directly to the image data, bypassing the vigra iterators and accessors.
337  // This is cheating. It will not work if the iterators describe subsets of the images or if
338  // the accessors perform computation.
339 #if 1
340  transformImageGPUIntern(coordXformOss.str(),
341  interpolatorOss.str(),
342  interp.size,
343  photometricOss.str(),
344  invLut,
345  destLut,
346  srcSize,
347  src.first[0],
352  srcAlpha.first[0],
354  destUL,
355  destSize,
356  dest.first[0],
361  alpha.first[0],
363  warparound);
364 #endif
365 
366 #if 0
367  //vigra::FRGBImage phonyDest(destSize);
368  vigra::FVector4Image phonyDest(destSize);
369  vigra::FImage phonyDestAlpha(destSize);
370  vigra::FRGBImage phonySrc(srcSize);
371  vigra::FImage phonySrcAlpha(srcSize);
372 
373  transformImageGPUIntern(oss.str(), srcSize, phonySrc[0], XGL_FLOAT, XGL_RGB,
374  phonySrcAlpha[0], XGL_FLOAT, XGL_RED,
375  destUL, destSize, phonyDest[0], XGL_FLOAT, XGL_RGBA,
376  phonyDestAlpha[0], XGL_FLOAT, XGL_RED,
377  warparound);
378 
379  // Test accuracy
380  int xstart = destUL.x;
381  int xend = destUL.x + destSize.x;
382  int ystart = destUL.y;
383  int yend = destUL.y + destSize.y;
384 
385  double samples = 0.0;
386  double sumError = 0.0;
387  double sumErrorSq = 0.0;
388 
389  // create dest y iterator
390  //vigra::FRGBImage::traverser yd = phonyDest.upperLeft();
391  vigra::FVector4Image::traverser yd = phonyDest.upperLeft();
392  vigra::FImage::traverser ydm = phonyDestAlpha.upperLeft();
393  DestImageIterator ydest(dest.first);
394  AlphaImageIterator ydesta(alpha.first);
395 
396  int numMessages = 0;
397 
398  for(int y=ystart; y < yend; ++y, ++yd.y, ++ydm.y, ++ydest.y, ++ydesta.y)
399  {
400  // create x iterators
401  //vigra::FRGBImage::traverser xd(yd);
402  vigra::FVector4Image::traverser xd(yd);
403  vigra::FImage::traverser xdm(ydm);
404  DestImageIterator xdest(ydest);
405  AlphaImageIterator xdesta(ydesta);
406 
407  for(int x=xstart; x < xend; ++x, ++xd.x, ++xdm.x, ++xdest.x, ++xdesta.x)
408  {
409  double sx,sy;
410  bool result = transform.transformImgCoordPartial(sx,sy,x,y);
411  float errorX = (*xd)[2] - static_cast<float>(sx);
412  float errorY = (*xd)[1] - static_cast<float>(sy);
413  double error = sqrt(errorX * errorX + errorY * errorY);
414 
415  if (error != 0.0 && numMessages < 150) {
416  std::cout << std::setprecision(20) << "pos=[" << x << ", " << y << "] shouldBe=[" << sx << ", " << sy << " is=[" << (*xd)[2] << ", " << (*xd)[1] << "] error=" << error << std::endl;
417  ++numMessages;
418  }
419 
420  sumError += error;
421  sumErrorSq += (error * error);
422 
423  samples += 1.0;
424 
425  dest.third.set(NumericTraits<DestValueType>::fromRealPromote(std::min(255.0, std::max(0.0, 255.0 * 10.0 * error))), xdest);
426  alpha.second.set(255, xdesta);
427  }
428  }
429 
430  double avgError = sumError/samples;
431 
432  std::cout << "numSamples=" << samples << std::endl
433  << "average error=" << avgError << std::endl
434  << "stddev=" << (sumErrorSq/samples - avgError*avgError) << std::endl;
435 #endif
436 
437 };
438 
439 
466 template <class SrcImageIterator, class SrcAccessor,
467  class DestImageIterator, class DestAccessor,
468  class AlphaImageIterator, class AlphaAccessor,
469  class TRANSFORM,
470  class PixelTransform>
471 void transformImageGPU(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
472  vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
473  std::pair<AlphaImageIterator, AlphaAccessor> alpha,
474  vigra::Diff2D destUL,
475  TRANSFORM & transform,
476  PixelTransform & pixelTransform,
477  bool warparound,
478  Interpolator interpol,
479  AppBase::ProgressDisplay* progress)
480 {
481  switch (interpol) {
482  case INTERP_CUBIC:
483  DEBUG_DEBUG("using cubic interpolator");
484  transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
485  vigra_ext::interp_cubic(), warparound,
486  progress);
487  break;
488  case INTERP_SPLINE_16:
489  DEBUG_DEBUG("interpolator: spline16");
490  transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
491  vigra_ext::interp_spline16(), warparound,
492  progress);
493  break;
494  case INTERP_SPLINE_36:
495  DEBUG_DEBUG("interpolator: spline36");
496  transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
497  vigra_ext::interp_spline36(), warparound,
498  progress);
499  break;
500  case INTERP_SPLINE_64:
501  DEBUG_DEBUG("interpolator: spline64");
502  transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
503  vigra_ext::interp_spline64(), warparound,
504  progress);
505  break;
506  case INTERP_SINC_256:
507  DEBUG_DEBUG("interpolator: sinc 256");
508  transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
509  vigra_ext::interp_sinc<8>(), warparound,
510  progress);
511  break;
512  case INTERP_BILINEAR:
513  transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
514  vigra_ext::interp_bilin(), warparound,
515  progress);
516  break;
518  transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
519  vigra_ext::interp_nearest(), warparound,
520  progress);
521  break;
522  case INTERP_SINC_1024:
523  transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
524  vigra_ext::interp_sinc<32>(), warparound,
525  progress);
526  break;
527  }
528 }
529 
531 template <class SrcImageIterator, class SrcAccessor,
532  class SrcAlphaIterator, class SrcAlphaAccessor,
533  class DestImageIterator, class DestAccessor,
534  class AlphaImageIterator, class AlphaAccessor,
535  class TRANSFORM, class PixelTransform>
536 void transformImageAlphaGPU(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
537  std::pair<SrcAlphaIterator, SrcAlphaAccessor> srcAlpha,
538  vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
539  std::pair<AlphaImageIterator, AlphaAccessor> alpha,
540  vigra::Diff2D destUL,
541  TRANSFORM & transform,
542  PixelTransform & pixelTransform,
543  bool warparound,
544  Interpolator interpol,
545  AppBase::ProgressDisplay* progress)
546 {
547  switch (interpol) {
548  case INTERP_CUBIC:
549  DEBUG_DEBUG("using cubic interpolator");
550  transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
551  vigra_ext::interp_cubic(), warparound,
552  progress);
553  break;
554  case INTERP_SPLINE_16:
555  DEBUG_DEBUG("interpolator: spline16");
556  transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
557  vigra_ext::interp_spline16(), warparound,
558  progress);
559  break;
560  case INTERP_SPLINE_36:
561  DEBUG_DEBUG("interpolator: spline36");
562  transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
563  vigra_ext::interp_spline36(), warparound,
564  progress);
565  break;
566  case INTERP_SPLINE_64:
567  DEBUG_DEBUG("interpolator: spline64");
568  transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
569  vigra_ext::interp_spline64(), warparound,
570  progress);
571  break;
572  case INTERP_SINC_256:
573  DEBUG_DEBUG("interpolator: sinc 256");
574  transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
575  vigra_ext::interp_sinc<8>(), warparound,
576  progress);
577  break;
578  case INTERP_BILINEAR:
579  transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
580  vigra_ext::interp_bilin(), warparound,
581  progress);
582  break;
584  transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
585  vigra_ext::interp_nearest(), warparound,
586  progress);
587  break;
588  case INTERP_SINC_1024:
589  transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
590  vigra_ext::interp_sinc<32>(), warparound,
591  progress);
592  break;
593  }
594 }
595 
596 }; // namespace
597 
598 #endif // _VIGRA_EXT_IMAGETRANSFORMSGPU_H
simple bilinear interpolation
misc math function &amp; classes used by other parts of the program
&quot;wrapper&quot; for efficient interpolation access to an image
cubic interpolation
sinc interpolation, with variable width
void transformImageGPU(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress)
Transform an image into the panorama.
spline16 interpolation
void transformImageAlphaGPUIntern(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, std::pair< SrcAlphaIterator, SrcAlphaAccessor > srcAlpha, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, TRANSFORM &transform, PixelTransform &pixelTransform, vigra::Diff2D destUL, Interpolator interp, bool warparound, AppBase::ProgressDisplay *progress)
transform input images with alpha channel
DEFINE_GPUNUMERICTRAITS(vigra::Int8, XGL_LUMINANCE8_ALPHA8, XGL_RGBA8, XGL_LUMINANCE8, XGL_RGB8, XGL_BYTE)
void SetGPUDebugMessages(const bool doPrint)
spline36 interpolation
several classes to calculate interpolator weights,
Definition: Interpolators.h:96
bool transformImageGPUIntern(const std::string &coordXformGLSL, const std::string &interpolatorGLSL, const int interpolatorSize, const std::string &photometricGLSL, const vector< double > &invLut, const vector< double > &destLut, const vigra::Diff2D srcSize, const void *const srcBuffer, const int srcGLInternalFormat, const int srcGLTransferFormat, const int srcGLFormat, const int srcGLType, const void *const srcAlphaBuffer, const int srcAlphaGLType, const vigra::Diff2D destUL, const vigra::Diff2D destSize, void *const destBuffer, const int destGLInternalFormat, const int destGLTransferFormat, const int destGLFormat, const int destGLType, void *const destAlphaBuffer, const int destAlphaGLType, const bool warparound)
void emitGLSL(std::ostringstream &oss) const
#define IMPEX
Definition: hugin_shared.h:39
Error_GpuNumericTraits_not_specialized_for_this_case ImagePixelComponentType
The pano tools interpolators ported to vigra.
spline64 interpolation
static T max(T x, T y)
Definition: svm.cpp:65
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
Interpolator
enum with all interpolation methods
Definition: Interpolators.h:78
static T min(T x, T y)
Definition: svm.cpp:62
void transformImageAlphaGPU(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, std::pair< SrcAlphaIterator, SrcAlphaAccessor > srcAlpha, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress)
Transform image, and respect a possible alpha channel.