00001 #include <posest/peh.h>
00002 #include <sba/sba.h>
00003 #include <Eigen/SVD>
00004 #include <Eigen/LU>
00005 #include <iostream>
00006 #include <opencv2/core/core.hpp>
00007 #include <opencv2/features2d/features2d.hpp>
00008
00009
00010 using namespace Eigen;
00011 using namespace sba;
00012 using namespace frame_common;
00013 using namespace std;
00014 using namespace cv;
00015
00016 namespace pe
00017 {
00018 void invert(Mat& rvec, Mat& tvec)
00019 {
00020 Mat R, RInv;
00021 Rodrigues(rvec,R);
00022 RInv = R.inv();
00023 Rodrigues(RInv, rvec);
00024 tvec = RInv*tvec;
00025 tvec = tvec*(-1);
00026 }
00027
00028 int PoseEstimatorH::estimate(const Frame& frame1, const Frame& frame2)
00029 {
00030 matches.clear();
00031 inliers.clear();
00032 cout << "Kpt size frame 1 = " << frame1.kpts.size() << endl;
00033 cout << "Kpt size frame 2 = " << frame2.kpts.size() << endl;
00034
00035 Mat mask;
00036 if (windowed)
00037 mask = cv::windowedMatchingMask(frame1.kpts, frame2.kpts, wx, wy);
00038 howardMatcher->match(frame1, frame2, matches, filteredIndices, mask);
00039 return estimate(frame1, frame2, matches);
00040 }
00041
00042 Mat calcTranslation(const vector<Point3f>& points1, const vector<Point3f>& points2)
00043 {
00044 assert(points1.size() == points2.size());
00045 Mat t = Mat::zeros(3, 1, CV_64F);
00046 for (size_t i = 0; i < points1.size(); i++)
00047 {
00048 t.at<double> (0, 0) += points2[i].x - points1[i].x;
00049 t.at<double> (1, 0) += points2[i].y - points1[i].y;
00050 t.at<double> (2, 0) += points2[i].z - points1[i].z;
00051 }
00052
00053 t /= points1.size();
00054 return t;
00055 }
00056
00057 void project3dPoints(const vector<Point3f>& points, const Mat& rvec, const Mat& tvec, vector<Point3f>& modif_points)
00058 {
00059 modif_points.clear();
00060 modif_points.resize(points.size());
00061 Mat R(3, 3, CV_64FC1);
00062 Rodrigues(rvec, R);
00063 for (size_t i = 0; i < points.size(); i++)
00064 {
00065 modif_points[i].x = R.at<double> (0, 0) * points[i].x + R.at<double> (0, 1) * points[i].y + R.at<double> (0, 2)
00066 * points[i].z + tvec.at<double> (0, 0);
00067 modif_points[i].y = R.at<double> (1, 0) * points[i].x + R.at<double> (1, 1) * points[i].y + R.at<double> (1, 2)
00068 * points[i].z + tvec.at<double> (1, 0);
00069 modif_points[i].z = R.at<double> (2, 0) * points[i].x + R.at<double> (2, 1) * points[i].y + R.at<double> (2, 2)
00070 * points[i].z + tvec.at<double> (2, 0);
00071 }
00072 }
00073
00074 int PoseEstimatorH::estimate(const Frame& f0, const Frame& f1,
00075 const std::vector<cv::DMatch> &peMatches)
00076 {
00077 cout << "Filtered matches size = " << filteredIndices.size() << endl;
00078 std::vector<cv::DMatch> matches;
00079 int nmatch = peMatches.size();
00080 for (size_t i=0; i<filteredIndices.size(); i++)
00081 {
00082 if (f0.disps[peMatches[filteredIndices[i]].queryIdx] > minMatchDisp &&
00083 f1.disps[peMatches[filteredIndices[i]].trainIdx] > minMatchDisp)
00084 {
00085 matches.push_back(peMatches[filteredIndices[i]]);
00086 }
00087 }
00088 cout << "Matches size after disparity filtering = " << matches.size() << endl;
00089
00090 vector<Point3f> opoints;
00091 vector<Point3f> opointsFrame2;
00092 vector<Point2f> ipoints;
00093 vector<cv::DMatch> inls;
00094 vector<int> indices;
00095 for (size_t i = 0; i < matches.size(); ++i)
00096 {
00097 if (f0.goodPts[matches[i].queryIdx] && f1.goodPts[matches[i].trainIdx])
00098 {
00099 ipoints.push_back(f1.kpts[matches[i].trainIdx].pt);
00100 Eigen::Vector4d vec = f0.pts[matches[i].queryIdx];
00101 Point3f op(vec(0), vec(1), vec(2));
00102 opoints.push_back(op);
00103
00104 Eigen::Vector4d vec2 = f1.pts[matches[i].trainIdx];
00105 Point3f op2(vec2(0), vec2(1), vec2(2));
00106 opointsFrame2.push_back(op2);
00107
00108 indices.push_back(i);
00109 }
00110 }
00111 bool matched = (int)matches.size() > minMatchesCount;
00112 if (matched)
00113 {
00114 Mat rvec, tvec;
00115 Mat intrinsic = Mat::zeros(Size(3, 3), CV_64F);
00116 intrinsic.at<double>(0, 0) = f1.cam.fx;
00117 intrinsic.at<double>(0, 2) = f1.cam.cx;
00118 intrinsic.at<double>(1, 1) = f1.cam.fy;
00119 intrinsic.at<double>(1, 2) = f1.cam.cy;
00120 intrinsic.at<double>(2, 2) = 1.0;
00121 solvePnP(Mat(opoints), Mat(ipoints), intrinsic, Mat::zeros(Size(1, 5), CV_64F), rvec, tvec, false);
00122 vector<Point2f> projectedPoints;
00123 projectPoints(Mat(opoints), rvec, tvec, intrinsic, Mat::zeros(Size(1, 5), CV_64F), projectedPoints);
00124
00125 vector<Point3f> inliersOpoints;
00126 vector<Point3f> inliersOpointsFrame2;
00127 vector<Point2f> inliersIpoints;
00128 for (size_t pointInd = 0; pointInd < projectedPoints.size(); pointInd++)
00129 {
00130 double dx = ipoints[pointInd].x - projectedPoints[pointInd].x;
00131 double dy = ipoints[pointInd].y - projectedPoints[pointInd].y;
00132 double dd = f1.disps[matches[indices[pointInd]].trainIdx] - f1.cam.fx*f1.cam.tx/opoints[pointInd].z;
00133
00134 if (dx*dx < maxInlierXDist2 && dy*dy < maxInlierXDist2 &&
00135 dd*dd < maxInlierDDist2)
00136 {
00137 inliersIpoints.push_back(ipoints[pointInd]);
00138 inliersOpoints.push_back(opoints[pointInd]);
00139 inliersOpointsFrame2.push_back(opointsFrame2[pointInd]);
00140
00141 }
00142 }
00143 cout << "Inliers matches size = " << inliersIpoints.size() << endl;
00144 if (inliersIpoints.size() > 5)
00145 {
00146 solvePnP(Mat(inliersOpoints), Mat(inliersIpoints), intrinsic, Mat::zeros(Size(1, 5), CV_64F), rvec, tvec, true);
00147 vector<Point3f> rotatedPoints;
00148 project3dPoints(Mat(inliersOpoints), rvec, tvec, rotatedPoints);
00149
00150
00151
00152
00153 vector<Point2f> projectedPoints;
00154 projectPoints(Mat(inliersOpoints), rvec, tvec, intrinsic, Mat::zeros(Size(1, 5), CV_64F), projectedPoints);
00155
00156 float reprojectionError = 0.0;
00157 for (size_t pointInd = 0; pointInd < projectedPoints.size(); pointInd++)
00158 {
00159 float error = norm(projectedPoints[pointInd] - inliersIpoints[pointInd]);
00160 if (error > reprojectionError)
00161 {
00162 reprojectionError = error;
00163 }
00164 }
00165 cout << "Reprojection error = " << reprojectionError << endl;
00166
00167
00168
00169
00170 }
00171 else
00172 {
00173 inls.clear();
00174 matched = false;
00175 }
00176
00177 if (matched)
00178 {
00180 vector<Point3f> mopoints;
00181 vector<Point2f> mipoints;
00182 vector<int> mindices;
00183 for (size_t i = 0; i < peMatches.size(); ++i)
00184 {
00185 if (f0.goodPts[peMatches[i].queryIdx] && f1.goodPts[peMatches[i].trainIdx])
00186 {
00187 mipoints.push_back(f1.kpts[peMatches[i].trainIdx].pt);
00188 Eigen::Vector4d vec = f0.pts[peMatches[i].queryIdx];
00189 Point3f op(vec(0), vec(1), vec(2));
00190 mopoints.push_back(op);
00191 mindices.push_back(i);
00192 }
00193 }
00194 vector<Point2f> mprojectedPoints;
00195 projectPoints(Mat(mopoints), rvec, tvec, intrinsic, Mat::zeros(Size(1, 5), CV_64F), mprojectedPoints);
00196 for (size_t pointInd = 0; pointInd < mprojectedPoints.size(); pointInd++)
00197 {
00198 double dx = mipoints[pointInd].x - mprojectedPoints[pointInd].x;
00199 double dy = mipoints[pointInd].y - mprojectedPoints[pointInd].y;
00200 double dd = f1.disps[peMatches[mindices[pointInd]].trainIdx] - f1.cam.fx*f1.cam.tx/mopoints[pointInd].z;
00201
00202 if (dx*dx < maxInlierXDist2 && dy*dy < maxInlierXDist2 &&
00203 dd*dd < maxInlierDDist2)
00204 {
00205 inls.push_back(peMatches[mindices[pointInd]]);
00206 }
00207 }
00208 cout << "inls size = " << inls.size() << endl;
00209
00210 if (norm(tvec) > 1.0)
00211 {
00212 inls.clear();
00213 return 0;
00214 }
00215
00216 cout << rvec << endl << tvec << endl;
00217 invert(rvec, tvec);
00218 cout << rvec << endl << tvec << endl;
00219 Mat R;
00220 cv::Rodrigues(rvec, R);
00221 Matrix3d R2;
00222 Vector3d tr;
00223 R2 << R.at<double>(0,0), R.at<double>(0,1), R.at<double>(0,2),
00224 R.at<double>(1,0), R.at<double>(1,1), R.at<double>(1,2),
00225 R.at<double>(2,0), R.at<double>(2,1), R.at<double>(2,2);
00226 tr << tvec.at<double>(0,0), tvec.at<double>(0,1), tvec.at<double>(0,2);
00227 rot = R2;
00228 trans = tr;
00229 inliers = inls;
00230 return inliers.size();
00231 }
00232 else
00233 return 0;
00234 }
00235 else
00236 return 0;
00237 }
00238 }