37 #ifndef VIGRA_BOUNDARYTENSOR_HXX 
   38 #define VIGRA_BOUNDARYTENSOR_HXX 
   43 #include "array_vector.hxx" 
   44 #include "basicimage.hxx" 
   45 #include "combineimages.hxx" 
   46 #include "numerictraits.hxx" 
   47 #include "convolution.hxx" 
   48 #include "multi_shape.hxx" 
   56 typedef ArrayVector<Kernel1D<double> > KernelArray;
 
   58 template <
class KernelArray>
 
   60 initGaussianPolarFilters1(
double std_dev, KernelArray & k)
 
   62     typedef typename KernelArray::value_type Kernel;
 
   63     typedef typename Kernel::iterator iterator;
 
   65     vigra_precondition(std_dev >= 0.0,
 
   66               "initGaussianPolarFilter1(): " 
   67               "Standard deviation must be >= 0.");
 
   71     int radius = (int)(4.0*std_dev + 0.5);
 
   72     std_dev *= 1.08179074376;
 
   74     double a = 0.558868151788 / VIGRA_CSTD::pow(std_dev, 5);
 
   75     double b = -2.04251639729 / VIGRA_CSTD::pow(std_dev, 3);
 
   76     double sigma22 = -0.5 / std_dev / std_dev;
 
   79     for(
unsigned int i=0; i<k.size(); ++i)
 
   81         k[i].initExplicitly(-radius, radius);
 
   82         k[i].setBorderTreatment(BORDER_TREATMENT_REFLECT);
 
   86     iterator c = k[0].center();
 
   87     for(ix=-radius; ix<=radius; ++ix)
 
   89         double x = (double)ix;
 
   94     for(ix=-radius; ix<=radius; ++ix)
 
   96         double x = (double)ix;
 
  102     for(ix=-radius; ix<=radius; ++ix)
 
  104         double x = (double)ix;
 
  109     for(ix=-radius; ix<=radius; ++ix)
 
  111         double x = (double)ix;
 
  116 template <
class KernelArray>
 
  118 initGaussianPolarFilters2(
double std_dev, KernelArray & k)
 
  120     typedef typename KernelArray::value_type Kernel;
 
  121     typedef typename Kernel::iterator iterator;
 
  123     vigra_precondition(std_dev >= 0.0,
 
  124               "initGaussianPolarFilter2(): " 
  125               "Standard deviation must be >= 0.");
 
  129     int radius = (int)(4.0*std_dev + 0.5);
 
  131     double sigma2 = std_dev*std_dev;
 
  132     double sigma22 = -0.5 / sigma2;
 
  134     for(
unsigned int i=0; i<k.size(); ++i)
 
  136         k[i].initExplicitly(-radius, radius);
 
  137         k[i].setBorderTreatment(BORDER_TREATMENT_REFLECT);
 
  141     iterator c = k[0].center();
 
  142     for(ix=-radius; ix<=radius; ++ix)
 
  144         double x = (double)ix;
 
  149     double f1 = f / sigma2;
 
  150     for(ix=-radius; ix<=radius; ++ix)
 
  152         double x = (double)ix;
 
  157     double f2 = f / (sigma2 * sigma2);
 
  158     for(ix=-radius; ix<=radius; ++ix)
 
  160         double x = (double)ix;
 
  165 template <
class KernelArray>
 
  167 initGaussianPolarFilters3(
double std_dev, KernelArray & k)
 
  169     typedef typename KernelArray::value_type Kernel;
 
  170     typedef typename Kernel::iterator iterator;
 
  172     vigra_precondition(std_dev >= 0.0,
 
  173               "initGaussianPolarFilter3(): " 
  174               "Standard deviation must be >= 0.");
 
  178     int radius = (int)(4.0*std_dev + 0.5);
 
  179     std_dev *= 1.15470053838;
 
  180     double sigma22 = -0.5 / std_dev / std_dev;
 
  182     double a = 0.883887052922 / VIGRA_CSTD::pow(std_dev, 5);
 
  184     for(
unsigned int i=0; i<k.size(); ++i)
 
  186         k[i].initExplicitly(-radius, radius);
 
  187         k[i].setBorderTreatment(BORDER_TREATMENT_REFLECT);
 
  193     iterator c = k[0].center();
 
  194     for(ix=-radius; ix<=radius; ++ix)
 
  196         double x = (double)ix;
 
  201     for(ix=-radius; ix<=radius; ++ix)
 
  203         double x = (double)ix;
 
  209     for(ix=-radius; ix<=radius; ++ix)
 
  211         double x = (double)ix;
 
  216     for(ix=-radius; ix<=radius; ++ix)
 
  218         double x = (double)ix;
 
  223 template <
