58#include <vigra/stdimage.hxx>
59#include <vigra/imageinfo.hxx>
60#include <vigra/impex.hxx>
61#include <vigra/accumulator.hxx>
62#include <vigra/multi_math.hxx>
73using namespace vigra ;
77template <
class view_type >
78long double check_diff (
const view_type& a ,
const view_type& b )
80 using namespace vigra::multi_math ;
81 using namespace vigra::acc;
83 typedef typename view_type::value_type value_type ;
84 typedef typename vigra::ExpandElementResult < value_type > :: type real_type ;
85 typedef MultiArray<view_type::actual_dimension,real_type> error_array ;
87 error_array ea ( vigra::multi_math::squaredNorm ( b - a ) ) ;
88 AccumulatorChain<real_type,Select< Mean, Maximum> > ac ;
89 extractFeatures(ea.begin(), ea.end(), ac);
90 std::cout <<
"warped image diff Mean: " << sqrt(get<Mean>(ac)) << std::endl;
92 long double max_error = sqrt(get<Maximum>(ac)) ;
93 std::cout <<
"warped image diff Maximum: "
94 << max_error << std::endl ;
115template <
class view_type ,
124 typedef typename view_type::value_type
pixel_type ;
125 typedef typename view_type::difference_type Shape;
126 typedef MultiArray < 2 , pixel_type > array_type ;
127 typedef int int_type ;
128 auto shape = data.shape() ;
130 long double max_error = 0.0L ;
141 int Nx = data.width() ;
142 int Ny = data.height() ;
146 size_t max_extent = shape[0] > shape[1] ? shape[0] : shape[1] ;
148 vigra::MultiArray < 1 , rc_type > indexes ( max_extent ) ;
149 for (
size_t i = 0 ; i < max_extent ; i++ )
152 vigra::MultiArrayView < 1 , rc_type > ix0
153 ( vigra::Shape1 ( shape[0] ) , indexes.data() ) ;
155 vigra::MultiArrayView < 1 , rc_type > ix1
156 ( vigra::Shape1 ( shape[1] ) , indexes.data() ) ;
165 std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
166 std::chrono::system_clock::time_point end ;
169 for (
int times = 0 ; times < TIMES ; times++ )
173 end = std::chrono::system_clock::now();
174 cout <<
"avg " << TIMES <<
" x prefilter:............................ "
175 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / float(TIMES)
182 start = std::chrono::system_clock::now();
186 vigra::MultiArrayView < 1 , pixel_type > fake_1d_array
187 ( vigra::Shape1 ( prod ( data.shape() ) ) , data.data() ) ;
189 vigra::TinyVector < vspline::bc_code , 1 > bcv1 ( bcv[0] ) ;
192 ( fake_1d_array.shape() , DEGREE , bcv1 ) ;
194 bsp1.
core = fake_1d_array ;
196 for (
int times = 0 ; times < TIMES ; times++ )
200 end = std::chrono::system_clock::now();
201 cout <<
"avg " << TIMES <<
" x prefilter as fake 1D array:........... "
202 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / float(TIMES)
207 bsp1.
core = fake_1d_array ;
210 start = std::chrono::system_clock::now();
212 vigra::MultiArray < 1 , pixel_type > fake_1d_target
213 ( vigra::Shape1 ( prod ( data.shape() ) ) ) ;
215 vspline::restore < 1 , pixel_type > ( bsp1 , fake_1d_target ) ;
217 for (
int times = 1 ; times < TIMES ; times++ )
218 vspline::restore < 1 , pixel_type > ( bsp1 , fake_1d_target ) ;
221 end = std::chrono::system_clock::now();
222 cout <<
"avg " << TIMES <<
" x restore original data from 1D:........ "
223 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / float(TIMES)
227 cout <<
"difference original data/restored data:" << endl ;
228 error = check_diff<decltype(fake_1d_array)> ( fake_1d_array , fake_1d_target ) ;
229 if ( error > max_error )
238 view_type cfview = bsp.
core ;
247 typedef vigra::TinyVector < int , 2 > dsc_coordinate_type ;
256 eval_type raw_ev ( bsp ) ;
257 dsc_eval_type dsc_ev ( bsp ) ;
261 auto ev = vspline::make_safe_evaluator < spline_type , rc_type > ( bsp ) ;
264 typedef vigra::MultiArray<2, coordinate_type> coordinate_array ;
272 coordinate_array fwarp ( Shape ( Tx , Ty ) ) ;
273 array_type _target ( Shape(Tx,Ty) ) ;
274 view_type target ( _target ) ;
276 rc_type dfx = 0.0 , dfy = 0.0 ;
278 for (
int times = 0 ; times < 1 ; times++ )
280 for (
int y = 0 ; y < Ty ; y++ )
283 for (
int x = 0 ; x < Tx ; x++ )
297 start = std::chrono::system_clock::now();
300 for (
int times = 0 ; times < TIMES ; times++ )
305 end = std::chrono::system_clock::now();
306 cout <<
"avg " << TIMES <<
" x transform with ready-made bspline:.... "
307 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / float(TIMES)
311 error = check_diff<view_type> ( target , data ) ;
312 if ( error > max_error )
319 start = std::chrono::system_clock::now();
322 for (
int times = 0 ; times < TIMES ; times++ )
326 end = std::chrono::system_clock::now();
327 cout <<
"avg " << TIMES <<
" x classic remap:........................ "
328 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / float(TIMES)
332 error = check_diff<view_type> ( target , data ) ;
333 if ( error > max_error )
342 start = std::chrono::system_clock::now();
345 for (
int times = 0 ; times < TIMES ; times++ )
349 end = std::chrono::system_clock::now();
350 cout <<
"avg " << TIMES <<
" x index-based transform................. "
351 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / float(TIMES)
355 cout <<
"difference original data/restored data:" << endl ;
356 error = check_diff<view_type> ( target , data ) ;
357 if ( error > max_error )
365 start = std::chrono::system_clock::now();
368 for (
int times = 0 ; times < TIMES ; times++ )
369 vspline::restore < 2 , pixel_type > ( bsp , target ) ;
372 end = std::chrono::system_clock::now();
373 cout <<
"avg " << TIMES <<
" x restore original data: .............. "
374 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / float(TIMES)
378 cout <<
"difference original data/restored data:" << endl ;
379 error = check_diff<view_type> ( data , target ) ;
380 if ( error > max_error )
385 start = std::chrono::system_clock::now();
388 for (
int times = 0 ; times < TIMES ; times++ )
392 end = std::chrono::system_clock::now();
393 cout <<
"avg " << TIMES <<
" x grid eval over canonical indexes: ... "
394 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / float(TIMES)
398 cout <<
"difference original data/restored data:" << endl ;
399 error = check_diff<view_type> ( data , target ) ;
400 if ( error > max_error )
405 start = std::chrono::system_clock::now();
408 for (
int times = 0 ; times < TIMES ; times++ )
412 end = std::chrono::system_clock::now();
413 cout <<
"avg " << TIMES <<
" x gen. grid eval over canonical indexes: "
414 << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / float(TIMES)
418 cout <<
"difference original data/restored data:" << endl ;
419 error = check_diff<view_type> ( data , target ) ;
420 if ( error > max_error )
427template <
class real_type ,
class rc_type >
430 long double max_error = 0.0L ;
433 cout << fixed << showpoint << setprecision(16) ;
437 vigra::ImageImportInfo imageInfo(name);
439 std::cout <<
"Image information:\n";
440 std::cout <<
" file format: " << imageInfo.getFileType() << std::endl;
441 std::cout <<
" width: " << imageInfo.width() << std::endl;
442 std::cout <<
" height: " << imageInfo.height() << std::endl;
443 std::cout <<
" pixel type: " << imageInfo.getPixelType() << std::endl;
444 std::cout <<
" color image: ";
445 if (imageInfo.isColor()) std::cout <<
"yes (";
446 else std::cout <<
"no (";
447 std::cout <<
"number of channels: " << imageInfo.numBands() <<
")\n";
449 typedef vigra::RGBValue<real_type,0,1,2>
pixel_type;
450 typedef vigra::MultiArray<2, pixel_type> array_type ;
451 typedef vigra::MultiArrayView<2, pixel_type> view_type ;
461 array_type containArray ( imageInfo.shape() );
462 view_type imageArray ( containArray ) ;
464 vigra::importImage(imageInfo, imageArray);
476 for (
int b = 0 ; b < 4 ; b++ )
479 for (
int spline_degree = 1 ; spline_degree < 8 ; spline_degree++ )
484 <<
" spline degree " << spline_degree
485 <<
" using Vc" << endl ;
490 <<
" spline degree " << spline_degree
491 <<
" using highway" << endl ;
493#elif defined USE_STDSIMD
496 <<
" spline degree " << spline_degree
497 <<
" using std::simd" << endl ;
502 <<
" spline degree " << spline_degree
503 <<
" using SIMD emulation" << endl ;
507 if ( spline_degree == 0 )
509 std::cout <<
"using specialized evaluator" << std::endl ;
510 error = run_test < view_type , real_type , rc_type , 0 >
511 ( imageArray , bc , spline_degree ) ;
512 if ( error > max_error )
514 std::cout <<
"using unspecialized evaluator" << std::endl ;
516 ( imageArray , bc , spline_degree ) ;
517 if ( error > max_error )
520 else if ( spline_degree == 1 )
522 std::cout <<
"using specialized evaluator" << std::endl ;
523 error = run_test < view_type , real_type , rc_type , 1 >
524 ( imageArray , bc , spline_degree ) ;
525 if ( error > max_error )
527 std::cout <<
"using unspecialized evaluator" << std::endl ;
529 ( imageArray , bc , spline_degree ) ;
530 if ( error > max_error )
536 ( imageArray , bc , spline_degree ) ;
537 if ( error > max_error )
545int main (
int argc ,
char * argv[] )
547 long double max_error = 0.0L ;
550 cout <<
"testing float data, float coordinates" << endl ;
551 error = process_image<float,float> ( argv[1] ) ;
552 if ( error > max_error )
554 cout <<
"max error of float/float test: " << error << std::endl << std::endl ;
556 cout << endl <<
"testing double data, double coordinates" << endl ;
557 error = process_image<double,double> ( argv[1] ) ;
558 if ( error > max_error )
560 cout <<
"max error of double/double test: " << error << std::endl << std::endl ;
562 cout << endl <<
"testing long double data, float coordinates" << endl ;
563 error = process_image<long double,float> ( argv[1] ) ;
564 if ( error > max_error )
566 cout <<
"max error of ldouble/float test: " << error << std::endl << std::endl ;
568 cout << endl <<
"testing long double data, double coordinates" << endl ;
569 error = process_image<long double,double> ( argv[1] ) ;
570 if ( error > max_error )
572 cout <<
"max error of ldouble/double test: " << error << std::endl << std::endl ;
574 cout <<
"testing float data, double coordinates" << endl ;
575 error = process_image<float,double> ( argv[1] ) ;
576 if ( error > max_error )
578 cout <<
"max error of float/double test: " << error << std::endl << std::endl ;
580 cout << endl <<
"testing double data, float coordinates" << endl ;
581 error = process_image<double,float> ( argv[1] ) ;
582 if ( error > max_error )
584 cout <<
"max error of double/float test: " << error << std::endl << std::endl ;
586 cout <<
"reached end. max error of all tests: " << max_error << std::endl ;
vigra::RGBValue< float, 0, 1, 2 > pixel_type
vigra::TinyVector< float, 2 > coordinate_type
vspline::bspline< pixel_type, 2 > spline_type
class evaluator encodes evaluation of a spline-like object. This is a generalization of b-spline eval...
void transform(const unary_functor_type &functor, const vigra::MultiArrayView< dimension, typename unary_functor_type::in_type > &input, vigra::MultiArrayView< dimension, typename unary_functor_type::out_type > &output, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
implementation of two-array transform using wielding::coupled_wield.
vigra::TinyVector< vspline::bc_code, dimension > bcv_type
a type for a set of boundary condition codes, one per axis
const std::string bc_name[]
bc_name is for diagnostic output of bc codes
void remap(const vigra::MultiArrayView< cf_dimension, original_type > &input, const vigra::MultiArrayView< trg_dimension, coordinate_type > &coordinates, vigra::MultiArrayView< trg_dimension, result_type > &output, bcv_type< bcv_dimension > bcv=bcv_type< bcv_dimension >(MIRROR), int degree=3, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
Implementation of 'classic' remap, which directly takes an array of values and remaps it,...
bc_code
This enumeration is used for codes connected to boundary conditions. There are two aspects to boundar...
vigra::TinyVector< vigra::MultiArrayView< 1, rc_ele_type >, dimension > grid_spec
int main(int argc, char *argv[])
long double run_test(view_type &data, vspline::bc_code bc, int DEGREE, int TIMES=32)
long double check_diff(const view_type &a, const view_type &b)
check for differences between two arrays
long double process_image(char *name)
class bspline now builds on class bspline_base, adding coefficient storage, while bspline_base provid...
void prefilter(vspline::xlf_type boost=vspline::xlf_type(1), int njobs=vspline::default_njobs)
prefilter converts the knot point data in the 'core' area into b-spline coefficients....
with the definition of 'simd_traits', we can proceed to implement 'vector_traits': struct vector_trai...
includes all headers from vspline (most of them indirectly)