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"
61struct 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)
79template <
class SrcIterator,
class SrcAccessor,
80 class DestIterator,
class DestAccessor >
81void 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);
138template <
class SrcIterator,
class SrcAccessor,
139 class DestIterator,
class DestAccessor>
140inline 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);
153template <
class SrcIterator,
class SrcShape,
class SrcAccessor,
154 class DestIterator,
class DestAccessor,
class Array>
155void 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;
187 Param(NumericTraits<TmpType>::zero())-
Arg1());
198 for(
int d = 1; d < N; ++d )
202 tmp.resize( shape[d] );
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();
381 for(
int k=0;
k<N; ++
k)
388 using namespace vigra::functor;
390 if(
dmax > NumericTraits<DestType>::toRealPromote(NumericTraits<DestType>::max())
405 detail::internalSeparableMultiArrayDistTmp(
tmpArray.traverser_begin(),
456template <
unsigned int N,
class T1,
class S1,
464 vigra_precondition(source.shape() ==
dest.shape(),
465 "separableMultiDistSquared(): shape mismatch between input and output.");
470template <
unsigned int N,
class T1,
class S1,
476 vigra_precondition(source.shape() ==
dest.shape(),
477 "separableMultiDistSquared(): shape mismatch between input and output.");
594 using namespace vigra::functor;
607 using namespace vigra::functor;
631template <
unsigned int N,
class T1,
class S1,
632 class T2,
class S2,
class Array>
639 vigra_precondition(source.shape() ==
dest.shape(),
640 "separableMultiDistance(): shape mismatch between input and output.");
645template <
unsigned int N,
class T1,
class S1,
652 vigra_precondition(source.shape() ==
dest.shape(),
653 "separableMultiDistance(): shape mismatch between input and output.");
661namespace lemon_graph {
663template <
class Graph,
class T1Map,
class T2Map>
665markRegionBoundaries(Graph
const & g,
666 T1Map const & labels,
675 typename T1Map::value_type center = labels[*node];
680 if(center != labels[g.target(*
arc)])
691doxygen_overloaded_function(
template <...> unsigned int markRegionBoundaries)
693template <
unsigned int N,
class T1,
class S1,
700 vigra_precondition(labels.
shape() ==
out.shape(),
701 "markRegionBoundaries(): shape mismatch between input and output.");
705 lemon_graph::markRegionBoundaries(graph, labels,
out);
719template <
class DestIterator,
class LabelIterator>
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;
741 LabelType current_label = *
ilabels;
742 for(
double begin = 0.0, current = 0.0; current <= w; ++
ilabels, ++
is, ++current)
744 apex_height = (current < w)
754 double diff = current - s.center;
755 double intersection = current + (apex_height - s.apex_height - sq(diff)) / (2.0 * diff);
771 if(current < w && current_label == *
ilabels)
776 for(
double c = begin; c < current; ++c, ++id)
778 while(c >= it->right)
780 *
id = sq(c - it->center) + it->apex_height;
802template <
unsigned int N,
class T1,
class S1,
805internalBoundaryMultiArrayDist(
816 for(
unsigned d = 0; d < N; ++d )
906template <
unsigned int N,
class T1,
class S1,
914 vigra_precondition(labels.shape() ==
dest.shape(),
915 "boundaryMultiDistance(): shape mismatch between input and output.");
917 using namespace vigra::functor;
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;
944 detail::internalBoundaryMultiArrayDist(labels,
tmpArray,
vigra::detail::MultiIteratorChooser< StrideTag >::template Traverser< actual_dimension, T, Tconst &, Tconst * >::type const_traverser
Definition multi_array.hxx:769
traverser traverser_begin()
Definition multi_array.hxx:1955
const difference_type & shape() const
Definition multi_array.hxx:1650
vigra::detail::MultiIteratorChooser< StrideTag >::template Traverser< actual_dimension, T, T &, T * >::type traverser
Definition multi_array.hxx:764
Class for a single RGB value.
Definition rgbvalue.hxx:128
size_type size() const
Definition tinyvector.hxx:913
iterator end()
Definition tinyvector.hxx:864
iterator begin()
Definition tinyvector.hxx:861
void separableMultiDistSquared(...)
Euclidean distance squared on multi-dimensional arrays.
BoundaryDistanceTag
Specify which boundary is used for boundaryMultiDistance().
Definition multi_distance.hxx:835
@ OuterBoundary
Pixels just outside of each region.
Definition multi_distance.hxx:836
@ InnerBoundary
Pixels just inside of each region.
Definition multi_distance.hxx:838
@ InterpixelBoundary
Half-integer points between pixels of different labels.
Definition multi_distance.hxx:837
void separableMultiDistance(...)
Euclidean distance on multi-dimensional arrays.
void boundaryMultiDistance(...)
Euclidean distance to the implicit boundaries of a multi-dimensional label array.
NeighborhoodType
Choose the neighborhood system in a dimension-independent way.
Definition multi_fwd.hxx:186
@ IndirectNeighborhood
use direct and indirect neighbors
Definition multi_fwd.hxx:188
@ DirectNeighborhood
use only direct neighbors
Definition multi_fwd.hxx:187
void transformMultiArray(...)
Transform a multi-dimensional array with a unary function or functor.
FFTWComplex< R >::SquaredNormType squaredNorm(const FFTWComplex< R > &a)
squared norm (= squared magnitude)
Definition fftw3.hxx:1044
void copyMultiArray(...)
Copy a multi-dimensional array.
void initMultiArrayBorder(...)
Write values to the specified border values in the array.