class SrcIterator, 
class SrcAccessor,
 
  224           class DestIterator, 
class DestAccessor>
 
  226 evenPolarFilters(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor src,
 
  227                  DestIterator dupperleft, DestAccessor dest,
 
  228                  double scale, 
bool noLaplacian)
 
  230     vigra_precondition(dest.size(dupperleft) == 3,
 
  231                        "evenPolarFilters(): image for even output must have 3 bands.");
 
  233     int w = slowerright.x - supperleft.x;
 
  234     int h = slowerright.y - supperleft.y;
 
  237        NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
 
  238     typedef BasicImage<TinyVector<TmpType, 3> > TmpImage;
 
  239     typedef typename TmpImage::traverser TmpTraverser;
 
  243     initGaussianPolarFilters2(scale, k2);
 
  246     VectorElementAccessor<typename TmpImage::Accessor> tmpBand(0, t.accessor());
 
  248                   destImage(t, tmpBand), k2[2], k2[0]);
 
  251                   destImage(t, tmpBand), k2[1], k2[1]);
 
  254                   destImage(t, tmpBand), k2[0], k2[2]);
 
  257     TmpTraverser tul(t.upperLeft());
 
  258     TmpTraverser tlr(t.lowerRight());
 
  259     for(; tul.y != tlr.y; ++tul.y, ++dupperleft.y)
 
  261         typename TmpTraverser::row_iterator tr = tul.rowIterator();
 
  262         typename TmpTraverser::row_iterator trend = tr + w;
 
  263         typename DestIterator::row_iterator d = dupperleft.rowIterator();
 
  266             for(; tr != trend; ++tr, ++d)
 
  268                 TmpType v = detail::RequiresExplicitCast<TmpType>::cast(0.5*
sq((*tr)[0]-(*tr)[2]) + 2.0*
sq((*tr)[1]));
 
  269                 dest.setComponent(v, d, 0);
 
  270                 dest.setComponent(0, d, 1);
 
  271                 dest.setComponent(v, d, 2);
 
  276             for(; tr != trend; ++tr, ++d)
 
  278                 dest.setComponent(
sq((*tr)[0]) + 
sq((*tr)[1]), d, 0);
 
  279                 dest.setComponent(-(*tr)[1] * ((*tr)[0] + (*tr)[2]), d, 1);
 
  280                 dest.setComponent(
sq((*tr)[1]) + 
sq((*tr)[2]), d, 2);
 
  286 template <
class SrcIterator, 
class SrcAccessor,
 
  287           class DestIterator, 
class DestAccessor>
 
  289 oddPolarFilters(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor src,
 
  290                 DestIterator dupperleft, DestAccessor dest,
 
  291                 double scale, 
bool addResult)
 
  293     vigra_precondition(dest.size(dupperleft) == 3,
 
  294                        "oddPolarFilters(): image for odd output must have 3 bands.");
 
  296     int w = slowerright.x - supperleft.x;
 
  297     int h = slowerright.y - supperleft.y;
 
  300        NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
 
  301     typedef BasicImage<TinyVector<TmpType, 4> > TmpImage;
 
  302     typedef typename TmpImage::traverser TmpTraverser;
 
  305     detail::KernelArray k1;
 
  306     detail::initGaussianPolarFilters1(scale, k1);
 
  309     VectorElementAccessor<typename TmpImage::Accessor> tmpBand(0, t.accessor());
 
  311                   destImage(t, tmpBand), k1[3], k1[0]);
 
  314                   destImage(t, tmpBand), k1[2], k1[1]);
 
  317                   destImage(t, tmpBand), k1[1], k1[2]);
 
  320                   destImage(t, tmpBand), k1[0], k1[3]);
 
  323     TmpTraverser tul(t.upperLeft());
 
  324     TmpTraverser tlr(t.lowerRight());
 
  325     for(; tul.y != tlr.y; ++tul.y, ++dupperleft.y)
 
  327         typename TmpTraverser::row_iterator tr = tul.rowIterator();
 
  328         typename TmpTraverser::row_iterator trend = tr + w;
 
  329         typename DestIterator::row_iterator d = dupperleft.rowIterator();
 
  332             for(; tr != trend; ++tr, ++d)
 
  334                 TmpType d0 = (*tr)[0] + (*tr)[2];
 
  335                 TmpType d1 = -(*tr)[1] - (*tr)[3];
 
  337                 dest.setComponent(dest.getComponent(d, 0) + 
sq(d0), d, 0);
 
  338                 dest.setComponent(dest.getComponent(d, 1) + d0 * d1, d, 1);
 
  339                 dest.setComponent(dest.getComponent(d, 2) + 
sq(d1), d, 2);
 
  344             for(; tr != trend; ++tr, ++d)
 
  346                 TmpType d0 = (*tr)[0] + (*tr)[2];
 
  347                 TmpType d1 = -(*tr)[1] - (*tr)[3];
 
  349                 dest.setComponent(
sq(d0), d, 0);
 
  350                 dest.setComponent(d0 * d1, d, 1);
 
  351                 dest.setComponent(
sq(d1), d, 2);
 
  436 template <
