00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <posest/pe3d.h>
00037 #include <sba/sba.h>
00038 #include <Eigen/SVD>
00039 #include <Eigen/LU>
00040 #include <iostream>
00041
00042
00043 using namespace Eigen;
00044 using namespace sba;
00045 using namespace frame_common;
00046 using namespace std;
00047
00048 namespace pe
00049 {
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 int PoseEstimator3d::estimate(const Frame& f0, const Frame& f1,
00062 const std::vector<cv::DMatch> &matches)
00063 {
00064
00065 std::vector<Vector4d, aligned_allocator<Vector4d> > p0;
00066 std::vector<Vector4d, aligned_allocator<Vector4d> > p1;
00067
00068 int nmatch = matches.size();
00069
00070
00071
00072 vector<int> m0, m1;
00073 for (int i=0; i<nmatch; i++)
00074 {
00075 if (f0.disps[matches[i].queryIdx] > minMatchDisp &&
00076 f1.disps[matches[i].trainIdx] > minMatchDisp)
00077 {
00078 m0.push_back(matches[i].queryIdx);
00079 m1.push_back(matches[i].trainIdx);
00080 }
00081 }
00082
00083 nmatch = m0.size();
00084 if (nmatch < 3) return 0;
00085
00086 int bestinl = 0;
00087
00088
00089 #pragma omp parallel for shared( bestinl )
00090 for (int i=0; i<numRansac; i++)
00091 {
00092
00093 int a=rand()%nmatch;
00094 int b = a;
00095 while (a==b)
00096 b=rand()%nmatch;
00097 int c = a;
00098 while (a==c || b==c)
00099 c=rand()%nmatch;
00100
00101 int i0a = m0[a];
00102 int i0b = m0[b];
00103 int i0c = m0[c];
00104 int i1a = m1[a];
00105 int i1b = m1[b];
00106 int i1c = m1[c];
00107
00108 if (i0a == i0b || i0a == i0c || i0b == i0c ||
00109 i1a == i1b || i1a == i1c || i1b == i1c)
00110 continue;
00111
00112
00113 Vector3d p0a = f0.pts[i0a].head<3>();
00114 Vector3d p0b = f0.pts[i0b].head<3>();
00115 Vector3d p0c = f0.pts[i0c].head<3>();
00116 Vector3d p1a = f1.pts[i1a].head<3>();
00117 Vector3d p1b = f1.pts[i1b].head<3>();
00118 Vector3d p1c = f1.pts[i1c].head<3>();
00119
00120 Vector3d c0 = (p0a+p0b+p0c)*(1.0/3.0);
00121 Vector3d c1 = (p1a+p1b+p1c)*(1.0/3.0);
00122
00123
00124 p0a -= c0;
00125 p0b -= c0;
00126 p0c -= c0;
00127 p1a -= c1;
00128 p1b -= c1;
00129 p1c -= c1;
00130
00131 Matrix3d H = p1a*p0a.transpose() + p1b*p0b.transpose() +
00132 p1c*p0c.transpose();
00133
00134 #if 0
00135 cout << p0a.transpose() << endl;
00136 cout << p0b.transpose() << endl;
00137 cout << p0c.transpose() << endl;
00138 #endif
00139
00140
00141 JacobiSVD<Matrix3d> svd(H, ComputeFullU | ComputeFullV);
00142 Matrix3d V = svd.matrixV();
00143 Matrix3d R = V * svd.matrixU().transpose();
00144 double det = R.determinant();
00145
00146 if (det < 0.0)
00147 {
00148
00149 V.col(2) = V.col(2)*-1.0;
00150 R = V * svd.matrixU().transpose();
00151 }
00152 Vector3d tr = c0-R*c1;
00153
00154
00155
00156
00157 #if 0
00158 R << 0.9997, 0.002515, 0.02418,
00159 -0.002474, .9999, -0.001698,
00160 -0.02418, 0.001638, 0.9997;
00161 tr << -0.005697, -0.01753, 0.05666;
00162 R = R.transpose();
00163 tr = -R*tr;
00164 #endif
00165
00166
00167 Matrix<double,3,4> tfm;
00168
00169
00170 tfm.block<3,3>(0,0) = R;
00171 tfm.col(3) = tr;
00172
00173
00174
00175
00176 int inl = 0;
00177 for (int i=0; i<nmatch; i++)
00178 {
00179 Vector3d pt = tfm*f1.pts[m1[i]];
00180 Vector3d ipt = f0.cam2pix(pt);
00181 const cv::KeyPoint &kp = f0.kpts[m0[i]];
00182 double dx = kp.pt.x - ipt.x();
00183 double dy = kp.pt.y - ipt.y();
00184 double dd = f0.disps[m0[i]] - ipt.z();
00185 if (dx*dx < maxInlierXDist2 && dy*dy < maxInlierXDist2 &&
00186 dd*dd < maxInlierDDist2)
00187 inl+=(int)sqrt(ipt.z());
00188
00189 }
00190
00191 #pragma omp critical
00192 if (inl > bestinl)
00193 {
00194 bestinl = inl;
00195 rot = R;
00196 trans = tr;
00197 }
00198 }
00199
00200
00201
00202
00203
00204 vector<cv::DMatch> inls;
00205 inliers.clear();
00206 Matrix<double,3,4> tfm;
00207 tfm.block<3,3>(0,0) = rot;
00208 tfm.col(3) = trans;
00209
00210 nmatch = matches.size();
00211 for (int i=0; i<nmatch; i++)
00212 {
00213 if (!f0.goodPts[matches[i].queryIdx] || !f1.goodPts[matches[i].trainIdx])
00214 continue;
00215 Vector3d pt = tfm*f1.pts[matches[i].trainIdx];
00216 Vector3d ipt = f0.cam2pix(pt);
00217 const cv::KeyPoint &kp = f0.kpts[matches[i].queryIdx];
00218 double dx = kp.pt.x - ipt.x();
00219 double dy = kp.pt.y - ipt.y();
00220 double dd = f0.disps[matches[i].queryIdx] - ipt.z();
00221 if (dx*dx < maxInlierXDist2 && dy*dy < maxInlierXDist2 &&
00222 dd*dd < maxInlierDDist2)
00223 inls.push_back(matches[i]);
00224 }
00225
00226 #if 0
00227 cout << endl << trans.transpose().head(3) << endl << endl;
00228 cout << rot << endl;
00229 #endif
00230
00231
00232 if (polish)
00233 {
00234
00235 SysSBA sba;
00236 sba.verbose = 0;
00237
00238
00239
00240 Vector4d v0 = Vector4d(0,0,0,1);
00241 Quaterniond q0 = Quaternion<double>(Vector4d(0,0,0,1));
00242 sba.addNode(v0, q0, f0.cam, true);
00243
00244 Quaterniond qr1(rot);
00245 Vector4d temptrans = Vector4d(trans(0), trans(1), trans(2), 1.0);
00246
00247
00248 qr1.normalize();
00249 sba.addNode(temptrans, qr1, f1.cam, false);
00250
00251 int in = 3;
00252 if (in > (int)inls.size())
00253 in = inls.size();
00254
00255
00256 for (int i=0; i<(int)inls.size(); i++)
00257 {
00258
00259 int i0 = inls[i].queryIdx;
00260 int i1 = inls[i].trainIdx;
00261 Vector4d pt = f0.pts[i0];
00262 sba.addPoint(pt);
00263
00264
00265 Vector3d ipt;
00266 ipt(0) = f0.kpts[i0].pt.x;
00267 ipt(1) = f0.kpts[i0].pt.y;
00268 ipt(2) = ipt(0)-f0.disps[i0];
00269 sba.addStereoProj(0, i, ipt);
00270
00271
00272 ipt(0) = f1.kpts[i1].pt.x;
00273 ipt(1) = f1.kpts[i1].pt.y;
00274 ipt(2) = ipt(0)-f1.disps[i1];
00275 sba.addStereoProj(1, i, ipt);
00276 }
00277
00278 sba.huber = 2.0;
00279 sba.doSBA(5,10e-4,SBA_DENSE_CHOLESKY);
00280 int nbad = sba.removeBad(2.0);
00281
00282 sba.doSBA(5,10e-5,SBA_DENSE_CHOLESKY);
00283
00284
00285
00286
00287 trans = sba.nodes[1].trans.head(3);
00288 Quaterniond q1;
00289 q1 = sba.nodes[1].qrot;
00290 rot = q1.toRotationMatrix();
00291
00292
00293 inliers.clear();
00294 for (int i=0; i<(int)inls.size(); i++)
00295 {
00296 ProjMap &prjs = sba.tracks[i].projections;
00297 if (prjs[0].isValid && prjs[1].isValid)
00298 inliers.push_back(inls[i]);
00299 }
00300 #if 0
00301 printf("Inliers: %d After polish: %d\n", (int)inls.size(), (int)inliers.size());
00302 #endif
00303 }
00304
00305 return (int)inliers.size();
00306 }
00307 }