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"
356 template <
class SrcIterator,
class SrcAccessor,
357 class DestIterator,
class DestAccessor,
360 SrcIterator slowerright, SrcAccessor sa,
361 DestIterator dupperleft, DestAccessor da,
362 Kernel1D<T>
const & kx, Kernel1D<T>
const & ky)
365 NumericTraits<typename SrcAccessor::value_type>::RealPromote
367 BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
370 destImage(tmp), kernel1d(kx));
372 destIter(dupperleft, da), kernel1d(ky));
375 template <
class SrcIterator,
class SrcAccessor,
376 class DestIterator,
class DestAccessor,
379 convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
380 pair<DestIterator, DestAccessor> dest,
381 Kernel1D<T>
const & kx, Kernel1D<T>
const & ky)
384 dest.first, dest.second, kx, ky);
387 template <
class T1,
class S1,
392 MultiArrayView<2, T2, S2> dest,
393 Kernel1D<T>
const & k)
395 vigra_precondition(src.shape() == dest.shape(),
396 "convolveImage(): shape mismatch between input and output.");
398 destImage(dest), k, k);
401 template <
class T1,
class S1,
406 MultiArrayView<2, T2, S2> dest,
407 Kernel1D<T>
const & kx, Kernel1D<T>
const & ky)
409 vigra_precondition(src.shape() == dest.shape(),
410 "convolveImage(): shape mismatch between input and output.");
412 destImage(dest), kx, ky);
500 template <
class SrcIterator,
class SrcAccessor,
501 class DestIterator,
class DestAccessor>
502 void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
503 DestIterator dest_ul, DestAccessor dest_acc,
double sharpening_factor)
506 vigra_precondition(sharpening_factor >= 0.0,
507 "simpleSharpening(): amount of sharpening must be >= 0.");
509 Kernel2D<double> kernel;
511 kernel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_factor/16.0,
512 -sharpening_factor/8.0, 1.0+sharpening_factor*0.75, -sharpening_factor/8.0,
513 -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_factor/16.0;
516 kernel.center(), kernel.accessor(),
517 kernel.upperLeft(), kernel.lowerRight() , BORDER_TREATMENT_REFLECT );
520 template <
class SrcIterator,
class SrcAccessor,
521 class DestIterator,
class DestAccessor>
524 pair<DestIterator, DestAccessor> dest,
double sharpening_factor)
527 dest.first, dest.second, sharpening_factor);
530 template <
class T1,
class S1,
534 MultiArrayView<2, T2, S2> dest,
535 double sharpening_factor)
537 vigra_precondition(src.shape() == dest.shape(),
538 "simpleSharpening(): shape mismatch between input and output.");
540 destImage(dest), sharpening_factor);
632 template <
class SrcIterator,
class SrcAccessor,
633 class DestIterator,
class DestAccessor>
635 DestIterator dest_ul, DestAccessor dest_acc,
double sharpening_factor,
638 vigra_precondition(sharpening_factor >= 0.0,
639 "gaussianSharpening(): amount of sharpening must be >= 0");
640 vigra_precondition(scale >= 0.0,
641 "gaussianSharpening(): scale parameter should be >= 0.");
643 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote ValueType;
645 BasicImage<ValueType> tmp(src_lr - src_ul, SkipInitialization);
647 gaussianSmoothing(src_ul, src_lr, src_acc, tmp.upperLeft(), tmp.accessor(), scale);
649 SrcIterator i_src = src_ul;
650 DestIterator i_dest = dest_ul;
651 typename BasicImage<ValueType>::traverser tmp_ul = tmp.upperLeft();
652 typename BasicImage<ValueType>::traverser i_tmp = tmp_ul;
653 typename BasicImage<ValueType>::Accessor tmp_acc = tmp.accessor();
655 for(; i_src.y != src_lr.y ; i_src.y++, i_dest.y++, i_tmp.y++ )
657 for (;i_src.x != src_lr.x ; i_src.x++, i_dest.x++, i_tmp.x++ )
659 dest_acc.set((1.0 + sharpening_factor)*src_acc(i_src) - sharpening_factor*tmp_acc(i_tmp), i_dest);
662 i_dest.x = dest_ul.x;
667 template <
class SrcIterator,
class SrcAccessor,
668 class DestIterator,
class DestAccessor>
671 pair<DestIterator, DestAccessor> dest,
double sharpening_factor,
675 dest.first, dest.second,
676 sharpening_factor, scale);
679 template <
class T1,
class S1,
683 MultiArrayView<2, T2, S2> dest,
684 double sharpening_factor,
687 vigra_precondition(src.shape() == dest.shape(),
688 "gaussianSharpening(): shape mismatch between input and output.");
691 sharpening_factor, scale);
777 template <
class SrcIterator,
class SrcAccessor,
778 class DestIterator,
class DestAccessor>
780 gaussianSmoothing(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor sa,
781 DestIterator dupperleft, DestAccessor da,
782 double scale_x,
double scale_y)
785 NumericTraits<typename SrcAccessor::value_type>::RealPromote
787 BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
789 Kernel1D<double> smooth_x, smooth_y;
790 smooth_x.initGaussian(scale_x);
791 smooth_x.setBorderTreatment(BORDER_TREATMENT_REFLECT);
792 smooth_y.initGaussian(scale_y);
793 smooth_y.setBorderTreatment(BORDER_TREATMENT_REFLECT);
796 destImage(tmp), kernel1d(smooth_x));
798 destIter(dupperleft, da), kernel1d(smooth_y));
801 template <
class SrcIterator,
class SrcAccessor,
802 class DestIterator,
class DestAccessor>
804 gaussianSmoothing(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor sa,
805 DestIterator dupperleft, DestAccessor da,
813 template <
class SrcIterator,
class SrcAccessor,
814 class DestIterator,
class DestAccessor>
817 pair<DestIterator, DestAccessor> dest,
818 double scale_x,
double scale_y)
821 dest.first, dest.second, scale_x, scale_y);
824 template <
class SrcIterator,
class SrcAccessor,
825 class DestIterator,
class DestAccessor>
828 pair<DestIterator, DestAccessor> dest,
832 dest.first, dest.second, scale, scale);
835 template <
class T1,
class S1,
839 MultiArrayView<2, T2, S2> dest,
840 double scale_x,
double scale_y)
842 vigra_precondition(src.shape() == dest.shape(),
843 "gaussianSmoothing(): shape mismatch between input and output.");
845 destImage(dest), scale_x, scale_y);
848 template <
class T1,
class S1,
852 MultiArrayView<2, T2, S2> dest,
855 vigra_precondition(src.shape() == dest.shape(),
856 "gaussianSmoothing(): shape mismatch between input and output.");
858 destImage(dest), scale, scale);
981 template <
class SrcIterator,
class SrcAccessor,
982 class DestIteratorX,
class DestAccessorX,
983 class DestIteratorY,
class DestAccessorY>
985 SrcIterator slowerright, SrcAccessor sa,
986 DestIteratorX dupperleftx, DestAccessorX dax,
987 DestIteratorY dupperlefty, DestAccessorY day,
991 NumericTraits<typename SrcAccessor::value_type>::RealPromote
993 BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
995 Kernel1D<double> smooth, grad;
996 smooth.initGaussian(scale);
997 grad.initGaussianDerivative(scale, 1);
1000 destImage(tmp), kernel1d(grad));
1002 destIter(dupperleftx, dax), kernel1d(smooth));
1004 destImage(tmp), kernel1d(smooth));
1006 destIter(dupperlefty, day), kernel1d(grad));
1009 template <
class SrcIterator,
class SrcAccessor,
1010 class DestIterator,
class DestAccessor>
1012 SrcIterator slowerright, SrcAccessor src,
1013 DestIterator dupperleft, DestAccessor dest,
1016 VectorElementAccessor<DestAccessor> gradx(0, dest), grady(1, dest);
1018 dupperleft, gradx, dupperleft, grady, scale);
1021 template <
class SrcIterator,
class SrcAccessor,
1022 class DestIteratorX,
class DestAccessorX,
1023 class DestIteratorY,
class DestAccessorY>
1026 pair<DestIteratorX, DestAccessorX> destx,
1027 pair<DestIteratorY, DestAccessorY> desty,
1031 destx.first, destx.second, desty.first, desty.second, scale);
1034 template <
class SrcIterator,
class SrcAccessor,
1035 class DestIterator,
class DestAccessor>
1038 pair<DestIterator, DestAccessor> dest,
1042 dest.first, dest.second, scale);
1045 template <
class T1,
class S1,
1046 class T2X,
class S2X,
1047 class T2Y,
class S2Y>
1050 MultiArrayView<2, T2X, S2X> destx,
1051 MultiArrayView<2, T2Y, S2Y> desty,
1054 vigra_precondition(src.shape() == destx.shape(),
1055 "gaussianGradient(): shape mismatch between input and output.");
1057 destImage(destx), destImage(desty), scale);
1060 template <
class T1,
class S1,
1064 MultiArrayView<2, TinyVector<T2, 2>, S2> dest,
1067 vigra_precondition(src.shape() == dest.shape(),
1068 "gaussianGradient(): shape mismatch between input and output.");
1070 destImage(dest), scale);
1210 template <
class SrcIterator,
class SrcAccessor,
1211 class DestIterator,
class DestAccessor>
1213 SrcIterator slr, SrcAccessor src,
1214 DestIterator dupperleft, DestAccessor dest,
1217 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
1218 BasicImage<TmpType> gradx(slr-sul, SkipInitialization), grady(slr-sul, SkipInitialization);
1221 destImage(gradx), destImage(grady), scale);
1222 combineTwoImages(srcImageRange(gradx), srcImage(grady), destIter(dupperleft, dest),
1223 MagnitudeFunctor<TmpType>());
1226 template <
class SrcIterator,
class SrcAccessor,
1227 class DestIterator,
class DestAccessor>
1230 pair<DestIterator, DestAccessor> dest,
1234 dest.first, dest.second, scale);
1317 template <
class SrcIterator,
class SrcAccessor,
1318 class DestIterator,
class DestAccessor>
1320 SrcIterator slowerright, SrcAccessor sa,
1321 DestIterator dupperleft, DestAccessor da,
1325 NumericTraits<typename SrcAccessor::value_type>::RealPromote
1327 BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization),
1328 tmpx(slowerright - supperleft, SkipInitialization),
1329 tmpy(slowerright - supperleft, SkipInitialization);
1331 Kernel1D<double> smooth, deriv;
1332 smooth.initGaussian(scale);
1333 deriv.initGaussianDerivative(scale, 2);
1336 destImage(tmp), kernel1d(deriv));
1338 destImage(tmpx), kernel1d(smooth));
1340 destImage(tmp), kernel1d(smooth));
1342 destImage(tmpy), kernel1d(deriv));
1344 destIter(dupperleft, da), std::plus<TmpType>());
1347 template <
class SrcIterator,
class SrcAccessor,
1348 class DestIterator,
class DestAccessor>
1351 pair<DestIterator, DestAccessor> dest,
1355 dest.first, dest.second, scale);
1358 template <
class T1,
class S1,
1362 MultiArrayView<2, T2, S2> dest,
1365 vigra_precondition(src.shape() == dest.shape(),
1366 "laplacianOfGaussian(): shape mismatch between input and output.");
1368 destImage(dest), scale);
1478 template <
class SrcIterator,
class SrcAccessor,
1479 class DestIteratorX,
class DestAccessorX,
1480 class DestIteratorXY,
class DestAccessorXY,
1481 class DestIteratorY,
class DestAccessorY>
1483 SrcIterator slowerright, SrcAccessor sa,
1484 DestIteratorX dupperleftx, DestAccessorX dax,
1485 DestIteratorXY dupperleftxy, DestAccessorXY daxy,
1486 DestIteratorY dupperlefty, DestAccessorY day,
1490 NumericTraits<typename SrcAccessor::value_type>::RealPromote
1492 BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
1494 Kernel1D<double> smooth, deriv1, deriv2;
1495 smooth.initGaussian(scale);
1496 deriv1.initGaussianDerivative(scale, 1);
1497 deriv2.initGaussianDerivative(scale, 2);
1500 destImage(tmp), kernel1d(deriv2));
1502 destIter(dupperleftx, dax), kernel1d(smooth));
1504 destImage(tmp), kernel1d(smooth));
1506 destIter(dupperlefty, day), kernel1d(deriv2));
1508 destImage(tmp), kernel1d(deriv1));
1510 destIter(dupperleftxy, daxy), kernel1d(deriv1));
1513 template <
class SrcIterator,
class SrcAccessor,
1514 class DestIteratorX,
class DestAccessorX,
1515 class DestIteratorXY,
class DestAccessorXY,
1516 class DestIteratorY,
class DestAccessorY>
1519 pair<DestIteratorX, DestAccessorX> destx,
1520 pair<DestIteratorXY, DestAccessorXY> destxy,
1521 pair<DestIteratorY, DestAccessorY> desty,
1525 destx.first, destx.second,
1526 destxy.first, destxy.second,
1527 desty.first, desty.second,
1531 template <
class T1,
class S1,
1532 class T2X,
class S2X,
1533 class T2XY,
class S2XY,
1534 class T2Y,
class S2Y>
1537 MultiArrayView<2, T2X, S2X> destx,
1538 MultiArrayView<2, T2XY, S2XY> destxy,
1539 MultiArrayView<2, T2Y, S2Y> desty,
1542 vigra_precondition(src.shape() == destx.shape() && src.shape() == destxy.shape() && src.shape() == desty.shape(),
1543 "hessianMatrixOfGaussian(): shape mismatch between input and output.");
1551 template <
class T1,
class S1,
1555 MultiArrayView<2, TinyVector<T2, 3>, S2> dest,
1558 vigra_precondition(src.shape() == dest.shape(),
1559 "hessianMatrixOfGaussian(): shape mismatch between input and output.");
1561 MultiArrayView<3, T2> expanded(dest.expandElements(0));
1564 destImage(expanded.bind<0>(0)),
1565 destImage(expanded.bind<0>(1)),
1566 destImage(expanded.bind<0>(2)),
1722 template <
class SrcIterator,
class SrcAccessor,
1723 class DestIteratorX,
class DestAccessorX,
1724 class DestIteratorXY,
class DestAccessorXY,
1725 class DestIteratorY,
class DestAccessorY>
1727 SrcIterator slowerright, SrcAccessor sa,
1728 DestIteratorX dupperleftx, DestAccessorX dax,
1729 DestIteratorXY dupperleftxy, DestAccessorXY daxy,
1730 DestIteratorY dupperlefty, DestAccessorY day,
1731 double inner_scale,
double outer_scale)
1734 NumericTraits<typename SrcAccessor::value_type>::RealPromote
1736 BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization),
1737 tmpx(slowerright - supperleft, SkipInitialization),
1738 tmpy(slowerright - supperleft, SkipInitialization);
1741 destImage(tmpx), destImage(tmpy), inner_scale);
1743 destImage(tmp), std::multiplies<TmpType>());
1745 destIter(dupperleftx, dax), outer_scale);
1747 destImage(tmp), std::multiplies<TmpType>());
1749 destIter(dupperlefty, day), outer_scale);
1751 destImage(tmp), std::multiplies<TmpType>());
1753 destIter(dupperleftxy, daxy), outer_scale);
1756 template <
class SrcIterator,
class SrcAccessor,
1757 class DestIteratorX,
class DestAccessorX,
1758 class DestIteratorXY,
class DestAccessorXY,
1759 class DestIteratorY,
class DestAccessorY>
1762 pair<DestIteratorX, DestAccessorX> destx,
1763 pair<DestIteratorXY, DestAccessorXY> destxy,
1764 pair<DestIteratorY, DestAccessorY> desty,
1765 double inner_scale,
double outer_scale)
1768 destx.first, destx.second,
1769 destxy.first, destxy.second,
1770 desty.first, desty.second,
1771 inner_scale, outer_scale);
1774 template <
class T,
class S,
1776 class TXY,
class SXY,
1780 MultiArrayView<2, TX, SX> destx,
1781 MultiArrayView<2, TXY, SXY> destxy,
1782 MultiArrayView<2, TY, SY> desty,
1783 double inner_scale,
double outer_scale)
1785 vigra_precondition(src.shape() == destx.shape(),
1786 "structureTensor(): shape mismatch between input and output.");
1788 destImage(destx), destImage(destxy), destImage(desty),
1789 inner_scale, outer_scale);
1794 template <
class SrcIterator,
class SrcAccessor,
1795 class DestIterator,
class DestAccessor>
1797 SrcIterator slowerright, SrcAccessor src,
1798 DestIterator dupperleft, DestAccessor dest,
1799 double inner_scale,
double outer_scale,
1802 typedef VectorElementAccessor<DestAccessor> DA;
1804 dupperleft, DA(0, dest),
1805 dupperleft, DA(1, dest),
1806 dupperleft, DA(2, dest),
1807 inner_scale, outer_scale);
1810 template <
class SrcIterator,
class SrcAccessor,
1811 class DestIterator,
class DestAccessor>
1813 SrcIterator slowerright, SrcAccessor src,
1814 DestIterator dupperleft, DestAccessor dest,
1815 double inner_scale,
double outer_scale,
1818 int bands = src.size(supperleft);
1819 typedef VectorElementAccessor<SrcAccessor> SA;
1823 inner_scale, outer_scale,
1826 BasicImage<typename DestAccessor::value_type> st(slowerright - supperleft, SkipInitialization);
1827 for(
int k=1; k < bands; ++k)
1830 st.upperLeft(), st.accessor(),
1831 inner_scale, outer_scale,
1833 combineTwoImages(srcImageRange(st), srcIter(dupperleft, dest), destIter(dupperleft, dest),
1834 std::plus<typename DestAccessor::value_type>());
1840 template <
class SrcIterator,
class SrcAccessor,
1841 class DestIterator,
class DestAccessor>
1843 SrcIterator slowerright, SrcAccessor src,
1844 DestIterator dupperleft, DestAccessor dest,
1845 double inner_scale,
double outer_scale)
1848 NumericTraits<typename SrcAccessor::value_type>::isScalar isScalar;
1850 dupperleft, dest, inner_scale, outer_scale, isScalar());
1853 template <
class SrcIterator,
class SrcAccessor,
1854 class DestIterator,
class DestAccessor>
1857 pair<DestIterator, DestAccessor> dest,
1858 double inner_scale,
double outer_scale)
1861 dest.first, dest.second,
1862 inner_scale, outer_scale);
1865 template <
class T1,
class S1,
1869 MultiArrayView<2, TinyVector<T2, 3>, S2> dest,
1870 double inner_scale,
double outer_scale)
1872 vigra_precondition(src.shape() == dest.shape(),
1873 "structureTensor(): shape mismatch between input and output.");
1876 inner_scale, outer_scale);
1883 #endif // VIGRA_CONVOLUTION_HXX