class SrcIterator, 
class SrcAccessor,
 
  437           class DestIterator, 
class DestAccessor>
 
  439                          DestIterator dupperleft, DestAccessor dest,
 
  440                          double scale, 
unsigned int xorder, 
unsigned int yorder)
 
  442     unsigned int order = xorder + yorder;
 
  444     vigra_precondition(order <= 2,
 
  445             "rieszTransformOfLOG(): can only compute Riesz transforms up to order 2.");
 
  446     vigra_precondition(scale > 0.0,
 
  447             "rieszTransformOfLOG(): scale must be positive.");
 
  449     int w = slowerright.x - supperleft.x;
 
  450     int h = slowerright.y - supperleft.y;
 
  452     typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
 
  453     typedef BasicImage<TmpType> TmpImage;
 
  459             detail::KernelArray k2;
 
  460             detail::initGaussianPolarFilters2(scale, k2);
 
  462             TmpImage t1(w, h), t2(w, h);
 
  465                           destImage(t1), k2[2], k2[0]);
 
  467                           destImage(t2), k2[0], k2[2]);
 
  469                              destIter(dupperleft, dest), std::plus<TmpType>());
 
  474             detail::KernelArray k1;
 
  475             detail::initGaussianPolarFilters1(scale, k1);
 
  477             TmpImage t1(w, h), t2(w, h);
 
  482                             destImage(t1), k1[3], k1[0]);
 
  484                             destImage(t2), k1[1], k1[2]);
 
  489                             destImage(t1), k1[0], k1[3]);
 
  491                             destImage(t2), k1[2], k1[1]);
 
  494                              destIter(dupperleft, dest), std::plus<TmpType>());
 
  499             detail::KernelArray k2;
 
  500             detail::initGaussianPolarFilters2(scale, k2);
 
  503                           destIter(dupperleft, dest), k2[xorder], k2[yorder]);
 
  509             detail::KernelArray k3;
 
  510             detail::initGaussianPolarFilters3(scale, k3);
 
  512             TmpImage t1(w, h), t2(w, h);
 
  517                             destImage(t1), k3[3], k3[0]);
 
  519                             destImage(t2), k3[1], k3[2]);
 
  524                             destImage(t1), k3[0], k3[3]);
 
  526                             destImage(t2), k3[2], k3[1]);
 
  529                              destIter(dupperleft, dest), std::minus<TmpType>());
 
  535 template <
class SrcIterator, 
class SrcAccessor,
 
  536           class DestIterator, 
class DestAccessor>
 
  539                          pair<DestIterator, DestAccessor> dest,
 
  540                          double scale, 
unsigned int xorder, 
unsigned int yorder)
 
  543                         scale, xorder, yorder);
 
  546 template <
class T1, 
class S1,
 
  550                     MultiArrayView<2, T2, S2> dest,
 
  551                     double scale, 
unsigned int xorder, 
unsigned int yorder)
 
  553     vigra_precondition(src.shape() == dest.shape(),
 
  554         "rieszTransformOfLOG(): shape mismatch between input and output.");
 
  556                         scale, xorder, yorder);
 
  639 template <
class SrcIterator, 
class SrcAccessor,
 
  640           class DestIterator, 
