37 #ifndef VIGRA_MULTI_DISTANCE_HXX 
   38 #define VIGRA_MULTI_DISTANCE_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 "functorexpression.hxx" 
   51 #include "multi_gridgraph.hxx"      
   52 #include "union_find.hxx"         
   60 template <
class Value>
 
   61 struct DistParabolaStackEntry
 
   63     double left, center, right;
 
   66     DistParabolaStackEntry(Value 
const & p, 
double l, 
double c, 
double r)
 
   67     : left(l), center(c), right(r), apex_height(p)
 
   79 template <
class SrcIterator, 
class SrcAccessor,
 
   80           class DestIterator, 
class DestAccessor >
 
   81 void distParabola(SrcIterator is, SrcIterator iend, SrcAccessor sa,
 
   82                   DestIterator 
id, DestAccessor da, 
double sigma )
 
   89     double sigma2 = sigma * sigma;
 
   90     double sigma22 = 2.0 * sigma2;
 
   92     typedef typename SrcAccessor::value_type SrcType;
 
   93     typedef DistParabolaStackEntry<SrcType> Influence;
 
   94     std::vector<Influence> _stack;
 
   95     _stack.push_back(Influence(sa(is), 0.0, 0.0, w));
 
   99     for(;current < w; ++is, ++current)
 
  105             Influence & s = _stack.back();
 
  106             double diff = current - s.center;
 
  107             intersection = current + (sa(is) - s.apex_height - sigma2*
sq(diff)) / (sigma22 * diff);
 
  109             if( intersection < s.left) 
 
  117             else if(intersection < s.right)
 
  119                 s.right = intersection;
 
  123         _stack.push_back(Influence(sa(is), intersection, current, w));
 
  129     typename std::vector<Influence>::iterator it = _stack.begin();
 
  130     for(current = 0.0; current < w; ++current, ++id)
 
  132         while( current >= it->right)
 
  134         da.set(sigma2 * 
sq(current - it->center) + it->apex_height, 
id);
 
  138 template <
class SrcIterator, 
class SrcAccessor,
 
  139           class DestIterator, 
class DestAccessor>
 
  140 inline void distParabola(triple<SrcIterator, SrcIterator, SrcAccessor> src,
 
  141                          pair<DestIterator, DestAccessor> dest, 
double sigma)
 
  143     distParabola(src.first, src.second, src.third,
 
  144                  dest.first, dest.second, sigma);
 
  153 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  154           class DestIterator, 
class DestAccessor, 
class Array>
 
  155 void internalSeparableMultiArrayDistTmp(
 
  156                       SrcIterator si, SrcShape 
const & shape, SrcAccessor src,
 
  157                       DestIterator di, DestAccessor dest, Array 
const & sigmas, 
bool invert)
 
  162     enum { N =  SrcShape::static_size};
 
  165     typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
 
  168     ArrayVector<TmpType> tmp( shape[0] );
 
  170     typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
 
  171     typedef MultiArrayNavigator<DestIterator, N> DNavigator;
 
  175     SNavigator snav( si, shape, 0 );
 
  176     DNavigator dnav( di, shape, 0 );
 
  178     using namespace vigra::functor;
 
  180     for( ; snav.hasMore(); snav++, dnav++ )
 
  185                 transformLine( snav.begin(), snav.end(), src, tmp.begin(),
 
  186                                typename AccessorTraits<TmpType>::default_accessor(),
 
  187                                Param(NumericTraits<TmpType>::zero())-Arg1());
 
  189                 copyLine( snav.begin(), snav.end(), src, tmp.begin(),
 
  190                           typename AccessorTraits<TmpType>::default_accessor() );
 
  192             detail::distParabola( srcIterRange(tmp.begin(), tmp.end(),
 
  193                           typename AccessorTraits<TmpType>::default_const_accessor()),
 
  194                           destIter( dnav.begin(), dest ), sigmas[0] );
 
  198     for( 
int d = 1; d < N; ++d )
 
  200         DNavigator dnav( di, shape, d );
 
  202         tmp.resize( shape[d] );
 
  205         for( ; dnav.hasMore(); dnav++ )
 
  208              copyLine( dnav.begin(), dnav.end(), dest,
 
  209                        tmp.begin(), 
typename AccessorTraits<TmpType>::default_accessor() );
 
  211              detail::distParabola( srcIterRange(tmp.begin(), tmp.end(),
 
  212                            typename AccessorTraits<TmpType>::default_const_accessor()),
 
  213                            destIter( dnav.begin(), dest ), sigmas[d] );
 
  219 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  220           class DestIterator, 
