36 #ifndef VIGRA_AFFINE_REGISTRATION_HXX
37 #define VIGRA_AFFINE_REGISTRATION_HXX
39 #include "mathutil.hxx"
41 #include "linear_solve.hxx"
42 #include "tinyvector.hxx"
43 #include "splineimageview.hxx"
44 #include "imagecontainer.hxx"
45 #include "multi_shape.hxx"
46 #include "affinegeometry.hxx"
71 template <
class SrcIterator,
class DestIterator>
72 linalg::TemporaryMatrix<double>
77 linalg::TemporaryMatrix<double> ret(identityMatrix<double>(3));
81 ret(0,2) = (*d)[0] - (*s)[0];
82 ret(1,2) = (*d)[1] - (*s)[1];
86 Matrix<double> m(4,4), r(4,1), so(4,1);
88 for(
int k=0; k<size; ++k, ++s, ++d)
100 r(2*k+1,0) = (*d)[1];
104 vigra_fail(
"affineMatrix2DFromCorrespondingPoints(): singular solution matrix.");
115 Matrix<double> m(3,3), rx(3,1), sx(3,1), ry(3,1), sy(3,1), c(3,1);
117 for(
int k=0; k<size; ++k, ++s, ++d)
128 vigra_fail(
"affineMatrix2DFromCorrespondingPoints(): singular solution matrix.");
147 template <
int SPLINEORDER = 2>
151 double burt_filter_strength;
152 int highest_level, iterations_per_level;
153 bool use_laplacian_pyramid;
156 : burt_filter_strength(0.4),
158 iterations_per_level(4),
159 use_laplacian_pyramid(
false)
164 : burt_filter_strength(other.burt_filter_strength),
165 highest_level(other.highest_level),
166 iterations_per_level(other.iterations_per_level),
167 use_laplacian_pyramid(other.use_laplacian_pyramid)
180 template <
int NEWORDER>
199 vigra_precondition(0.25 <= center && center <= 0.5,
200 "AffineMotionEstimationOptions::burtFilterCenterStrength(): center must be between 0.25 and 0.5 (inclusive).");
201 burt_filter_strength = center;
214 highest_level = (int)level;
224 vigra_precondition(0 < iter,
225 "AffineMotionEstimationOptions::iterationsPerLevel(): must do at least one iteration per level.");
226 iterations_per_level = (int)iter;
239 use_laplacian_pyramid = !f;
252 use_laplacian_pyramid = f;
259 struct TranslationEstimationFunctor
261 template <
class SplineImage,
class Image>
262 void operator()(SplineImage
const & src, Image
const & dest, Matrix<double> & matrix)
const
264 int w = dest.width();
265 int h = dest.height();
267 Matrix<double> grad(2,1), m(2,2), r(2,1), s(2,1);
268 double dx = matrix(0,0), dy = matrix(1,0);
270 for(
int y = 0; y < h; ++y)
272 double sx = matrix(0,1)*y + matrix(0,2);
273 double sy = matrix(1,1)*y + matrix(1,2);
274 for(
int x = 0; x < w; ++x, sx += dx, sy += dy)
276 if(!src.isInside(sx, sy))
279 grad(0,0) = src.dx(sx, sy);
280 grad(1,0) = src.dy(sx, sy);
281 double diff = dest(x, y) - src(sx, sy);
290 matrix(0,2) -= s(0,0);
291 matrix(1,2) -= s(1,0);
295 struct SimilarityTransformEstimationFunctor
297 template <
class SplineImage,
class Image>
298 void operator()(SplineImage
const & src, Image
const & dest, Matrix<double> & matrix)
const
300 int w = dest.width();
301 int h = dest.height();
303 Matrix<double> grad(2,1), coord(4, 2), c(4, 1), m(4, 4), r(4,1), s(4,1);
306 double dx = matrix(0,0), dy = matrix(1,0);
308 for(
int y = 0; y < h; ++y)
310 double sx = matrix(0,1)*y + matrix(0,2);
311 double sy = matrix(1,1)*y + matrix(1,2);
312 for(
int x = 0; x < w; ++x, sx += dx, sy += dy)
314 if(!src.isInside(sx, sy))
317 grad(0,0) = src.dx(sx, sy);
318 grad(1,0) = src.dy(sx, sy);
319 coord(2,0) = (double)x;
320 coord(3,1) = (double)x;
321 coord(3,0) = -(double)y;
322 coord(2,1) = (double)y;
323 double diff = dest(x, y) - src(sx, sy);
333 matrix(0,2) -= s(0,0);
334 matrix(1,2) -= s(1,0);
335 matrix(0,0) -= s(2,0);
336 matrix(1,1) -= s(2,0);
337 matrix(0,1) += s(3,0);
338 matrix(1,0) -= s(3,0);
342 struct AffineTransformEstimationFunctor
344 template <
class SplineImage,
class Image>
345 void operator()(SplineImage
const & src, Image
const & dest, Matrix<double> & matrix)
const
347 int w = dest.width();
348 int h = dest.height();
350 Matrix<double> grad(2,1), coord(6, 2), c(6, 1), m(6,6), r(6,1), s(6,1);
353 double dx = matrix(0,0), dy = matrix(1,0);
355 for(
int y = 0; y < h; ++y)
357 double sx = matrix(0,1)*y + matrix(0,2);
358 double sy = matrix(1,1)*y + matrix(1,2);
359 for(
int x = 0; x < w; ++x, sx += dx, sy += dy)
361 if(!src.isInside(sx, sy))
364 grad(0,0) = src.dx(sx, sy);
365 grad(1,0) = src.dy(sx, sy);
366 coord(2,0) = (double)x;
367 coord(4,1) = (double)x;
368 coord(3,0) = (double)y;
369 coord(5,1) = (double)y;
370 double diff = dest(x, y) - src(sx, sy);
380 matrix(0,2) -= s(0,0);
381 matrix(1,2) -= s(1,0);
382 matrix(0,0) -= s(2,0);
383 matrix(0,1) -= s(3,0);
384 matrix(1,0) -= s(4,0);
385 matrix(1,1) -= s(5,0);
389 template <
class SrcIterator,
class SrcAccessor,
390 class DestIterator,
class DestAccessor,
391 int SPLINEORDER,
class Functor>
393 estimateAffineMotionImpl(SrcIterator sul, SrcIterator slr, SrcAccessor src,
394 DestIterator dul, DestIterator dlr, DestAccessor dest,
395 Matrix<double> & affineMatrix,
396 AffineMotionEstimationOptions<SPLINEORDER>
const & options,
399 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote STmpType;
400 typedef BasicImage<STmpType> STmpImage;
401 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote DTmpType;
402 typedef BasicImage<DTmpType> DTmpImage;
404 int toplevel = options.highest_level;
405 ImagePyramid<STmpImage> srcPyramid(0, toplevel, sul, slr, src);
406 ImagePyramid<DTmpImage> destPyramid(0, toplevel, dul, dlr, dest);
408 if(options.use_laplacian_pyramid)
419 Matrix<double> currentMatrix(affineMatrix(2,2) == 0.0
420 ? identityMatrix<double>(3)
422 currentMatrix(0,2) /= std::pow(2.0, toplevel);
423 currentMatrix(1,2) /= std::pow(2.0, toplevel);
425 for(
int level = toplevel; level >= 0; --level)
427 SplineImageView<SPLINEORDER, STmpType> sp(srcImageRange(srcPyramid[level]));
429 for(
int iter = 0; iter < options.iterations_per_level; ++iter)
431 motionModel(sp, destPyramid[level], currentMatrix);
436 currentMatrix(0,2) *= 2.0;
437 currentMatrix(1,2) *= 2.0;
441 affineMatrix = currentMatrix;
510 template <
class SrcIterator,
class SrcAccessor,
511 class DestIterator,
class DestAccessor,
515 DestIterator dul, DestIterator dlr, DestAccessor dest,
516 Matrix<double> & affineMatrix,
517 AffineMotionEstimationOptions<SPLINEORDER>
const & options)
519 detail::estimateAffineMotionImpl(sul, slr, src, dul, dlr, dest, affineMatrix,
520 options, detail::TranslationEstimationFunctor());
523 template <
class SrcIterator,
class SrcAccessor,
524 class DestIterator,
class DestAccessor>
527 DestIterator dul, DestIterator dlr, DestAccessor dest,
528 Matrix<double> & affineMatrix)
531 affineMatrix, AffineMotionEstimationOptions<>());
534 template <
class SrcIterator,
class SrcAccessor,
535 class DestIterator,
class DestAccessor,
539 triple<DestIterator, DestIterator, DestAccessor> dest,
540 Matrix<double> & affineMatrix,
541 AffineMotionEstimationOptions<SPLINEORDER>
const & options)
544 affineMatrix, options);
547 template <
class SrcIterator,
class SrcAccessor,
548 class DestIterator,
class DestAccessor>
551 triple<DestIterator, DestIterator, DestAccessor> dest,
552 Matrix<double> & affineMatrix)
555 affineMatrix, AffineMotionEstimationOptions<>());
558 template <
class T1,
class S1,
563 MultiArrayView<2, T2, S2> dest,
564 Matrix<double> & affineMatrix,
565 AffineMotionEstimationOptions<SPLINEORDER>
const & options)
568 affineMatrix, options);
571 template <
class T1,
class S1,
575 MultiArrayView<2, T2, S2> dest,
576 Matrix<double> & affineMatrix)
579 affineMatrix, AffineMotionEstimationOptions<>());
648 template <
class SrcIterator,
class SrcAccessor,
649 class DestIterator,
class DestAccessor,
653 DestIterator dul, DestIterator dlr, DestAccessor dest,
654 Matrix<double> & affineMatrix,
655 AffineMotionEstimationOptions<SPLINEORDER>
const & options)
657 detail::estimateAffineMotionImpl(sul, slr, src, dul, dlr, dest, affineMatrix,
658 options, detail::SimilarityTransformEstimationFunctor());
661 template <
class SrcIterator,
class SrcAccessor,
662 class DestIterator,
class DestAccessor>
665 DestIterator dul, DestIterator dlr, DestAccessor dest,
666 Matrix<double> & affineMatrix)
669 affineMatrix, AffineMotionEstimationOptions<>());
672 template <
class SrcIterator,
class SrcAccessor,
673 class DestIterator,
class DestAccessor,
677 triple<DestIterator, DestIterator, DestAccessor> dest,
678 Matrix<double> & affineMatrix,
679 AffineMotionEstimationOptions<SPLINEORDER>
const & options)
682 affineMatrix, options);
685 template <
class SrcIterator,
class SrcAccessor,
686 class DestIterator,
class DestAccessor>
689 triple<DestIterator, DestIterator, DestAccessor> dest,
690 Matrix<double> & affineMatrix)
693 affineMatrix, AffineMotionEstimationOptions<>());
696 template <
class T1,
class S1,
701 MultiArrayView<2, T2, S2> dest,
702 Matrix<double> & affineMatrix,
703 AffineMotionEstimationOptions<SPLINEORDER>
const & options)
706 affineMatrix, options);
709 template <
class T1,
class S1,
713 MultiArrayView<2, T2, S2> dest,
714 Matrix<double> & affineMatrix)
717 affineMatrix, AffineMotionEstimationOptions<>());
815 template <
class SrcIterator,
class SrcAccessor,
816 class DestIterator,
class DestAccessor,
820 DestIterator dul, DestIterator dlr, DestAccessor dest,
821 Matrix<double> & affineMatrix,
822 AffineMotionEstimationOptions<SPLINEORDER>
const & options)
824 detail::estimateAffineMotionImpl(sul, slr, src, dul, dlr, dest, affineMatrix,
825 options, detail::AffineTransformEstimationFunctor());
828 template <
class SrcIterator,
class SrcAccessor,
829 class DestIterator,
class DestAccessor>
832 DestIterator dul, DestIterator dlr, DestAccessor dest,
833 Matrix<double> & affineMatrix)
836 affineMatrix, AffineMotionEstimationOptions<>());
839 template <
class SrcIterator,
class SrcAccessor,
840 class DestIterator,
class DestAccessor,
844 triple<DestIterator, DestIterator, DestAccessor> dest,
845 Matrix<double> & affineMatrix,
846 AffineMotionEstimationOptions<SPLINEORDER>
const & options)
849 affineMatrix, options);
852 template <
class SrcIterator,
class SrcAccessor,
853 class DestIterator,
class DestAccessor>
856 triple<DestIterator, DestIterator, DestAccessor> dest,
857 Matrix<double> & affineMatrix)
860 affineMatrix, AffineMotionEstimationOptions<>());
863 template <
class T1,
class S1,
868 MultiArrayView<2, T2, S2> dest,
869 Matrix<double> & affineMatrix,
870 AffineMotionEstimationOptions<SPLINEORDER>
const & options)
872 vigra_precondition(src.shape() == dest.shape(),
873 "estimateAffineTransform(): shape mismatch between input and output.");
875 affineMatrix, options);
878 template <
class T1,
class S1,
882 MultiArrayView<2, T2, S2> dest,
883 Matrix<double> & affineMatrix)
885 vigra_precondition(src.shape() == dest.shape(),
886 "estimateAffineTransform(): shape mismatch between input and output.");
888 affineMatrix, AffineMotionEstimationOptions<>());
AffineMotionEstimationOptions & highestPyramidLevel(unsigned int level)
Define the highest level of the image pyramid.
Definition: affine_registration.hxx:212
AffineMotionEstimationOptions & useGaussianPyramid(bool f=true)
Base registration on a Gaussian pyramid.
Definition: affine_registration.hxx:237
AffineMotionEstimationOptions< NEWORDER > splineOrder() const
Change the spline order for intensity interpolation.
Definition: affine_registration.hxx:181
Option object for affine registration functions.
Definition: affine_registration.hxx:148
AffineMotionEstimationOptions & iterationsPerLevel(unsigned int iter)
Number of Gauss-Newton iterations per level.
Definition: affine_registration.hxx:222
AffineMotionEstimationOptions & burtFilterCenterStrength(double center)
Define amount of smoothing before subsampling to the next pyramid level.
Definition: affine_registration.hxx:197
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...
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
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:1459
AffineMotionEstimationOptions & useLaplacianPyramid(bool f=true)
Base registration on a Laplacian pyramid.
Definition: affine_registration.hxx:250
void pyramidReduceBurtLaplacian(ImagePyramid< Image, Alloc > &pyramid, int fromLevel, int toLevel, double centerValue=0.4)
Create a Laplacian pyramid.
Definition: resampling_convolution.hxx:1197
linalg::TemporaryMatrix< double > affineMatrix2DFromCorrespondingPoints(SrcIterator s, SrcIterator send, DestIterator d)
Create homogeneous matrix that maps corresponding points onto each other.
Definition: affine_registration.hxx:73