38 #ifndef VIGRA_MULTI_CONVOLUTION_H
39 #define VIGRA_MULTI_CONVOLUTION_H
41 #include "separableconvolution.hxx"
42 #include "array_vector.hxx"
43 #include "multi_array.hxx"
44 #include "accessor.hxx"
45 #include "numerictraits.hxx"
46 #include "navigator.hxx"
47 #include "metaprogramming.hxx"
48 #include "multi_pointoperators.hxx"
49 #include "multi_math.hxx"
50 #include "functorexpression.hxx"
51 #include "tinyvector.hxx"
52 #include "algorithm.hxx"
66 DoubleYielder(
double v,
unsigned,
const char *
const) : value(v) {}
67 DoubleYielder(
double v) : value(v) {}
69 double operator*()
const {
return value; }
73 struct IteratorDoubleYielder
76 IteratorDoubleYielder(X i,
unsigned,
const char *
const) : it(i) {}
77 IteratorDoubleYielder(X i) : it(i) {}
78 void operator++() { ++it; }
79 double operator*()
const {
return *it; }
83 struct SequenceDoubleYielder
85 typename X::const_iterator it;
86 SequenceDoubleYielder(
const X & seq,
unsigned dim,
87 const char *
const function_name =
"SequenceDoubleYielder")
90 if (seq.size() == dim)
92 std::string msg =
"(): Parameter number be equal to the number of spatial dimensions.";
93 vigra_precondition(
false, function_name + msg);
95 void operator++() { ++it; }
96 double operator*()
const {
return *it; }
100 struct WrapDoubleIterator
103 typename IfBool< IsConvertibleTo<X, double>::value,
105 typename IfBool< IsIterator<X>::value || IsArray<X>::value,
106 IteratorDoubleYielder<X>,
107 SequenceDoubleYielder<X>
112 template <
class Param1,
class Param2,
class Param3>
113 struct WrapDoubleIteratorTriple
115 typename WrapDoubleIterator<Param1>::type sigma_eff_it;
116 typename WrapDoubleIterator<Param2>::type sigma_d_it;
117 typename WrapDoubleIterator<Param3>::type step_size_it;
118 WrapDoubleIteratorTriple(Param1 sigma_eff, Param2 sigma_d, Param3 step_size)
119 : sigma_eff_it(sigma_eff), sigma_d_it(sigma_d), step_size_it(step_size) {}
126 double sigma_eff()
const {
return *sigma_eff_it; }
127 double sigma_d()
const {
return *sigma_d_it; }
128 double step_size()
const {
return *step_size_it; }
129 static void sigma_precondition(
double sigma,
const char *
const function_name)
133 std::string msg =
"(): Scale must be positive.";
134 vigra_precondition(
false, function_name + msg);
137 double sigma_scaled(
const char *
const function_name =
"unknown function ",
138 bool allow_zero =
false)
const
140 sigma_precondition(sigma_eff(), function_name);
141 sigma_precondition(sigma_d(), function_name);
142 double sigma_squared =
sq(sigma_eff()) -
sq(sigma_d());
143 if (sigma_squared > 0.0 || (allow_zero && sigma_squared == 0.0))
145 return std::sqrt(sigma_squared) / step_size();
149 std::string msg =
"(): Scale would be imaginary";
152 vigra_precondition(
false, function_name + msg +
".");
158 template <
unsigned dim>
159 struct multiArrayScaleParam
161 typedef TinyVector<double, dim> p_vector;
162 typedef typename p_vector::const_iterator return_type;
165 template <
class Param>
166 multiArrayScaleParam(Param val,
const char *
const function_name =
"multiArrayScaleParam")
168 typename WrapDoubleIterator<Param>::type in(val, dim, function_name);
169 for (
unsigned i = 0; i != dim; ++i, ++in)
172 return_type operator()()
const
176 static void precondition(
unsigned n_par,
const char *
const function_name =
"multiArrayScaleParam")
180 std::string msg =
"(): dimension parameter must be ";
181 vigra_precondition(dim == n_par, function_name + msg + n);
183 multiArrayScaleParam(
double v0,
double v1,
const char *
const function_name =
"multiArrayScaleParam")
185 precondition(2, function_name);
186 vec = p_vector(v0, v1);
188 multiArrayScaleParam(
double v0,
double v1,
double v2,
const char *
const function_name =
"multiArrayScaleParam")
190 precondition(3, function_name);
191 vec = p_vector(v0, v1, v2);
193 multiArrayScaleParam(
double v0,
double v1,
double v2,
double v3,
const char *
const function_name =
"multiArrayScaleParam")
195 precondition(4, function_name);
196 vec = p_vector(v0, v1, v2, v3);
198 multiArrayScaleParam(
double v0,
double v1,
double v2,
double v3,
double v4,
const char *
const function_name =
"multiArrayScaleParam")
200 precondition(5, function_name);
201 vec = p_vector(v0, v1, v2, v3, v4);
207 #define VIGRA_CONVOLUTION_OPTIONS(function_name, default_value, member_name, getter_setter_name) \
208 template <class Param> \
209 ConvolutionOptions & function_name(const Param & val) \
211 member_name = ParamVec(val, "ConvolutionOptions::" #function_name); \
214 ConvolutionOptions & function_name() \
216 member_name = ParamVec(default_value, "ConvolutionOptions::" #function_name); \
219 ConvolutionOptions & function_name(double v0, double v1) \
221 member_name = ParamVec(v0, v1, "ConvolutionOptions::" #function_name); \
224 ConvolutionOptions & function_name(double v0, double v1, double v2) \
226 member_name = ParamVec(v0, v1, v2, "ConvolutionOptions::" #function_name); \
229 ConvolutionOptions & function_name(double v0, double v1, double v2, double v3) \
231 member_name = ParamVec(v0, v1, v2, v3, "ConvolutionOptions::" #function_name); \
234 ConvolutionOptions & function_name(double v0, double v1, double v2, double v3, double v4) \
236 member_name = ParamVec(v0, v1, v2, v3, v4, "ConvolutionOptions::" #function_name); \
239 typename ParamVec::p_vector get##getter_setter_name()const{ \
240 return member_name.vec; \
242 void set##getter_setter_name(typename ParamVec::p_vector vec){ \
243 member_name.vec = vec; \
334 template <
unsigned dim>
339 typedef detail::multiArrayScaleParam<dim> ParamVec;
340 typedef typename ParamVec::return_type ParamIt;
345 ParamVec outer_scale;
347 Shape from_point, to_point;
357 typedef typename detail::WrapDoubleIteratorTriple<ParamIt, ParamIt, ParamIt>
359 typedef typename detail::WrapDoubleIterator<ParamIt>::type
362 ScaleIterator scaleParams()
const
364 return ScaleIterator(sigma_eff(), sigma_d(), step_size());
366 StepIterator stepParams()
const
368 return StepIterator(step_size());
375 return outer.
stdDev(outer_scale()).resolutionStdDev(0.0);
380 VIGRA_CONVOLUTION_OPTIONS(
stepSize, 1.0, step_size, StepSize)
415 VIGRA_CONVOLUTION_OPTIONS(
stdDev, 0.0, sigma_eff, StdDev)
416 VIGRA_CONVOLUTION_OPTIONS(
innerScale, 0.0, sigma_eff, InnerScale)
446 VIGRA_CONVOLUTION_OPTIONS(
outerScale, 0.0, outer_scale, OuterScale)
478 vigra_precondition(ratio >= 0.0,
479 "ConvolutionOptions::filterWindowSize(): ratio must not be negative.");
480 window_ratio = ratio;
484 double getFilterWindowSize()
const {
505 std::pair<Shape, Shape> getSubarray()
const{
506 std::pair<Shape, Shape> res;
507 res.first = from_point;
508 res.second = to_point;
522 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
523 class DestIterator,
class DestAccessor,
class KernelIterator>
525 internalSeparableConvolveMultiArrayTmp(
526 SrcIterator si, SrcShape
const & shape, SrcAccessor src,
527 DestIterator di, DestAccessor dest, KernelIterator kit)
529 enum { N = 1 + SrcIterator::level };
531 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
532 typedef typename AccessorTraits<TmpType>::default_accessor TmpAcessor;
535 ArrayVector<TmpType> tmp( shape[0] );
537 typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
538 typedef MultiArrayNavigator<DestIterator, N> DNavigator;
544 SNavigator snav( si, shape, 0 );
545 DNavigator dnav( di, shape, 0 );
547 for( ; snav.hasMore(); snav++, dnav++ )
550 copyLine(snav.begin(), snav.end(), src, tmp.begin(), acc);
553 destIter( dnav.begin(), dest ),
560 for(
int d = 1; d < N; ++d, ++kit )
562 DNavigator dnav( di, shape, d );
564 tmp.resize( shape[d] );
566 for( ; dnav.hasMore(); dnav++ )
569 copyLine(dnav.begin(), dnav.end(), dest, tmp.begin(), acc);
572 destIter( dnav.begin(), dest ),
584 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
585 class DestIterator,
class DestAccessor,
class KernelIterator>
587 internalSeparableConvolveSubarray(
588 SrcIterator si, SrcShape
const & shape, SrcAccessor src,
589 DestIterator di, DestAccessor dest, KernelIterator kit,
590 SrcShape
const & start, SrcShape
const & stop)
592 enum { N = 1 + SrcIterator::level };
594 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
595 typedef MultiArray<N, TmpType> TmpArray;
596 typedef typename TmpArray::traverser TmpIterator;
597 typedef typename AccessorTraits<TmpType>::default_accessor TmpAcessor;
599 SrcShape sstart, sstop, axisorder, tmpshape;
600 TinyVector<double, N> overhead;
601 for(
int k=0; k<N; ++k)
604 sstart[k] = start[k] - kit[k].right();
607 sstop[k] = stop[k] - kit[k].left();
608 if(sstop[k] > shape[k])
610 overhead[k] = double(sstop[k] - sstart[k]) / (stop[k] - start[k]);
613 indexSort(overhead.begin(), overhead.end(), axisorder.begin(), std::greater<double>());
614 SrcShape dstart, dstop(sstop - sstart);
615 dstop[axisorder[0]] = stop[axisorder[0]] - start[axisorder[0]];
618 MultiArray<N, TmpType> tmp(dstop);
620 typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
621 typedef MultiArrayNavigator<TmpIterator, N> TNavigator;
627 SNavigator snav( si, sstart, sstop, axisorder[0]);
628 TNavigator tnav( tmp.traverser_begin(), dstart, dstop, axisorder[0]);
630 ArrayVector<TmpType> tmpline(sstop[axisorder[0]] - sstart[axisorder[0]]);
632 int lstart = start[axisorder[0]] - sstart[axisorder[0]];
633 int lstop = lstart + (stop[axisorder[0]] - start[axisorder[0]]);
635 for( ; snav.hasMore(); snav++, tnav++ )
638 copyLine(snav.begin(), snav.end(), src, tmpline.begin(), acc);
640 convolveLine(srcIterRange(tmpline.begin(), tmpline.end(), acc),
641 destIter(tnav.begin(), acc),
642 kernel1d( kit[axisorder[0]] ), lstart, lstop);
647 for(
int d = 1; d < N; ++d)
649 TNavigator tnav( tmp.traverser_begin(), dstart, dstop, axisorder[d]);
651 ArrayVector<TmpType> tmpline(dstop[axisorder[d]] - dstart[axisorder[d]]);
653 int lstart = start[axisorder[d]] - sstart[axisorder[d]];
654 int lstop = lstart + (stop[axisorder[d]] - start[axisorder[d]]);
656 for( ; tnav.hasMore(); tnav++ )
659 copyLine(tnav.begin(), tnav.end(), acc, tmpline.begin(), acc );
661 convolveLine(srcIterRange(tmpline.begin(), tmpline.end(), acc),
662 destIter( tnav.begin() + lstart, acc ),
663 kernel1d( kit[axisorder[d]] ), lstart, lstop);
666 dstart[axisorder[d]] = lstart;
667 dstop[axisorder[d]] = lstop;
670 copyMultiArray(tmp.traverser_begin()+dstart, stop-start, acc, di, dest);
676 scaleKernel(K & kernel,
double a)
678 for(
int i = kernel.left(); i <= kernel.right(); ++i)
679 kernel[i] = detail::RequiresExplicitCast<typename K::value_type>::cast(kernel[i] * a);
862 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
863 class DestIterator,
class DestAccessor,
class KernelIterator>
866 DestIterator d, DestAccessor dest,
867 KernelIterator kernels,
868 SrcShape start = SrcShape(),
869 SrcShape stop = SrcShape())
871 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
874 if(stop != SrcShape())
877 enum { N = 1 + SrcIterator::level };
878 detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, start);
879 detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, stop);
881 for(
int k=0; k<N; ++k)
882 vigra_precondition(0 <= start[k] && start[k] < stop[k] && stop[k] <= shape[k],
883 "separableConvolveMultiArray(): invalid subarray shape.");
885 detail::internalSeparableConvolveSubarray(s, shape, src, d, dest, kernels, start, stop);
887 else if(!IsSameType<TmpType, typename DestAccessor::value_type>::boolResult)
890 MultiArray<SrcShape::static_size, TmpType> tmpArray(shape);
891 detail::internalSeparableConvolveMultiArrayTmp( s, shape, src,
892 tmpArray.traverser_begin(),
typename AccessorTraits<TmpType>::default_accessor(), kernels );
898 detail::internalSeparableConvolveMultiArrayTmp( s, shape, src, d, dest, kernels );
902 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
903 class DestIterator,
class DestAccessor,
class T>
906 DestIterator d, DestAccessor dest,
907 Kernel1D<T>
const & kernel,
908 SrcShape
const & start = SrcShape(),
909 SrcShape
const & stop = SrcShape())
911 ArrayVector<Kernel1D<T> > kernels(shape.size(), kernel);
916 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
917 class DestIterator,
class DestAccessor,
class KernelIterator>
920 pair<DestIterator, DestAccessor>
const & dest,
922 SrcShape
const & start = SrcShape(),
923 SrcShape
const & stop = SrcShape())
926 dest.first, dest.second, kit, start, stop );
929 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
930 class DestIterator,
class DestAccessor,
class T>
933 pair<DestIterator, DestAccessor>
const & dest,
934 Kernel1D<T>
const & kernel,
935 SrcShape
const & start = SrcShape(),
936 SrcShape
const & stop = SrcShape())
938 ArrayVector<Kernel1D<T> > kernels(source.second.size(), kernel);
941 dest.first, dest.second, kernels.begin(), start, stop);
944 template <
unsigned int N,
class T1,
class S1,
946 class KernelIterator>
949 MultiArrayView<N, T2, S2> dest,
951 typename MultiArrayShape<N>::type start =
typename MultiArrayShape<N>::type(),
952 typename MultiArrayShape<N>::type stop =
typename MultiArrayShape<N>::type())
954 if(stop !=
typename MultiArrayShape<N>::type())
956 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), start);
957 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), stop);
958 vigra_precondition(dest.shape() == (stop - start),
959 "separableConvolveMultiArray(): shape mismatch between ROI and output.");
963 vigra_precondition(source.shape() == dest.shape(),
964 "separableConvolveMultiArray(): shape mismatch between input and output.");
967 destMultiArray(dest), kit, start, stop );
970 template <
unsigned int N,
class T1,
class S1,
975 MultiArrayView<N, T2, S2> dest,
976 Kernel1D<T>
const & kernel,
977 typename MultiArrayShape<N>::type
const & start =
typename MultiArrayShape<N>::type(),
978 typename MultiArrayShape<N>::type
const & stop =
typename MultiArrayShape<N>::type())
980 ArrayVector<Kernel1D<T> > kernels(N, kernel);
1073 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1074 class DestIterator,
class DestAccessor,
class T>
1077 DestIterator d, DestAccessor dest,
1079 SrcShape
const & start = SrcShape(),
1080 SrcShape
const & stop = SrcShape())
1082 enum { N = 1 + SrcIterator::level };
1083 vigra_precondition( dim < N,
1084 "convolveMultiArrayOneDimension(): The dimension number to convolve must be smaller "
1085 "than the data dimensionality" );
1087 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
1088 typedef typename AccessorTraits<TmpType>::default_const_accessor TmpAccessor;
1089 ArrayVector<TmpType> tmp( shape[dim] );
1091 typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
1092 typedef MultiArrayNavigator<DestIterator, N> DNavigator;
1094 SrcShape sstart, sstop(shape), dstart, dstop(shape);
1096 if(stop != SrcShape())
1101 sstop[dim] = shape[dim];
1102 dstop = stop - start;
1105 SNavigator snav( s, sstart, sstop, dim );
1106 DNavigator dnav( d, dstart, dstop, dim );
1108 for( ; snav.hasMore(); snav++, dnav++ )
1111 copyLine(snav.begin(), snav.end(), src,
1112 tmp.begin(),
typename AccessorTraits<TmpType>::default_accessor() );
1114 convolveLine(srcIterRange( tmp.begin(), tmp.end(), TmpAccessor()),
1115 destIter( dnav.begin(), dest ),
1116 kernel1d( kernel), start[dim], stop[dim]);
1120 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1121 class DestIterator,
class DestAccessor,
class T>
1124 pair<DestIterator, DestAccessor>
const & dest,
1126 Kernel1D<T>
const & kernel,
1127 SrcShape
const & start = SrcShape(),
1128 SrcShape
const & stop = SrcShape())
1131 dest.first, dest.second, dim, kernel, start, stop);
1134 template <
unsigned int N,
class T1,
class S1,
1139 MultiArrayView<N, T2, S2> dest,
1141 Kernel1D<T>
const & kernel,
1142 typename MultiArrayShape<N>::type start =
typename MultiArrayShape<N>::type(),
1143 typename MultiArrayShape<N>::type stop =
typename MultiArrayShape<N>::type())
1145 if(stop !=
typename MultiArrayShape<N>::type())
1147 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), start);
1148 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), stop);
1149 vigra_precondition(dest.shape() == (stop - start),
1150 "convolveMultiArrayOneDimension(): shape mismatch between ROI and output.");
1154 vigra_precondition(source.shape() == dest.shape(),
1155 "convolveMultiArrayOneDimension(): shape mismatch between input and output.");
1158 destMultiArray(dest), dim, kernel, start, stop);
1299 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1300 class DestIterator,
class DestAccessor>
1303 DestIterator d, DestAccessor dest,
1304 const ConvolutionOptions<SrcShape::static_size> & opt,
1305 const char *
const function_name =
"gaussianSmoothMultiArray" )
1307 static const int N = SrcShape::static_size;
1309 typename ConvolutionOptions<N>::ScaleIterator params = opt.scaleParams();
1310 ArrayVector<Kernel1D<double> > kernels(N);
1312 for (
int dim = 0; dim < N; ++dim, ++params)
1313 kernels[dim].initGaussian(params.sigma_scaled(function_name,
true),
1314 1.0, opt.window_ratio);
1319 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1320 class DestIterator,
class DestAccessor>
1323 DestIterator d, DestAccessor dest,
double sigma,
1324 const ConvolutionOptions<SrcShape::static_size> & opt = ConvolutionOptions<SrcShape::static_size>())
1326 ConvolutionOptions<SrcShape::static_size> par = opt;
1330 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1331 class DestIterator,
class DestAccessor>
1334 pair<DestIterator, DestAccessor>
const & dest,
1335 const ConvolutionOptions<SrcShape::static_size> & opt)
1338 dest.first, dest.second, opt );
1341 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1342 class DestIterator,
class DestAccessor>
1345 pair<DestIterator, DestAccessor>
const & dest,
double sigma,
1346 const ConvolutionOptions<SrcShape::static_size> & opt = ConvolutionOptions<SrcShape::static_size>())
1349 dest.first, dest.second, sigma, opt );
1352 template <
unsigned int N,
class T1,
class S1,
1356 MultiArrayView<N, T2, S2> dest,
1357 ConvolutionOptions<N> opt)
1359 if(opt.to_point !=
typename MultiArrayShape<N>::type())
1361 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.from_point);
1362 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.to_point);
1363 vigra_precondition(dest.shape() == (opt.to_point - opt.from_point),
1364 "gaussianSmoothMultiArray(): shape mismatch between ROI and output.");
1368 vigra_precondition(source.shape() == dest.shape(),
1369 "gaussianSmoothMultiArray(): shape mismatch between input and output.");
1373 destMultiArray(dest), opt );
1376 template <
unsigned int N,
class T1,
class S1,
1380 MultiArrayView<N, T2, S2> dest,
1382 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
1511 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1512 class DestIterator,
class DestAccessor>
1515 DestIterator di, DestAccessor dest,
1516 ConvolutionOptions<SrcShape::static_size>
const & opt,
1517 const char *
const function_name =
"gaussianGradientMultiArray")
1519 typedef typename DestAccessor::value_type DestType;
1520 typedef typename DestType::value_type DestValueType;
1521 typedef typename NumericTraits<DestValueType>::RealPromote KernelType;
1523 static const int N = SrcShape::static_size;
1524 typedef typename ConvolutionOptions<N>::ScaleIterator ParamType;
1526 for(
int k=0; k<N; ++k)
1530 vigra_precondition(N == (
int)dest.size(di),
1531 "gaussianGradientMultiArray(): Wrong number of channels in output array.");
1533 ParamType params = opt.scaleParams();
1534 ParamType params2(params);
1536 ArrayVector<Kernel1D<KernelType> > plain_kernels(N);
1537 for (
int dim = 0; dim < N; ++dim, ++params)
1539 double sigma = params.sigma_scaled(function_name);
1540 plain_kernels[dim].initGaussian(sigma, 1.0, opt.window_ratio);
1543 typedef VectorElementAccessor<DestAccessor> ElementAccessor;
1546 for (
int dim = 0; dim < N; ++dim, ++params2)
1548 ArrayVector<Kernel1D<KernelType> > kernels(plain_kernels);
1549 kernels[dim].initGaussianDerivative(params2.sigma_scaled(), 1, 1.0, opt.window_ratio);
1550 detail::scaleKernel(kernels[dim], 1.0 / params2.step_size());
1552 opt.from_point, opt.to_point);
1556 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1557 class DestIterator,
class DestAccessor>
1560 DestIterator di, DestAccessor dest,
double sigma,
1561 ConvolutionOptions<SrcShape::static_size> opt = ConvolutionOptions<SrcShape::static_size>())
1566 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1567 class DestIterator,
class DestAccessor>
1570 pair<DestIterator, DestAccessor>
const & dest,
1571 ConvolutionOptions<SrcShape::static_size>
const & opt )
1574 dest.first, dest.second, opt );
1577 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1578 class DestIterator,
class DestAccessor>
1581 pair<DestIterator, DestAccessor>
const & dest,
1583 const ConvolutionOptions<SrcShape::static_size> & opt = ConvolutionOptions<SrcShape::static_size>())
1586 dest.first, dest.second, sigma, opt );
1589 template <
unsigned int N,
class T1,
class S1,
1593 MultiArrayView<N, TinyVector<T2, N>, S2> dest,
1594 ConvolutionOptions<N> opt )
1596 if(opt.to_point !=
typename MultiArrayShape<N>::type())
1598 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.from_point);
1599 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.to_point);
1600 vigra_precondition(dest.shape() == (opt.to_point - opt.from_point),
1601 "gaussianGradientMultiArray(): shape mismatch between ROI and output.");
1605 vigra_precondition(source.shape() == dest.shape(),
1606 "gaussianGradientMultiArray(): shape mismatch between input and output.");
1610 destMultiArray(dest), opt );
1613 template <
unsigned int N,
class T1,
class S1,
1617 MultiArrayView<N, TinyVector<T2, N>, S2> dest,
1619 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
1632 template <
unsigned int N,
class T1,
class S1,
1635 gaussianGradientMagnitudeImpl(MultiArrayView<N+1, T1, S1>
const & src,
1636 MultiArrayView<N, T2, S2> dest,
1637 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
1639 typename MultiArrayShape<N>::type shape(src.shape().template subarray<0,N>());
1640 if(opt.to_point !=
typename MultiArrayShape<N>::type())
1642 detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, opt.from_point);
1643 detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, opt.to_point);
1644 vigra_precondition(dest.shape() == (opt.to_point - opt.from_point),
1645 "gaussianGradientMagnitude(): shape mismatch between ROI and output.");
1649 vigra_precondition(shape == dest.shape(),
1650 "gaussianGradientMagnitude(): shape mismatch between input and output.");
1655 typedef typename NumericTraits<T1>::RealPromote TmpType;
1656 MultiArray<N, TinyVector<TmpType, N> > grad(dest.shape());
1658 using namespace multi_math;
1660 for(
int k=0; k<src.shape(N); ++k)
1672 template <
unsigned int N,
class T1,
class S1,
1676 MultiArrayView<N, T2, S2> dest,
1677 ConvolutionOptions<N>
const & opt)
1679 detail::gaussianGradientMagnitudeImpl<N, T1>(src, dest, opt);
1682 template <
unsigned int N,
class T1,
class S1,
1686 MultiArrayView<N, T2, S2> dest,
1687 ConvolutionOptions<N>
const & opt)
1689 detail::gaussianGradientMagnitudeImpl<N, T1>(src.insertSingletonDimension(N), dest, opt);
1692 template <
unsigned int N,
class T1,
int M,
class S1,
1696 MultiArrayView<N, T2, S2> dest,
1697 ConvolutionOptions<N>
const & opt)
1699 detail::gaussianGradientMagnitudeImpl<N, T1>(src.expandElements(N), dest, opt);
1702 template <
unsigned int N,
class T1,
unsigned int R,
unsigned int G,
unsigned int B,
class S1,
1706 MultiArrayView<N, T2, S2> dest,
1707 ConvolutionOptions<N>
const & opt)
1709 detail::gaussianGradientMagnitudeImpl<N, T1>(src.expandElements(N), dest, opt);
1712 template <
unsigned int N,
class T1,
class S1,
1716 MultiArrayView<N, T2, S2> dest,
1718 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
1723 template <
unsigned int N,
class T1,
class S1,
1727 MultiArrayView<N, T2, S2> dest,
1729 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
1731 gaussianGradientMagnitude<N>(src, dest, opt.stdDev(sigma));
1844 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1845 class DestIterator,
class DestAccessor>
1848 DestIterator di, DestAccessor dest,
1849 const ConvolutionOptions<SrcShape::static_size> & opt = ConvolutionOptions<SrcShape::static_size>())
1851 typedef typename DestAccessor::value_type DestType;
1852 typedef typename DestType::value_type DestValueType;
1853 typedef typename NumericTraits<DestValueType>::RealPromote KernelType;
1855 static const int N = SrcShape::static_size;
1856 typedef typename ConvolutionOptions<N>::StepIterator StepType;
1858 for(
int k=0; k<N; ++k)
1862 vigra_precondition(N == (
int)dest.size(di),
1863 "symmetricGradientMultiArray(): Wrong number of channels in output array.");
1865 Kernel1D<KernelType> filter;
1866 filter.initSymmetricDifference();
1868 StepType step_size_it = opt.stepParams();
1870 typedef VectorElementAccessor<DestAccessor> ElementAccessor;
1873 for (
int d = 0; d < N; ++d, ++step_size_it)
1875 Kernel1D<KernelType> symmetric(filter);
1876 detail::scaleKernel(symmetric, 1 / *step_size_it);
1878 di, ElementAccessor(d, dest),
1879 d, symmetric, opt.from_point, opt.to_point);
1883 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
1884 class DestIterator,
class DestAccessor>
1887 pair<DestIterator, DestAccessor>
const & dest,
1888 const ConvolutionOptions<SrcShape::static_size> & opt = ConvolutionOptions<SrcShape::static_size>())
1891 dest.first, dest.second, opt);
1894 template <
unsigned int N,
class T1,
class S1,
1898 MultiArrayView<N, TinyVector<T2, N>, S2> dest,
1899 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
1901 if(opt.to_point !=
typename MultiArrayShape<N>::type())
1903 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.from_point);
1904 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.to_point);
1905 vigra_precondition(dest.shape() == (opt.to_point - opt.from_point),
1906 "symmetricGradientMultiArray(): shape mismatch between ROI and output.");
1910 vigra_precondition(source.shape() == dest.shape(),
1911 "symmetricGradientMultiArray(): shape mismatch between input and output.");
1915 destMultiArray(dest), opt);
2038 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2039 class DestIterator,
class DestAccessor>
2042 DestIterator di, DestAccessor dest,
2043 ConvolutionOptions<SrcShape::static_size>
const & opt )
2045 using namespace functor;
2047 typedef typename DestAccessor::value_type DestType;
2048 typedef typename NumericTraits<DestType>::RealPromote KernelType;
2049 typedef typename AccessorTraits<KernelType>::default_accessor DerivativeAccessor;
2051 static const int N = SrcShape::static_size;
2052 typedef typename ConvolutionOptions<N>::ScaleIterator ParamType;
2054 ParamType params = opt.scaleParams();
2055 ParamType params2(params);
2057 ArrayVector<Kernel1D<KernelType> > plain_kernels(N);
2058 for (
int dim = 0; dim < N; ++dim, ++params)
2060 double sigma = params.sigma_scaled(
"laplacianOfGaussianMultiArray");
2061 plain_kernels[dim].initGaussian(sigma, 1.0, opt.window_ratio);
2064 SrcShape dshape(shape);
2065 if(opt.to_point != SrcShape())
2066 dshape = opt.to_point - opt.from_point;
2068 MultiArray<N, KernelType> derivative(dshape);
2071 for (
int dim = 0; dim < N; ++dim, ++params2)
2073 ArrayVector<Kernel1D<KernelType> > kernels(plain_kernels);
2074 kernels[dim].initGaussianDerivative(params2.sigma_scaled(), 2, 1.0, opt.window_ratio);
2075 detail::scaleKernel(kernels[dim], 1.0 /
sq(params2.step_size()));
2080 di, dest, kernels.begin(), opt.from_point, opt.to_point);
2085 derivative.traverser_begin(), DerivativeAccessor(),
2086 kernels.begin(), opt.from_point, opt.to_point);
2088 di, dest, Arg1() + Arg2() );
2093 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2094 class DestIterator,
class DestAccessor>
2097 DestIterator di, DestAccessor dest,
double sigma,
2098 ConvolutionOptions<SrcShape::static_size> opt = ConvolutionOptions<SrcShape::static_size>())
2103 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2104 class DestIterator,
class DestAccessor>
2107 pair<DestIterator, DestAccessor>
const & dest,
2108 ConvolutionOptions<SrcShape::static_size>
const & opt )
2111 dest.first, dest.second, opt );
2114 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2115 class DestIterator,
class DestAccessor>
2118 pair<DestIterator, DestAccessor>
const & dest,
2120 const ConvolutionOptions<SrcShape::static_size> & opt = ConvolutionOptions<SrcShape::static_size>())
2123 dest.first, dest.second, sigma, opt );
2126 template <
unsigned int N,
class T1,
class S1,
2130 MultiArrayView<N, T2, S2> dest,
2131 ConvolutionOptions<N> opt )
2133 if(opt.to_point !=
typename MultiArrayShape<N>::type())
2135 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.from_point);
2136 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.to_point);
2137 vigra_precondition(dest.shape() == (opt.to_point - opt.from_point),
2138 "laplacianOfGaussianMultiArray(): shape mismatch between ROI and output.");
2142 vigra_precondition(source.shape() == dest.shape(),
2143 "laplacianOfGaussianMultiArray(): shape mismatch between input and output.");
2147 destMultiArray(dest), opt );
2150 template <
unsigned int N,
class T1,
class S1,
2154 MultiArrayView<N, T2, S2> dest,
2156 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
2270 template <
class Iterator,
2271 unsigned int N,
class T,
class S>
2274 MultiArrayView<N, T, S> divergence,
2275 ConvolutionOptions<N> opt)
2277 typedef typename std::iterator_traits<Iterator>::value_type ArrayType;
2278 typedef typename ArrayType::value_type SrcType;
2279 typedef typename NumericTraits<SrcType>::RealPromote TmpType;
2280 typedef Kernel1D<double> Kernel;
2282 vigra_precondition(std::distance(vectorField, vectorFieldEnd) == N,
2283 "gaussianDivergenceMultiArray(): wrong number of input arrays.");
2286 typename ConvolutionOptions<N>::ScaleIterator params = opt.scaleParams();
2287 ArrayVector<double> sigmas(N);
2288 ArrayVector<Kernel> kernels(N);
2289 for(
unsigned int k = 0; k < N; ++k, ++params)
2291 sigmas[k] = params.sigma_scaled(
"gaussianDivergenceMultiArray");
2292 kernels[k].initGaussian(sigmas[k], 1.0, opt.window_ratio);
2295 MultiArray<N, TmpType> tmpDeriv(divergence.shape());
2297 for(
unsigned int k=0; k < N; ++k, ++vectorField)
2299 kernels[k].initGaussianDerivative(sigmas[k], 1, 1.0, opt.window_ratio);
2307 divergence += tmpDeriv;
2309 kernels[k].initGaussian(sigmas[k], 1.0, opt.window_ratio);
2313 template <
class Iterator,
2314 unsigned int N,
class T,
class S>
2317 MultiArrayView<N, T, S> divergence,
2319 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
2324 template <
unsigned int N,
class T1,
class S1,
2328 MultiArrayView<N, T2, S2> divergence,
2329 ConvolutionOptions<N>
const & opt)
2331 ArrayVector<MultiArrayView<N, T1> > field;
2332 for(
unsigned int k=0; k<N; ++k)
2333 field.push_back(vectorField.bindElementChannel(k));
2338 template <
unsigned int N,
class T1,
class S1,
2342 MultiArrayView<N, T2, S2> divergence,
2344 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
2471 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2472 class DestIterator,
class DestAccessor>
2475 DestIterator di, DestAccessor dest,
2476 ConvolutionOptions<SrcShape::static_size>
const & opt )
2478 typedef typename DestAccessor::value_type DestType;
2479 typedef typename DestType::value_type DestValueType;
2480 typedef typename NumericTraits<DestValueType>::RealPromote KernelType;
2482 static const int N = SrcShape::static_size;
2483 static const int M = N*(N+1)/2;
2484 typedef typename ConvolutionOptions<N>::ScaleIterator ParamType;
2486 for(
int k=0; k<N; ++k)
2490 vigra_precondition(M == (
int)dest.size(di),
2491 "hessianOfGaussianMultiArray(): Wrong number of channels in output array.");
2493 ParamType params_init = opt.scaleParams();
2495 ArrayVector<Kernel1D<KernelType> > plain_kernels(N);
2496 ParamType params(params_init);
2497 for (
int dim = 0; dim < N; ++dim, ++params)
2499 double sigma = params.sigma_scaled(
"hessianOfGaussianMultiArray");
2500 plain_kernels[dim].initGaussian(sigma, 1.0, opt.window_ratio);
2503 typedef VectorElementAccessor<DestAccessor> ElementAccessor;
2506 ParamType params_i(params_init);
2507 for (
int b=0, i=0; i<N; ++i, ++params_i)
2509 ParamType params_j(params_i);
2510 for (
int j=i; j<N; ++j, ++b, ++params_j)
2512 ArrayVector<Kernel1D<KernelType> > kernels(plain_kernels);
2515 kernels[i].initGaussianDerivative(params_i.sigma_scaled(), 2, 1.0, opt.window_ratio);
2519 kernels[i].initGaussianDerivative(params_i.sigma_scaled(), 1, 1.0, opt.window_ratio);
2520 kernels[j].initGaussianDerivative(params_j.sigma_scaled(), 1, 1.0, opt.window_ratio);
2522 detail::scaleKernel(kernels[i], 1 / params_i.step_size());
2523 detail::scaleKernel(kernels[j], 1 / params_j.step_size());
2525 kernels.begin(), opt.from_point, opt.to_point);
2530 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2531 class DestIterator,
class DestAccessor>
2534 DestIterator di, DestAccessor dest,
double sigma,
2535 ConvolutionOptions<SrcShape::static_size> opt = ConvolutionOptions<SrcShape::static_size>())
2540 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2541 class DestIterator,
class DestAccessor>
2544 pair<DestIterator, DestAccessor>
const & dest,
2545 ConvolutionOptions<SrcShape::static_size>
const & opt )
2548 dest.first, dest.second, opt );
2551 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2552 class DestIterator,
class DestAccessor>
2555 pair<DestIterator, DestAccessor>
const & dest,
2557 const ConvolutionOptions<SrcShape::static_size> & opt = ConvolutionOptions<SrcShape::static_size>())
2560 dest.first, dest.second, sigma, opt );
2563 template <
unsigned int N,
class T1,
class S1,
2567 MultiArrayView<N, TinyVector<T2,
int(N*(N+1)/2)>, S2> dest,
2568 ConvolutionOptions<N> opt )
2570 if(opt.to_point !=
typename MultiArrayShape<N>::type())
2572 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.from_point);
2573 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.to_point);
2574 vigra_precondition(dest.shape() == (opt.to_point - opt.from_point),
2575 "hessianOfGaussianMultiArray(): shape mismatch between ROI and output.");
2579 vigra_precondition(source.shape() == dest.shape(),
2580 "hessianOfGaussianMultiArray(): shape mismatch between input and output.");
2584 destMultiArray(dest), opt );
2587 template <
unsigned int N,
class T1,
class S1,
2591 MultiArrayView<N, TinyVector<T2,
int(N*(N+1)/2)>, S2> dest,
2593 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
2600 template<
int N,
class VectorType>
2601 struct StructurTensorFunctor
2603 typedef VectorType result_type;
2604 typedef typename VectorType::value_type ValueType;
2607 VectorType operator()(T
const & in)
const
2610 for(
int b=0, i=0; i<N; ++i)
2612 for(
int j=i; j<N; ++j, ++b)
2614 res[b] = detail::RequiresExplicitCast<ValueType>::cast(in[i]*in[j]);
2747 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2748 class DestIterator,
class DestAccessor>
2751 DestIterator di, DestAccessor dest,
2752 ConvolutionOptions<SrcShape::static_size> opt)
2754 static const int N = SrcShape::static_size;
2755 static const int M = N*(N+1)/2;
2757 typedef typename DestAccessor::value_type DestType;
2758 typedef typename DestType::value_type DestValueType;
2759 typedef typename NumericTraits<DestValueType>::RealPromote KernelType;
2760 typedef TinyVector<KernelType, N> GradientVector;
2761 typedef typename AccessorTraits<GradientVector>::default_accessor GradientAccessor;
2762 typedef typename AccessorTraits<DestType>::default_accessor GradientTensorAccessor;
2764 for(
int k=0; k<N; ++k)
2768 vigra_precondition(M == (
int)dest.size(di),
2769 "structureTensorMultiArray(): Wrong number of channels in output array.");
2771 ConvolutionOptions<N> innerOptions = opt;
2772 ConvolutionOptions<N> outerOptions = opt.outerOptions();
2773 typename ConvolutionOptions<N>::ScaleIterator params = outerOptions.scaleParams();
2775 SrcShape gradientShape(shape);
2776 if(opt.to_point != SrcShape())
2778 detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, opt.from_point);
2779 detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, opt.to_point);
2781 for(
int k=0; k<N; ++k, ++params)
2783 Kernel1D<double> gauss;
2784 gauss.initGaussian(params.sigma_scaled(
"structureTensorMultiArray"), 1.0, opt.window_ratio);
2785 int dilation = gauss.right();
2786 innerOptions.from_point[k] = std::max<MultiArrayIndex>(0, opt.from_point[k] - dilation);
2787 innerOptions.to_point[k] = std::min<MultiArrayIndex>(shape[k], opt.to_point[k] + dilation);
2789 outerOptions.from_point -= innerOptions.from_point;
2790 outerOptions.to_point -= innerOptions.from_point;
2791 gradientShape = innerOptions.to_point - innerOptions.from_point;
2794 MultiArray<N, GradientVector> gradient(gradientShape);
2795 MultiArray<N, DestType> gradientTensor(gradientShape);
2797 gradient.traverser_begin(), GradientAccessor(),
2799 "structureTensorMultiArray");
2802 gradientTensor.traverser_begin(), GradientTensorAccessor(),
2803 detail::StructurTensorFunctor<N, DestType>());
2806 di, dest, outerOptions,
2807 "structureTensorMultiArray");
2810 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2811 class DestIterator,
class DestAccessor>
2814 DestIterator di, DestAccessor dest,
2815 double innerScale,
double outerScale,
2816 ConvolutionOptions<SrcShape::static_size> opt = ConvolutionOptions<SrcShape::static_size>())
2819 opt.stdDev(innerScale).outerScale(outerScale));
2822 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2823 class DestIterator,
class DestAccessor>
2826 pair<DestIterator, DestAccessor>
const & dest,
2827 ConvolutionOptions<SrcShape::static_size>
const & opt )
2830 dest.first, dest.second, opt );
2834 template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
2835 class DestIterator,
class DestAccessor>
2838 pair<DestIterator, DestAccessor>
const & dest,
2839 double innerScale,
double outerScale,
2840 const ConvolutionOptions<SrcShape::static_size> & opt = ConvolutionOptions<SrcShape::static_size>())
2843 dest.first, dest.second,
2844 innerScale, outerScale, opt);
2847 template <
unsigned int N,
class T1,
class S1,
2851 MultiArrayView<N, TinyVector<T2,
int(N*(N+1)/2)>, S2> dest,
2852 ConvolutionOptions<N> opt )
2854 if(opt.to_point !=
typename MultiArrayShape<N>::type())
2856 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.from_point);
2857 detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt.to_point);
2858 vigra_precondition(dest.shape() == (opt.to_point - opt.from_point),
2859 "structureTensorMultiArray(): shape mismatch between ROI and output.");
2863 vigra_precondition(source.shape() == dest.shape(),
2864 "structureTensorMultiArray(): shape mismatch between input and output.");
2868 destMultiArray(dest), opt );
2872 template <
unsigned int N,
class T1,
class S1,
2876 MultiArrayView<N, TinyVector<T2,
int(N*(N+1)/2)>, S2> dest,
2877 double innerScale,
double outerScale,
2878 ConvolutionOptions<N> opt = ConvolutionOptions<N>())
2888 #endif //-- VIGRA_MULTI_CONVOLUTION_H
ConvolutionOptions< dim > & outerScale(...)
Generic 1 dimensional convolution kernel.
Definition: separableconvolution.hxx:52
void indexSort(Iterator first, Iterator last, IndexIterator index_first, Compare c)
Return the index permutation that would sort the input array.
Definition: algorithm.hxx:414
void symmetricGradientMultiArray(...)
Calculate gradient of a multi-dimensional arrays using symmetric difference filters.
void gaussianDivergenceMultiArray(...)
Calculate the divergence of a vector field using Gaussian derivative filters.
FFTWComplex< R >::SquaredNormType squaredNorm(const FFTWComplex< R > &a)
squared norm (= squared magnitude)
Definition: fftw3.hxx:1044
void separableConvolveMultiArray(...)
Separated convolution on multi-dimensional arrays.
ConvolutionOptions< dim > & subarray(Shape const &from, Shape const &to)
Definition: multi_convolution.hxx:498
void convolveLine(...)
Performs a 1-dimensional convolution of the source signal using the given kernel. ...
void gaussianGradientMultiArray(...)
Calculate Gaussian gradient of a multi-dimensional arrays.
ConvolutionOptions< dim > & stepSize(...)
Definition: multi_fwd.hxx:63
void laplacianOfGaussianMultiArray(...)
Calculate Laplacian of a N-dimensional arrays using Gaussian derivative filters.
NumericTraits< T >::Promote sq(T t)
The square function.
Definition: mathutil.hxx:382
vigra::GridGraph< N, DirectedTag >::vertex_descriptor source(typename vigra::GridGraph< N, DirectedTag >::edge_descriptor const &e, vigra::GridGraph< N, DirectedTag > const &g)
Get a vertex descriptor for the start vertex of edge e in graph g (API: boost).
Definition: multi_gridgraph.hxx:2943
ConvolutionOptions< dim > & filterWindowSize(double ratio)
Definition: multi_convolution.hxx:476
void gaussianGradientMagnitude(...)
Calculate the gradient magnitude by means of a 1st derivatives of Gaussian filter.
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
Options class template for convolutions.
Definition: multi_convolution.hxx:335
void copyMultiArray(...)
Copy a multi-dimensional array.
void outer(const MultiArrayView< 2, T, C1 > &x, const MultiArrayView< 2, T, C2 > &y, MultiArrayView< 2, T, C3 > &r)
Definition: matrix.hxx:1459
void combineTwoMultiArrays(...)
Combine two multi-dimensional arrays into one using a binary function or functor. ...
void transformMultiArray(...)
Transform a multi-dimensional array with a unary function or functor.
ConvolutionOptions< dim > & innerScale(...)
void convolveMultiArrayOneDimension(...)
Convolution along a single dimension of a multi-dimensional arrays.
ConvolutionOptions< dim > & resolutionStdDev(...)
void gaussianSmoothMultiArray(...)
Isotropic Gaussian smoothing of a multi-dimensional arrays.
void hessianOfGaussianMultiArray(...)
Calculate Hessian matrix of a N-dimensional arrays using Gaussian derivative filters.
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root.
Definition: fixedpoint.hxx:616
ConvolutionOptions< dim > & stdDev(...)
void structureTensorMultiArray(...)
Calculate the structure tensor of a multi-dimensional arrays.