Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
hugin_base/vigra_ext/Pyramid.h
Go to the documentation of this file.00001 // -*- c-basic-offset: 4 -*- 00024 #ifndef VIGRA_EXT_PYRAMID_H 00025 #define VIGRA_EXT_PYRAMID_H 00026 00027 #include <vigra/separableconvolution.hxx> 00028 00029 #include <hugin_utils/utils.h> 00030 00031 00032 // TODO: use fast version from enblend 3.0 00033 #include <vigra_ext/pyramid2.h> 00034 00035 00036 namespace vigra_ext { 00037 00038 template <class ImageIn, class Image> 00039 void reduceNTimes(ImageIn & in, Image & out, int n) 00040 { 00041 typedef typename Image::value_type vt; 00042 typedef typename vigra::NumericTraits<vt>::RealPromote SKIPSMType; 00043 if (n <= 0) { 00044 out = in; 00045 return; 00046 } 00047 00048 size_t w = in.width(); 00049 size_t h = in.height(); 00050 // Size of next level 00051 w = (w + 1) >> 1; 00052 h = (h + 1) >> 1; 00053 00054 Image temp; 00055 Image * curr = &temp; 00056 Image * next = &out; 00057 if( (n % 2) == 1) 00058 { 00059 // even number of reduce operations, first reduce into output image 00060 curr = &out; 00061 next = &temp; 00062 } 00063 curr->resize(w,h); 00064 enblend::reduce<SKIPSMType>(false, srcImageRange(in), destImageRange(*curr)); 00065 n--; 00066 w = (w + 1) >> 1; 00067 h = (h + 1) >> 1; 00068 for( ; n > 0 ; --n) { 00069 next->resize(w,h); 00070 enblend::reduce<SKIPSMType>(false, srcImageRange(*curr), destImageRange(*next)); 00071 w = (w + 1) >> 1; 00072 h = (h + 1) >> 1; 00073 Image * t = curr; 00074 curr = next; 00075 next = t; 00076 } 00077 } 00078 00079 template <class Image, class ImageMask> 00080 void reduceNTimes(Image & in, ImageMask & inMask, Image & out, ImageMask & outMask, int n) 00081 { 00082 typedef typename Image::value_type vt; 00083 typedef typename vigra::NumericTraits<vt>::RealPromote SKIPSMType; 00084 typedef typename ImageMask::value_type mt; 00085 // typedef typename vigra::NumericTraits<mt>::Promote SKIPSMAlphaType; 00086 typedef double SKIPSMAlphaType; 00087 00088 if (n <= 0) { 00089 out = in; 00090 outMask = inMask; 00091 return; 00092 } 00093 00094 size_t w = in.width(); 00095 size_t h = in.height(); 00096 // Size of next level 00097 w = (w + 1) >> 1; 00098 h = (h + 1) >> 1; 00099 00100 Image temp; 00101 ImageMask tempMask; 00102 Image * curr = &temp; 00103 ImageMask * currMask = &tempMask; 00104 Image * next = &out; 00105 ImageMask * nextMask = &outMask; 00106 if( (n % 2) == 1) 00107 { 00108 // even number of reduce operations, first reduce into output image 00109 curr = &out; 00110 currMask = &outMask; 00111 next = &temp; 00112 nextMask = &tempMask; 00113 } 00114 curr->resize(w,h); 00115 currMask->resize(w,h); 00116 enblend::reduce<SKIPSMType, SKIPSMAlphaType>(false, srcImageRange(in), srcImage(inMask), 00117 destImageRange(*curr), destImageRange(*currMask)); 00118 n--; 00119 w = (w + 1) >> 1; 00120 h = (h + 1) >> 1; 00121 for( ; n > 0 ; --n) { 00122 next->resize(w,h); 00123 nextMask->resize(w,h); 00124 enblend::reduce<SKIPSMType, SKIPSMAlphaType>(false, srcImageRange(*curr), srcImage(*currMask), 00125 destImageRange(*next), destImageRange(*nextMask)); 00126 w = (w + 1) >> 1; 00127 h = (h + 1) >> 1; 00128 Image * t = curr; 00129 ImageMask * tm = currMask; 00130 curr = next; 00131 currMask = nextMask; 00132 next = t; 00133 nextMask = tm; 00134 } 00135 } 00136 00137 template <class ImageIn, class ImageOut> 00138 void reduceToNextLevel(ImageIn & in, ImageOut & out) 00139 { 00140 typedef typename ImageOut::value_type vt; 00141 typedef typename vigra::NumericTraits<vt>::RealPromote SKIPSMType; 00142 00143 size_t w = in.width(); 00144 size_t h = in.height(); 00145 // Size of next level 00146 w = (w + 1) >> 1; 00147 h = (h + 1) >> 1; 00148 out.resize(w,h); 00149 enblend::reduce<SKIPSMType>(false, srcImageRange(in), destImageRange(out)); 00150 } 00151 00152 template <class ImageIn, class ImageInMask, class ImageOut, class ImageOutMask> 00153 void reduceToNextLevel(ImageIn & in, ImageInMask & inMask, ImageOut & out, ImageOutMask & outMask) 00154 { 00155 typedef typename ImageOut::value_type vt; 00156 typedef typename vigra::NumericTraits<vt>::RealPromote SKIPSMType; 00157 //typedef typename vigra::NumericTraits<typename ImageOutMask::value_type>::Promote SKIPSMAlphaType; 00158 typedef double SKIPSMAlphaType; 00159 00160 size_t w = in.width(); 00161 size_t h = in.height(); 00162 // Size of next level 00163 w = (w + 1) >> 1; 00164 h = (h + 1) >> 1; 00165 out.resize(w,h); 00166 enblend::reduce<SKIPSMType, SKIPSMAlphaType>(false, srcImageRange(in), srcImage(inMask), 00167 destImageRange(out), destImageRange(outMask)); 00168 } 00169 00170 00171 static const double AA = 0.4; 00172 static const double W[] = {0.25 - AA / 2.0, 0.25, AA, 0.25, 0.25 - AA / 2.0}; 00173 00178 template <class Image> 00179 void reduceToNextLevelOld(Image & in, Image & out) 00180 { 00181 DEBUG_TRACE(""); 00182 // image size at current level 00183 int width = in.width(); 00184 int height = in.height(); 00185 00186 // image size at next smaller level 00187 int newwidth = (width + 1) / 2; 00188 int newheight = (height + 1) / 2; 00189 00190 // resize result image to appropriate size 00191 out.resize(newwidth, newheight); 00192 00193 // define a Gaussian kernel (size 5x1) 00194 // with sigma = 1 00195 vigra::Kernel1D<double> filter; 00196 filter.initExplicitly(-2, 2) = W[0], W[1], W[2], W[3], W[4]; 00197 00198 vigra::BasicImage<typename Image::value_type> tmpimage1(width, height); 00199 vigra::BasicImage<typename Image::value_type> tmpimage2(width, height); 00200 00201 // smooth (band limit) input image 00202 separableConvolveX(srcImageRange(in), 00203 destImage(tmpimage1), kernel1d(filter)); 00204 separableConvolveY(srcImageRange(tmpimage1), 00205 destImage(tmpimage2), kernel1d(filter)); 00206 00207 // downsample smoothed image 00208 resizeImageNoInterpolation(srcImageRange(tmpimage2), destImageRange(out)); 00209 00210 } 00211 00212 } // namespace 00213 00214 00215 #endif // VIGRA_EXT_PYRAMID_H
1.3.9.1