[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

multi_resize.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2004 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 
37 #ifndef VIGRA_MULTI_RESIZE_HXX
38 #define VIGRA_MULTI_RESIZE_HXX
39 
40 #include <vector>
41 #include "resizeimage.hxx"
42 #include "navigator.hxx"
43 
44 namespace vigra {
45 
46 namespace detail {
47 
48 template <class SrcIterator, class Shape, class SrcAccessor,
49  class DestIterator, class DestAccessor, class Kernel>
50 void
51 internalResizeMultiArrayOneDimension(
52  SrcIterator si, Shape const & sshape, SrcAccessor src,
53  DestIterator di, Shape const & dshape, DestAccessor dest,
54  Kernel const & spline, unsigned int d)
55 {
56  enum { N = 1 + SrcIterator::level };
57 
58  typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
59 
60  typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
61  typedef MultiArrayNavigator<DestIterator, N> DNavigator;
62 
63  SNavigator snav( si, sshape, d );
64  DNavigator dnav( di, dshape, d );
65 
66  int ssize = sshape[d];
67  int dsize = dshape[d];
68 
69  vigra_precondition(ssize > 1,
70  "resizeMultiArraySplineInterpolation(): "
71  "Source array too small.\n");
72 
73  Rational<int> ratio(dsize - 1, ssize - 1);
74  Rational<int> offset(0);
75  resampling_detail::MapTargetToSourceCoordinate mapCoordinate(ratio, offset);
76  int period = lcm(ratio.numerator(), ratio.denominator());
77 
78  ArrayVector<double> const & prefilterCoeffs = spline.prefilterCoefficients();
79  ArrayVector<Kernel1D<double> > kernels(period);
80  createResamplingKernels(spline, mapCoordinate, kernels);
81 
82  // temporay array to hold the current line to enable in-place operation
83  ArrayVector<TmpType> tmp( ssize );
84  typename ArrayVector<TmpType>::iterator t = tmp.begin(), tend = tmp.end();
85  typename AccessorTraits<TmpType>::default_accessor ta;
86 
87  for( ; snav.hasMore(); snav++, dnav++ )
88  {
89  // first copy source to temp for maximum cache efficiency
90  copyLine( snav.begin(), snav.end(), src, t, ta);
91 
92  for(unsigned int b = 0; b < prefilterCoeffs.size(); ++b)
93  {
94  recursiveFilterLine(t, tend, ta, t, ta,
95  prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
96  }
97  resamplingConvolveLine(t, tend, ta,
98  dnav.begin(), dnav.begin() + dsize, dest,
99  kernels, mapCoordinate);
100  }
101 }
102 
103 } // namespace detail
104 
105 /** \addtogroup GeometricTransformations Geometric Transformations
106 */
107 //@{
108 
109 
110 /***************************************************************/
111 /* */
112 /* resizeMultiArraySplineInterpolation */
113 /* */
114 /***************************************************************/
115 
116 /** \brief Resize MultiArray using B-spline interpolation.
117 
118  <b> Declarations:</b>
119 
120  pass arguments explicitly:
121  \code
122  namespace vigra {
123  template <class SrcIterator, class Shape, class SrcAccessor,
124  class DestIterator, class DestAccessor,
125  class Kernel = BSpline<3, double> >
126  void
127  resizeMultiArraySplineInterpolation(
128  SrcIterator si, Shape const & sshape, SrcAccessor src,
129  DestIterator di, Shape const & dshape, DestAccessor dest,
130  Kernel const & spline = BSpline<3, double>());
131  }
132  \endcode
133 
134 
135  use argument objects in conjunction with \ref ArgumentObjectFactories :
136  \code
137  namespace vigra {
138  template <class SrcIterator, class Shape, class SrcAccessor,
139  class DestIterator, class DestAccessor,
140  class Kernel = BSpline<3, double> >
141  void
142  resizeMultiArraySplineInterpolation(
143  triple<SrcIterator, Shape, SrcAccessor> src,
144  triple<DestIterator, Shape, DestAccessor> dest,
145  Kernel const & spline = BSpline<3, double>());
146  }
147  \endcode
148 
149  The function implements separable spline interpolation algorithm described in
150 
151  M. Unser, A. Aldroubi, M. Eden, <i>"B-Spline Signal Processing"</i>
152  IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 821-833 (part I),
153  pp. 834-848 (part II), 1993.
154 
155  to obtain optimal interpolation quality and speed. You may pass the funcion
156  a spline of arbitrary order (e.g. <TT>BSpline<ORDER, double></tt> or
157  <TT>CatmullRomSpline<double></tt>). The default is a third order spline
158  which gives a twice continuously differentiable interpolant.
159  The implementation ensures that image values are interpolated rather
160  than smoothed by first calling a recursive (sharpening) prefilter as
161  described in the above paper. Then the actual interpolation is done
162  using \ref resamplingConvolveLine().
163 
164  The range of both the input and output images (resp. regions)
165  must be given. The input image must have a size of at
166  least 4x4, the destination of at least 2x2. The scaling factors are then calculated
167  accordingly. If the source image is larger than the destination, it
168  is smoothed (band limited) using a recursive
169  exponential filter. The source value_type (SrcAccessor::value_type) must
170  be a linear algebra, i.e. it must support addition, subtraction,
171  and multiplication (+, -, *), multiplication with a scalar
172  real number and \ref NumericTraits "NumericTraits".
173  The function uses accessors.
174 
175  <b> Usage:</b>
176 
177  <b>\#include</b> <<a href="multi__resize_8hxx-source.html">vigra/multi_resize.hxx</a>><br>
178  Namespace: vigra
179 
180  \code
181  typedef vigra::MultiArray<3, float>::difference_type Shape;
182  vigra::MultiArray<3, float> src(Shape(5, 7, 10)),
183  dest(Shape(9, 13, 19)); // double the size
184 
185  // use default cubic spline interpolator
186  vigra::resizeMultiArraySplineInterpolation(
187  srcMultiArrayRange(src),
188  destMultiArrayRange(dest));
189 
190  \endcode
191 
192  <b> Required Interface:</b>
193 
194  The source and destination iterators must be compatible with \ref vigra::MultiIterator. The array value
195  types must be models of \ref LinearSpace.
196 */
198 
199 template <class SrcIterator, class Shape, class SrcAccessor,
200  class DestIterator, class DestAccessor,
201  class Kernel>
202 void
204  SrcIterator si, Shape const & sshape, SrcAccessor src,
205  DestIterator di, Shape const & dshape, DestAccessor dest,
206  Kernel const & spline)
207 {
208  enum { N = 1 + SrcIterator::level };
209  typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType;
210  typedef MultiArray<N, TmpType> TmpArray;
211  typedef typename AccessorTraits<TmpType>::default_accessor TmpAccessor;
212 
213  if(N==1)
214  {
215  detail::internalResizeMultiArrayOneDimension(si, sshape, src,
216  di, dshape, dest, spline, 0);
217  }
218  else
219  {
220  unsigned int d = 0;
221  Shape tmpShape(sshape);
222  tmpShape[d] = dshape[d];
223  MultiArray<N, TmpType> tmp(tmpShape);
224  TmpAccessor ta;
225 
226  detail::internalResizeMultiArrayOneDimension(si, sshape, src,
227  tmp.traverser_begin(), tmpShape, ta, spline, d);
228  d = 1;
229  for(; d<N-1; ++d)
230  {
231  tmpShape[d] = dshape[d];
232  MultiArray<N, TmpType> dtmp(tmpShape);
233 
234  detail::internalResizeMultiArrayOneDimension(tmp.traverser_begin(), tmp.shape(), ta,
235  dtmp.traverser_begin(), tmpShape, ta, spline, d);
236  dtmp.swap(tmp);
237  }
238  detail::internalResizeMultiArrayOneDimension(tmp.traverser_begin(), tmp.shape(), ta,
239  di, dshape, dest, spline, d);
240  }
241 }
242 
243 template <class SrcIterator, class Shape, class SrcAccessor,
244  class DestIterator, class DestAccessor,
245  class Kernel>
246 inline void
247 resizeMultiArraySplineInterpolation(triple<SrcIterator, Shape, SrcAccessor> src,
248  triple<DestIterator, Shape, DestAccessor> dest,
249  Kernel const & spline)
250 {
251  resizeMultiArraySplineInterpolation(src.first, src.second, src.third,
252  dest.first, dest.second, dest.third, spline);
253 }
254 
255 template <class SrcIterator, class Shape, class SrcAccessor,
256  class DestIterator, class DestAccessor>
257 inline void
259  SrcIterator si, Shape const & sshape, SrcAccessor src,
260  DestIterator di, Shape const & dshape, DestAccessor dest)
261 {
262  resizeMultiArraySplineInterpolation(si, sshape, src, di, dshape, dest, BSpline<3, double>());
263 }
264 
265 template <class SrcIterator, class Shape, class SrcAccessor,
266  class DestIterator, class DestAccessor>
267 inline void
268 resizeMultiArraySplineInterpolation(triple<SrcIterator, Shape, SrcAccessor> src,
269  triple<DestIterator, Shape, DestAccessor> dest)
270 {
271  resizeMultiArraySplineInterpolation(src.first, src.second, src.third,
272  dest.first, dest.second, dest.third);
273 }
274 
275 //@}
276 
277 } // namespace vigra
278 
279 #endif // VIGRA_MULTI_RESIZE_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.7.1 (Thu Jun 14 2012)