37 #ifndef VIGRA_CONVOLUTION_HXX 
   38 #define VIGRA_CONVOLUTION_HXX 
   41 #include "stdconvolution.hxx" 
   42 #include "separableconvolution.hxx" 
   43 #include "recursiveconvolution.hxx" 
   44 #include "nonlineardiffusion.hxx" 
   45 #include "combineimages.hxx" 
   46 #include "multi_shape.hxx" 
  319 template <
class SrcIterator, 
class SrcAccessor,
 
  320           class DestIterator, 
class DestAccessor,
 
  323                    SrcIterator slowerright, SrcAccessor sa,
 
  324                    DestIterator dupperleft, DestAccessor da,
 
  325                    Kernel1D<T> 
const & kx, Kernel1D<T> 
const & ky)
 
  328         NumericTraits<typename SrcAccessor::value_type>::RealPromote
 
  330     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
 
  333                        destImage(tmp), kernel1d(kx));
 
  335                        destIter(dupperleft, da), kernel1d(ky));
 
  338 template <
class SrcIterator, 
class SrcAccessor,
 
  339           class DestIterator, 
class DestAccessor,
 
  342 convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
 
  343               pair<DestIterator, DestAccessor> dest,
 
  344               Kernel1D<T> 
const & kx, Kernel1D<T> 
const & ky)
 
  347                   dest.first, dest.second, kx, ky);
 
  350 template <
class T1, 
class S1,
 
  355               MultiArrayView<2, T2, S2> dest,
 
  356               Kernel1D<T> 
const & k)
 
  358     vigra_precondition(src.shape() == dest.shape(),
 
  359         "convolveImage(): shape mismatch between input and output.");
 
  361                   destImage(dest), k, k);
 
  364 template <
class T1, 
class S1,
 
  369               MultiArrayView<2, T2, S2> dest,
 
  370               Kernel1D<T> 
const & kx, Kernel1D<T> 
const & ky)
 
  372     vigra_precondition(src.shape() == dest.shape(),
 
  373         "convolveImage(): shape mismatch between input and output.");
 
  375                   destImage(dest), kx, ky);
 
  463 template <
class SrcIterator, 
class SrcAccessor,
 
  464           class DestIterator, 
class DestAccessor>
 
  465 void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
 
  466                     DestIterator dest_ul, DestAccessor dest_acc, 
double sharpening_factor)
 
  469     vigra_precondition(sharpening_factor >= 0.0,
 
  470                        "simpleSharpening(): amount of sharpening must be >= 0.");
 
  472     Kernel2D<double> kernel;
 
  474     kernel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0,
 
  475                                                         -sharpening_factor/8.0,   1.0+sharpening_factor*0.75,  -sharpening_factor/8.0,
 
  476                                                         -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0;
 
  479                   kernel.center(), kernel.accessor(),
 
  480                   kernel.upperLeft(), kernel.lowerRight() , BORDER_TREATMENT_REFLECT );
 
  483 template <
class SrcIterator, 
class SrcAccessor,
 
  484           class DestIterator, 
class DestAccessor>
 
  487                       pair<DestIterator, DestAccessor> dest, 
double sharpening_factor)
 
  490                      dest.first, dest.second, sharpening_factor);
 
  493 template <
class T1, 
class S1,
 
  497                  MultiArrayView<2, T2, S2> dest,
 
  498                  double sharpening_factor)
 
  500     vigra_precondition(src.shape() == dest.shape(),
 
  501         "simpleSharpening(): shape mismatch between input and output.");
 
  503                      destImage(dest), sharpening_factor);
 
  595 template <
class SrcIterator, 
class SrcAccessor,
 
  596           class DestIterator, 
class DestAccessor>
 
  598                         DestIterator dest_ul, DestAccessor dest_acc, 
