bazar  1.3.1
homography.cpp
Go to the documentation of this file.
1 /*
2 Copyright 2005, 2006 Computer Vision Lab,
3 Ecole Polytechnique Federale de Lausanne (EPFL), Switzerland.
4 All rights reserved.
5 
6 This file is part of BazAR.
7 
8 BazAR is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2 of the License, or (at your option) any later
11 version.
12 
13 BazAR is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 BazAR; if not, write to the Free Software Foundation, Inc., 51 Franklin
19 Street, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21 #include <iostream>
22 #include <float.h>
23 #include <math.h>
24 
25 #include <math/robust_estimators.h>
26 #include <general/general.h>
27 #include "affinity.h"
28 #include "homography.h"
29 
30 using namespace std;
31 
32 
34 {
35  initialize();
36 }
37 
38 homography::homography(float u1, float v1, float up1, float vp1,
39  float u2, float v2, float up2, float vp2,
40  float u3, float v3, float up3, float vp3,
41  float u4, float v4, float up4, float vp4)
42 {
43  initialize();
44 
45  estimate(u1, v1, up1, vp1,
46  u2, v2, up2, vp2,
47  u3, v3, up3, vp3,
48  u4, v4, up4, vp4);
49 }
50 
52 {
53  if (AA) cvReleaseMat(&AA);
54  if (B) cvReleaseMat(&AA);
55  if (X) cvReleaseMat(&AA);
56  if (AA_n) cvReleaseMat(&AA_n);
57  if (B_n) cvReleaseMat(&AA_n);
58  if (X_n) cvReleaseMat(&AA_n);
59  delete [] data.ptr;
60 }
61 
62 void homography::initialize(void)
63 {
64  AA = cvCreateMat(8, 8, CV_32FC1);
65  B = cvCreateMat(8, 1, CV_32FC1);
66  X = cvCreateMat(8, 1, CV_32FC1);
67 
68  AA_n = NULL;
69  B_n = NULL;
70  X_n = NULL;
71  match_number = 0;
72  actual_match_number = 0;
73 
74 
75  type = CV_32FC1;
76 
77  type = CV_MAT_MAGIC_VAL | CV_MAT_CONT_FLAG | CV_MAT_TYPE(type);
78  cols = 3;
79  rows = 3;
80  step = cols * CV_ELEM_SIZE(type);
81  data.ptr = (uchar*)new float[cols * rows];
82  refcount = NULL;
83 }
84 
85 ostream& operator<< (ostream& o, const homography& H)
86 {
87  o << cvmGet(&H, 0, 0) << "\t" << cvmGet(&H, 0, 1) << "\t" << cvmGet(&H, 0, 2) << endl;
88  o << cvmGet(&H, 1, 0) << "\t" << cvmGet(&H, 1, 1) << "\t" << cvmGet(&H, 1, 2) << endl;
89  o << cvmGet(&H, 2, 0) << "\t" << cvmGet(&H, 2, 1) << "\t" << cvmGet(&H, 2, 2) << endl;
90 
91  return o;
92 }
93 
94 void homography::add_match(CvMat * pAA, CvMat * pB, int point_index,
95  float u, float v, float up, float vp)
96 {
97  int row = point_index * 2;
98 
99  ::cvmSet(pAA, row, 0, 0);
100  ::cvmSet(pAA, row, 1, 0);
101  ::cvmSet(pAA, row, 2, 0);
102  ::cvmSet(pAA, row, 3, -u);
103  ::cvmSet(pAA, row, 4, -v);
104  ::cvmSet(pAA, row, 5, -1);
105  ::cvmSet(pAA, row, 6, u * vp);
106  ::cvmSet(pAA, row, 7, v * vp);
107 
108  ::cvmSet(pB, row, 0, -vp);
109 
110  row++;
111 
112  ::cvmSet(pAA, row, 0, u);
113  ::cvmSet(pAA, row, 1, v);
114  ::cvmSet(pAA, row, 2, 1);
115  ::cvmSet(pAA, row, 3, 0);
116  ::cvmSet(pAA, row, 4, 0);
117  ::cvmSet(pAA, row, 5, 0);
118  ::cvmSet(pAA, row, 6, -u * up);
119  ::cvmSet(pAA, row, 7, -v * up);
120 
121  ::cvmSet(pB, row, 0, up);
122 }
123 
124 bool homography::estimate(float u1, float v1, float up1, float vp1,
125  float u2, float v2, float up2, float vp2,
126  float u3, float v3, float up3, float vp3,
127  float u4, float v4, float up4, float vp4)
128 {
129  add_match(AA, B, 0, u1, v1, up1, vp1);
130  add_match(AA, B, 1, u2, v2, up2, vp2);
131  add_match(AA, B, 2, u3, v3, up3, vp3);
132  add_match(AA, B, 3, u4, v4, up4, vp4);
133 
134  int ok = cvSolve(AA, B, X, CV_SVD);
135 
136  if (ok != 1)
137  {
138  cerr << "homography::estimate: cvSolve failure" << endl;
139  return false;
140  }
141 
142  cvmSet(0, 0, ::cvmGet(X, 0, 0));
143  cvmSet(0, 1, ::cvmGet(X, 1, 0));
144  cvmSet(0, 2, ::cvmGet(X, 2, 0));
145 
146  cvmSet(1, 0, ::cvmGet(X, 3, 0));
147  cvmSet(1, 1, ::cvmGet(X, 4, 0));
148  cvmSet(1, 2, ::cvmGet(X, 5, 0));
149 
150  cvmSet(2, 0, ::cvmGet(X, 6, 0));
151  cvmSet(2, 1, ::cvmGet(X, 7, 0));
152  cvmSet(2, 2, 1.);
153 
154  return true;
155 }
156 
157 void homography::transform_point(float u, float v, float * up, float * vp)
158 {
159  float k = float(1. / (cvmGet(2, 0) * u + cvmGet(2, 1) * v + cvmGet(2, 2)));
160 
161  *up = float(k * (cvmGet(0, 0) * u + cvmGet(0, 1) * v + cvmGet(0, 2)));
162  *vp = float(k * (cvmGet(1, 0) * u + cvmGet(1, 1) * v + cvmGet(1, 2)));
163 }
164 
165 void homography::transform_point(double u, double v, double * up, double * vp)
166 {
167  float k = float(1. / (cvmGet(2, 0) * u + cvmGet(2, 1) * v + cvmGet(2, 2)));
168 
169  *up = k * (cvmGet(0, 0) * u + cvmGet(0, 1) * v + cvmGet(0, 2));
170  *vp = k * (cvmGet(1, 0) * u + cvmGet(1, 1) * v + cvmGet(1, 2));
171 }
172 
173 
175 {
176  if (n == 0)
177  return;
178 
179  match_number = n;
180  actual_match_number = 0;
181 
182  if (AA_n != NULL)
183  release_matches();
184 
185  AA_n = cvCreateMat(2 * match_number, 8, CV_32FC1);
186  X_n = cvCreateMat(8, 1, CV_32FC1);
187  B_n = cvCreateMat(2 * match_number, 1, CV_32FC1);
188 }
189 
191 {
192  cvReleaseMat(&AA_n);
193  cvReleaseMat(&B_n);
194  cvReleaseMat(&X_n);
195 }
196 
197 void homography::add_match(float u, float v, float up, float vp)
198 {
199  add_match(AA_n, B_n, actual_match_number, u, v, up, vp);
200  actual_match_number++;
201 }
202 
204 {
205  if (match_number != actual_match_number)
206  {
207  cerr << "error when calling estimate_linear_method: not enough given matches." << endl;
208  return;
209  }
210 
211  int ok = cvSolve(AA_n, B_n, X_n, CV_SVD);
212 
213  if (ok != 1)
214  {
215  cerr << "homography::estimate: cvSolve failure" << endl;
216  return;
217  }
218 
219  cvmSet(0, 0, ::cvmGet(X_n, 0, 0));
220  cvmSet(0, 1, ::cvmGet(X_n, 1, 0));
221  cvmSet(0, 2, ::cvmGet(X_n, 2, 0));
222 
223  cvmSet(1, 0, ::cvmGet(X_n, 3, 0));
224  cvmSet(1, 1, ::cvmGet(X_n, 4, 0));
225  cvmSet(1, 2, ::cvmGet(X_n, 5, 0));
226 
227  cvmSet(2, 0, ::cvmGet(X_n, 6, 0));
228  cvmSet(2, 1, ::cvmGet(X_n, 7, 0));
229  cvmSet(2, 2, 1.);
230 }