Hugin trunk 0.1
Loading...
Searching...
No Matches
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#include <stdexcept>
34
35#include <hugin_shared.h>
36#include <vigra/basicimage.hxx>
37#include <vigra_ext/ROIImage.h>
39#include <vigra/accessor.hxx>
41
43#include <hugin_utils/utils.h>
45
46using vigra::NumericTraits;
47
48namespace vigra_ext
49{
50
51IMPEX void SetGPUDebugMessages(const bool doPrint);
52
53bool IMPEX transformImageGPUIntern(const std::string& coordXformGLSL,
54 const std::string& interpolatorGLSL,
55 const int interpolatorSize,
56 const std::string& photometricGLSL,
57 const std::vector<double>& invLut,
58 const std::vector<double>& destLut,
59 const vigra::Diff2D srcSize,
60 const void* const srcBuffer,
61 const int srcGLInternalFormat, const int srcGLTransferFormat, const int srcGLFormat, const int srcGLType,
62 const void* const srcAlphaBuffer,
63 const int srcAlphaGLType,
64 const vigra::Diff2D destUL,
65 const vigra::Diff2D destSize,
66 void* const destBuffer,
67 const int destGLInternalFormat, const int destGLTransferFormat, const int destGLFormat, const int destGLType,
68 void* const destAlphaBuffer,
69 const int destAlphaGLType,
70 const bool warparound);
71
72// This is to avoid including GL headers in this file.
73enum {
74 // gltypes
76 // Internalformats
79 // formats
81};
82
84
85template <class A>
94
95#define DEFINE_GPUNUMERICTRAITS(IMAGECOMPONENT, GLFORMAT, GLFORMATRGB, GLTRANSFER, GLTRANSFERRGB, GLTYPE) \
96template<> \
97struct GpuNumericTraits<IMAGECOMPONENT> { \
98 typedef IMAGECOMPONENT ImagePixelComponentType; \
99 enum {NumBands = 1}; \
100 enum {ImageGLInternalFormat = GLFORMAT}; \
101 enum {ImageGLTransferFormat = GLTRANSFER}; \
102 enum {ImageGLFormat = XGL_LUMINANCE}; \
103 enum {ImagePixelComponentGLType = GLTYPE}; \
104}; \
105template<> \
106struct GpuNumericTraits<vigra::RGBValue<IMAGECOMPONENT, 0, 1, 2> > { \
107 typedef IMAGECOMPONENT ImagePixelComponentType; \
108 enum {NumBands = 3}; \
109 enum {ImageGLInternalFormat = GLFORMATRGB}; \
110 enum {ImageGLTransferFormat = GLTRANSFERRGB}; \
111 enum {ImageGLFormat = XGL_RGB}; \
112 enum {ImagePixelComponentGLType = GLTYPE}; \
113}; \
114template<> \
115struct GpuNumericTraits<vigra::TinyVector<IMAGECOMPONENT, 2> > { \
116 typedef IMAGECOMPONENT ImagePixelComponentType; \
117 enum {NumBands = 2}; \
118 enum {ImageGLInternalFormat = GLFORMAT}; \
119 enum {ImageGLTransferFormat = GLFORMAT}; \
120 enum {ImageGLFormat = XGL_LUMINANCE_ALPHA}; \
121 enum {ImagePixelComponentGLType = GLTYPE}; \
122}; \
123template<> \
124struct GpuNumericTraits<vigra::TinyVector<IMAGECOMPONENT, 4> > { \
125 typedef IMAGECOMPONENT ImagePixelComponentType; \
126 enum {NumBands = 4}; \
127 enum {ImageGLInternalFormat = GLFORMATRGB}; \
128 enum {ImageGLTransferFormat = GLFORMATRGB}; \
129 enum {ImageGLFormat = XGL_RGBA}; \
130 enum {ImagePixelComponentGLType = GLTYPE}; \
131};
132
140
141// FIXME ACM this is wrong, there is no GL_DOUBLE for transfering doubles.
143
144
171template <class SrcImageIterator, class SrcAccessor,
172 class DestImageIterator, class DestAccessor,
173 class TRANSFORM,
174 class PixelTransform,
176 class Interpolator>
177void transformImageGPUIntern(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
178 vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
179 std::pair<AlphaImageIterator, AlphaAccessor> alpha,
180 TRANSFORM & transform,
182 vigra::Diff2D destUL,
184 bool warparound,
186{
187 typedef typename SrcAccessor::value_type SrcValueType;
188 typedef typename DestAccessor::value_type DestValueType;
189 typedef typename AlphaAccessor::value_type AlphaValueType;
190
191 vigra::Diff2D srcSize = src.second - src.first;
192 vigra::Diff2D destSize = dest.second - dest.first;
193
196
197 // Emit coordinate transform and interpolator as GLSL shader program.
198
199 std::ostringstream coordXformOss;
200 coordXformOss << std::setprecision(20) << std::showpoint;
201 transform.emitGLSL(coordXformOss);
202
203 std::ostringstream interpolatorOss;
204 interpolatorOss << std::setprecision(20) << std::showpoint;
205 interpol.emitGLSL(interpolatorOss);
206
207 std::ostringstream photometricOss;
208 std::vector<double> invLut;
209 std::vector<double> destLut;
210 photometricOss << std::setprecision(20) << std::showpoint;
212
213 // Do remapping.
214 // Give the GPU pointers directly to the image data, bypassing the vigra iterators and accessors.
215 // This is cheating. It will not work if the iterators describe subsets of the images or if
216 // the accessors perform computation.
218 interpolatorOss.str(),
219 interp.size,
220 photometricOss.str(),
221 invLut,
222 destLut,
223 srcSize,
224 src.first[0],
229 NULL, /* no alpha buffer */
230 XGL_BYTE,
231 destUL,
232 destSize,
233 dest.first[0],
238 alpha.first[0],
240 warparound);
241
242}
243
244
246template <class SrcImageIterator, class SrcAccessor,
248 class DestImageIterator, class DestAccessor,
249 class TRANSFORM,
250 class PixelTransform,
252 class Interpolator>
253void transformImageAlphaGPUIntern(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
254 std::pair<SrcAlphaIterator, SrcAlphaAccessor> srcAlpha,
255 vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
256 std::pair<AlphaImageIterator, AlphaAccessor> alpha,
257 TRANSFORM & transform,
259 vigra::Diff2D destUL,
261 bool warparound,
263{
264 typedef typename SrcAccessor::value_type SrcValueType;
265 typedef typename SrcAlphaAccessor::value_type SrcAlphaType;
266 typedef typename DestAccessor::value_type DestValueType;
267 typedef typename AlphaAccessor::value_type DestAlphaType;
268
269 vigra::Diff2D srcSize = src.second - src.first;
270 vigra::Diff2D destSize = dest.second - dest.first;
271
272 // Note that GPU interpolators are the same for source images with and without alpha channels.
275
276 // Emit coordinate transform and interpolator as GLSL shader program.
277
278 std::ostringstream coordXformOss;
279 coordXformOss << std::setprecision(20) << std::showpoint;
280 if(!transform.emitGLSL(coordXformOss))
281 {
282 std::cerr << "nona: Found unsupported transformation in stack." << std::endl
283 << " This geometric transformation is not supported by GPU." << std::endl
284 << " Remove -g switch and try with CPU transformation." << std::endl;
285 exit(1);
286 };
287
288 std::ostringstream interpolatorOss;
289 interpolatorOss << std::setprecision(20) << std::showpoint;
290 interpol.emitGLSL(interpolatorOss);
291
292 std::ostringstream photometricOss;
293 std::vector<double> invLut;
294 std::vector<double> destLut;
295 photometricOss << std::setprecision(20) << std::showpoint;
297
298/*
299 // Experiment: measure speedup with TinyVector4 source images.
300 typedef typename GpuNumericTraits<SrcValueType>::ImagePixelComponentType SrcImagePixelComponentType;
301 typedef vigra::TinyVector<SrcImagePixelComponentType, 4> SrcVectorValueType;
302 //class SrcVectorPixelType : public SrcVectorValueType {
303 //public:
304 // SrcVectorPixelType() : SrcVectorValueType() { }
305 // SrcVectorPixelType(const SrcImagePixelComponentType & s) : SrcVectorValueType(s) { }
306 // SrcVectorPixelType(const vigra::RGBValue<SrcImagePixelComponentType> & s) : SrcVectorValueType(s.red(), s.green(), s.blue(), 0) { }
307 //};
308 //std::allocator<SrcVectorPixelType> al;
309 //vigra::BasicImage<SrcVectorPixelType, std::allocator<SrcVectorPixelType> > srcVectorImage(srcSize, al);
310 vigra::BasicImage<SrcVectorValueType> srcVectorImage(srcSize);
311 //vigra::copyImage(src, destImage(srcVectorImage));
312 vigra::copyImage(srcAlpha.first, srcAlpha.first + (src.second - src.first), srcAlpha.second, srcVectorImage.upperLeft(), vigra::VectorComponentAccessor<SrcVectorValueType>(3));
313
314 transformImageGPUIntern(coordXformOss.str(),
315 interpolatorOss.str(),
316 interp.size,
317 srcSize,
318 srcVectorImage[0],
319 GpuNumericTraits<SrcVectorValueType>::ImageGLInternalFormat,
320 GpuNumericTraits<SrcVectorValueType>::ImageGLTransferFormat,
321 GpuNumericTraits<SrcVectorValueType>::ImageGLFormat,
322 GpuNumericTraits<SrcVectorValueType>::ImagePixelComponentGLType,
323 NULL,
324 XGL_BYTE,
325 destUL,
326 destSize,
327 dest.first[0],
328 GpuNumericTraits<DestValueType>::ImageGLInternalFormat,
329 GpuNumericTraits<DestValueType>::ImageGLTransferFormat,
330 GpuNumericTraits<DestValueType>::ImageGLFormat,
331 GpuNumericTraits<DestValueType>::ImagePixelComponentGLType,
332 alpha.first[0],
333 GpuNumericTraits<DestAlphaType>::ImagePixelComponentGLType,
334 warparound);
335*/
336 // Do remapping.
337 // Give the GPU pointers directly to the image data, bypassing the vigra iterators and accessors.
338 // This is cheating. It will not work if the iterators describe subsets of the images or if
339 // the accessors perform computation.
340#if 1
342 interpolatorOss.str(),
343 interp.size,
344 photometricOss.str(),
345 invLut,
346 destLut,
347 srcSize,
348 src.first[0],
353 srcAlpha.first[0],
355 destUL,
356 destSize,
357 dest.first[0],
362 alpha.first[0],
364 warparound);
365#endif
366
367#if 0
368 //vigra::FRGBImage phonyDest(destSize);
369 vigra::FVector4Image phonyDest(destSize);
370 vigra::FImage phonyDestAlpha(destSize);
371 vigra::FRGBImage phonySrc(srcSize);
372 vigra::FImage phonySrcAlpha(srcSize);
373
378 warparound);
379
380 // Test accuracy
381 int xstart = destUL.x;
382 int xend = destUL.x + destSize.x;
383 int ystart = destUL.y;
384 int yend = destUL.y + destSize.y;
385
386 double samples = 0.0;
387 double sumError = 0.0;
388 double sumErrorSq = 0.0;
389
390 // create dest y iterator
391 //vigra::FRGBImage::traverser yd = phonyDest.upperLeft();
392 vigra::FVector4Image::traverser yd = phonyDest.upperLeft();
393 vigra::FImage::traverser ydm = phonyDestAlpha.upperLeft();
395 AlphaImageIterator ydesta(alpha.first);
396
397 int numMessages = 0;
398
399 for(int y=ystart; y < yend; ++y, ++yd.y, ++ydm.y, ++ydest.y, ++ydesta.y)
400 {
401 // create x iterators
402 //vigra::FRGBImage::traverser xd(yd);
403 vigra::FVector4Image::traverser xd(yd);
404 vigra::FImage::traverser xdm(ydm);
407
408 for(int x=xstart; x < xend; ++x, ++xd.x, ++xdm.x, ++xdest.x, ++xdesta.x)
409 {
410 double sx,sy;
411 bool result = transform.transformImgCoordPartial(sx,sy,x,y);
412 float errorX = (*xd)[2] - static_cast<float>(sx);
413 float errorY = (*xd)[1] - static_cast<float>(sy);
414 double error = sqrt(errorX * errorX + errorY * errorY);
415
416 if (error != 0.0 && numMessages < 150) {
417 std::cout << std::setprecision(20) << "pos=[" << x << ", " << y << "] shouldBe=[" << sx << ", " << sy << " is=[" << (*xd)[2] << ", " << (*xd)[1] << "] error=" << error << std::endl;
418 ++numMessages;
419 }
420
421 sumError += error;
422 sumErrorSq += (error * error);
423
424 samples += 1.0;
425
426 dest.third.set(NumericTraits<DestValueType>::fromRealPromote(std::min(255.0, std::max(0.0, 255.0 * 10.0 * error))), xdest);
427 alpha.second.set(255, xdesta);
428 }
429 }
430
431 double avgError = sumError/samples;
432
433 std::cout << "numSamples=" << samples << std::endl
434 << "average error=" << avgError << std::endl
435 << "stddev=" << (sumErrorSq/samples - avgError*avgError) << std::endl;
436#endif
437
438};
439
440
467template <class SrcImageIterator, class SrcAccessor,
468 class DestImageIterator, class DestAccessor,
470 class TRANSFORM,
471 class PixelTransform>
472void transformImageGPU(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
473 vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
474 std::pair<AlphaImageIterator, AlphaAccessor> alpha,
475 vigra::Diff2D destUL,
476 TRANSFORM & transform,
478 bool warparound,
481{
482 switch (interpol) {
483 case INTERP_CUBIC:
484 DEBUG_DEBUG("using cubic interpolator");
487 progress);
488 break;
489 case INTERP_SPLINE_16:
490 DEBUG_DEBUG("interpolator: spline16");
493 progress);
494 break;
495 case INTERP_SPLINE_36:
496 DEBUG_DEBUG("interpolator: spline36");
499 progress);
500 break;
501 case INTERP_SPLINE_64:
502 DEBUG_DEBUG("interpolator: spline64");
505 progress);
506 break;
507 case INTERP_SINC_256:
508 DEBUG_DEBUG("interpolator: sinc 256");
511 progress);
512 break;
513 case INTERP_BILINEAR:
516 progress);
517 break;
521 progress);
522 break;
523 case INTERP_SINC_1024:
526 progress);
527 break;
528 case INTERP_AABOX:
530 case INTERP_AACUBIC:
531 case INTERP_AALANCZOS:
532 throw std::logic_error("Anti-aliased interpolation not supported on GPU");
533 }
534}
535
537template <class SrcImageIterator, class SrcAccessor,
539 class DestImageIterator, class DestAccessor,
541 class TRANSFORM, class PixelTransform>
542void transformImageAlphaGPU(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
543 std::pair<SrcAlphaIterator, SrcAlphaAccessor> srcAlpha,
544 vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
545 std::pair<AlphaImageIterator, AlphaAccessor> alpha,
546 vigra::Diff2D destUL,
547 TRANSFORM & transform,
549 bool warparound,
552{
553 switch (interpol) {
554 case INTERP_CUBIC:
555 DEBUG_DEBUG("using cubic interpolator");
558 progress);
559 break;
560 case INTERP_SPLINE_16:
561 DEBUG_DEBUG("interpolator: spline16");
564 progress);
565 break;
566 case INTERP_SPLINE_36:
567 DEBUG_DEBUG("interpolator: spline36");
570 progress);
571 break;
572 case INTERP_SPLINE_64:
573 DEBUG_DEBUG("interpolator: spline64");
576 progress);
577 break;
578 case INTERP_SINC_256:
579 DEBUG_DEBUG("interpolator: sinc 256");
582 progress);
583 break;
584 case INTERP_BILINEAR:
587 progress);
588 break;
592 progress);
593 break;
594 case INTERP_SINC_1024:
597 progress);
598 break;
599 case INTERP_AABOX:
601 case INTERP_AACUBIC:
602 case INTERP_AALANCZOS:
603 throw std::logic_error("Anti-aliased interpolation not supported on GPU");
604 }
605}
606
607}; // namespace
608
609#endif // _VIGRA_EXT_IMAGETRANSFORMSGPU_H
#define DEFINE_GPUNUMERICTRAITS(IMAGECOMPONENT, GLFORMAT, GLFORMATRGB, GLTRANSFER, GLTRANSFERRGB, GLTYPE)
The pano tools interpolators ported to vigra.
"wrapper" for efficient interpolation access to an image
misc math function & classes used by other parts of the program
#define IMPEX
#define DEBUG_DEBUG(msg)
Definition utils.h:68
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
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 SetGPUDebugMessages(const bool doPrint)
Interpolator
enum with all interpolation methods
@ INTERP_NEAREST_NEIGHBOUR
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.
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.
Error_GpuNumericTraits_not_specialized_for_this_case ImagePixelComponentType
simple bilinear interpolation
cubic interpolation
several classes to calculate interpolator weights,
sinc interpolation, with variable width
spline16 interpolation
spline36 interpolation
spline64 interpolation
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41