class DestAccessor, 
class Array>
 
  221 inline void internalSeparableMultiArrayDistTmp( SrcIterator si, SrcShape 
const & shape, SrcAccessor src,
 
  222                                                 DestIterator di, DestAccessor dest, Array 
const & sigmas)
 
  224     internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigmas, 
false );
 
  227 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  228           class DestIterator, 
class DestAccessor>
 
  229 inline void internalSeparableMultiArrayDistTmp( SrcIterator si, SrcShape 
const & shape, SrcAccessor src,
 
  230                                                 DestIterator di, DestAccessor dest)
 
  232     ArrayVector<double> sigmas(shape.size(), 1.0);
 
  233     internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigmas, 
false );
 
  365 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  366           class DestIterator, 
class DestAccessor, 
class Array>
 
  368                                 DestIterator d, DestAccessor dest, 
bool background,
 
  369                                 Array 
const & pixelPitch)
 
  371     int N = shape.size();
 
  373     typedef typename SrcAccessor::value_type SrcType;
 
  374     typedef typename DestAccessor::value_type DestType;
 
  375     typedef typename NumericTraits<DestType>::RealPromote Real;
 
  377     SrcType zero = NumericTraits<SrcType>::zero();
 
  380     bool pixelPitchIsReal = 
false;
 
  381     for( 
int k=0; k<N; ++k)
 
  383         if(
int(pixelPitch[k]) != pixelPitch[k])
 
  384             pixelPitchIsReal = 
true;
 
  385         dmax += 
sq(pixelPitch[k]*shape[k]);
 
  388     using namespace vigra::functor;
 
  390     if(dmax > NumericTraits<DestType>::toRealPromote(NumericTraits<DestType>::max())
 
  394         Real maxDist = (Real)dmax, rzero = (Real)0.0;
 
  395         MultiArray<SrcShape::static_size, Real> tmpArray(shape);
 
  396         if(background == 
true)
 
  398                                  tmpArray.traverser_begin(), 
typename AccessorTraits<Real>::default_accessor(),
 
  399                                  ifThenElse( Arg1() == Param(zero), Param(maxDist), Param(rzero) ));
 
  402                                  tmpArray.traverser_begin(), 
typename AccessorTraits<Real>::default_accessor(),
 
  403                                  ifThenElse( Arg1() != Param(zero), Param(maxDist), Param(rzero) ));
 
  405         detail::internalSeparableMultiArrayDistTmp( tmpArray.traverser_begin(),
 
  406                 shape, 
typename AccessorTraits<Real>::default_accessor(),
 
  407                 tmpArray.traverser_begin(),
 
  408                 typename AccessorTraits<Real>::default_accessor(), pixelPitch);
 
  415         DestType maxDist = DestType(
std::ceil(dmax)), rzero = (DestType)0;
 
  416         if(background == 
true)
 
  418                                  ifThenElse( Arg1() == Param(zero), Param(maxDist), Param(rzero) ));
 
  421                                  ifThenElse( Arg1() != Param(zero), Param(maxDist), Param(rzero) ));
 
  423         detail::internalSeparableMultiArrayDistTmp( d, shape, dest, d, dest, pixelPitch);
 
  427 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  428           class DestIterator, 
class DestAccessor>
 
  431                                 DestIterator d, DestAccessor dest, 
bool background)
 
  433     ArrayVector<double> pixelPitch(shape.size(), 1.0);
 
  437 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  438           class DestIterator, 
class DestAccessor, 
class Array>
 
  440                                        pair<DestIterator, DestAccessor> 
const & dest, 
bool background,
 
  441                                        Array 
const & pixelPitch)
 
  444                                dest.first, dest.second, background, pixelPitch );
 
  447 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  448           class DestIterator, 
class DestAccessor>
 
  450                                        pair<DestIterator, DestAccessor> 
const & dest, 
bool background)
 
  453                                dest.first, dest.second, background );
 
  456 template <
unsigned int N, 
class T1, 
class S1,
 
  461                           MultiArrayView<N, T2, S2> dest, 
bool background,
 
  462                           Array 
