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

projective_registration.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 2007-2014 by Benjamin Seppke */
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_PROJECTIVE_REGISTRATION_HXX
37 #define VIGRA_PROJECTIVE_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
45 namespace vigra
46 {
47
48 /** \addtogroup Registration Image Registration
49 */
50 //@{
51
52 /********************************************************/
53 /* */
54 /* projectiveMatrix2DFromCorrespondingPoints */
55 /* */
56 /********************************************************/
57
58 /** \brief Create homogeneous matrix that maps corresponding points onto each other.
59
60 For use with \ref projectiveWarpImage(). Since four corresponding points are needed to be given,
61 the matrix will compute a full projective transform.
62 */
63 template <class SrcPointIterator, class DestPointIterator>
64 linalg::TemporaryMatrix<double>
65 projectiveMatrix2DFromCorrespondingPoints(SrcPointIterator s, SrcPointIterator send, DestPointIterator d)
66 {
67 //Calculate the matrix using least squares of all points of points like the result is:
68 // ( x2 ) ( s_x r1 t_x ) ( x1 )
69 // ( y2 ) = ( r2 s_y t_y ) * ( y1 )
70 // ( 1 ) ( p1 p2 1 ) ( 1 )
71 int size = send - s;
72
73 vigra_assert(size >= 4,
74 "projectiveMatrix2DFromCorrespondingPoints(): need at least four corresponding points.");
75
76 vigra::Matrix<double> A(2*size,8, 0.0), b(2*size,1), res(8,1);
77 for (int i =0; i<size; ++i, ++s, ++d)
78 {
79 //m_00 m_01 m_02 m_10 m_11 m_12 m_20 m_21
80 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
81 A(i,0)=(*d)[0]; A(i,1)=(*d)[1]; A(i,2)=1; A(i,3)=0; A(i,4)=0; A(i,5)=0; A(i,6)=-1*((*d)[0])*((*s)[0]); A(i,7)=-1*((*d)[1])*((*s)[0]);
82 b(i,0)=(*s)[0];
83
84 A(size+i,0)=0; A(size+i,1)=0; A(size+i,2)=0; A(size+i,3)=(*d)[0]; A(size+i,4)=(*d)[1]; A(size+i,5)=1; A(size+i,6)=-1*((*d)[0])*((*s)[1]); A(size+i,7)=-1*((*d)[1])*((*s)[1]);
85 b(size+i,0)=(*s)[1];
86
87 }
88
89 vigra_assert(linearSolve(A, b, res),
90 "projectiveMatrix2DFromCorrespondingPoints(): singular solution matrix.");
91
92 linalg::TemporaryMatrix<double> projectiveMat(3,3);
93 projectiveMat(0,0) = res(0,0); projectiveMat(0,1) = res(1,0); projectiveMat(0,2) = res(2,0);
94 projectiveMat(1,0) = res(3,0); projectiveMat(1,1) = res(4,0); projectiveMat(1,2) = res(5,0);
95 projectiveMat(2,0) = res(6,0); projectiveMat(2,1) = res(7,0); projectiveMat(2,2) = 1;
96
97 return projectiveMat;
98 }
99
100 /********************************************************/
101 /* */
102 /* projectiveWarpImage */
103 /* */
104 /********************************************************/
105
106 /** \brief Warp an image according to an projective transformation.
107
108 The matrix can be computed from a set of correspondung points
109 using \ref projectiveMatrix2DFromCorrespondingPoints().
110
111 <b> Declarations:</b>
112
113 <b>\#include</b> <vigra/projective_registration.hxx><br>
114 Namespace: vigra
115
116 pass 2D array views:
117 \code
118 namespace vigra {
119 template <int ORDER, class T,
120 class T2, class S2,
121 class C>
122 void
123 projectiveWarpImage(SplineImageView<ORDER, T> const & src,
124 MultiArrayView<2, T2, S2> dest,
125 MultiArrayView<2, double, C> const & projectiveMatrix);
126 }
127 \endcode
128
129 \deprecatedAPI{projectiveWarpImage}
130 pass \ref ImageIterators and \ref DataAccessors :
131
132 pass arguments explicitly:
133 \code
134 namespace vigra {
135 template <int ORDER, class T,
136 class DestIterator, class DestAccessor,
137 class C>
138 void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
139 DestIterator dul, DestIterator dlr, DestAccessor dest,
140 MultiArrayView<2, double, C> const & projectiveMatrix);
141 }
142 \endcode
143
144 use argument objects in conjunction with \ref ArgumentObjectFactories :
145 \code
146 namespace vigra {
147 template <int ORDER, class T,
148 class DestIterator, class DestAccessor,
149 class C>
150 void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
151 triple<DestIterator, DestIterator, DestAccessor> dest,
152 MultiArrayView<2, double, C> const & projectiveMatrix);
153 }
154 \endcode
155 \deprecatedEnd
156
157 The algorithm applies the given \a projectiveMatrix to the <i>destination coordinates</i> and copies
158 the image value from the resulting source coordinates, using the given SplineImageView \a src for interpolation.
159 If the resulting coordinate is outside the source image, nothing will be written at that destination point.
160
161 \code
162 for all dest pixels:
163 currentSrcCoordinate = projectiveMatrix * currentDestCoordinate;
164 if src.isInside(currentSrcCoordinate):
165 dest[currentDestCoordinate] = src[currentSrcCoordinate]; // copy an interpolated value
166 \endcode
167
168 The matrix represent a 2-dimensional projective transform by means of homogeneous coordinates,
169 i.e. it must be a 3x3 matrix whose last row is (p1,p2,1).
170
171 <b> Required Interface:</b>
172
173 \code
174 DestImageIterator dest_upperleft;
175
176 double x = ..., y = ...;
177
178 if (spline.isInside(x,y))
179 dest_accessor.set(spline(x, y), dest_upperleft);
180
181 \endcode
182
183 <b>See also:</b> Functions to specify projective transformation: \ref translationMatrix2D(), \ref scalingMatrix2D(),
184 \ref shearMatrix2D(), \ref rotationMatrix2DRadians(), \ref rotationMatrix2DDegrees() and \ref projectiveMatrix2DFromCorrespondingPoints()
185 */
186 doxygen_overloaded_function(template <...> void projectiveWarpImage)
187
188 template <int ORDER, class T,
189 class DestIterator, class DestAccessor,
190 class C>
191 void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
192 DestIterator dul, DestIterator dlr, DestAccessor dest,
193 MultiArrayView<2, double, C> const & projectiveMatrix)
194 {
195 vigra_precondition(rowCount(projectiveMatrix) == 3 && columnCount(projectiveMatrix) == 3 && projectiveMatrix(2,2) == 1.0,
196 "projectiveWarpImage(): matrix doesn't represent an projective transformation with homogeneous 2D coordinates.");
197
198
199 double w = dlr.x - dul.x;
200 double h = dlr.y - dul.y;
201
202 for(double y = 0.0; y < h; ++y, ++dul.y)
203 {
204 typename DestIterator::row_iterator rd = dul.rowIterator();
205 for(double x=0.0; x < w; ++x, ++rd)
206 {
207 double fac = 1.0/(x*projectiveMatrix(2,0) + y*projectiveMatrix(2,1) + 1);
208 double sx = (x*projectiveMatrix(0,0) + y*projectiveMatrix(0,1) + projectiveMatrix(0,2)) * fac;
209 double sy = (x*projectiveMatrix(1,0) + y*projectiveMatrix(1,1) + projectiveMatrix(1,2)) * fac;
210 if(src.isInside(sx, sy))
211 dest.set(src(sx, sy), rd);
212 }
213 }
214 }
215
216 template <int ORDER, class T,
217 class DestIterator, class DestAccessor,
218 class C>
219 inline
220 void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
221 triple<DestIterator, DestIterator, DestAccessor> dest,
222 MultiArrayView<2, double, C> const & projectiveMatrix)
223 {
224 projectiveWarpImage(src, dest.first, dest.second, dest.third, projectiveMatrix);
225 }
226
227
228 template <int ORDER, class T,
229 class T2, class S2,
230 class C>
231 inline
232 void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
233 MultiArrayView<2, T2, S2> dest,
234 MultiArrayView<2, double, C> const & projectiveMatrix)
235 {
236 projectiveWarpImage(src, destImageRange(dest), projectiveMatrix);
237 }
238
239
240 //@}
241
242 } // namespace vigra
243
244
245 #endif /* VIGRA_PROJECTIVE_REGISTRATION_HXX */
vigra::linalg::rowCount
MultiArrayIndex rowCount(const MultiArrayView< 2, T, C > &x)
Definition: matrix.hxx:669
vigra::linalg::Matrix
Definition: matrix.hxx:121
vigra
Definition: accessor.hxx:43
vigra::projectiveWarpImage
void projectiveWarpImage(...)
Warp an image according to an projective transformation.
vigra::doxygen_overloaded_function
doxygen_overloaded_function(template<... > void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
vigra::SplineImageView::isInside
bool isInside(double x, double y) const
Definition: splineimageview.hxx:487
vigra::projectiveMatrix2DFromCorrespondingPoints
linalg::TemporaryMatrix< double > projectiveMatrix2DFromCorrespondingPoints(SrcPointIterator s, SrcPointIterator send, DestPointIterator d)
Create homogeneous matrix that maps corresponding points onto each other.
Definition: projective_registration.hxx:65
vigra::linalg::columnCount
MultiArrayIndex columnCount(const MultiArrayView< 2, T, C > &x)
Definition: matrix.hxx:682
vigra::MultiArrayView
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:652
vigra::SplineImageView
Create a continuous view onto a discrete image using splines.
Definition: splineimageview.hxx:99
vigra::linalg::linearSolve
bool linearSolve(...)

© 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.11.0