double sharpening_factor,
 
  601     vigra_precondition(sharpening_factor >= 0.0,
 
  602                        "gaussianSharpening(): amount of sharpening must be >= 0");
 
  603     vigra_precondition(scale >= 0.0,
 
  604                        "gaussianSharpening(): scale parameter should be >= 0.");
 
  606     typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote ValueType;
 
  608     BasicImage<ValueType> tmp(src_lr - src_ul, SkipInitialization);
 
  610     gaussianSmoothing(src_ul, src_lr, src_acc, tmp.upperLeft(), tmp.accessor(), scale);
 
  612     SrcIterator i_src = src_ul;
 
  613     DestIterator i_dest = dest_ul;
 
  614     typename BasicImage<ValueType>::traverser tmp_ul = tmp.upperLeft();
 
  615     typename BasicImage<ValueType>::traverser i_tmp = tmp_ul;
 
  616     typename BasicImage<ValueType>::Accessor tmp_acc = tmp.accessor();
 
  618     for(; i_src.y != src_lr.y ; i_src.y++, i_dest.y++, i_tmp.y++ )
 
  620         for (;i_src.x != src_lr.x ; i_src.x++, i_dest.x++, i_tmp.x++ )
 
  622             dest_acc.set((1.0 + sharpening_factor)*src_acc(i_src) - sharpening_factor*tmp_acc(i_tmp), i_dest);
 
  625         i_dest.x = dest_ul.x;
 
  630 template <
class SrcIterator, 
class SrcAccessor,
 
  631           class DestIterator, 
class DestAccessor>
 
  634                    pair<DestIterator, DestAccessor> dest, 
double sharpening_factor,
 
  638                        dest.first, dest.second,
 
  639                        sharpening_factor, scale);
 
  642 template <
class T1, 
class S1,
 
  646                    MultiArrayView<2, T2, S2> dest,
 
  647                    double sharpening_factor,
 
  650     vigra_precondition(src.shape() == dest.shape(),
 
  651         "gaussianSharpening(): shape mismatch between input and output.");
 
  654                        sharpening_factor, scale);
 
  740 template <
class SrcIterator, 
class SrcAccessor,
 
  741           class DestIterator, 
class DestAccessor>
 
  743 gaussianSmoothing(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor sa,
 
  744                   DestIterator dupperleft, DestAccessor da,
 
  745                   double scale_x, 
double scale_y)
 
  748         NumericTraits<typename SrcAccessor::value_type>::RealPromote
 
  750     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
 
  752     Kernel1D<double> smooth_x, smooth_y;
 
  753     smooth_x.initGaussian(scale_x);
 
  754     smooth_x.setBorderTreatment(BORDER_TREATMENT_REFLECT);
 
  755     smooth_y.initGaussian(scale_y);
 
  756     smooth_y.setBorderTreatment(BORDER_TREATMENT_REFLECT);
 
  759                        destImage(tmp), kernel1d(smooth_x));
 
  761                        destIter(dupperleft, da), kernel1d(smooth_y));
 
  764 template <
class SrcIterator, 
class SrcAccessor,
 
  765           class DestIterator, 
class DestAccessor>
 
  767 gaussianSmoothing(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor sa,
 
  768                   DestIterator dupperleft, DestAccessor da,
 
  776 template <
class SrcIterator, 
class SrcAccessor,
 
  777           class DestIterator, 
class DestAccessor>
 
  780                   pair<DestIterator, DestAccessor> dest,
 
  781                   double scale_x, 
double scale_y)
 
  784                  dest.first, dest.second, scale_x, scale_y);
 
  787 template <
class SrcIterator, 
class SrcAccessor,
 
  788           class DestIterator, 
class DestAccessor>
 
  791                   pair<DestIterator, DestAccessor> dest,
 
  795                       dest.first, dest.second, scale, scale);
 
  798 template <
class T1, 
class S1,
 
  802                   MultiArrayView<2, T2, S2> dest,
 
  803                   double scale_x, 
double scale_y)
 
  805     vigra_precondition(src.shape() == dest.shape(),
 
  806         "gaussianSmoothing(): shape mismatch between input and output.");
 
  808                       destImage(dest), scale_x, scale_y);
 
  811 template <
