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
34#include <hugin_shared.h>
35#include <vigra/basicimage.hxx>
36#include <vigra_ext/ROIImage.h>
38#include <vigra/accessor.hxx>
40
42#include <hugin_utils/utils.h>
44
45using vigra::NumericTraits;
46
47namespace vigra_ext
48{
49
50IMPEX void SetGPUDebugMessages(const bool doPrint);
51
52bool 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.
72enum {
73 // gltypes
75 // Internalformats
78 // formats
80};
81
83
84template <class A>
93
94#define DEFINE_GPUNUMERICTRAITS(IMAGECOMPONENT, GLFORMAT, GLFORMATRGB, GLTRANSFER, GLTRANSFERRGB, GLTYPE) \
95template<> \
96struct 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}; \
104template<> \
105struct 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}; \
113template<> \
114struct 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}; \
122template<> \
123struct 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
170template <class SrcImageIterator, class SrcAccessor,
171 class DestImageIterator, class DestAccessor,
172 class TRANSFORM,
173 class PixelTransform,
175 class Interpolator>
176void transformImageGPUIntern(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
177 vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
178 std::pair<AlphaImageIterator, AlphaAccessor> alpha,
179 TRANSFORM & transform,
181 vigra::Diff2D destUL,
183 bool warparound,
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
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;
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.
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
245template <class SrcImageIterator, class SrcAccessor,
247 class DestImageIterator, class DestAccessor,
248 class TRANSFORM,
249 class PixelTransform,
251 class Interpolator>
252void 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,
258 vigra::Diff2D destUL,
260 bool warparound,
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.
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;
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
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
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();
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);
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
466template <class SrcImageIterator, class SrcAccessor,
467 class DestImageIterator, class DestAccessor,
469 class TRANSFORM,
470 class PixelTransform>
471void 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,
477 bool warparound,
480{
481 switch (interpol) {
482 case INTERP_CUBIC:
483 DEBUG_DEBUG("using cubic interpolator");
486 progress);
487 break;
488 case INTERP_SPLINE_16:
489 DEBUG_DEBUG("interpolator: spline16");
492 progress);
493 break;
494 case INTERP_SPLINE_36:
495 DEBUG_DEBUG("interpolator: spline36");
498 progress);
499 break;
500 case INTERP_SPLINE_64:
501 DEBUG_DEBUG("interpolator: spline64");
504 progress);
505 break;
506 case INTERP_SINC_256:
507 DEBUG_DEBUG("interpolator: sinc 256");
510 progress);
511 break;
512 case INTERP_BILINEAR:
515 progress);
516 break;
520 progress);
521 break;
522 case INTERP_SINC_1024:
525 progress);
526 break;
527 }
528}
529
531template <class SrcImageIterator, class SrcAccessor,
533 class DestImageIterator, class DestAccessor,
535 class TRANSFORM, class PixelTransform>
536void 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,
543 bool warparound,
546{
547 switch (interpol) {
548 case INTERP_CUBIC:
549 DEBUG_DEBUG("using cubic interpolator");
552 progress);
553 break;
554 case INTERP_SPLINE_16:
555 DEBUG_DEBUG("interpolator: spline16");
558 progress);
559 break;
560 case INTERP_SPLINE_36:
561 DEBUG_DEBUG("interpolator: spline36");
564 progress);
565 break;
566 case INTERP_SPLINE_64:
567 DEBUG_DEBUG("interpolator: spline64");
570 progress);
571 break;
572 case INTERP_SINC_256:
573 DEBUG_DEBUG("interpolator: sinc 256");
576 progress);
577 break;
578 case INTERP_BILINEAR:
581 progress);
582 break;
586 progress);
587 break;
588 case INTERP_SINC_1024:
591 progress);
592 break;
593 }
594}
595
596}; // namespace
597
598#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