utils.h
Go to the documentation of this file.
00001 #ifndef UTILS
00002 #define UTILS
00003 
00004 #include <ros/ros.h>
00005 #include <tf/transform_broadcaster.h>
00006 #include <opencv2/features2d/features2d.hpp>
00007 #include <opencv2/nonfree/features2d.hpp>
00008 #include <opencv2/nonfree/nonfree.hpp>
00009 #include <image_geometry/stereo_camera_model.h>
00010 
00011 using namespace std;
00012 using namespace cv;
00013 
00014 namespace haloc
00015 {
00016 
00017 class Utils
00018 {
00019 
00020 public:
00021 
00028   static void keypointDetector(const Mat& image,
00029                                vector<KeyPoint>& key_points,
00030                                string type)
00031   {
00032     // Check Opponent color space descriptors
00033     size_t pos = 0;
00034     if ( (pos=type.find("Opponent")) == 0)
00035     {
00036       pos += string("Opponent").size();
00037       type = type.substr(pos);
00038     }
00039 
00040     initModule_nonfree();
00041     Ptr<FeatureDetector> cv_detector;
00042     cv_detector = FeatureDetector::create(type);
00043     try
00044     {
00045       cv_detector->detect(image, key_points);
00046     }
00047     catch (Exception& e)
00048     {
00049       ROS_WARN("[StereoSlam:] cv_detector exception: %s", e.what());
00050     }
00051   }
00052 
00059   static void descriptorExtraction(const Mat& image,
00060    vector<KeyPoint>& key_points, Mat& descriptors, string type)
00061   {
00062     Ptr<DescriptorExtractor> cv_extractor;
00063     cv_extractor = DescriptorExtractor::create(type);
00064     try
00065     {
00066       cv_extractor->compute(image, key_points, descriptors);
00067     }
00068     catch (Exception& e)
00069     {
00070       ROS_WARN("[StereoSlam:] cv_extractor exception: %s", e.what());
00071     }
00072   }
00073 
00081   static void ratioMatching(const Mat& descriptors1, const Mat& descriptors2,
00082     double ratio, const Mat& match_mask, vector<DMatch>& matches)
00083   {
00084     matches.clear();
00085     if (descriptors1.empty() || descriptors2.empty())
00086       return;
00087     assert(descriptors1.type() == descriptors2.type());
00088     assert(descriptors1.cols == descriptors2.cols);
00089 
00090     const int knn = 2;
00091     Ptr<DescriptorMatcher> descriptor_matcher;
00092     // choose matcher based on feature type
00093     if (descriptors1.type() == CV_8U)
00094     {
00095       descriptor_matcher = DescriptorMatcher::create("BruteForce-Hamming");
00096     }
00097     else
00098     {
00099       descriptor_matcher = DescriptorMatcher::create("BruteForce");
00100     }
00101     vector<vector<DMatch> > knn_matches;
00102     descriptor_matcher->knnMatch(descriptors1, descriptors2,
00103             knn_matches, knn, match_mask);
00104 
00105     for (unsigned m = 0; m < knn_matches.size(); m++)
00106     {
00107       if (knn_matches[m].size() < 2) continue;
00108       if (knn_matches[m][0].distance <= knn_matches[m][1].distance * ratio)
00109         matches.push_back(knn_matches[m][0]);
00110     }
00111   }
00112 
00121   static void thresholdMatching(const Mat& descriptors1, const Mat& descriptors2,
00122     double threshold, const Mat& match_mask, vector<DMatch>& matches)
00123   {
00124     matches.clear();
00125     if (descriptors1.empty() || descriptors2.empty())
00126       return;
00127     assert(descriptors1.type() == descriptors2.type());
00128     assert(descriptors1.cols == descriptors2.cols);
00129 
00130     const int knn = 2;
00131     Ptr<DescriptorMatcher> descriptor_matcher;
00132     // choose matcher based on feature type
00133     if (descriptors1.type() == CV_8U)
00134     {
00135       descriptor_matcher = DescriptorMatcher::create("BruteForce-Hamming");
00136     }
00137     else
00138     {
00139       descriptor_matcher = DescriptorMatcher::create("BruteForce");
00140     }
00141     vector<vector<DMatch> > knn_matches;
00142     descriptor_matcher->knnMatch(descriptors1, descriptors2,
00143             knn_matches, knn, match_mask);
00144 
00145     for (size_t m = 0; m < knn_matches.size(); m++)
00146     {
00147       if (knn_matches[m].size() < 2) continue;
00148       float dist1 = knn_matches[m][0].distance;
00149       float dist2 = knn_matches[m][1].distance;
00150       if (dist1 / dist2 < threshold)
00151       {
00152         matches.push_back(knn_matches[m][0]);
00153       }
00154     }
00155   }
00156 
00163   static void crossCheckFilter(
00164       const vector<DMatch>& matches1to2,
00165       const vector<DMatch>& matches2to1,
00166       vector<DMatch>& checked_matches)
00167   {
00168     checked_matches.clear();
00169     for (size_t i = 0; i < matches1to2.size(); ++i)
00170     {
00171       bool match_found = false;
00172       const DMatch& forward_match = matches1to2[i];
00173       for (size_t j = 0; j < matches2to1.size() && match_found == false; ++j)
00174       {
00175         const DMatch& backward_match = matches2to1[j];
00176         if (forward_match.trainIdx == backward_match.queryIdx &&
00177             forward_match.queryIdx == backward_match.trainIdx)
00178         {
00179           checked_matches.push_back(forward_match);
00180           match_found = true;
00181         }
00182       }
00183     }
00184   }
00185 
00194   static void crossCheckThresholdMatching(
00195     const Mat& descriptors1, const Mat& descriptors2,
00196     double threshold, const Mat& match_mask,
00197     vector<DMatch>& matches)
00198   {
00199     vector<DMatch> query_to_train_matches;
00200     thresholdMatching(descriptors1, descriptors2, threshold, match_mask, query_to_train_matches);
00201     vector<DMatch> train_to_query_matches;
00202     Mat match_mask_t;
00203     if (!match_mask.empty()) match_mask_t = match_mask.t();
00204     thresholdMatching(descriptors2, descriptors1, threshold, match_mask_t, train_to_query_matches);
00205 
00206     crossCheckFilter(query_to_train_matches, train_to_query_matches, matches);
00207   }
00208 
00216   static bool calculate3DPoint(const image_geometry::StereoCameraModel stereo_camera_model,
00217                                const Point2d& left_point,
00218                                const Point2d& right_point,
00219                                double max_proj_err,
00220                                Point3d& world_point)
00221   {
00222     // Get the world point
00223     double disparity = left_point.x - right_point.x;
00224     stereo_camera_model.projectDisparityTo3d(left_point, disparity, world_point);
00225 
00226     // Filter the given world point
00227     // Extract camera parameters
00228     double fx_l = stereo_camera_model.left().fx();
00229     double fy_l = stereo_camera_model.left().fy();
00230     double cx_l = stereo_camera_model.left().cx();
00231     double cy_l = stereo_camera_model.left().cy();
00232 
00233     double fx_r = stereo_camera_model.right().fx();
00234     double fy_r = stereo_camera_model.right().fy();
00235     double cx_r = stereo_camera_model.right().cx();
00236     double cy_r = stereo_camera_model.right().cy();
00237 
00238     double baseline = stereo_camera_model.baseline();
00239 
00240     // Direccion vectors
00241     double x_l = (1.0/fx_l) * (left_point.x - cx_l);
00242     double y_l = (1.0/fy_l) * (left_point.y - cy_l);
00243     double z_l = 1.0;
00244 
00245     double x_r = (1.0/fx_r) * (right_point.x - cx_r);
00246     double y_r = (1.0/fy_r) * (right_point.y - cy_r);
00247     double z_r = 1.0;
00248 
00249     tf::Vector3 u(x_l, y_l, z_l);
00250     tf::Vector3 v(x_r, y_r, z_r);
00251     tf::Vector3 w0(-baseline, 0.0, 0.0);
00252 
00253     // Origins
00254     tf::Vector3 l0(0.0, 0.0, 0.0);
00255     tf::Vector3 r0(baseline, 0.0, 0.0);
00256 
00257     // Temporal variables
00258     double a = u.dot(u);
00259     double b = u.dot(v);
00260     double c = v.dot(v);
00261     double d = u.dot(w0);
00262     double e = v.dot(w0);
00263 
00264     // Minimum distance between the two projected points
00265     tf::Vector3 dv = (l0-r0) + ( ( (b*e-c*d)*u - (a*e-b*d)*v ) / (a*c - b*b) );
00266     double dist = sqrt( dv.x()*dv.x() + dv.y()*dv.y() + dv.z()*dv.z() );
00267     if (dist > max_proj_err)
00268     {
00269       return false;
00270     }
00271     else
00272     {
00273       return true;
00274     }
00275   }
00276 
00282   static bool sortByMatching(const pair<int, float> d1, const pair<int, float> d2)
00283   {
00284     return (d1.second < d2.second);
00285   }
00286 
00292   static bool sortDescByDistance(const DMatch& d1, const DMatch& d2)
00293   {
00294     return (d1.distance < d2.distance);
00295   }
00296 
00302   static bool sortByResponse(const KeyPoint kp1, const KeyPoint kp2)
00303   {
00304     return (kp1.response > kp2.response);
00305   }
00306 
00312   static bool sortByLikelihood(const pair<int, float> p1, const pair<int, float> p2)
00313   {
00314     return (p1.second > p2.second);
00315   }
00316 
00323   static tf::Transform buildTransformation(Mat rvec, Mat tvec)
00324   {
00325     if (rvec.empty() || tvec.empty())
00326       return tf::Transform();
00327 
00328     tf::Vector3 axis(rvec.at<double>(0, 0),
00329                rvec.at<double>(1, 0),
00330                  rvec.at<double>(2, 0));
00331     double angle = norm(rvec);
00332     tf::Quaternion quaternion(axis, angle);
00333 
00334     tf::Vector3 translation(tvec.at<double>(0, 0), tvec.at<double>(1, 0),
00335         tvec.at<double>(2, 0));
00336 
00337     return tf::Transform(quaternion, translation);
00338   }
00339 };
00340 
00341 } // namespace
00342 
00343 #endif // UTILS
00344 
00345 


libhaloc
Author(s): Pep Lluis Negre
autogenerated on Thu Jun 6 2019 21:25:00