class T1, 
class S1,
 
  815                   MultiArrayView<2, T2, S2> dest,
 
  818     vigra_precondition(src.shape() == dest.shape(),
 
  819         "gaussianSmoothing(): shape mismatch between input and output.");
 
  821                       destImage(dest), scale, scale);
 
  944 template <
class SrcIterator, 
class SrcAccessor,
 
  945           class DestIteratorX, 
class DestAccessorX,
 
  946           class DestIteratorY, 
class DestAccessorY>
 
  948                         SrcIterator slowerright, SrcAccessor sa,
 
  949                         DestIteratorX dupperleftx, DestAccessorX dax,
 
  950                         DestIteratorY dupperlefty, DestAccessorY day,
 
  954         NumericTraits<typename SrcAccessor::value_type>::RealPromote
 
  956     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
 
  958     Kernel1D<double> smooth, grad;
 
  959     smooth.initGaussian(scale);
 
  960     grad.initGaussianDerivative(scale, 1);
 
  963                        destImage(tmp), kernel1d(grad));
 
  965                        destIter(dupperleftx, dax), kernel1d(smooth));
 
  967                        destImage(tmp), kernel1d(smooth));
 
  969                        destIter(dupperlefty, day), kernel1d(grad));
 
  972 template <
class SrcIterator, 
class SrcAccessor,
 
  973           class DestIterator, 
class DestAccessor>
 
  975                         SrcIterator slowerright, SrcAccessor src,
 
  976                         DestIterator dupperleft, DestAccessor dest,
 
  979     VectorElementAccessor<DestAccessor> gradx(0, dest), grady(1, dest);
 
  981                      dupperleft, gradx, dupperleft, grady, scale);
 
  984 template <
class SrcIterator, 
class SrcAccessor,
 
  985           class DestIteratorX, 
class DestAccessorX,
 
  986           class DestIteratorY, 
class DestAccessorY>
 
  989                  pair<DestIteratorX, DestAccessorX> destx,
 
  990                  pair<DestIteratorY, DestAccessorY> desty,
 
  994                  destx.first, destx.second, desty.first, desty.second, scale);
 
  997 template <
class SrcIterator, 
class SrcAccessor,
 
  998           class DestIterator, 
class DestAccessor>
 
 1001                  pair<DestIterator, DestAccessor> dest,
 
 1005                      dest.first, dest.second, scale);
 
 1008 template <
class T1, 
class S1,
 
 1009           class T2X, 
class S2X,
 
 1010           class T2Y, 
class S2Y>
 
 1013                  MultiArrayView<2, T2X, S2X> destx,
 
 1014                  MultiArrayView<2, T2Y, S2Y> desty,
 
 1017     vigra_precondition(src.shape() == destx.shape(),
 
 1018         "gaussianGradient(): shape mismatch between input and output.");
 
 1020                      destImage(destx), destImage(desty), scale);
 
 1023 template <
class T1, 
class S1,
 
 1027                  MultiArrayView<2, TinyVector<T2, 2>, S2> dest,
 
 1030     vigra_precondition(src.shape() == dest.shape(),
 
 1031         "gaussianGradient(): shape mismatch between input and output.");
 
 1033                      destImage(dest), scale);
 
 1200 template <
class SrcIterator, 
class SrcAccessor,
 
 1201           class DestIterator, 
class DestAccessor>
 
 1203                                SrcIterator slr, SrcAccessor src,
 
 1204                                DestIterator dupperleft, DestAccessor dest,
 
 1207     typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
 
 1208     BasicImage<TmpType> gradx(slr-sul, SkipInitialization), grady(slr-sul, SkipInitialization);
 
 1211                      destImage(gradx), destImage(grady), scale);
 
 1212     combineTwoImages(srcImageRange(gradx), srcImage(grady), destIter(dupperleft, dest),
 
 1213                      MagnitudeFunctor<TmpType>());
 
 1216 template <
class SrcIterator, 
class SrcAccessor,
 
 1217           class DestIterator, 