const & pixelPitch)
 
  464     vigra_precondition(source.shape() == dest.shape(),
 
  465         "separableMultiDistSquared(): shape mismatch between input and output.");
 
  467                                destMultiArray(dest), background, pixelPitch );
 
  470 template <
unsigned int N, 
class T1, 
class S1,
 
  474                           MultiArrayView<N, T2, S2> dest, 
bool background)
 
  476     vigra_precondition(source.shape() == dest.shape(),
 
  477         "separableMultiDistSquared(): shape mismatch between input and output.");
 
  479                                destMultiArray(dest), background );
 
  585 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  586           class DestIterator, 
class DestAccessor, 
class Array>
 
  588                              DestIterator d, DestAccessor dest, 
bool background,
 
  589                              Array 
const & pixelPitch)
 
  594     using namespace vigra::functor;
 
  599 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  600           class DestIterator, 
class DestAccessor>
 
  602                              DestIterator d, DestAccessor dest, 
bool background)
 
  607     using namespace vigra::functor;
 
  612 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  613           class DestIterator, 
class DestAccessor, 
class Array>
 
  615                                     pair<DestIterator, DestAccessor> 
const & dest, 
bool background,
 
  616                                     Array 
const & pixelPitch)
 
  619                             dest.first, dest.second, background, pixelPitch );
 
  622 template <
class SrcIterator, 
class SrcShape, 
class SrcAccessor,
 
  623           class DestIterator, 
class DestAccessor>
 
  625                                     pair<DestIterator, DestAccessor> 
const & dest, 
bool background)
 
  628                             dest.first, dest.second, background );
 
  631 template <
unsigned int N, 
class T1, 
class S1,
 
  632           class T2, 
class S2, 
class Array>
 
  635                        MultiArrayView<N, T2, S2> dest,
 
  637                        Array 
const & pixelPitch)
 
  639     vigra_precondition(source.shape() == dest.shape(),
 
  640         "separableMultiDistance(): shape mismatch between input and output.");
 
  642                             destMultiArray(dest), background, pixelPitch );
 
  645 template <
