Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TextureTransformAffine.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #include <Base/Common/BIASpragmaStart.hh>
26 #include <Image/TextureTransformAffine.hh>
27 #include <MathAlgo/SVD.hh>
28 #include <iostream>
29 
30 using namespace std;
31 
32 
33 
34 #define MIN_DET 1e-6
35 
38 
39  Jac.newsize(6,6);
40  double * pD = Jac.GetData();
41 
42  const double a11 = P_[0];
43  const double a12 = P_[1];
44  const double a21 = P_[2];
45  const double a22 = P_[3];
46  const double tx = P_[4];
47  const double ty = P_[5];
48 
49 
50  const double det = a11*a22+a11+a22+1.0-a12*a21;
51  if (fabs(det)<MIN_DET) {
52  // we have one thousand/million times minification, degenerate case !
53  return -1;
54  }
55  const double detdet = det * det;
56 
57  *pD++ = -(a22+1.0)*(a22+1.0)/detdet;
58  *pD++ = (a22+1.0)/detdet*a21;
59  *pD++ = (a22+1.0)/detdet*a12;
60  *pD++ = -a12/detdet*a21;
61  *pD++ = 0;
62  *pD++ = 0;
63 
64  *pD++ = (a22+1.0)/detdet*a12;
65  *pD++ = -(a11*a22+a11+a22+1.0)/detdet;
66  *pD++ = -a12*a12/detdet;
67  *pD++ = a12/detdet*(a11+1.0);
68  *pD++ = 0;
69  *pD++ = 0;
70 
71  *pD++ = (a22+1.0)/detdet*a21;
72  *pD++ = -a21*a21/detdet;
73  *pD++ = -(a11*a22+a11+a22+1.0)/detdet;
74  *pD++ = a21/detdet*(a11+1.0);
75  *pD++ = 0;
76  *pD++ = 0;
77 
78  *pD++ = -a12/detdet*a21;
79  *pD++ = a21/detdet*(a11+1.0);
80  *pD++ = a12/detdet*(a11+1.0);
81  *pD++ = -(a11+1.0)*(a11+1.0)/detdet;
82  *pD++ = 0;
83  *pD++ = 0;
84 
85  *pD++ = (a22+1.0)*(tx*a22+tx-a12*ty)/detdet;
86  *pD++ = -(tx*a21*a22+tx*a21-ty*a11*a22-ty*a11-ty*a22-ty)/detdet;
87  *pD++ = -a12*(tx*a22+tx-a12*ty)/detdet;
88  *pD++ = a12*(tx*a21-ty*a11-ty)/detdet;
89  *pD++ = -(a22+1.0)/det;
90  *pD++ = a12/det;
91 
92  *pD++ = -a21*(tx*a22+tx-a12*ty)/detdet;
93  *pD++ = a21*(tx*a21-ty*a11-ty)/detdet;
94  *pD++ = (tx*a11*a22+tx*a11+tx*a22+tx-a12*ty*a11-a12*ty)/detdet;
95  *pD++ = -(a11+1.0)*(tx*a21-ty*a11-ty)/detdet;
96  *pD++ = a21/det;
97  *pD++ = -(a11+1.0)/det;
98 
99 
100  return 0;
101 }
102 
103 
104 
106 MapForward(const HomgPoint2D& src, HomgPoint2D& sink) const
107 {
108  sink[0] = src[0]*A_[0][0] + src[1]*A_[0][1] + tx_;
109  sink[1] = src[0]*A_[1][0] + src[1]*A_[1][1] + ty_;
110  sink[2] = 1;
111  return 0;
112 }
113 
115 MapBackward(const HomgPoint2D& sink, HomgPoint2D& src) const
116 {
117  src[0] = sink[0]*Ainv_[0][0] + sink[1]*Ainv_[0][1] + txinv_;
118  src[1] = sink[0]*Ainv_[1][0] + sink[1]*Ainv_[1][1] + tyinv_;
119  src[2] = 1;
120  return 0;
121 }
122 
123 
126 
127 
128  Jac.newsize(2,6);
129  Jac.SetZero();
130  Jac[0][0] = src[0]-origin_[0];
131  Jac[0][1] = src[1]-origin_[1];
132  Jac[0][4] = 1;
133  Jac[1][2] = src[0]-origin_[0];
134  Jac[1][3] = src[1]-origin_[1];
135  Jac[1][5] = 1;
136  return 0;
137 }
138 
141  Jac.newsize(2,6);
142  Jac.SetZero();
143  //cout<<"Jacobian evaluated at "<<sink<<endl;
144  const double c11 = P_[0];
145  const double c12 = P_[1];
146  const double c21 = P_[2];
147  const double c22 = P_[3];
148  const double c13 = P_[4];
149  const double c23 = P_[5];
150  const double det = c11*c22+c11+c22+1-c21*c12;
151  if (fabs(det)<MIN_DET) {
152  // det is too small to make sense
153  return -1;
154  }
155  const double detdet = det*det;
156  const double x = sink[0]-origin_[0]-P_[4];
157  const double y = sink[1]-origin_[1]-P_[5];
158  // cout<<"diff from transferred origin is "<<x<<";"<<y<<endl;
159  Jac[0][0] = -(c22+1)*(x*c22+x-c12*y+c12*c23-c13*c22-c13)/detdet;
160  Jac[0][1] = (x*c21*c22 + x*c21 - y*c11*c22 - y*c11 - y*c22 - y +
161  c23*c11*c22 + c23*c11 + c23*c22 + c23 - c13*c21*c22 -
162  c13*c21)/detdet;
163 
164  Jac[0][2] = c12*(x*c22+x-c12*y+c12*c23-c13*c22-c13)/detdet;
165  Jac[0][3] = -c12*(x*c21-y*c11-y+c23*c11+c23-c13*c21)/detdet;
166  Jac[0][4] = -(c22+1)/det;
167  Jac[0][5] = c12/det;
168 
169  Jac[1][0] = c21*(x*c22+x-c12*y+c12*c23-c13*c22-c13)/detdet;
170  Jac[1][1] = -c21*(x*c21-y*c11-y+c23*c11+c23-c13*c21)/detdet;
171  Jac[1][2] = -(x*c11*c22 + x*c11 + x*c22 + x -c12*y*c11 -c12*y -
172  c13*c11*c22 - c13*c11 - c13*c22 - c13 + c12*c23*c11
173  + c12*c23)/detdet;
174  Jac[1][3] = (c11+1)*(x*c21-y*c11-y+c23*c11+c23-c13*c21)/detdet;
175  Jac[1][4] = c21/det;
176  Jac[1][5] = -(c11+1)/det;
177 
178  return 0;
179 }
180 
183  BIASASSERT(p.Size()==6);
184 #ifdef BIAS_DEBUG
185  for (unsigned int i=0; i<6; i++) {
186  INFNANCHECK(p[i]);
187  }
188 #endif
189  P_ = p;
190  InterpretParameters(p, A_[0][0], A_[0][1], A_[1][0], A_[1][1], tx_, ty_);
191 
192  if (A_.Invert( Ainv_)!=0) {
193  BIASERR("Error inverting A_="<<A_<<" with det "<<A_.det());
194  Ainv_.SetZero();
195  }
196  txinv_ = -(Ainv_[0][0]*tx_ + Ainv_[0][1]*ty_);
197  tyinv_ = -(Ainv_[1][0]*tx_ + Ainv_[1][1]*ty_);
198 }
199 
200 
203 #ifdef BIAS_DEBUG
204  for (unsigned int i=0; i<6; i++) {
205  INFNANCHECK(deltaP[i]);
206  }
207 #endif
208  Matrix3x3<double> A1(MatrixZero), A2inv;
209  A1[2][2] = 1.0;
210  InterpretParameters(deltaP, A1[0][0], A1[0][1], A1[1][0], A1[1][1],
211  A1[0][2], A1[1][2]);
212  if (A1.GetInverse(A2inv)!=0) {
213  BIASERR("Error inverting warp "<<A1);
214  // try pseudoinverse
215  Matrix<double> m(A1); // convert to Matrix
216  SVD mysvd(m);
217  A2inv = mysvd.Invert();
218  }
219 
220  A1[0][0] = A_[0][0];
221  A1[0][1] = A_[0][1];
222  A1[0][2] = tx_;
223  A1[1][0] = A_[1][0];
224  A1[1][1] = A_[1][1];
225  A1[1][2] = ty_;
226 
227  A1 = A2inv * A1;
228 
229  Vector<double> p(6);
230  p[0] = A1[0][0] - 1.0;
231  p[1] = A1[0][1];
232  p[2] = A1[1][0];
233  p[3] = A1[1][1] - 1.0;
234  p[4] = A1[0][2] + (A1[0][0]-1.0)*origin_[0] + A1[0][1]*origin_[1];
235  p[5] = A1[1][2] + A1[1][0]*origin_[0] + (A1[1][1]-1.0)*origin_[1];
236  SetParameters(p);
237 }
238 
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Definition: SVD.hh:92
int ParameterJacobianForward(Matrix< double > &Jac, const HomgPoint2D &src)
transformed position change when parameters change
int ParameterJacobianBackward(Matrix< double > &Jac, const HomgPoint2D &sink)
transformed position change when parameters change
Matrix< T > & newsize(Subscript M, Subscript N)
Definition: cmat.h:269
int MapBackward(const HomgPoint2D &sink, HomgPoint2D &src) const
map a point in image &quot;source&quot; to a point in image &quot;sink&quot;
unsigned int Size() const
length of the vector
Definition: Vector.hh:143
int MapForward(const HomgPoint2D &src, HomgPoint2D &sink) const
map a point in image &quot;source&quot; to a point in image &quot;sink&quot;
void SetZero()
Sets all values to zero.
Definition: Matrix.hh:856
T * GetData()
get the pointer to the data array of the matrix (for faster direct memeory access) ...
Definition: Matrix.hh:185
void ComposeWithInverseDeltaP(const Vector< double > &deltaP)
concatenate *this and an inverse transform with param deltaP and save new parameter vector to *this...
Matrix< double > Invert()
returns pseudoinverse of A = U * S * V^T A^+ = V * S^+ * U^T
Definition: SVD.cpp:214
int ParameterInversionJacobian(Matrix< double > &Jac) const
compute parameters for inverse operation and obtain the jacobian of the inverse parameters with respe...
void SetParameters(const Vector< double > &p)
a11-1, a12, a21, a22-1, dx, dy