32#include <vigra/convolution.hxx>
33#include <vigra/error.hxx>
34#include <vigra/inspectimage.hxx>
35#include <vigra/numerictraits.hxx>
36#include <vigra/rgbvalue.hxx>
37#include <vigra/sized_int.hxx>
38#include <vigra/transformimage.hxx>
48using vigra::linearRangeMapping;
49using vigra::NumericTraits;
50using vigra::transformImage;
53using vigra::UInt16Image;
54using vigra::UInt16RGBImage;
58#define IMUL6(A) (A * SKIPSMImagePixelType(6))
59#define IMUL5(A) (A * SKIPSMImagePixelType(5))
60#define IMUL11(A) (A * SKIPSMImagePixelType(11))
61#define AMUL6(A) (A * SKIPSMAlphaPixelType(6))
68template <
typename ImagePixelComponentType>
74 "filterHalfWidth: levels outside of range [1,29]");
200 "src image too small in reduce");
586 mask.first, mask.second,
588 destMask.first, destMask.second, destMask.third);
613 "src image too small in reduce");
863#define SKIPSM_EXPAND(SCALE_OUT00, SCALE_OUT10, SCALE_OUT01, SCALE_OUT11) \
864 current = SKIPSMImagePixelType(sa(sx)); \
865 out00 = sc1a[srcx] + IMUL6(sc0a[srcx]); \
866 out10 = sc1b[srcx] + IMUL6(sc0b[srcx]); \
867 out01 = sc0a[srcx]; \
868 out11 = sc0b[srcx]; \
869 sc1a[srcx] = sc0a[srcx]; \
870 sc1b[srcx] = sc0b[srcx]; \
871 sc0a[srcx] = sr1 + IMUL6(sr0) + current; \
872 sc0b[srcx] = (sr0 + current) * 4; \
875 out00 += sc0a[srcx]; \
876 out10 += sc0b[srcx]; \
877 out01 += sc0a[srcx]; \
878 out11 += sc0b[srcx]; \
879 out00 /= SKIPSMImagePixelType(SCALE_OUT00); \
880 out10 /= SKIPSMImagePixelType(SCALE_OUT10); \
881 out01 /= SKIPSMImagePixelType(SCALE_OUT01); \
882 out11 /= SKIPSMImagePixelType(SCALE_OUT11); \
883 da.set(cf(SKIPSMImagePixelType(da(dx)), out00), dx); \
885 da.set(cf(SKIPSMImagePixelType(da(dx)), out10), dx); \
887 da.set(cf(SKIPSMImagePixelType(da(dxx)), out01), dxx); \
889 da.set(cf(SKIPSMImagePixelType(da(dxx)), out11), dxx); \
894#define SKIPSM_EXPAND_SHIFT \
895 current = SKIPSMImagePixelType(sa(sx)); \
896 out00 = sc1a[srcx] + IMUL6(sc0a[srcx]); \
897 out10 = sc1b[srcx] + IMUL6(sc0b[srcx]); \
898 out01 = sc0a[srcx]; \
899 out11 = sc0b[srcx]; \
900 sc1a[srcx] = sc0a[srcx]; \
901 sc1b[srcx] = sc0b[srcx]; \
902 sc0a[srcx] = sr1 + IMUL6(sr0) + current; \
903 sc0b[srcx] = (sr0 + current) * 4; \
906 out00 += sc0a[srcx]; \
907 out10 += sc0b[srcx]; \
908 out01 += sc0a[srcx]; \
909 out11 += sc0b[srcx]; \
914 da.set(cf(SKIPSMImagePixelType(da(dx)), out00), dx); \
916 da.set(cf(SKIPSMImagePixelType(da(dx)), out10), dx); \
918 da.set(cf(SKIPSMImagePixelType(da(dxx)), out01), dxx); \
920 da.set(cf(SKIPSMImagePixelType(da(dxx)), out11), dxx); \
924#define SKIPSM_EXPAND_ROW_END(SCALE_OUT00, SCALE_OUT10, SCALE_OUT01, SCALE_OUT11) \
925 out00 = sc1a[srcx] + IMUL6(sc0a[srcx]); \
926 out10 = sc1b[srcx] + IMUL6(sc0b[srcx]); \
927 out00 /= SKIPSMImagePixelType(SCALE_OUT00); \
928 out10 /= SKIPSMImagePixelType(SCALE_OUT10); \
929 da.set(cf(da(dx), out00), dx); \
931 da.set(cf(da(dx), out10), dx); \
933 if ((dst_h & 1) == 0) { \
934 out01 = sc0a[srcx]; \
935 out11 = sc0b[srcx]; \
936 out01 /= SKIPSMImagePixelType(SCALE_OUT01); \
937 out11 /= SKIPSMImagePixelType(SCALE_OUT11); \
938 da.set(cf(da(dxx), out01), dxx); \
940 da.set(cf(da(dxx), out11), dxx); \
946#define SKIPSM_EXPAND_COLUMN_END(SCALE_OUT00, SCALE_OUT10, SCALE_OUT01, SCALE_OUT11) \
947 out00 = sc1a[srcx] + IMUL6(sc0a[srcx]); \
948 out01 = sc0a[srcx]; \
949 out10 = sc1b[srcx] + IMUL6(sc0b[srcx]); \
950 out11 = sc0b[srcx]; \
951 sc1a[srcx] = sc0a[srcx]; \
952 sc1b[srcx] = sc0b[srcx]; \
953 sc0a[srcx] = sr1 + IMUL6(sr0); \
954 sc0b[srcx] = sr0 * 4; \
955 out00 += sc0a[srcx]; \
956 out01 += sc0a[srcx]; \
957 out00 /= SKIPSMImagePixelType(SCALE_OUT00); \
958 out01 /= SKIPSMImagePixelType(SCALE_OUT01); \
959 da.set(cf(da(dx), out00), dx); \
960 da.set(cf(da(dxx), out01), dxx); \
961 if ((dst_w & 1) == 0) { \
964 out10 += sc0b[srcx]; \
965 out11 += sc0b[srcx]; \
966 out10 /= SKIPSMImagePixelType(SCALE_OUT10); \
967 out11 /= SKIPSMImagePixelType(SCALE_OUT11); \
968 da.set(cf(da(dx), out10), dx); \
969 da.set(cf(da(dxx), out11), dxx); \
974#define SKIPSM_EXPAND_COLUMN_END_WRAPAROUND(SCALE_OUT00, SCALE_OUT10, SCALE_OUT01, SCALE_OUT11) \
975 out00 = sc1a[srcx] + IMUL6(sc0a[srcx]); \
976 out01 = sc0a[srcx]; \
977 out10 = sc1b[srcx] + IMUL6(sc0b[srcx]); \
978 out11 = sc0b[srcx]; \
979 sc1a[srcx] = sc0a[srcx]; \
980 sc1b[srcx] = sc0b[srcx]; \
981 sc0a[srcx] = sr1 + IMUL6(sr0) + SKIPSMImagePixelType(sa(sy)); \
982 sc0b[srcx] = (sr0 + SKIPSMImagePixelType(sa(sy))) * 4; \
983 out00 += sc0a[srcx]; \
984 out01 += sc0a[srcx]; \
985 out00 /= SKIPSMImagePixelType(SCALE_OUT00); \
986 out01 /= SKIPSMImagePixelType(SCALE_OUT01); \
987 da.set(cf(da(dx), out00), dx); \
988 da.set(cf(da(dxx), out01), dxx); \
989 if ((dst_w & 1) == 0) { \
992 out10 += sc0b[srcx]; \
993 out11 += sc0b[srcx]; \
994 out10 /= SKIPSMImagePixelType(SCALE_OUT10); \
995 out11 /= SKIPSMImagePixelType(SCALE_OUT11); \
996 da.set(cf(da(dx), out10), dx); \
997 da.set(cf(da(dxx), out11), dxx); \
1002#define SKIPSM_EXPAND_ROW_COLUMN_END(SCALE_OUT00, SCALE_OUT10, SCALE_OUT01, SCALE_OUT11) \
1003 out00 = sc1a[srcx] + IMUL6(sc0a[srcx]); \
1004 out00 /= SKIPSMImagePixelType(SCALE_OUT00); \
1005 da.set(cf(da(dx), out00), dx); \
1006 if ((dst_w & 1) == 0) { \
1007 out10 = sc1b[srcx] + IMUL6(sc0b[srcx]); \
1008 out10 /= SKIPSMImagePixelType(SCALE_OUT10); \
1010 da.set(cf(da(dx), out10), dx); \
1012 if ((dst_h & 1) == 0) { \
1013 out01 = sc0a[srcx]; \
1014 out01 /= SKIPSMImagePixelType(SCALE_OUT01); \
1015 da.set(cf(da(dxx), out01), dxx); \
1016 if ((dst_w & 1) == 0) { \
1017 out11 = sc0b[srcx]; \
1018 out11 /= SKIPSMImagePixelType(SCALE_OUT11); \
1020 da.set(cf(da(dxx), out11), dxx); \
1357template<
typename T1,
typename T2,
typename T3>
1360 return NumericTraits<T3>::fromPromote(a + b);
1384 std::minus<SKIPSMImagePixelType>());
1400 typename SrcImageType::ConstAccessor
sa,
1402 typename AlphaImageType::ConstAccessor
aa) {
1420 cout <<
"Generating Gaussian pyramid: g0";
1426 for (
unsigned int l = 1; l <
numLevels; l++) {
1480 alpha.first, alpha.second);
1491 typename SrcImageType::ConstAccessor
sa) {
1505 gp0->upperLeft(),
gp0->accessor());
1510 cout <<
"Generating Gaussian pyramid: g0";
1515 for (
unsigned int l = 1; l <
numLevels; l++) {
1564 typename SrcImageType::ConstAccessor
sa,
1566 typename AlphaImageType::ConstAccessor
aa) {
1580 cout <<
"Generating Laplacian pyramid:";
1586 for (
unsigned int l = 0; l < (
numLevels-1); l++) {
1621 alpha.first, alpha.second);
1625template <
typename SKIPSMImagePixelType,
typename Pyram
idImageType>
1629 cout <<
"Collapsing Laplacian pyramid: "
1630 <<
"l" << p->size()-1;
1636 for (
int l = (p->size()-2); l >= 0; l--) {
1655template <
typename Pyram
idImageType>
1665 for (
unsigned int i = 0;
i <
v->size();
i++) {
1672 linearRangeMapping(NumericTraits<PyramidValueType>::min(),
1673 NumericTraits<PyramidValueType>::max(),
1674 NumericTraits<UInt16>::min(),
1675 NumericTraits<UInt16>::max()));
1683template <
typename Pyram
idImageType>
1688 for (
unsigned int i = 0;
i < (
v->size() - 1);
i++) {
1694 for (
unsigned int i = 0;
i <
v->size();
i++) {
1699 UInt16RGBImage
usPyramid((*
v)[
i]->width(), (*
v)[
i]->height());
1703 typename UInt16RGBImage::value_type(NumericTraits<UInt16>::min()),
1704 typename UInt16RGBImage::value_type(NumericTraits<UInt16>::max())));
1712template <
typename Pyram
idImageType>
1714 typedef typename NumericTraits<typename PyramidImageType::value_type>::isScalar
pyramid_is_scalar;
unsigned int filterHalfWidth(const unsigned int levels)
Calculate the half-width of a n-level filter.
void reduce(bool wraparound, SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor sa, AlphaIterator alpha_upperleft, AlphaAccessor aa, DestImageIterator dest_upperleft, DestImageIterator dest_lowerright, DestAccessor da, DestAlphaIterator dest_alpha_upperleft, DestAlphaIterator dest_alpha_lowerright, DestAlphaAccessor daa)
The Burt & Adelson Reduce operation.
void expand(bool add, bool wraparound, SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor sa, DestImageIterator dest_upperleft, DestImageIterator dest_lowerright, DestAccessor da, CombineFunctor cf)
The Burt & Adelson Expand operation.
void transformImage(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform an image into the panorama.
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
#define SKIPSM_EXPAND(SCALE_OUT00, SCALE_OUT10, SCALE_OUT01, SCALE_OUT11)
#define SKIPSM_EXPAND_ROW_END(SCALE_OUT00, SCALE_OUT10, SCALE_OUT01, SCALE_OUT11)
#define SKIPSM_EXPAND_COLUMN_END(SCALE_OUT00, SCALE_OUT10, SCALE_OUT01, SCALE_OUT11)
#define SKIPSM_EXPAND_COLUMN_END_WRAPAROUND(SCALE_OUT00, SCALE_OUT10, SCALE_OUT01, SCALE_OUT11)
#define SKIPSM_EXPAND_ROW_COLUMN_END(SCALE_OUT00, SCALE_OUT10, SCALE_OUT01, SCALE_OUT11)
#define SKIPSM_EXPAND_SHIFT
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.