unsigned int N, 
class T1, 
class S1,
 
  649                        MultiArrayView<N, T2, S2> dest,
 
  652     vigra_precondition(source.shape() == dest.shape(),
 
  653         "separableMultiDistance(): shape mismatch between input and output.");
 
  655                             destMultiArray(dest), background );
 
  661 namespace lemon_graph {
 
  663 template <
class Graph, 
class T1Map, 
class T2Map>
 
  665 markRegionBoundaries(Graph 
const & g,
 
  666                      T1Map 
const & labels,
 
  669     typedef typename Graph::NodeIt        graph_scanner;
 
  670     typedef typename Graph::OutBackArcIt  neighbor_iterator;
 
  673     for (graph_scanner node(g); node != INVALID; ++node)
 
  675         typename T1Map::value_type center = labels[*node];
 
  677         for (neighbor_iterator arc(g, node); arc != INVALID; ++arc)
 
  680             if(center != labels[g.target(*arc)])
 
  683                 out[g.target(*arc)] = 1;
 
  693 template <
unsigned int N, 
class T1, 
class S1,
 
  696 markRegionBoundaries(MultiArrayView<N, T1, S1> 
const & labels,
 
  697                      MultiArrayView<N, T2, S2> out,
 
  700     vigra_precondition(labels.shape() == out.shape(),
 
  701         "markRegionBoundaries(): shape mismatch between input and output.");
 
  703     GridGraph<N, undirected_tag> graph(labels.shape(), neighborhood);
 
  705     lemon_graph::markRegionBoundaries(graph, labels, out);
 
  719 template <
class DestIterator, 
class LabelIterator>
 
  721 boundaryDistParabola(DestIterator is, DestIterator iend,
 
  722                      LabelIterator ilabels,
 
  724                      bool array_border_is_active=
false)
 
  727     double w = iend - is;
 
  731     DestIterator 
id = is;
 
  732     typedef typename LabelIterator::value_type LabelType;
 
  733     typedef typename DestIterator::value_type DestType;
 
  734     typedef detail::DistParabolaStackEntry<DestType> Influence;
 
  735     typedef std::vector<Influence> Stack;
 
  737     double apex_height = array_border_is_active
 
  740     Stack _stack(1, Influence(apex_height, 0.0, -1.0, w));
 
  741     LabelType current_label = *ilabels;
 
  742     for(
double begin = 0.0, current = 0.0; current <= w; ++ilabels, ++is, ++current)
 
  744         apex_height = (current < w)
 
  745                           ? (current_label == *ilabels)
 
  748                           : array_border_is_active
 
  753             Influence & s = _stack.back();
 
  754             double diff = current - s.center;
 
  755             double intersection = current + (apex_height - s.apex_height - 
sq(diff)) / (2.0 * diff);
 
  757             if(intersection < s.left) 
 
  761                     intersection = begin; 
 
  765             else if(intersection < s.right)
 
  767                 s.right = intersection;
 
  770                 _stack.push_back(Influence(apex_height, intersection, current, w));
 
  771             if(current < w && current_label == *ilabels)
 
  775             typename Stack::iterator it = _stack.begin();
 
  776             for(
double c = begin; c < current; ++c, ++id)
 
  778                 while(c >= it->right)
 
  780                 *
id = 
sq(c - it->center) + it->apex_height;
 
  787             current_label = *ilabels;
 
  789             Stack(1, Influence(0.0, begin-1.0, begin-1.0, w)).swap(_stack);
 
  802 template <
unsigned int N, 
class T1, 
class S1,
 
  805 internalBoundaryMultiArrayDist(
 
  806                       MultiArrayView<N, T1, S1> 
const & labels,
 
  807                       MultiArrayView<N, T2, S2> dest,
 
  808                       double dmax, 
bool array_border_is_active=
false)
 
  810     typedef typename MultiArrayView<N, T1, S1>::const_traverser LabelIterator;
 
  811     typedef typename MultiArrayView<N, T2, S2>::traverser DestIterator;
 
  812     typedef MultiArrayNavigator<LabelIterator, N> LabelNavigator;
 
  813     typedef MultiArrayNavigator<DestIterator, N> DNavigator;
 
  816     for( 
unsigned d = 0; d < N; ++d )
 
  818         LabelNavigator lnav( labels.traverser_begin(), labels.shape(), d );
 
  819         DNavigator dnav( dest.traverser_begin(), dest.shape(), d );
 
  821         for( ; dnav.hasMore(); dnav++, lnav++ )
 
  823             boundaryDistParabola(dnav.begin(), dnav.end(),
 
  825                                  dmax, array_border_is_active);
 
  906 template <
unsigned int N, 
class T1, 
class S1,
 
  910                       MultiArrayView<N, T2, S2> dest,
 
  911                       bool array_border_is_active=
false,
 
  914     vigra_precondition(labels.shape() == dest.shape(),
 
  915         "boundaryMultiDistance(): shape mismatch between input and output.");
 
  917     using namespace vigra::functor;
 
  921         MultiArray<N, unsigned char> boundaries(labels.shape());
 
  924         if(array_border_is_active)
 
  934             vigra_precondition(!NumericTraits<T2>::isIntegral::value,
 
  935                 "boundaryMultiDistance(..., InterpixelBoundary): output pixel type must be float or double.");
 
  939         if(dmax > 
double(NumericTraits<T2>::max()))
 
  942             typedef typename NumericTraits<T2>::RealPromote Real;
 
  943             MultiArray<N, Real> tmpArray(labels.shape());
 
  944             detail::internalBoundaryMultiArrayDist(labels, tmpArray,
 
  945                                                       dmax, array_border_is_active);
 
  951             detail::internalBoundaryMultiArrayDist(labels, dest, dmax, array_border_is_active);
 
  962 #endif        //-- VIGRA_MULTI_DISTANCE_HXX 
void initMultiArrayBorder(...)
Write values to the specified border values in the array. 
FFTWComplex< R >::SquaredNormType squaredNorm(const FFTWComplex< R > &a)
squared norm (= squared magnitude) 
Definition: fftw3.hxx:1044
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
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays. 
void copyMultiArray(...)
Copy a multi-dimensional array. 
use direct and indirect neighbors 
Definition: multi_fwd.hxx:188
void transformMultiArray(...)
Transform a multi-dimensional array with a unary function or functor. 
int ceil(FixedPoint< IntBits, FracBits > v)
rounding up. 
Definition: fixedpoint.hxx:675
use only direct neighbors 
Definition: multi_fwd.hxx:187
NeighborhoodType
Choose the neighborhood system in a dimension-independent way. 
Definition: multi_fwd.hxx:186
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root. 
Definition: fixedpoint.hxx:616