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.