aimstil  5.0.5
imageInterpolation.h
Go to the documentation of this file.
1 #ifndef TIL_IMAGEINTERPOLATION_H
2 #define TIL_IMAGEINTERPOLATION_H
3 
4 // includes from BOOST library
5 //#include <boost/utility/result_of.hpp>
6 
7 // include from TIL library
8 #include "til/til_common.h"
9 #include "til/til_declarations.h"
10 #include "til/imageTools.h"
11 #include "til/PointerTraits.h"
12 #include "til/recursiveFilters.h"
13 
14 
15 // Namespace
16 namespace til {
17 
18 
19 template < typename Interpolation, typename Extrapolation, typename Mapping, typename TImageIn, typename TImageOut >
20 typename enable_if<is_Mapping<Mapping> >::type
22 (
23  const TImageIn &in,
24  TImageOut &out,
25  const Mapping &map
26  )
27 {
28  typedef typename TImageIn::value_type TIn;
29  typedef typename TImageOut::value_type TOut;
30 
31  notSameImageCheck(in, out);
32 
33  // Add extrapolation capability to image
34  //ConstPtr<ExtrapolableImage<Extrapolation, TImageIn> > eIm = extrapolable<Extrapolation>(in);
35 
36  typename Iterator<TImageOut>::Volumetric iOut(out);
37  for (; !iOut.isAtEnd(); ++iOut)
38  {
39  //*iOut = castValue<TIn, TOut>(Interpolation::template compute<Extrapolation, TImageIn>(in, map(iOut.pos())));
40  *iOut = castValue<typename Interpolation::ReturnType, TOut>(Interpolation::template compute<Extrapolation, TImageIn>(in, map(iOut.pos())));
41  }
42 
43  // TODO: what about the origin??
44 }
45 
46 
53 // NB: even if dim == in.getDim(), we still resample the image. The reason is that
54 // in can be a coefficient image (e.g. cubic spline coefficients) that would
55 // need resampling anyway.
56 // NB2: YES, we need Extrapolation even to resample an image to another size! Actually
57 // this is necessary only for supersampling, but I figured out it would be better not to
58 // split these two cases. TODO: is it really so? Maybe it is better to have an subsampling
59 // function, that could for example also take care of smothing before sampling (this
60 // function does not do that).
61 template < typename Interpolation, typename Extrapolation, typename TImageIn, typename TImageOut >
62 void
64 (
65  const TImageIn &in,
66  TImageOut &out,
67  const numeric_array<int,3> &dim
68  )
69 {
70  // Check that the input image is allocated
71  allocationCheck(in);
72  // Check that it has a size > 0 (division by getDim later on)
73  if (in.size() <= 0)
74  {
75  throw std::invalid_argument("in has invalid size");
76  }
77  // Compute voxel dimension of the output
78  numeric_array<t_voxsize,3> vdim = in.vdim() * div<numeric_array<t_voxsize,3> >(dim, in.dim());
79  // Chech whether output image is allocated
80  if (!isAllocated(out))
81  {
82  // if not, allocate output
83  out.init(dim, vdim);
84  }
85  else
86  {
87  // If it is allocated, check that this is consistent with parameter 'dim'
88  if (out.dim() != dim)
89  {
90  throw std::invalid_argument("out and dim arguments are inconsistent");
91  }
92  // Set new voxel size
93  out.set_vdim(vdim);
94  }
95  // resample image
96  resample<Interpolation, Extrapolation>(in, out, getScalingBetween(out, in));
97 }
98 
99 
100 
102 template < typename Interpolation, typename Extrapolation, typename TImageIn, typename TImageOut >
103 void
104 resample
105 (
106  const TImageIn &in,
107  TImageOut &out,
108  const numeric_array<t_voxsize,3> &vDim
109 )
110 {
111  typedef typename TImageIn::value_type TIn;
112  typedef typename TImageOut::value_type TOut;
113 
114  allocationCheck(in);
115 
116  typename Iterator<TImageOut>::Volumetric iOut(out);
117  for (; !iOut.isAtEnd(); ++iOut)
118  {/*
119  *iOut = castValue<TIn, TOut>(
120  Interpolation::compute(in,
121  iOut.getX()*a.matrix().getXX() + a.transl().getX(),
122  iOut.getY()*a.matrix().getYY() + a.transl().getY(),
123  iOut.getZ()*a.matrix().getZZ() + a.transl().getZ()));
124  */
125  }
126 }
127 
128 /*
129 // NB: Out is reallocated, so there is no need to allocate it first
130 // TODO: actually I am not sure this is really good... say we want to resample inside
131 // an existing image?
132 template < typename Interpolation, typename TImageIn, typename TImageOut>
133 typename enable_if_c<is_Image<TImageIn>::value && is_Image<TImageOut>::value>::type
134 resample(const ConstPtr<TImageIn> &in, Ptr<TImageOut> &out, const Vector<int,3> &newDim)
135 {
136 
137  // Check whether input image is allocated
138  allocationCheck(in);
139 
140  // Check whether new dimension is correct
141  if (newDim.getX() < 1 ||
142  newDim.getY() < 1 ||
143  newDim.getZ() < 1)
144  {
145  throw std::invalid_argument("Invalid Size");
146  }
147 
148  {
149  Vector<t_voxsize,3> newVDim(EXPAND_VECTOR(in->getVDim()));
150  newVDim *= in->getDim();
151  //mul(newVDim, in->getDim());
152  newVDim /= newDim;
153  //div(newVDim, newDim);
154  out = new TImageOut(newDim, newVDim);
155  }
156 
157 
158  // If input and output size are the same, simply convert image
159  // NB: this is not good, because in can be a coefficient image
160  // (e.g. cubic spline coefficients) and then in and out
161  // would be different even though the size is the same
162  / *
163  if (in->getDim() == out.getDim())
164  {
165  convert(in, out);
166  }
167  * /
168 
169  // Compute the affine transform between input and output
170  AffineMap<double> a;
171  computeAffineTransformBetween(getBoundingBox(out), getBoundingBox(in), a);
172 
173  // Reinterpolate image
174  //resampleAffine<Interpolation>(in, out, a);
175 }
176 */
177 
178 /*
179 
180 // Same thing as resample, exept that input image is smoothed if
181 // downsampled
182 // Take much more memmory, of course.
183 
184 //template < typename Interpolation, typename Tout = typename Interpolation::value_type >
185 template < typename Interpolation, typename Tout >
186 Ptr<Image<Tout> > resampleSmooth(ConstPtr<Image<typename Interpolation::value_type> > &in, Vector<int,3> &newDim)
187 {
188  Ptr<Image<double> > in2 = Image<double>::New(param(in));
189  convert(in, in2);
190 
191  Ptr<Image<double> > temp = Image<double>::New(param(in));
192  Ptr<Image<double> > temp2 = in2;
193 
194  double sigma;
195 
196  // NB: right now, the cutoff is done with gaussian filtering
197  // A more correct version would use a (yet unimplemented) FFT
198  // to do the actual bandwith cutoff.
199 
200  const double SIGMA_FACTOR = 0.3;
201 
202  if (newDim.getX() < in2->getX())
203  {
204  sigma = sqrt(SQUARE(in2->getX()/newDim.getX())-1)*SIGMA_FACTOR;
205  recursiveFilteringAlongSingleAxis(temp2, temp, sigma, 0, 0);
206  std::swap(temp, temp2);
207  }
208  if (newDim.getY() < in2->getY())
209  {
210  sigma = sqrt(SQUARE(in2->getY()/newDim.getY())-1)*SIGMA_FACTOR;
211  recursiveFilteringAlongSingleAxis(temp2, temp, sigma, 1, 0);
212  std::swap(temp, temp2);
213  }
214  if (newDim.getZ() < in2->getZ())
215  {
216  sigma = sqrt(SQUARE(in2->getZ()/newDim.getZ())-1)*SIGMA_FACTOR;
217  recursiveFilteringAlongSingleAxis(temp2, temp, sigma, 2, 0);
218  std::swap(temp, temp2);
219  }
220 
221  return resample<Interpolation, double>(temp2, newDim);
222 }
223 
224 */
225 
226 
227 } // namespace
228 
229 
230 #endif
231 
A trait class to assign iterators to image types.
boost::enable_if_c< is_Image< TImage1 >::value &&is_Image< TImage2 >::value >::type notSameImageCheck(const TImage1 &im1, const TImage2 &im2)
Definition: imageTools.h:108
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
ScalingMap< double > getScalingBetween(const TImage1 &from, const TImage2 &to)
Computes the mapping that transforms im1 into im2, assuming that they cover exactly the same volume i...
General macros, definitions and functions.
Small miscellaneous utility functions for images.
This file contains forward declarations of classes defined in the TIL library.
INLINE void allocationCheck(const TImage &im)
Check whether smart pointer and image are allocated.
Definition: imageTools.h:42
INLINE bool isAllocated(const TImage &im)
Check whether smart pointer and image are allocated.
Definition: imageTools.h:36
enable_if< is_Mapping< Mapping > >::type resample(const TImageIn &in, TImageOut &out, const Mapping &map)