class DestAccessor>
 
 1220                           pair<DestIterator, DestAccessor> dest,
 
 1224                               dest.first, dest.second, scale);
 
 1307 template <
class SrcIterator, 
class SrcAccessor,
 
 1308           class DestIterator, 
class DestAccessor>
 
 1310                         SrcIterator slowerright, SrcAccessor sa,
 
 1311                         DestIterator dupperleft, DestAccessor da,
 
 1315         NumericTraits<typename SrcAccessor::value_type>::RealPromote
 
 1317     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization),
 
 1318                         tmpx(slowerright - supperleft, SkipInitialization),
 
 1319                         tmpy(slowerright - supperleft, SkipInitialization);
 
 1321     Kernel1D<double> smooth, deriv;
 
 1322     smooth.initGaussian(scale);
 
 1323     deriv.initGaussianDerivative(scale, 2);
 
 1326                        destImage(tmp), kernel1d(deriv));
 
 1328                        destImage(tmpx), kernel1d(smooth));
 
 1330                        destImage(tmp), kernel1d(smooth));
 
 1332                        destImage(tmpy), kernel1d(deriv));
 
 1334                        destIter(dupperleft, da), std::plus<TmpType>());
 
 1337 template <
class SrcIterator, 
class SrcAccessor,
 
 1338           class DestIterator, 
class DestAccessor>
 
 1341                     pair<DestIterator, DestAccessor> dest,
 
 1345                         dest.first, dest.second, scale);
 
 1348 template <
class T1, 
class S1,
 
 1352                     MultiArrayView<2, T2, S2> dest,
 
 1355     vigra_precondition(src.shape() == dest.shape(),
 
 1356         "laplacianOfGaussian(): shape mismatch between input and output.");
 
 1358                         destImage(dest), scale);
 
 1468 template <
class SrcIterator, 
class SrcAccessor,
 
 1469           class DestIteratorX, 
class DestAccessorX,
 
 1470           class DestIteratorXY, 
class DestAccessorXY,
 
 1471           class DestIteratorY, 
class DestAccessorY>
 
 1473                         SrcIterator slowerright, SrcAccessor sa,
 
 1474                         DestIteratorX dupperleftx, DestAccessorX dax,
 
 1475                         DestIteratorXY dupperleftxy, DestAccessorXY daxy,
 
 1476                         DestIteratorY dupperlefty, DestAccessorY day,
 
 1480         NumericTraits<typename SrcAccessor::value_type>::RealPromote
 
 1482     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
 
 1484     Kernel1D<double> smooth, deriv1, deriv2;
 
 1485     smooth.initGaussian(scale);
 
 1486     deriv1.initGaussianDerivative(scale, 1);
 
 1487     deriv2.initGaussianDerivative(scale, 2);
 
 1490                        destImage(tmp), kernel1d(deriv2));
 
 1492                        destIter(dupperleftx, dax), kernel1d(smooth));
 
 1494                        destImage(tmp), kernel1d(smooth));
 
 1496                        destIter(dupperlefty, day), kernel1d(deriv2));
 
 1498                        destImage(tmp), kernel1d(deriv1));
 
 1500                        destIter(dupperleftxy, daxy), kernel1d(deriv1));
 
 1503 template <
class SrcIterator, 
class SrcAccessor,
 
 1504           class DestIteratorX, 
class DestAccessorX,
 
 1505           class DestIteratorXY, 
class DestAccessorXY,
 
 1506           class DestIteratorY, 
class DestAccessorY>
 
 1509                         pair<DestIteratorX, DestAccessorX> destx,
 
 1510                         pair<DestIteratorXY, DestAccessorXY> destxy,
 
 1511                         pair<DestIteratorY, DestAccessorY> desty,
 
 1515                             destx.first, destx.second,
 
 1516                             destxy.first, destxy.second,
 
 1517                             desty.first, desty.second,
 
 1521 template <
class T1, 
class S1,
 
 1522           class T2X, 
class S2X,
 
 1523           class T2XY, 
class S2XY,
 
 1524           class T2Y, 
