1 #include "HMatrixEstimation.hh"
3 #include <MathAlgo/SVD.hh>
4 #include <MathAlgo/Lapack.hh>
5 #include <Base/Geometry/KMatrix.hh>
6 #include "Parametrization.hh"
7 #include "MathAlgo/Minpack.hh"
16 vector<double> params;
18 for (
unsigned int i = 0; i < 8; i++) params.push_back(x[i]);
31 const unsigned int uiDataSize = 4*pCurrentObjectH->
pointsFrom_.size();
32 const vector<BIAS::HomgPoint2D> &p1 = pCurrentObjectH->
pointsFrom_;
33 const vector<BIAS::HomgPoint2D> &p2 = pCurrentObjectH->
pointsTo_;
36 for (
unsigned int j = 0; j < uiDataSize; j+=4) {
39 fvec[j] = ep1[0]-p1[j/4][0];
40 fvec[j+1] = ep1[1]-p1[j/4][1];
43 fvec[j+2] = ep2[0]-p2[j/4][0];
44 fvec[j+3] = ep2[1]-p2[j/4][1];
45 errorsum += (ep1-p1[j/4]).NormL2() +(ep2-p2[j/4]).NormL2();
53 const std::vector<BIAS::HomgPoint2D> &p2)
55 BIASASSERT(p1.size() == p2.size());
57 BIASERR(
"At least 5 points correspondences are needed for homography optimization!");
58 return HE_NOT_ENOUGH_POINTS;
66 vector<double> vecHParamsStart, vecHParamsResult;
70 for (
unsigned int i = 0; i < 8; i++)
71 HParamsStart[i] = vecHParamsStart[i];
73 HParamsStart, HParamsResult,
74 MINPACK_DEF_TOLERANCE);
76 BIASERR(
"Error in Levenberg-Marquardt optimization of homography!");
80 vecHParamsResult.resize(8);
81 for (
unsigned int i=0; i<8; i++) vecHParamsResult[i] = HParamsResult[i];
92 Compute(
const vector<BIAS::HomgPoint2D>& points1,
93 const vector<BIAS::HomgPoint2D>& points2,
HMatrix& H)
96 BIASASSERT(points1.size() == points2.size());
97 if (points1.size() < 4) {
98 BIASERR(
"At least 4 points correspondences are needed for homography estimation!");
99 return HE_NOT_ENOUGH_POINTS;
101 pointsFrom_ = points1;
104 const std::vector<BIAS::HomgPoint2D> *pp1 = &points1;
105 const std::vector<BIAS::HomgPoint2D> *pp2 = &points2;
106 std::vector<BIAS::HomgPoint2D> p1norm;
107 std::vector<BIAS::HomgPoint2D> p2norm;
109 if (normalizeHartley_) {
110 normalization_.Hartley(points1, p1norm, K1);
111 normalization_.Hartley(points2, p2norm, K2);
120 register unsigned int p=0, p2=0;
121 for (p=0, p2=0; p<2*(*pp1).size(); p+=2, p2++){
123 A[p][0] = A[p][1] = A[p][2] = 0.0;
124 A[p+1][3] = A[p+1][4] = A[p+1][5] = 0.0;
126 A[p+1][0] = (*pp2)[p2][2] * (*pp1)[p2][0];
127 A[p+1][1] = (*pp2)[p2][2] * (*pp1)[p2][1];
128 A[p+1][2] = (*pp2)[p2][2] * (*pp1)[p2][2];
130 A[p][3] = - A[p+1][0];
131 A[p][4] = - A[p+1][1];
132 A[p][5] = - A[p+1][2];
134 A[p][6] = (*pp2)[p2][1] * (*pp1)[p2][0];
135 A[p][7] = (*pp2)[p2][1] * (*pp1)[p2][1];
136 A[p][8] = (*pp2)[p2][1] * (*pp1)[p2][2];
138 A[p+1][6] = - (*pp2)[p2][0] * (*pp1)[p2][0];
139 A[p+1][7] = - (*pp2)[p2][0] * (*pp1)[p2][1];
140 A[p+1][8] = - (*pp2)[p2][0] * (*pp1)[p2][2];
154 if (normalizeHartley_) H = K2.
Invert() * H * K1;
163 const vector<BIAS::HomgPoint2D>& points2,
HMatrix& H)
170 BIASASSERT(points1.size() == points2.size());
172 pointsFrom_ = points1;
176 const std::vector<BIAS::HomgPoint2D> *pp1 = &points1;
177 const std::vector<BIAS::HomgPoint2D> *pp2 = &points2;
178 std::vector<BIAS::HomgPoint2D> p1norm;
179 std::vector<BIAS::HomgPoint2D> p2norm;
181 if (normalizeHartley_) {
182 normalization_.Hartley(points1, p1norm, K1);
183 normalization_.Hartley(points2, p2norm, K2);
194 const unsigned int nummeas = 2*(*pp1).size();
195 for (
register unsigned int p=0, p2=0; p<nummeas; p+=2, p2++){
196 A[p][3] = -(A[p+1][0] = (*pp2)[p2][2] * (*pp1)[p2][0]);
197 A[p][4] = -(A[p+1][1] = (*pp2)[p2][2] * (*pp1)[p2][1]);
198 A[p][5] = -(A[p+1][2] = (*pp2)[p2][2] * (*pp1)[p2][2]);
200 A[p][6] = (*pp2)[p2][1] * (*pp1)[p2][2];
201 A[p+1][6] = - (*pp2)[p2][0] * (*pp1)[p2][2];
209 const HMATRIX_TYPE normalization = 1.0 / VT[6][6];
210 HMATRIX_TYPE* pHData = H.
GetData();
211 for (
int p = 0; p < 6; p++){
212 *pHData++ = VT[6][p] * normalization;
220 if (normalizeHartley_) H = K2.
Invert() * H * K1;
231 BIASASSERT(fromPoint.size() == toPoints.size());
232 vector<BIAS::HomgPoint2D> fromPointHomg(fromPoint.size());
233 vector<BIAS::HomgPoint2D> toPointsHomg(toPoints.size());
234 for (
unsigned int i = 0; i < fromPoint.size(); i++) {
235 fromPointHomg[i][0]= fromPoint[i][0];
236 fromPointHomg[i][1]= fromPoint[i][1];
237 fromPointHomg[i][2]= 1.0;
238 toPointsHomg[i][0]= toPoints[i][0];
239 toPointsHomg[i][1]= toPoints[i][1];
240 toPointsHomg[i][2]= 1.0;
242 return Compute(fromPointHomg, toPointsHomg, H);
249 for (
unsigned int c = 0; c < pointsFrom_.size(); c++) {
250 mapped = H_ * pointsFrom_[c];
252 mapped -= pointsTo_[c];
253 err += mapped[0]*mapped[0] + mapped[1]*mapped[1];
255 err /= (double)pointsFrom_.
size();
int ComputeAffine(const std::vector< BIAS::HomgPoint2D > &fromPoints, const std::vector< BIAS::HomgPoint2D > &toPoints, HMatrix &H)
Compute affine transformation between 2d points, i.e.
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
a 3x3 Matrix describing projective transformations between planes
double GetError() const
Returns the average squared error of the estimation applying the estimated homography matrix to all c...
This class is used for parametrizing F- and H-matrices, generally for optimization purposes...
HomgPoint2D & Homogenize()
homogenize class data member elements to W==1 by divison by W
std::vector< BIAS::HomgPoint2D > pointsFrom_
Stores the points in image 1 (used in Optimize and GetError)
int Optimize(BIAS::HMatrix &H, const std::vector< BIAS::HomgPoint2D > &p1, const std::vector< BIAS::HomgPoint2D > &p2)
Optimize a given homography matrix from 2d point correspondences.
static int HErrorFunction_(void *p, int m, int n, const double *x, double *fvec, int iflag)
Objective function for Levenberg-Marquardt optimization.
int GetInverse(Matrix3x3< T > &inv) const
Matrix inversion: inverts this and stores resulty in argument inv.
bool HMatrixToParams(const BIAS::HMatrix &Mat, std::vector< double > &Params)
parametizes an H-matrix to eight parameters
int Compute(const std::vector< BIAS::HomgPoint2D > &fromPoints, const std::vector< BIAS::HomgPoint2D > &toPoints, HMatrix &H)
Calculate homography between 2d points using the DLT.
long int LevenbergMarquardt(minpack_funcder_mn fun, void *p, long int m, long int n, Vector< double > &InitialGuess, Vector< double > &Result, double Tolerance)
Solves an overdetermined system f(x) = 0 of m non-linear equations with n parameters using the Levenb...
std::vector< BIAS::HomgPoint2D > pointsTo_
Stores the points in image 2 (used in Optimize and GetError)
int General_singular_value_decomposition(char jobu, char jobvt, const BIAS::Matrix< double > &A, BIAS::Vector< double > &ret_S, BIAS::Matrix< double > &ret_U, BIAS::Matrix< double > &ret_VT)
solve general eigenproblem.
Estimate 3x3 matrix relating image coordinates with each other, i.e.
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
KMatrix Invert() const
returns analyticaly inverted matrix
const unsigned int size() const
void SetIdentity()
set the elements of this matrix to the identity matrix (possibly overriding the inherited method) ...
bool ParamsToHMatrix(BIAS::HMatrix &Mat, const std::vector< double > &Params)
composes an H-matrix from the seven given parameters