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

affine_registration.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 2005-2006 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 #ifndef VIGRA_AFFINE_REGISTRATION_HXX
37 #define VIGRA_AFFINE_REGISTRATION_HXX
38 
39 #include "mathutil.hxx"
40 #include "matrix.hxx"
41 #include "linear_solve.hxx"
42 #include "tinyvector.hxx"
43 #include "splineimageview.hxx"
44 #include "imagecontainer.hxx"
45 #include <cmath>
46 
47 namespace vigra {
48 
49 /** \addtogroup Registration Image Registration
50 */
51 //@{
52 
53 /********************************************************/
54 /* */
55 /* affineMatrix2DFromCorrespondingPoints */
56 /* */
57 /********************************************************/
58 
59 /** \brief Create homogeneous matrix that maps corresponding points onto each other.
60 
61  For use with \ref affineWarpImage(). Since only two corresponding points are given,
62  the matrix will not use a full affine transform, but only a similarity transform
63  (translation, rotation, and uniform scaling). See \
64 */
65 template <class SrcIterator, class DestIterator>
66 linalg::TemporaryMatrix<double>
67 affineMatrix2DFromCorrespondingPoints(SrcIterator s, SrcIterator send, DestIterator d)
68 {
69  int size = send - s;
70 
71  linalg::TemporaryMatrix<double> ret(identityMatrix<double>(3));
72 
73  if(size == 1)
74  {
75  ret(0,2) = (*d)[0] - (*s)[0];
76  ret(1,2) = (*d)[1] - (*s)[1];
77  }
78  else if(size == 2)
79  {
80  Matrix<double> m(4,4), r(4,1), so(4,1);
81 
82  for(int k=0; k<size; ++k, ++s, ++d)
83  {
84  m(2*k,0) = (*s)[0];
85  m(2*k,1) = -(*s)[1];
86  m(2*k,2) = 1.0;
87  m(2*k,3) = 0.0;
88  r(2*k,0) = (*d)[0];
89 
90  m(2*k+1,0) = (*s)[1];
91  m(2*k+1,1) = (*s)[0];
92  m(2*k+1,2) = 0.0;
93  m(2*k+1,3) = 1.0;
94  r(2*k+1,0) = (*d)[1];
95  }
96 
97  if(!linearSolve(m, r, so))
98  vigra_fail("affineMatrix2DFromCorrespondingPoints(): singular solution matrix.");
99 
100  ret(0,0) = so(0,0);
101  ret(1,1) = so(0,0);
102  ret(0,1) = -so(1,0);
103  ret(1,0) = so(1,0);
104  ret(0,2) = so(2,0);
105  ret(1,2) = so(3,0);
106  }
107  else if(size >= 3)
108  {
109  Matrix<double> m(3,3), rx(3,1), sx(3,1), ry(3,1), sy(3,1), c(3,1);
110  c(2,0) = 1.0;
111  for(int k=0; k<size; ++k, ++s, ++d)
112  {
113  c(0,0) = (*s)[0];
114  c(1,0) = (*s)[1];
115 
116  m += outer(c);
117  rx += (*d)[0]*c;
118  ry += (*d)[1]*c;
119  }
120 
121  if(!linearSolve(m, rx, sx) || !linearSolve(m, ry, sy))
122  vigra_fail("affineMatrix2DFromCorrespondingPoints(): singular solution matrix.");
123 
124  ret(0,0) = sx(0,0);
125  ret(0,1) = sx(1,0);
126  ret(0,2) = sx(2,0);
127  ret(1,0) = sy(0,0);
128  ret(1,1) = sy(1,0);
129  ret(1,2) = sy(2,0);
130  }
131 
132  return ret;
133 }
134 
135 template <int SPLINEORDER = 2>
136 class AffineMotionEstimationOptions
137 {
138  public:
139  double burt_filter_strength;
140  int highest_level, iterations_per_level;
141  bool use_laplacian_pyramid;
142 
143  AffineMotionEstimationOptions()
144  : burt_filter_strength(0.4),
145  highest_level(4),
146  iterations_per_level(4),
147  use_laplacian_pyramid(false)
148  {}
149 
150  template <int ORDER>
151  AffineMotionEstimationOptions(AffineMotionEstimationOptions<ORDER> const & other)
152  : burt_filter_strength(other.burt_filter_strength),
153  highest_level(other.highest_level),
154  iterations_per_level(other.iterations_per_level),
155  use_laplacian_pyramid(other.use_laplacian_pyramid)
156  {}
157 
158  template <int NEWORDER>
159  AffineMotionEstimationOptions<NEWORDER> splineOrder() const
160  {
161  return AffineMotionEstimationOptions<NEWORDER>(*this);
162  }
163 
164  AffineMotionEstimationOptions & burtFilterStrength(double strength)
165  {
166  vigra_precondition(0.25 <= strength && strength <= 0.5,
167  "AffineMotionEstimationOptions::burtFilterStrength(): strength must be between 0.25 and 0.5 (inclusive).");
168  burt_filter_strength = strength;
169  return *this;
170  }
171 
172  AffineMotionEstimationOptions & highestPyramidLevel(unsigned int level)
173  {
174  highest_level = (int)level;
175  return *this;
176  }
177 
178  AffineMotionEstimationOptions & iterationsPerLevel(unsigned int iter)
179  {
180  vigra_precondition(0 < iter,
181  "AffineMotionEstimationOptions::iterationsPerLevel(): must do at least one iteration per level.");
182  iterations_per_level = (int)iter;
183  return *this;
184  }
185 
186  AffineMotionEstimationOptions & useGaussianPyramid(bool f = true)
187  {
188  use_laplacian_pyramid = !f;
189  return *this;
190  }
191 
192  AffineMotionEstimationOptions & useLaplacianPyramid(bool f = true)
193  {
194  use_laplacian_pyramid = f;
195  return *this;
196  }
197 };
198 
199 namespace detail {
200 
201 struct TranslationEstimationFunctor
202 {
203  template <class SplineImage, class Image>
204  void operator()(SplineImage const & src, Image const & dest, Matrix<double> & matrix) const
205  {
206  int w = dest.width();
207  int h = dest.height();
208 
209  Matrix<double> grad(2,1), m(2,2), r(2,1), s(2,1);
210  double dx = matrix(0,0), dy = matrix(1,0);
211 
212  for(int y = 0; y < h; ++y)
213  {
214  double sx = matrix(0,1)*y + matrix(0,2);
215  double sy = matrix(1,1)*y + matrix(1,2);
216  for(int x = 0; x < w; ++x, sx += dx, sy += dy)
217  {
218  if(!src.isInside(sx, sy))
219  continue;
220 
221  grad(0,0) = src.dx(sx, sy);
222  grad(1,0) = src.dy(sx, sy);
223  double diff = dest(x, y) - src(sx, sy);
224 
225  m += outer(grad);
226  r -= diff*grad;
227  }
228  }
229 
230  linearSolve(m, r, s);
231 
232  matrix(0,2) -= s(0,0);
233  matrix(1,2) -= s(1,0);
234  }
235 };
236 
237 struct SimilarityTransformEstimationFunctor
238 {
239  template <class SplineImage, class Image>
240  void operator()(SplineImage const & src, Image const & dest, Matrix<double> & matrix) const
241  {
242  int w = dest.width();
243  int h = dest.height();
244 
245  Matrix<double> grad(2,1), coord(4, 2), c(4, 1), m(4, 4), r(4,1), s(4,1);
246  coord(0,0) = 1.0;
247  coord(1,1) = 1.0;
248  double dx = matrix(0,0), dy = matrix(1,0);
249 
250  for(int y = 0; y < h; ++y)
251  {
252  double sx = matrix(0,1)*y + matrix(0,2);
253  double sy = matrix(1,1)*y + matrix(1,2);
254  for(int x = 0; x < w; ++x, sx += dx, sy += dy)
255  {
256  if(!src.isInside(sx, sy))
257  continue;
258 
259  grad(0,0) = src.dx(sx, sy);
260  grad(1,0) = src.dy(sx, sy);
261  coord(2,0) = (double)x;
262  coord(3,1) = (double)x;
263  coord(3,0) = -(double)y;
264  coord(2,1) = (double)y;
265  double diff = dest(x, y) - src(sx, sy);
266 
267  c = coord * grad;
268  m += outer(c);
269  r -= diff*c;
270  }
271  }
272 
273  linearSolve(m, r, s);
274 
275  matrix(0,2) -= s(0,0);
276  matrix(1,2) -= s(1,0);
277  matrix(0,0) -= s(2,0);
278  matrix(1,1) -= s(2,0);
279  matrix(0,1) += s(3,0);
280  matrix(1,0) -= s(3,0);
281  }
282 };
283 
284 struct AffineTransformEstimationFunctor
285 {
286  template <class SplineImage, class Image>
287  void operator()(SplineImage const & src, Image const & dest, Matrix<double> & matrix) const
288  {
289  int w = dest.width();
290  int h = dest.height();
291 
292  Matrix<double> grad(2,1), coord(6, 2), c(6, 1), m(6,6), r(6,1), s(6,1);
293  coord(0,0) = 1.0;
294  coord(1,1) = 1.0;
295  double dx = matrix(0,0), dy = matrix(1,0);
296 
297  for(int y = 0; y < h; ++y)
298  {
299  double sx = matrix(0,1)*y + matrix(0,2);
300  double sy = matrix(1,1)*y + matrix(1,2);
301  for(int x = 0; x < w; ++x, sx += dx, sy += dy)
302  {
303  if(!src.isInside(sx, sy))
304  continue;
305 
306  grad(0,0) = src.dx(sx, sy);
307  grad(1,0) = src.dy(sx, sy);
308  coord(2,0) = (double)x;
309  coord(4,1) = (double)x;
310  coord(3,0) = (double)y;
311  coord(5,1) = (double)y;
312  double diff = dest(x, y) - src(sx, sy);
313 
314  c = coord * grad;
315  m += outer(c);
316  r -= diff*c;
317  }
318  }
319 
320  linearSolve(m, r, s);
321 
322  matrix(0,2) -= s(0,0);
323  matrix(1,2) -= s(1,0);
324  matrix(0,0) -= s(2,0);
325  matrix(0,1) -= s(3,0);
326  matrix(1,0) -= s(4,0);
327  matrix(1,1) -= s(5,0);
328  }
329 };
330 
331 template <class SrcIterator, class SrcAccessor,
332  class DestIterator, class DestAccessor,
333  int SPLINEORDER, class Functor>
334 void
335 estimateAffineMotionImpl(SrcIterator sul, SrcIterator slr, SrcAccessor src,
336  DestIterator dul, DestIterator dlr, DestAccessor dest,
337  Matrix<double> & affineMatrix,
338  AffineMotionEstimationOptions<SPLINEORDER> const & options,
339  Functor motionModel)
340 {
341  typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote STmpType;
342  typedef BasicImage<STmpType> STmpImage;
343  typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote DTmpType;
344  typedef BasicImage<DTmpType> DTmpImage;
345 
346  int toplevel = options.highest_level;
347  ImagePyramid<STmpImage> srcPyramid(0, toplevel, sul, slr, src);
348  ImagePyramid<DTmpImage> destPyramid(0, toplevel, dul, dlr, dest);
349 
350  if(options.use_laplacian_pyramid)
351  {
352  pyramidReduceBurtLaplacian(srcPyramid, 0, toplevel, options.burt_filter_strength);
353  pyramidReduceBurtLaplacian(destPyramid, 0, toplevel, options.burt_filter_strength);
354  }
355  else
356  {
357  pyramidReduceBurtFilter(srcPyramid, 0, toplevel, options.burt_filter_strength);
358  pyramidReduceBurtFilter(destPyramid, 0, toplevel, options.burt_filter_strength);
359  }
360 
361  Matrix<double> currentMatrix(affineMatrix(2,2) == 0.0
362  ? identityMatrix<double>(3)
363  : affineMatrix);
364  currentMatrix(0,2) /= std::pow(2.0, toplevel);
365  currentMatrix(1,2) /= std::pow(2.0, toplevel);
366 
367  for(int level = toplevel; level >= 0; --level)
368  {
369  SplineImageView<SPLINEORDER, STmpType> sp(srcImageRange(srcPyramid[level]));
370 
371  for(int iter = 0; iter < options.iterations_per_level; ++iter)
372  {
373  motionModel(sp, destPyramid[level], currentMatrix);
374  }
375 
376  if(level > 0)
377  {
378  currentMatrix(0,2) *= 2.0;
379  currentMatrix(1,2) *= 2.0;
380  }
381  }
382 
383  affineMatrix = currentMatrix;
384 }
385 
386 } // namespace detail
387 
388 /********************************************************/
389 /* */
390 /* estimateTranslation */
391 /* */
392 /********************************************************/
393 
394 /** \brief Estimate the optical flow between two images according to a translation model.
395 
396  Sorry, no \ref detailedDocumentation() available yet.
397 
398  <b> Declarations:</b>
399 
400  <b>\#include</b> <vigra/affine_registration.hxx><br>
401  Namespace: vigra
402 
403  pass arguments explicitly:
404  \code
405  namespace vigra {
406  template <class SrcIterator, class SrcAccessor,
407  class DestIterator, class DestAccessor,
408  int SPLINEORDER = 2>
409  void
410  estimateTranslation(SrcIterator sul, SrcIterator slr, SrcAccessor src,
411  DestIterator dul, DestIterator dlr, DestAccessor dest,
412  Matrix<double> & affineMatrix,
413  AffineMotionEstimationOptions<SPLINEORDER> const & options =
414  AffineMotionEstimationOptions<>())
415  }
416  \endcode
417 
418 
419  use argument objects in conjunction with \ref ArgumentObjectFactories :
420  \code
421  namespace vigra {
422  template <class SrcIterator, class SrcAccessor,
423  class DestIterator, class DestAccessor,
424  int SPLINEORDER = 2>
425  void
426  estimateTranslation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
427  triple<DestIterator, DestIterator, DestAccessor> dest,
428  Matrix<double> & affineMatrix,
429  AffineMotionEstimationOptions<SPLINEORDER> const & options =
430  AffineMotionEstimationOptions<>())
431  }
432  \endcode
433 */
434 doxygen_overloaded_function(template <...> void estimateTranslation)
435 
436 template <class SrcIterator, class SrcAccessor,
437  class DestIterator, class DestAccessor,
438  int SPLINEORDER>
439 inline void
440 estimateTranslation(SrcIterator sul, SrcIterator slr, SrcAccessor src,
441  DestIterator dul, DestIterator dlr, DestAccessor dest,
442  Matrix<double> & affineMatrix,
443  AffineMotionEstimationOptions<SPLINEORDER> const & options)
444 {
445  detail::estimateAffineMotionImpl(sul, slr, src, dul, dlr, dest, affineMatrix,
446  options, detail::TranslationEstimationFunctor());
447 }
448 
449 template <class SrcIterator, class SrcAccessor,
450  class DestIterator, class DestAccessor>
451 inline void
452 estimateTranslation(SrcIterator sul, SrcIterator slr, SrcAccessor src,
453  DestIterator dul, DestIterator dlr, DestAccessor dest,
454  Matrix<double> & affineMatrix)
455 {
456  estimateTranslation(sul, slr, src, dul, dlr, dest,
457  affineMatrix, AffineMotionEstimationOptions<>());
458 }
459 
460 template <class SrcIterator, class SrcAccessor,
461  class DestIterator, class DestAccessor,
462  int SPLINEORDER>
463 inline void
464 estimateTranslation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
465  triple<DestIterator, DestIterator, DestAccessor> dest,
466  Matrix<double> & affineMatrix,
467  AffineMotionEstimationOptions<SPLINEORDER> const & options)
468 {
469  estimateTranslation(src.first, src.second, src.third, dest.first, dest.second, dest.third,
470  affineMatrix, options);
471 }
472 
473 template <class SrcIterator, class SrcAccessor,
474  class DestIterator, class DestAccessor>
475 inline void
476 estimateTranslation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
477  triple<DestIterator, DestIterator, DestAccessor> dest,
478  Matrix<double> & affineMatrix)
479 {
480  estimateTranslation(src.first, src.second, src.third, dest.first, dest.second, dest.third,
481  affineMatrix, AffineMotionEstimationOptions<>());
482 }
483 
484 /********************************************************/
485 /* */
486 /* estimateSimilarityTransform */
487 /* */
488 /********************************************************/
489 
490 /** \brief Estimate the optical flow between two images according to a similarity transform model
491  (e.g. translation, rotation, and uniform scaling).
492 
493  Sorry, no \ref detailedDocumentation() available yet.
494 
495  <b> Declarations:</b>
496 
497  <b>\#include</b> <vigra/affine_registration.hxx><br>
498  Namespace: vigra
499 
500  pass arguments explicitly:
501  \code
502  namespace vigra {
503  template <class SrcIterator, class SrcAccessor,
504  class DestIterator, class DestAccessor,
505  int SPLINEORDER = 2>
506  void
507  estimateSimilarityTransform(SrcIterator sul, SrcIterator slr, SrcAccessor src,
508  DestIterator dul, DestIterator dlr, DestAccessor dest,
509  Matrix<double> & affineMatrix,
510  AffineMotionEstimationOptions<SPLINEORDER> const & options =
511  AffineMotionEstimationOptions<>())
512  }
513  \endcode
514 
515 
516  use argument objects in conjunction with \ref ArgumentObjectFactories :
517  \code
518  namespace vigra {
519  template <class SrcIterator, class SrcAccessor,
520  class DestIterator, class DestAccessor,
521  int SPLINEORDER = 2>
522  void
523  estimateSimilarityTransform(triple<SrcIterator, SrcIterator, SrcAccessor> src,
524  triple<DestIterator, DestIterator, DestAccessor> dest,
525  Matrix<double> & affineMatrix,
526  AffineMotionEstimationOptions<SPLINEORDER> const & options =
527  AffineMotionEstimationOptions<>())
528  }
529  \endcode
530 */
531 doxygen_overloaded_function(template <...> void estimateSimilarityTransform)
532 
533 template <class SrcIterator, class SrcAccessor,
534  class DestIterator, class DestAccessor,
535  int SPLINEORDER>
536 inline void
537 estimateSimilarityTransform(SrcIterator sul, SrcIterator slr, SrcAccessor src,
538  DestIterator dul, DestIterator dlr, DestAccessor dest,
539  Matrix<double> & affineMatrix,
540  AffineMotionEstimationOptions<SPLINEORDER> const & options)
541 {
542  detail::estimateAffineMotionImpl(sul, slr, src, dul, dlr, dest, affineMatrix,
543  options, detail::SimilarityTransformEstimationFunctor());
544 }
545 
546 template <class SrcIterator, class SrcAccessor,
547  class DestIterator, class DestAccessor>
548 inline void
549 estimateSimilarityTransform(SrcIterator sul, SrcIterator slr, SrcAccessor src,
550  DestIterator dul, DestIterator dlr, DestAccessor dest,
551  Matrix<double> & affineMatrix)
552 {
553  estimateSimilarityTransform(sul, slr, src, dul, dlr, dest,
554  affineMatrix, AffineMotionEstimationOptions<>());
555 }
556 
557 template <class SrcIterator, class SrcAccessor,
558  class DestIterator, class DestAccessor,
559  int SPLINEORDER>
560 inline void
561 estimateSimilarityTransform(triple<SrcIterator, SrcIterator, SrcAccessor> src,
562  triple<DestIterator, DestIterator, DestAccessor> dest,
563  Matrix<double> & affineMatrix,
564  AffineMotionEstimationOptions<SPLINEORDER> const & options)
565 {
566  estimateSimilarityTransform(src.first, src.second, src.third, dest.first, dest.second, dest.third,
567  affineMatrix, options);
568 }
569 
570 template <class SrcIterator, class SrcAccessor,
571  class DestIterator, class DestAccessor>
572 inline void
573 estimateSimilarityTransform(triple<SrcIterator, SrcIterator, SrcAccessor> src,
574  triple<DestIterator, DestIterator, DestAccessor> dest,
575  Matrix<double> & affineMatrix)
576 {
577  estimateSimilarityTransform(src.first, src.second, src.third, dest.first, dest.second, dest.third,
578  affineMatrix, AffineMotionEstimationOptions<>());
579 }
580 
581 /********************************************************/
582 /* */
583 /* estimateAffineTransform */
584 /* */
585 /********************************************************/
586 
587 /** \brief Estimate the optical flow between two images according to an affine transform model
588  (e.g. translation, rotation, non-uniform scaling, and shearing).
589 
590  Sorry, no \ref detailedDocumentation() available yet.
591 
592  <b> Declarations:</b>
593 
594  <b>\#include</b> <vigra/affine_registration.hxx><br>
595  Namespace: vigra
596 
597  pass arguments explicitly:
598  \code
599  namespace vigra {
600  template <class SrcIterator, class SrcAccessor,
601  class DestIterator, class DestAccessor,
602  int SPLINEORDER = 2>
603  void
604  estimateAffineTransform(SrcIterator sul, SrcIterator slr, SrcAccessor src,
605  DestIterator dul, DestIterator dlr, DestAccessor dest,
606  Matrix<double> & affineMatrix,
607  AffineMotionEstimationOptions<SPLINEORDER> const & options =
608  AffineMotionEstimationOptions<>())
609  }
610  \endcode
611 
612 
613  use argument objects in conjunction with \ref ArgumentObjectFactories :
614  \code
615  namespace vigra {
616  template <class SrcIterator, class SrcAccessor,
617  class DestIterator, class DestAccessor,
618  int SPLINEORDER = 2>
619  void
620  estimateAffineTransform(triple<SrcIterator, SrcIterator, SrcAccessor> src,
621  triple<DestIterator, DestIterator, DestAccessor> dest,
622  Matrix<double> & affineMatrix,
623  AffineMotionEstimationOptions<SPLINEORDER> const & options =
624  AffineMotionEstimationOptions<>())
625  }
626  \endcode
627 */
628 doxygen_overloaded_function(template <...> void estimateAffineTransform)
629 
630 template <class SrcIterator, class SrcAccessor,
631  class DestIterator, class DestAccessor,
632  int SPLINEORDER>
633 inline void
634 estimateAffineTransform(SrcIterator sul, SrcIterator slr, SrcAccessor src,
635  DestIterator dul, DestIterator dlr, DestAccessor dest,
636  Matrix<double> & affineMatrix,
637  AffineMotionEstimationOptions<SPLINEORDER> const & options)
638 {
639  detail::estimateAffineMotionImpl(sul, slr, src, dul, dlr, dest, affineMatrix,
640  options, detail::AffineTransformEstimationFunctor());
641 }
642 
643 template <class SrcIterator, class SrcAccessor,
644  class DestIterator, class DestAccessor>
645 inline void
646 estimateAffineTransform(SrcIterator sul, SrcIterator slr, SrcAccessor src,
647  DestIterator dul, DestIterator dlr, DestAccessor dest,
648  Matrix<double> & affineMatrix)
649 {
650  estimateAffineTransform(sul, slr, src, dul, dlr, dest,
651  affineMatrix, AffineMotionEstimationOptions<>());
652 }
653 
654 template <class SrcIterator, class SrcAccessor,
655  class DestIterator, class DestAccessor,
656  int SPLINEORDER>
657 inline void
658 estimateAffineTransform(triple<SrcIterator, SrcIterator, SrcAccessor> src,
659  triple<DestIterator, DestIterator, DestAccessor> dest,
660  Matrix<double> & affineMatrix,
661  AffineMotionEstimationOptions<SPLINEORDER> const & options)
662 {
663  estimateAffineTransform(src.first, src.second, src.third, dest.first, dest.second, dest.third,
664  affineMatrix, options);
665 }
666 
667 template <class SrcIterator, class SrcAccessor,
668  class DestIterator, class DestAccessor>
669 inline void
670 estimateAffineTransform(triple<SrcIterator, SrcIterator, SrcAccessor> src,
671  triple<DestIterator, DestIterator, DestAccessor> dest,
672  Matrix<double> & affineMatrix)
673 {
674  estimateAffineTransform(src.first, src.second, src.third, dest.first, dest.second, dest.third,
675  affineMatrix, AffineMotionEstimationOptions<>());
676 }
677 
678 //@}
679 
680 } // namespace vigra
681 
682 
683 #endif /* VIGRA_AFFINE_REGISTRATION_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.8.0 (Wed Sep 26 2012)