Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
InvestigateEpipoleEstimation.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003, 2004 (see file CONTACTS 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 /**
26  @example InvestigateEpipoleEstimation.cpp
27  @relates EpipoleEstimation
28  @brief example investigating epipole estimation
29  @ingroup g_examples
30  @author MIP
31 */
32 
33 #include "bias_config.h"
34 #include "Geometry/EpipoleEstimation.hh"
35 #include "Base/Math/Random.hh"
36 #include "Base/Geometry/KMatrix.hh"
37 #include "Base/Geometry/RMatrixBase.hh"
38 #include "Geometry/FMatrix.hh"
39 #include "Geometry/PMatrix.hh"
40 #include "Base/Debug/TimeMeasure.hh"
41 
42 #include <iostream>
43 #include <iomanip>
44 
45 #define EPIPOLE_FACTOR 15.0
46 #define BACK 0
47 #define LINE 70
48 #define MATCH 255
49 
50 using namespace BIAS;
51 using namespace std;
52 
53 // minor noise in camera position
55 BIAS::KMatrix K, Kinv;
56 BIAS::HomgPoint2D true_epipole, estimated_epipole, estimated_epipole2, center;
57 vector<BIAS::HomgPoint2D> match1, match2;
58 
59 void CreateMatches2(vector<HomgPoint2D>& match1, vector<HomgPoint2D>& match2,
60  unsigned int match_count, unsigned int width,
61  unsigned int height, double spatial_noise_sigma,
62  double r_ang)
63 {
64  PMatrix P1, P2;
65  RMatrixBase R1, R2;
66  HomgPoint3D C1, C2;
67  KMatrix K;
68  K.SetIdentity();
69  K[0][0]=K[1][1]=840.0;
70  K[0][2]=(width-1.0)/2.0;
71  K[1][2]=(height-1.0)/2.0;
72  R1.SetIdentity();
73  R2.SetXYZ(r_ang, 0.0, 0.0);
74  C1.Set(0.0, 0.0, 0.0);
75  // movement 45 deg to camera plane
76  // for about 45 centimeter
77  C2.Set(0.3, 0.0, 0.3);
78 
79  P1.Compose(K, R1, C1);
80  P2.Compose(K, R2, C2);
81 
82  vector<PMatrix> pvec;
83  pvec.push_back(P1);
84  pvec.push_back(P2);
85  // cout << pvec[0] << "\n" << pvec[1] << endl;
86 
87  true_epipole = P2 * C1;
88  true_epipole.Homogenize();
89 
90  vector<vector<HomgPoint2D> > i_matches, n_matches;
91  vector<HomgPoint3D> p3d;
92 
93  CreateMatches(pvec, match_count, width, height, spatial_noise_sigma,
94  i_matches, n_matches, p3d, 2.0, -30.0, 30.0, -30.0, 30.0,
95  -30.0, 30.0, false);
96 
97  match1.resize(match_count);
98  match2.resize(match_count);
99  for (unsigned i=0; i<match_count; i++){
100  match1[i]=n_matches[i][0];
101  match2[i]=n_matches[i][1];
102  // cout << n_matches[i][0]<<"\t"<<n_matches[i][1]<<endl;
103  }
104  //cout << endl<<endl;
105 }
106 
107 void CreateMatches(vector<BIAS::HomgPoint2D>& match1,
108  vector<BIAS::HomgPoint2D>& match2,
109  unsigned int match_count, BIAS::HomgPoint2D epipole,
110  unsigned int width, unsigned int height,
111  double maxdisparity, double mindisparity,
112  double spatial_noise_sigma)
113 {
114  Random ran;
115  BIAS::HomgPoint2D p1, p2;
116  double dist, p1epipoledist;
117 
118 
119  match1.clear();
120  match2.clear();
121  p1[2]=p2[2]=1.0;
122  for (unsigned int i=0; i<match_count; i++){
123  do {
124  // create first point per random
125  p1[0]=ran.GetUniformDistributed(0.0, (double)width-1.0);
126  p1[1]=ran.GetUniformDistributed(0.0, (double)height-1.0);
127  // distance from epipole
128  p1epipoledist=sqrt((epipole[0]-p1[0])*(epipole[0]-p1[0])+
129  (epipole[1]-p1[1])*(epipole[1]-p1[1]));
130  do dist=ran.GetUniformDistributed(mindisparity, maxdisparity);
131  while (dist>=p1epipoledist);
132  //cout << p1epipoledist << " " << dist << endl;
133  p2[0]=p1[0]+(epipole[0]-p1[0])*dist/p1epipoledist
134  + ran.GetNormalDistributed(0.0, spatial_noise_sigma);
135  p2[1]=p1[1]+(epipole[1]-p1[1])*dist/p1epipoledist
136  + ran.GetNormalDistributed(0.0, spatial_noise_sigma);
137  // add some noise to camera orientation
138  p2=K*R*Kinv*p2;
139  p2.Homogenize();
140  } while (p2[0]<0.0 || p2[0]>(double)(width-1) ||
141  p2[1]<0.0 || p2[1]>(double)(height-1));
142  //cout << setw(4) << i << ":\t"<<p1 << "\t"<<p2 << endl;
143  match1.push_back(p1);
144  match2.push_back(p2);
145  }
146  //cout << endl;
147 }
148 
149 void AddErr(double& mean_ep_dist, double& mean_ang, double& mean_el_dist)
150 {
151  mean_ep_dist += estimated_epipole.Distance(true_epipole);
152 
153  HomgLine2D l1, l2;
154  vector<HomgPoint2D>::iterator it1, it2;
156  double ma=0.0, md=0.0;
157  int c=0;
158  E.SetAsCrossProductMatrix(true_epipole);
159  for (it1=match1.begin(), it2=match2.begin();
160  it1!=match1.end() && it2!=match2.end(); it1++, it2++, c++){
161  l1.Set(true_epipole, *it2);
162  l1.Homogenize();
163  l2.Set(estimated_epipole, *it2);
164  l2.Homogenize();
165  ma+=fabs(atan2(l1[1], l1[0])-atan2(l2[1], l2[0]));
166  md+=(*it1).ScalarProduct(E*(*it2));
167  }
168  mean_ang=ma/(double)c;
169  mean_el_dist=md/(double)c;
170 }
171 
172 int main(int argc, char *argv[])
173 {
174  ofstream os("errcp3.txt");
175  ofstream os2("errls3.txt");
176  Random ran;
177  double spatial_noise_sigma=0.0;
178  double max_disparity=50.0;
179  double mindisparity=2.0;
180  unsigned int match_count=80;
181  unsigned int width=640, height=480;
182  int count=100;
183  double mean_ep_dist_ls, mean_ep_dist_cp, mean_ang_ls, mean_ang_cp;
184  double mean_el_dist_ls, mean_el_dist_cp;
185  EpipoleEstimation ee;
186  TimeMeasure tc;
187  //double cf=1000/(2.4*1024*1024*1024);
188  //cerr <<cf<<endl;
189  center.Set(width/2, height/2);
190 
191  if (argc>=2) match_count=atoi(argv[1]);
192  if (argc>=3) spatial_noise_sigma=atof(argv[2]);
193 
194  K.Fill(0.0);
195  K[0][0]=K[1][1]=840.0;
196  K[0][2]=double(width)/2.0;
197  K[1][2]=double(height)/2.0;
198  K[2][2]=1.0;
199  Kinv=K.Invert();
200 
201  true_epipole[2]=1.0;
202  true_epipole[0]=
203  ran.GetUniformDistributed(-EPIPOLE_FACTOR*(double)width,
204  (EPIPOLE_FACTOR+1.0)*(double)width);
205  true_epipole[1]=ran.GetUniformDistributed(-EPIPOLE_FACTOR*(double)height,
206  EPIPOLE_FACTOR+1.0*(double)height);
207 
208  CreateMatches2(match1, match2, match_count, width, height,
209  spatial_noise_sigma, 0.0);
210 
211  os <<"# EpipoleEstimationCrossProduct\n"
212  <<"# true epipole: "<<true_epipole[0]<<" "<<true_epipole[1]
213  <<" "<<true_epipole[2]<<endl
214  <<"# "<<match_count<<" matches"
215  <<"\n# max disparity: "<<max_disparity
216  <<"\n# min disparity: "<<mindisparity<<endl;
217  os2 <<"# EpipoleEstimationCrossProduct\n"
218  <<"# true epipole: "<<true_epipole[0]<<" "<<true_epipole[1]
219  <<" "<<true_epipole[2]<<endl
220  <<"# "<<match_count<<" matches"
221  <<"\n# max disparity: "<<max_disparity
222  <<"\n# min disparity: "<<mindisparity<<endl;
223 
224  double err_r;
225 
226  for (spatial_noise_sigma=0.0; spatial_noise_sigma<1.05;
227  spatial_noise_sigma+=0.1){
228  os <<endl<<endl<<"# spatial noise: "<<spatial_noise_sigma
229  <<"\n# spat-nois\trot-err(DEG)\trot-err(RAD)\tabs-dist-err"
230  <<"\tabs-angle-err\tabs-el-dist-err\n";
231  os2 <<endl<<endl<<"# spatial noise: "<<spatial_noise_sigma
232  <<"\n# spat-nois\trot-err(DEG)\trot-err(RAD)\tabs-dist-err"
233  <<"\tabs-angle-err\tabs-el-dist-err\n";
234  for (err_r=1e-3; err_r<=0.5; err_r*=2.0){
235  mean_ep_dist_ls = mean_ep_dist_cp = mean_ang_ls = mean_ang_cp =
236  mean_el_dist_ls = mean_el_dist_cp = 0.0;
237  for (int c=0; c<count; c++){
238  CreateMatches2(match1, match2, match_count, width, height,
239  spatial_noise_sigma, err_r);
240 
241  if (ee.CrossProductLeastSquaresSVD(match1,match2,
242  estimated_epipole)!=0){
243  BIASERR("error estimating epipole");
244  return 0;
245  }
246  AddErr(mean_ep_dist_cp, mean_ang_cp, mean_el_dist_cp);
247 
248  if (ee.MatchLengthWeightedLeastSquares(match1, match2,
249  estimated_epipole)!=0){
250  BIASERR("error estimating epipole");
251  return 0;
252  }
253  AddErr(mean_ep_dist_ls, mean_ang_ls, mean_el_dist_ls);
254 
255  cout <<".";
256  cout.flush();
257  } // for (int c=0; c<count; c++){
258  mean_ep_dist_ls /= count;
259  mean_ep_dist_cp /= count;
260  mean_ang_ls /= count;
261  mean_ang_cp /= count;
262  mean_el_dist_ls /= count;
263  mean_el_dist_cp /= count;
264 
265  os2 <<setw(6)<<spatial_noise_sigma<< "\t"<< setw(6) << err_r/2/M_PI*360
266  << setw(12) << err_r << "\t" << setw(12)
267  <<mean_ep_dist_ls << "\t" << setw(12)
268  <<mean_ang_ls<<"\t"<<mean_el_dist_ls<<endl;
269 
270  os <<setw(6)<<spatial_noise_sigma<< "\t"<< setw(6) << err_r/2/M_PI*360
271  << setw(12) <<err_r << "\t" << setw(12)
272  <<mean_ep_dist_cp << "\t" << setw(12)
273  <<mean_ang_cp<<"\t"<<mean_el_dist_cp<<endl;
274 
275  cout <<endl;
276  cout <<setw(12)<<spatial_noise_sigma<<setw(12)<<err_r<<"\t"<<setw(12)
277  <<mean_ep_dist_ls
278  << "\t"<<setw(12)<<mean_ang_ls<<"\t"<<mean_el_dist_ls<<endl;
279  cout <<setw(12)<<spatial_noise_sigma<<setw(12)<<err_r<<"\t"<<setw(12)
280  <<mean_ep_dist_cp
281  << "\t"<<setw(12)<<mean_ang_cp<<"\t"<<mean_el_dist_cp<<endl;
282  }
283  }
284  os2.close();
285  os.close();
286  return 0;
287 }
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
void SetXYZ(ROTATION_MATRIX_TYPE PhiX, ROTATION_MATRIX_TYPE PhiY, ROTATION_MATRIX_TYPE PhiZ)
Set Euler angles (in rad) in order XYZ.
HOMGPOINT2D_TYPE Distance(const HomgPoint2D &point) const
Definition: HomgPoint2D.hh:367
void Set(const HOMGPOINT3D_TYPE &x, const HOMGPOINT3D_TYPE &y, const HOMGPOINT3D_TYPE &z)
set elementwise with given 3 euclidean scalar values.
Definition: HomgPoint3D.hh:321
HomgPoint2D & Homogenize()
homogenize class data member elements to W==1 by divison by W
Definition: HomgPoint2D.hh:215
double GetUniformDistributed(const double min, const double max)
on succesive calls return uniform distributed random variable between min and max ...
Definition: Random.hh:84
void Set(const HomgPoint2D &p1, const HomgPoint2D &p2)
constructing a line through two points
Definition: HomgLine2D.hh:131
a line l = (a b c)^T is a form of the implicit straight line equation 0 = a*x + b*y + c if homogenize...
Definition: HomgLine2D.hh:48
void Homogenize()
aequivalent to homogenize for points the gradient triangle is normed to hypothenuse length of 1 ...
Definition: HomgLine2D.hh:149
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
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
double GetNormalDistributed(const double mean, const double sigma)
on succesive calls return normal distributed random variable with mean and standard deviation sigma ...
Definition: Random.hh:71
describes a projective 3D -&gt; 2D mapping in homogenous coordinates
Definition: PMatrix.hh:88
void SetAsCrossProductMatrix(const Vector3< T > &vec)
Sets matrix from vector as cross product matrix of this vector.
Definition: Matrix3x3.cpp:275
KMatrix Invert() const
returns analyticaly inverted matrix
Definition: KMatrix.cpp:31
void Set(const HOMGPOINT2D_TYPE &x, const HOMGPOINT2D_TYPE &y)
set elementwise with given 2 euclidean scalar values.
Definition: HomgPoint2D.hh:174
class for producing random numbers from different distributions
Definition: Random.hh:51
class TimeMeasure contains functions for timing real time and cpu time.
Definition: TimeMeasure.hh:111
void Compose(const Matrix3x3< double > &K, const Matrix3x3< double > &R, const Vector3< double > &C)
composes this from K, R and C using P = [ K R&#39; | -K R&#39; C ] with R&#39; = transpose(R) ...
Definition: PMatrix.cpp:581
void SetIdentity()
set the elements of this matrix to the identity matrix (possibly overriding the inherited method) ...
Definition: Matrix3x3.hh:429