[ 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 "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 */
vigra::MultiArrayView::shape
const difference_type & shape() const
Definition: multi_array.hxx:1551
vigra
Definition: accessor.hxx:43
vigra::estimateSimilarityTransform
void estimateSimilarityTransform(...)
Estimate the optical flow between two images according to a similarity transform model (e...
vigra::estimateAffineTransform
void estimateAffineTransform(...)
Estimate the optical flow between two images according to an affine transform model (e...
vigra::estimateTranslation
void estimateTranslation(...)
Estimate the optical flow between two images according to a translation model.
vigra::pyramidReduceBurtFilter
void pyramidReduceBurtFilter(...)
Two-fold down-sampling for image pyramid construction.
vigra::linalg::outer
void outer(const MultiArrayView< 2, T, C1 > &x, const MultiArrayView< 2, T, C2 > &y, MultiArrayView< 2, T, C3 > &r)
Definition: matrix.hxx:1457
vigra::BasicImage
Fundamental class template for images.
Definition: basicimage.hxx:473
vigra::MultiArrayView
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:655
vigra::pyramidReduceBurtLaplacian
void pyramidReduceBurtLaplacian(ImagePyramid< Image, Alloc > &pyramid, int fromLevel, int toLevel, double centerValue=0.4)
Create a Laplacian pyramid.
Definition: resampling_convolution.hxx:1154
vigra::SplineImageView
Create a continuous view onto a discrete image using splines.
Definition: splineimageview.hxx:99
vigra::ImagePyramid
Class template for logarithmically tapering image pyramids.
Definition: imagecontainer.hxx:465
vigra::linalg::linearSolve
bool linearSolve(...)
vigra::affineMatrix2DFromCorrespondingPoints
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