class DestAccessor>
 
  641 void boundaryTensor(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor src,
 
  642                     DestIterator dupperleft, DestAccessor dest,
 
  645     vigra_precondition(dest.size(dupperleft) == 3,
 
  646                        "boundaryTensor(): image for even output must have 3 bands.");
 
  647     vigra_precondition(scale > 0.0,
 
  648                        "boundaryTensor(): scale must be positive.");
 
  650     detail::evenPolarFilters(supperleft, slowerright, src,
 
  651                              dupperleft, dest, scale, 
false);
 
  652     detail::oddPolarFilters(supperleft, slowerright, src,
 
  653                              dupperleft, dest, scale, 
true);
 
  656 template <
class SrcIterator, 
class SrcAccessor,
 
  657           class DestIterator, 
class DestAccessor>
 
  659 void boundaryTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
 
  660                     pair<DestIterator, DestAccessor> dest,
 
  664                    dest.first, dest.second, scale);
 
  667 template <
class T1, 
class S1,
 
  671                MultiArrayView<2, T2, S2> dest,
 
  674     vigra_precondition(src.shape() == dest.shape(),
 
  675         "boundaryTensor(): shape mismatch between input and output.");
 
  677                    destImage(dest), scale);
 
  729 template <
class SrcIterator, 
class SrcAccessor,
 
  730           class DestIterator, 
class DestAccessor>
 
  731 void boundaryTensor1(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor src,
 
  732                     DestIterator dupperleft, DestAccessor dest,
 
  735     vigra_precondition(dest.size(dupperleft) == 3,
 
  736                        "boundaryTensor1(): image for even output must have 3 bands.");
 
  737     vigra_precondition(scale > 0.0,
 
  738                        "boundaryTensor1(): scale must be positive.");
 
  740     detail::evenPolarFilters(supperleft, slowerright, src,
 
  741                              dupperleft, dest, scale, 
true);
 
  742     detail::oddPolarFilters(supperleft, slowerright, src,
 
  743                              dupperleft, dest, scale, 
true);
 
  746 template <
class SrcIterator, 
class SrcAccessor,
 
  747           class DestIterator, 
class DestAccessor>
 
  749 void boundaryTensor1(triple<SrcIterator, SrcIterator, SrcAccessor> src,
 
  750                      pair<DestIterator, DestAccessor> dest,
 
  754                     dest.first, dest.second, scale);
 
  757 template <
class T1, 
class S1,
 
  761                 MultiArrayView<2, T2, S2> dest,
 
  764     vigra_precondition(src.shape() == dest.shape(),
 
  765         "boundaryTensor1(): shape mismatch between input and output.");
 
  767                     destImage(dest), scale);
 
  779 template <
class SrcIterator, 
class SrcAccessor,
 
  780           class DestIteratorEven, 
class DestAccessorEven,
 
  781           class DestIteratorOdd, 
