00001
00008 #include "sfm_utils.h"
00009
00010 using std::vector;
00011 using Sophus::SE3; using Sophus::SO3;
00012 using Eigen::Vector3d; using Eigen::VectorXd; using Eigen::Matrix3d; using Eigen::MatrixXd;
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 void computeStructure0( const SE3 & T_c1c2, const ImageMatchVec & matches_c1c2,
00053 VectorXd & depths_c1){
00054 int n = matches_c1c2.size();
00055 assert(n >= 1);
00056 depths_c1 = VectorXd::Zero(n);
00057 for(int i = 0 ; i < n; i++){
00058 Vector3d A;
00059 Vector3d b;
00060 A = matches_c1c2[i].second.cross(T_c1c2.rotation_matrix() * matches_c1c2[i].first);
00061 b = -matches_c1c2[i].second.cross(T_c1c2.translation());
00062 Eigen::Matrix<double, 1, 1> tmp =
00063 A.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV).solve(b);
00064 depths_c1(i) = tmp(0,0);
00065 }
00066 }
00067
00068
00069 void computeStructure0ForcePositiveDepths( const SE3 & T_c1c2, const ImageMatchVec & matches_c1c2,
00070 VectorXd & depths_c1){
00071 computeStructure0(T_c1c2, matches_c1c2, depths_c1);
00072 int n = matches_c1c2.size();
00073 for(int i = 0 ; i < n; i++){
00074 if(depths_c1(i) < 0.0) depths_c1(i) = - depths_c1(i);
00075 }
00076 }
00077
00078
00079
00080 void computeStructure(
00081 const SE3 & T_c1c2,
00082 const ImageMatchVec & matches_c1c2,
00083 Points3dSTL & triangulated_points_c1){
00084 VectorXd lambda_1;
00085 computeStructure0(T_c1c2, matches_c1c2, lambda_1);
00086 triangulated_points_c1.clear();
00087 for(unsigned int i=0 ; i < matches_c1c2.size(); i++){
00088 triangulated_points_c1.push_back(matches_c1c2[i].first * lambda_1(i));
00089 }
00090 }
00091
00092
00093 void computeStructureForcePositiveDepths(
00094 const SE3 & T_c1c2,
00095 const ImageMatchVec & matches_c1c2,
00096 Points3dSTL & triangulated_points_c1){
00097 VectorXd lambda_1;
00098 computeStructure0ForcePositiveDepths(T_c1c2, matches_c1c2, lambda_1);
00099 triangulated_points_c1.clear();
00100 for(unsigned int i=0 ; i < matches_c1c2.size(); i++){
00101 triangulated_points_c1.push_back(matches_c1c2[i].first * lambda_1(i));
00102 }
00103 }
00104
00105 void computeStructure(
00106 const Sophus::SE3 & T_c1c2, const ImageMatch& match_c1c2, Vector3d & triangulated_point_c1){
00107 ImageMatchVec imv;
00108 imv.push_back(match_c1c2);
00109 Points3dSTL pv;
00110 computeStructure(T_c1c2, imv, pv);
00111 triangulated_point_c1=pv[0];
00112 }
00113
00114 void computeStructureForcePositiveDepth(
00115 const Sophus::SE3 & T_c1c2, const ImageMatch& match_c1c2, Vector3d & triangulated_point_c1){
00116 ImageMatchVec imv;
00117 imv.push_back(match_c1c2);
00118 Points3dSTL pv;
00119 computeStructureForcePositiveDepths(T_c1c2, imv, pv);
00120 triangulated_point_c1=pv[0];
00121 }
00122
00123 typedef ALIGNED<pair<int, Vector3d> >::vector IdxPoint3dVec;
00124
00125
00126
00127 void computeStructure(
00128 const SE3 & T_c1c2,
00129 const ImageMatchVec & matches_c1c2,
00130 const IdxPoint3dVec & idx_points3d_c1,
00131 Points3dSTL & points3d_c1,
00132 SE3 & scaled_T_c1c2){
00133 points3d_c1.clear();
00134 computeStructure(T_c1c2, matches_c1c2, points3d_c1);
00135 IdxPoint3dVec tmp=switchCont<vector>(getByIdx(
00136 indexBy( makeSeq(0, (int)matches_c1c2.size() - 1, 1), points3d_c1),
00137 transformF<int>(idx_points3d_c1, getFirst)));
00138 double scale = computeScale(
00139 transformF<Vector3d>(idx_points3d_c1, getSecond),
00140 transformF<Vector3d>(tmp, getSecond));
00141 scaled_T_c1c2 = SE3(T_c1c2.rotation_matrix(), T_c1c2.translation() * scale);
00142 for(unsigned int i=0 ; i < points3d_c1.size(); i++){
00143 points3d_c1[i] *= scale;
00144 }
00145 }
00146
00147 void computeScale( const Points3dSTL& points1, const Points3dSTL& points2,
00148 double& low, double& mid, double& hi){
00149 assert(points1.size() >= 3);
00150 assert(points1.size() == points2.size());
00151 vector<double> ratios;
00152 for(unsigned int i = 0; i < points1.size(); i++){
00153 ratios.push_back(points1[i].norm() / (points2[i]).norm());
00154 }
00155 std::sort(ratios.begin(), ratios.end());
00156
00157 int idx = ratios.size() / 2;
00158 low = ratios[idx-1];
00159 mid = ratios[idx];
00160 hi = ratios[idx+1];
00161 ROS_INFO_STREAM_NAMED("SFM:", "scale ratios around median (low, mid, hi):" << low << " " << mid << " " << hi);
00162 }
00163
00164 double computeScale( const Points3dSTL& points1, const Points3dSTL& points2){
00165 double low, mid, hi;
00166 computeScale(points1, points2, low, mid, hi);
00167 return mid;
00168 }
00169
00170
00171 ALIGNED<SE3>::vector extractRtFromE(const Matrix3d & E){
00172 Eigen::JacobiSVD<Eigen::Matrix3d> svd(E, Eigen::ComputeFullU | Eigen::ComputeFullV);
00173 Matrix3d U, V;
00174 U=svd.matrixU();
00175 V=svd.matrixV();
00176
00177
00178 if(U.determinant() < 0) U = (-U).eval();
00179 if(V.determinant() < 0) V = (-V).eval();
00180 assert(isApprox(U.determinant(), 1.0, 0.0001));
00181 assert(isApprox(V.determinant(), 1.0, 0.0001));
00182
00183
00184 Matrix3d W = Matrix3d::Zero();
00185 W(0,1) = -1; W(1,0) = 1; W(2,2) = 1;
00186 Matrix3d Z = Matrix3d::Zero();
00187 Z(0,1) = 1; Z(1,0) = -1;
00188
00189 Matrix3d R1 = U * W * V.transpose();
00190 Matrix3d R2 = U * W.transpose() * V.transpose();
00191
00192 Matrix3d Sigma = Matrix3d::Zero(); Sigma(0,0) = 1; Sigma(1,1) = 1;
00193 Vector3d t = SO3::vee(U * Z * U.transpose());
00194
00195 ALIGNED<SE3>::vector transforms;
00196 transforms.push_back(SE3(R1,t));
00197 transforms.push_back(SE3(R2,t));
00198 return transforms;
00199 }
00200
00201
00202
00203
00204 bool extractTransformFromE( const ImageMatchVec & image_matches, const Matrix3d & E, SE3 & res_tr){
00205 using std::tr1::signbit;
00206 ALIGNED<SE3>::vector transforms = extractRtFromE(E);
00207 BOOST_FOREACH(SE3 transform, transforms){
00208 bool assigned = true;
00209 VectorXd lambda_1;
00210 computeStructure0(transform, image_matches, lambda_1);
00211 if(lambda_1(0) < 0){
00212 res_tr = SE3(transform.rotation_matrix(), -transform.translation());
00213 lambda_1 = (-lambda_1).eval();
00214 } else{
00215 res_tr = transform;
00216 }
00217 for(Points3dSTL::size_type i=0; i < image_matches.size(); i++){
00218 if (lambda_1(i) < 0){
00219 assigned=false;
00220 break;
00221 }
00222 Vector3d a, b;
00223 a=res_tr * (image_matches[i].first * lambda_1(i));
00224 b=image_matches[i].second;
00225
00226 for(int j=0; j<3; j++){
00227 if(signbit(a(j)) != signbit(b(j))){
00228 i=image_matches.size();
00229 assigned=false;
00230 break;
00231 }
00232 }
00233 }
00234 if(assigned) return true;
00235 }
00236 return false;
00237 }
00238
00239