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

affine_registration.hxx VIGRA

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

© 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.10.0 (Fri Feb 21 2014)