Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Normalization.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 "Normalization.hh"
26 
27 #include <Base/Geometry/KMatrix.hh>
28 #include <Base/Geometry/RMatrixBase.hh>
29 #include <Base/Geometry/HomgPoint2D.hh>
30 #include <Base/Geometry/HomgPoint3D.hh>
31 #include <Base/Math/Matrix4x4.hh>
32 #include <Base/Debug/Debug.hh>
33 
34 using namespace BIAS;
35 using namespace std;
36 
37 
39 Hartley(const vector<HomgPoint3D>& Points, vector<HomgPoint3D>& NormPoints,
40  Matrix4x4<double> & normMatrix) const
41 {
42  normMatrix.SetIdentity();
43  const unsigned int uiPointCount(Points.size());
44  // we need at least two points for a stddev
45  if (uiPointCount<2) return -1;
46 
47  int result = 0;
48 
49  NormPoints.resize(uiPointCount);
50 
51  // compute mean
52  double meanX(0), meanY(0), meanZ(0);
53  for (unsigned int i=0; i<uiPointCount; i++) {
54  meanX += Points[i][0];
55  meanY += Points[i][1];
56  meanZ += Points[i][2];
57 #ifdef BIAS_DEBUG
58  if (Points[i][3]!=1.0) {
59  BIASERR("Supplied non-homogenized point ("<<i<<") ! "<<Points[i]);
60  BIASABORT;
61  }
62 #endif
63  }
64  meanX /= (double)uiPointCount;
65  meanY /= (double)uiPointCount;
66  meanZ /= (double)uiPointCount;
67 
68  // compute mean distance from center
69  double meandist(0);
70  for (unsigned int i=0; i<uiPointCount; i++) {
71  const BIAS::HomgPoint3D& CurPoint = Points[i];
72  meandist += sqrt((CurPoint[0]-meanX) * (CurPoint[0]-meanX) +
73  (CurPoint[1]-meanY) * (CurPoint[1]-meanY) +
74  (CurPoint[2]-meanZ) * (CurPoint[2]-meanZ));
75  }
76  meandist /= (double)uiPointCount;
77 
78  if (meandist>0.0) {
79  // compute Normalization such that mean is zero and mean distance is sqrt2
80  normMatrix[0][0] = M_SQRT2/meandist;
81  normMatrix[0][3] = -meanX/meandist;
82  normMatrix[1][1] = M_SQRT2/meandist;
83  normMatrix[1][3] = -meanY/meandist;
84 
85  normMatrix[2][2] = M_SQRT2/meandist;
86  normMatrix[2][3] = -meanZ/meandist;
87  } else {
88  // stddev is zero, all the same point !!!
89  result = -2;
90  }
91  HomgPoint3D p;
92  // now normalize all the points
93  for (unsigned int i=0; i<uiPointCount; i++) {
94  normMatrix.Mult(Points[i], p);
95  NormPoints[i]=p;
96  }
97  return result;
98 }
99 
100 
101 int Normalization::
102 Hartley(const vector<HomgPoint2D>& Points, vector<HomgPoint2D>& NormPoints,
103  KMatrix& Normalization) const
104 {
105  Normalization.SetIdentity();
106  const unsigned int uiPointCount(Points.size());
107  // we need at least two points for a stddev
108  if (uiPointCount<2) return -1;
109 
110  int result = 0;
111 
112  NormPoints.reserve(uiPointCount);
113 #ifdef BIAS_DEBUG
114  if (NormPoints.size()>0) {
115  BIASERR("non-empty vector supplied !");
116  BIASABORT;
117  }
118 #endif
119  // compute mean
120  double meanX(0), meanY(0);
121  for (unsigned int i=0; i<uiPointCount; i++) {
122  meanX += Points[i][0];
123  meanY += Points[i][1];
124 #ifdef BIAS_DEBUG
125  if (Points[i][2]!=1.0) {
126  BIASERR("Supplied non-homogenized point ("<<i<<") ! "<<Points[i]);
127  BIASABORT;
128  }
129 #endif
130  }
131  meanX /= (double)uiPointCount;
132  meanY /= (double)uiPointCount;
133 
134  // compute mean distance from center
135  double meandist(0);
136  for (unsigned int i=0; i<uiPointCount; i++) {
137  const BIAS::HomgPoint2D& CurPoint = Points[i];
138  meandist += sqrt((CurPoint[0]-meanX) * (CurPoint[0]-meanX) +
139  (CurPoint[1]-meanY) * (CurPoint[1]-meanY));
140  }
141  meandist /= (double)uiPointCount;
142 
143  if (meandist>0.0) {
144  // compute Normalization such that mean is zero and mean distance is sqrt2
145  Normalization[0][0] = M_SQRT2/meandist;
146  Normalization[0][2] = -meanX/meandist;
147  Normalization[1][1] = M_SQRT2/meandist;
148  Normalization[1][2] = -meanY/meandist;
149  } else {
150  // stddev is zero, all the same point !!!
151  result = -2;
152  }
153  HomgPoint2D p;
154  // now normalize all the points
155  for (unsigned int i=0; i<uiPointCount; i++) {
156  Normalization.Mult(Points[i], p);
157  NormPoints.push_back(p.Homogenize());
158  }
159  return result;
160 }
161 
162 int Normalization::
163 Woelk(const vector<HomgPoint2D>& Points,
164  vector<HomgPoint2D>& NormPoints,
166 {
167  const unsigned int uiPointCount(Points.size());
168  // we need at least two points for a stddev
169  if (uiPointCount<2) return -1;
170 
171  // compute mean
172  Vector3<double> mean(0.0);
173  for (unsigned int i=0; i<uiPointCount; i++) {
174  BIASASSERT(Equal(Points[i].NormL2(), 1.0));
175  mean += Points[i];
176  }
177  mean /= (double)uiPointCount;
178 
179  // compute rotation such that mean vector is (0, 0, 1)
180  BIASASSERT(!Equal(mean.NormL2(), 0.0));
181  Vector3<double> nmean = mean / mean.NormL2();
182  const Vector3<double> z(0.0, 0.0, 1.0);
183  Vector3<double> axis = nmean.CrossProduct(z);
184  double angle = axis.NormL2();
185  // rounding error guards
186  if (angle>=1.0) angle = 1.0;
187  if (angle<=-1.0) angle = -1.0;
188  if (Equal(angle, 0.0)){
189  axis.Set(0.0, 0.0, 1.0);
190  } else {
191  axis /= angle;
192  }
193  angle = asin(angle);
194  RMatrixBase R;
195  R.Set(axis, angle);
196 
197  //cout << "R * mean = "<<R*nmean<<endl;
198 
199  // compute mean angle to (0,0,1)
200  Vector3<double> diff;
201  double ang;
202  double meanang = 0.0;
203  double max_ang = 1.0;
204  for (unsigned int i=0; i<uiPointCount; i++) {
205  diff = R * Points[i];
206  ang = diff.ScalarProduct(z);
207  meanang += ang;
208  max_ang = min(ang, max_ang);
209  }
210  meanang /= (double)uiPointCount;
211  if (max_ang>=1.0) max_ang = 1.0;
212  if (max_ang<=-1.0) max_ang = -1.0;
213  max_ang = acos(max_ang);
214  //INFNANCKECK(max_ang);
215  //cout << "max angle: "<<max_ang/M_PI*180.0<<endl;
216  if (meanang>=1.0) meanang = 1.0;
217  if (meanang<=-1.0) meanang = -1.0;
218  meanang = acos(meanang);
219  //INFNANCKECK(meanang);
220  //cout << "mean angle: "<<meanang/M_PI*180.0<<endl;
221 
222  // the maximum allowed angle
223  const double ang_thresh = 1.4; // 80 deg
224  // the angular threshold represents a tradeoff between the
225  // accuracy of the rotation matrix and the accuracy of the
226  // epipole, when using the normalization for essential matrix
227  // estimation. (heuristically investigated)
228  // bigger angular threshold result in better estimation of the epipole
229  const double des_ang = 1.0; // 60 deg
230  //const double des_ang = .785375; // 45 deg
231  //const double des_ang = 1.3962; // 80 deg
233  // compute normalization such that the mean angle is des_ang
234  // and the maximum angle does not exceed ang_thresh
235  if (max_ang<ang_thresh && meanang<des_ang){
236  double des_scale = tan(des_ang) / tan(meanang);
237  //cout << "desired scale: "<<des_scale<<endl;
238  double max_scale = tan(ang_thresh) / tan(max_ang);
239  //cout << "max scale: "<<max_scale<<endl;
240  double scale = min(des_scale, max_scale);
241  //cout << "scale: "<<scale<<endl;
242  for (int i=0; i<2; i++){
243  K[i][i] = scale;
244  }
245  K[2][2] = 1.0;
246  }
247  Normalization = K * R;
248 
249  // now normalize all the points
250  NormPoints.resize(uiPointCount);
251  max_ang = 1.0;
252  for (unsigned int i=0; i<uiPointCount; i++) {
253  Normalization.Mult(Points[i], NormPoints[i]);
254  //BIASASSERT(!Equal(NormPoints[i].NormL2(), 0.0));
255  //NormPoints[i] /= NormPoints[i].NormL2();
256  //max_ang = min(max_ang, NormPoints[i].ScalarProduct(z));
257  }
258  //cout << "max angle after scaling: "<<acos(max_ang)*180.0/M_PI<<endl;
259  return 0;
260 }
261 #undef M_SQRT3
void Set(const T *pv)
copy the array of vectorsize beginning at *T to this-&gt;data_
Definition: Vector3.hh:532
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
void ScalarProduct(const Vector3< T > &argvec, T &result) const
scalar product (=inner product) of two vectors, storing the result in result
Definition: Vector3.hh:603
HomgPoint2D & Homogenize()
homogenize class data member elements to W==1 by divison by W
Definition: HomgPoint2D.hh:215
void Set(const Vector3< ROTATION_MATRIX_TYPE > &w, const ROTATION_MATRIX_TYPE phi)
Set from rotation axis w and angle phi (in rad)
void CrossProduct(const Vector3< T > &argvec, Vector3< T > &destvec) const
cross product of two vectors destvec = this x argvec
Definition: Vector3.hh:594
void Mult(const Vector3< T > &argvec, Vector3< T > &destvec) const
matrix - vector multiplicate this matrix with Vector3, storing the result in destvec calculates: dest...
Definition: Matrix3x3.hh:302
void Mult(const Vector4< T > &argvec, Vector4< T > &destvec) const
matrix - vector multiplicate this matrix with Vector4, storing the result in destvec, calculates: destvec = (this Matrix) * argvec
Definition: Matrix4x4.hh:121
class Normalization Functions, e.g.
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
int Hartley(const std::vector< HomgPoint2D > &Points, std::vector< HomgPoint2D > &NormPoints, KMatrix &Normalization) const
linearly transform Points with 3x3 matrix, such that they have mean zero and stddev sqrt(2) ...
bool Equal(const T left, const T right, const T eps)
comparison function for floating point values See http://www.boost.org/libs/test/doc/components/test_...
void SetIdentity()
set the elements of this matrix to the identity matrix (posisbly overriding the inherited method) ...
Definition: Matrix4x4.hh:260
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
Definition: KMatrix.hh:48
Implements a 3D rotation matrix.
Definition: RMatrixBase.hh:44
int Woelk(const std::vector< HomgPoint2D > &Points, std::vector< HomgPoint2D > &NormPoints, Matrix3x3< double > &Normalization) const
normalization for fisheye cameras wher points may have a w component = 0
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
Definition: Vector3.hh:633
void SetIdentity()
set the elements of this matrix to the identity matrix (possibly overriding the inherited method) ...
Definition: Matrix3x3.hh:429