class S2Y>
 
 1527                         MultiArrayView<2, T2X, S2X> destx,
 
 1528                         MultiArrayView<2, T2XY, S2XY> destxy,
 
 1529                         MultiArrayView<2, T2Y, S2Y> desty,
 
 1532     vigra_precondition(src.shape() == destx.shape() && src.shape() == destxy.shape() && src.shape() == desty.shape(),
 
 1533         "hessianMatrixOfGaussian(): shape mismatch between input and output.");
 
 1541 template <
class T1, 
class S1,
 
 1545                         MultiArrayView<2, TinyVector<T2, 3>, S2> dest,
 
 1548     vigra_precondition(src.shape() == dest.shape(),
 
 1549         "hessianMatrixOfGaussian(): shape mismatch between input and output.");
 
 1551     MultiArrayView<3, T2> expanded(dest.expandElements(0));
 
 1552     MultiArrayView<2, T2> dxx(expanded.template bind<0>(0));
 
 1553     MultiArrayView<2, T2> dxy(expanded.template bind<0>(1));
 
 1554     MultiArrayView<2, T2> dyy(expanded.template bind<0>(2));
 
 1715 template <
class SrcIterator, 
class SrcAccessor,
 
 1716           class DestIteratorX, 
class DestAccessorX,
 
 1717           class DestIteratorXY, 
class DestAccessorXY,
 
 1718           class DestIteratorY, 
class DestAccessorY>
 
 1720                         SrcIterator slowerright, SrcAccessor sa,
 
 1721                         DestIteratorX dupperleftx, DestAccessorX dax,
 
 1722                         DestIteratorXY dupperleftxy, DestAccessorXY daxy,
 
 1723                         DestIteratorY dupperlefty, DestAccessorY day,
 
 1724                         double inner_scale, 
double outer_scale)
 
 1727         NumericTraits<typename SrcAccessor::value_type>::RealPromote
 
 1729     BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization),
 
 1730                         tmpx(slowerright - supperleft, SkipInitialization),
 
 1731                         tmpy(slowerright - supperleft, SkipInitialization);
 
 1734            destImage(tmpx), destImage(tmpy), inner_scale);
 
 1736                      destImage(tmp), std::multiplies<TmpType>());
 
 1738                       destIter(dupperleftx, dax), outer_scale);
 
 1740                      destImage(tmp), std::multiplies<TmpType>());
 
 1742                       destIter(dupperlefty, day), outer_scale);
 
 1744                      destImage(tmp), std::multiplies<TmpType>());
 
 1746                       destIter(dupperleftxy, daxy), outer_scale);
 
 1749 template <
class SrcIterator, 
class SrcAccessor,
 
 1750           class DestIteratorX, 
class DestAccessorX,
 
 1751           class DestIteratorXY, 
class DestAccessorXY,
 
 1752           class DestIteratorY, 
class DestAccessorY>
 
 1755                   pair<DestIteratorX, DestAccessorX> destx,
 
 1756                   pair<DestIteratorXY, DestAccessorXY> destxy,
 
 1757                   pair<DestIteratorY, DestAccessorY> desty,
 
 1758                   double inner_scale, 
double outer_scale)
 
 1761                  destx.first, destx.second,
 
 1762                  destxy.first, destxy.second,
 
 1763                  desty.first, desty.second,
 
 1764                  inner_scale, outer_scale);
 
 1767 template <
class T, 
class S,
 
 1769           class TXY, 
class SXY,
 
 1773                 MultiArrayView<2, TX, SX> destx,
 
 1774                 MultiArrayView<2, TXY, SXY> destxy,
 
 1775                 MultiArrayView<2, TY, SY> desty,
 
 1776                 double inner_scale, 
double outer_scale)
 
 1778     vigra_precondition(src.shape() == destx.shape(),
 
 1779         "structureTensor(): shape mismatch between input and output.");
 
 1781                     destImage(destx), destImage(destxy), destImage(desty),
 
 1782                     inner_scale, outer_scale);
 
 1787 template <