class DestAccessorOdd>
 
  782 void boundaryTensor3(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor sa,
 
  783                      DestIteratorEven dupperleft_even, DestAccessorEven 
even,
 
  784                      DestIteratorOdd dupperleft_odd, DestAccessorOdd 
odd,
 
  787     vigra_precondition(even.size(dupperleft_even) == 3,
 
  788                        "boundaryTensor3(): image for even output must have 3 bands.");
 
  789     vigra_precondition(odd.size(dupperleft_odd) == 3,
 
  790                        "boundaryTensor3(): image for odd output must have 3 bands.");
 
  792     detail::evenPolarFilters(supperleft, slowerright, sa,
 
  793                              dupperleft_even, even, scale, 
false);
 
  795     int w = slowerright.x - supperleft.x;
 
  796     int h = slowerright.y - supperleft.y;
 
  799        NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
 
  800     typedef BasicImage<TinyVector<TmpType, 4> > TmpImage;
 
  801     TmpImage t1(w, h), t2(w, h);
 
  803     detail::KernelArray k1, k3;
 
  804     detail::initGaussianPolarFilters1(scale, k1);
 
  805     detail::initGaussianPolarFilters3(scale, k3);
 
  808     VectorElementAccessor<typename TmpImage::Accessor> tmpBand(0, t1.accessor());
 
  810                   destImage(t1, tmpBand), k1[3], k1[0]);
 
  813                   destImage(t1, tmpBand), k1[1], k1[2]);
 
  816                   destImage(t1, tmpBand), k3[3], k3[0]);
 
  819                   destImage(t1, tmpBand), k3[1], k3[2]);
 
  823                   destImage(t2, tmpBand), k1[0], k1[3]);
 
  826                   destImage(t2, tmpBand), k1[2], k1[1]);
 
  829                   destImage(t2, tmpBand), k3[0], k3[3]);
 
  832                   destImage(t2, tmpBand), k3[2], k3[1]);
 
  835     typedef typename TmpImage::traverser TmpTraverser;
 
  836     TmpTraverser tul1(t1.upperLeft());
 
  837     TmpTraverser tlr1(t1.lowerRight());
 
  838     TmpTraverser tul2(t2.upperLeft());
 
  839     for(; tul1.y != tlr1.y; ++tul1.y, ++tul2.y, ++dupperleft_odd.y)
 
  841         typename TmpTraverser::row_iterator tr1 = tul1.rowIterator();
 
  842         typename TmpTraverser::row_iterator trend1 = tr1 + w;
 
  843         typename TmpTraverser::row_iterator tr2 = tul2.rowIterator();
 
  844         typename DestIteratorOdd::row_iterator o = dupperleft_odd.rowIterator();
 
  845         for(; tr1 != trend1; ++tr1, ++tr2, ++o)
 
  847             TmpType d11 =  (*tr1)[0] + (*tr1)[2];
 
  848             TmpType d12 = -(*tr1)[1] - (*tr1)[3];
 
  849             TmpType d31 =  (*tr2)[0] - (*tr2)[2];
 
  850             TmpType d32 =  (*tr2)[1] - (*tr2)[3];
 
  851             TmpType d111 = 0.75 * d11 + 0.25 * d31;
 
  852             TmpType d112 = 0.25 * (d12 + d32);
 
  853             TmpType d122 = 0.25 * (d11 - d31);
 
  854             TmpType d222 = 0.75 * d12 - 0.25 * d32;
 
  855             TmpType d2 = 
sq(d112);
 
  856             TmpType d3 = 
sq(d122);
 
  858             odd.setComponent(0.25 * (
sq(d111) + 2.0*d2 + d3), o, 0);
 
  859             odd.setComponent(0.25 * (d111*d112 + 2.0*d112*d122 + d122*d222), o, 1);
 
  860             odd.setComponent(0.25 * (d2 + 2.0*d3 + 
sq(d222)), o, 2);
 
  865 template <
class SrcIterator, 
class SrcAccessor,
 
  866           class DestIteratorEven, 
class DestAccessorEven,
 
  867           class DestIteratorOdd, 
class DestAccessorOdd>
 
  869 void boundaryTensor3(triple<SrcIterator, SrcIterator, SrcAccessor> src,
 
  870                      pair<DestIteratorEven, DestAccessorEven> even,
 
  871                      pair<DestIteratorOdd, DestAccessorOdd> odd,
 
  874     boundaryTensor3(src.first, src.second, src.third,
 
  875                     even.first, even.second, odd.first, odd.second, scale);
 
  878 template <
class T1, 
class S1,
 
  879           class T2E, 
class S2Even,
 
  880           class T2O, 
class S2Odd>
 
  882 void boundaryTensor3(MultiArrayView<2, T1, S1> 
const & src,
 
  883                      MultiArrayView<2, T2E, S2Even> even,
 
  884                      MultiArrayView<2, T2O, S2Odd> odd,
 
  887     vigra_precondition(src.shape() == even.shape() && src.shape() == odd.shape(),
 
  888         "boundaryTensor3(): shape mismatch between input and output.");
 
  889     boundaryTensor3(srcImageRange(src),
 
  890                     destImage(even), destImage(odd), scale);
 
  897 #endif // VIGRA_BOUNDARYTENSOR_HXX 
void rieszTransformOfLOG(...)
Calculate Riesz transforms of the Laplacian of Gaussian. 
void convolveImage(...)
Convolve an image with the given kernel(s). 
linalg::TemporaryMatrix< T > exp(MultiArrayView< 2, T, C > const &v)
bool odd(int t)
Check if an integer is odd. 
NumericTraits< T >::Promote sq(T t)
The square function. 
Definition: mathutil.hxx:382
void combineTwoImages(...)
Combine two source images into destination image. 
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays. 
bool even(int t)
Check if an integer is even. 
void boundaryTensor1(...)
Boundary tensor variant. 
void boundaryTensor(...)
Calculate the boundary tensor for a scalar valued image. 
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root. 
Definition: fixedpoint.hxx:616