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