class SrcIterator, 
class SrcAccessor,
 
 1788           class DestIterator, 
class DestAccessor>
 
 1790                      SrcIterator slowerright, SrcAccessor src,
 
 1791                      DestIterator dupperleft, DestAccessor dest,
 
 1792                      double inner_scale, 
double outer_scale,
 
 1795     typedef VectorElementAccessor<DestAccessor> DA;
 
 1797                     dupperleft, DA(0, dest),
 
 1798                     dupperleft, DA(1, dest),
 
 1799                     dupperleft, DA(2, dest),
 
 1800                     inner_scale, outer_scale);
 
 1803 template <
class SrcIterator, 
class SrcAccessor,
 
 1804           class DestIterator, 
class DestAccessor>
 
 1806                      SrcIterator slowerright, SrcAccessor src,
 
 1807                      DestIterator dupperleft, DestAccessor dest,
 
 1808                      double inner_scale, 
double outer_scale,
 
 1811     int bands = src.size(supperleft);
 
 1812     typedef VectorElementAccessor<SrcAccessor> SA;
 
 1816                     inner_scale, outer_scale,
 
 1819     BasicImage<typename DestAccessor::value_type> st(slowerright - supperleft, SkipInitialization);
 
 1820     for(
int k=1; k < bands; ++k)
 
 1823                         st.upperLeft(), st.accessor(),
 
 1824                         inner_scale, outer_scale,
 
 1826         combineTwoImages(srcImageRange(st), srcIter(dupperleft, dest), destIter(dupperleft, dest),
 
 1827                          std::plus<typename DestAccessor::value_type>());
 
 1833 template <
class SrcIterator, 
class SrcAccessor,
 
 1834           class DestIterator, 
class DestAccessor>
 
 1836                         SrcIterator slowerright, SrcAccessor src,
 
 1837                         DestIterator dupperleft, DestAccessor dest,
 
 1838                         double inner_scale, 
double outer_scale)
 
 1841         NumericTraits<typename SrcAccessor::value_type>::isScalar isScalar;
 
 1842     detail::structureTensor(supperleft, slowerright, src,
 
 1843                             dupperleft, dest, inner_scale, outer_scale, isScalar());
 
 1846 template <
class SrcIterator, 
class SrcAccessor,
 
 1847           class DestIterator, 
class DestAccessor>
 
 1850                 pair<DestIterator, DestAccessor> dest,
 
 1851                 double inner_scale, 
double outer_scale)
 
 1854                     dest.first, dest.second,
 
 1855                     inner_scale, outer_scale);
 
 1858 template <
class T1, 
class S1,
 
 1862                 MultiArrayView<2, TinyVector<T2, 3>, S2> dest,
 
 1863                 double inner_scale, 
double outer_scale)
 
 1865     vigra_precondition(src.shape() == dest.shape(),
 
 1866         "structureTensor(): shape mismatch between input and output.");
 
 1869                     inner_scale, outer_scale);
 
 1876 #endif // VIGRA_CONVOLUTION_HXX 
void laplacianOfGaussian(...)
Filter image with the Laplacian of Gaussian operator at the given scale. 
void convolveImage(...)
Convolve an image with the given kernel(s). 
void separableConvolveX(...)
Performs a 1 dimensional convolution in x direction. 
void simpleSharpening(...)
Perform simple sharpening function. 
void hessianMatrixOfGaussian(...)
Filter image with the 2nd derivatives of the Gaussian at the given scale to get the Hessian matrix...
void combineTwoImages(...)
Combine two source images into destination image. 
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. 
void structureTensor(...)
Calculate the Structure Tensor for each pixel of and image, using Gaussian (derivative) filters...
void gaussianSharpening(...)
Perform sharpening function with gaussian filter. 
void gaussianGradient(...)
Calculate the gradient vector by means of a 1st derivatives of Gaussian filter. 
void gaussianSmoothing(...)
Perform isotropic Gaussian convolution. 
void separableConvolveY(...)
Performs a 1 dimensional convolution in y direction.