flann_matching.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (Modified BSD License)
00003  *
00004  *  Copyright (c) 2016, PAL Robotics, S.L.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of PAL Robotics, S.L. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  */
00034 
00036 // ROS HEADERS
00037 #include <ros/ros.h>
00038 #include <ros/package.h>
00039 #include <cv_bridge/cv_bridge.h>
00040 #include <sensor_msgs/image_encodings.h>
00041 #include <sensor_msgs/Image.h>
00042 #include <image_transport/image_transport.h>
00043 #include <vector>
00044 
00045 // OpenCV headers
00046 #include <opencv2/core/core.hpp>
00047 #include <opencv2/features2d/features2d.hpp>
00048 #include <opencv2/nonfree/features2d.hpp>
00049 #include <opencv2/nonfree/nonfree.hpp>
00050 #include <opencv2/highgui/highgui.hpp>
00051 #include <opencv2/calib3d/calib3d.hpp>
00052 
00053 //Custom Headers
00054 #include <opencv_tut/valueMatrix.h>
00055 
00056 
00057 class FlannMatching
00058 {
00059 public:
00060         FlannMatching(ros::NodeHandle nh_);
00061         ~FlannMatching();
00062         
00063 protected:
00064         void imageCB(const sensor_msgs::ImageConstPtr& msg);
00065         void guiCB(const opencv_tut::valueMatrixConstPtr& msg);
00066         void homography(std::vector<cv::KeyPoint> aruco_, std::vector<cv::KeyPoint> feed_, std::vector<cv::DMatch> match, cv::Mat aruco_img, cv::Mat matches_mat);
00067         void Matcher(cv::Mat in_feed,cv::Mat in_static ,cv::Mat& out);
00068 
00069         image_transport::ImageTransport _imageTransport;
00070         image_transport::Subscriber image_sub;
00071         ros::Subscriber  gui_sub;
00072 
00073         std::string extractor_gui, feature_gui, matcher_gui, path;
00074         bool knn;
00075         int k;
00076         float dist_check;
00077 };
00078 
00079 const std::string win = "Matcher";
00080 
00081 FlannMatching::FlannMatching(ros::NodeHandle nh_): _imageTransport(nh_)
00082 {
00083         image_sub = _imageTransport.subscribe("xtion/rgb/image_raw", 1, &FlannMatching::imageCB, this, image_transport::TransportHints("compressed"));
00084         gui_sub = nh_.subscribe("/opencv_tut/flann_matching_gui", 1, &FlannMatching::guiCB, this);
00085         
00086         cv::namedWindow(win, CV_WINDOW_FREERATIO);
00087         
00088         feature_gui = "SURF";
00089         extractor_gui = "SURF";
00090         matcher_gui = "FlannBased";
00091         knn = false;
00092         k = 2;
00093         dist_check = 0.6;
00094         path = ros::package::getPath("opencv_tut") + "/resources/aruco.jpg";
00095 }
00096 
00097 FlannMatching::~FlannMatching()
00098 {
00099         cv::destroyAllWindows();
00100 }
00101 
00102 void FlannMatching::guiCB(const opencv_tut::valueMatrixConstPtr& msg)
00103 {
00104         if(msg->header.frame_id == "dist")
00105                 dist_check = msg->value;
00106         else if(msg->header.frame_id == "k")
00107                 k = msg->value;
00108         else if(msg->header.frame_id == "k")
00109                 k = msg->value;
00110         else if(msg->header.frame_id == "dist_check")
00111                 dist_check = msg->value;
00112         else if(msg->header.frame_id == "path")
00113                 path = ros::package::getPath("opencv_tut") + msg->option;
00114         else if(msg->header.frame_id == "Keypoints")
00115                 knn = msg->tick;
00116         else if(msg->header.frame_id == "feature_choice")
00117                 feature_gui = msg->option;
00118         else if(msg->header.frame_id == "extracter_choice")
00119                 extractor_gui = msg->option;
00120         else if(msg->header.frame_id == "matcher_choice")
00121                 matcher_gui = msg->option;
00122 }
00123 
00124 void FlannMatching::imageCB(const sensor_msgs::ImageConstPtr& msg)
00125 {
00126         cv::Mat img, orb_mat, sift_mat, new_mat;
00127         cv_bridge::CvImagePtr cvPtr;
00128 
00129         try
00130         { 
00131                 cvPtr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
00132         }
00133         catch (cv_bridge::Exception& e) 
00134         {
00135                 ROS_ERROR("cv_bridge exception: %s", e.what());
00136                 return;
00137         }
00138 
00139         cvPtr->image.copyTo(img);
00140 
00141         cv::Mat img_stat = cv::imread(path);
00142         if(!img_stat.data)
00143                 ROS_INFO("NO DATA FROM STATIC IMAGE");
00144         if(!img.data)
00145                 ROS_INFO("NO DATA FROM IMAGE FEED");
00146 
00147         this->Matcher(img, img_stat, new_mat);
00148         cv::imshow(win, new_mat);
00149         cv::waitKey(1);
00150 }
00151 
00152 void FlannMatching::Matcher(cv::Mat in_feed,cv::Mat in_static ,cv::Mat& out)
00153 {
00154         cv::initModule_nonfree();
00155 
00156         cv::Mat desc_feed, desc_static;
00157         cv::Ptr<cv::FeatureDetector> detector = cv::FeatureDetector::create(feature_gui);
00158 
00159         std::vector<cv::KeyPoint> vec_feed, vec_static;
00160 
00161         detector->detect(in_feed, vec_feed);
00162         detector->detect(in_static, vec_static);
00163 
00164         cv::Ptr<cv::DescriptorExtractor> extractor = cv::DescriptorExtractor::create(extractor_gui);
00165         extractor->compute(in_feed, vec_feed, desc_feed);
00166         extractor->compute(in_static, vec_static, desc_static);
00167 
00168         if(desc_feed.type() != CV_32F || desc_static.type() != CV_32F)
00169         {
00170                 desc_feed.convertTo(desc_feed, CV_32F);
00171                 desc_static.convertTo(desc_static, CV_32F);
00172         }
00173 
00174         if(matcher_gui == "BruteForce-Hamming" || matcher_gui == "BruteForce-Hamming(2)")
00175         {
00176                 desc_feed.convertTo(desc_feed, CV_8U);
00177                 desc_static.convertTo(desc_static, CV_8U);
00178         }
00179 
00180         cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create(matcher_gui);
00181         std::vector<std::vector<cv::DMatch>> matches;
00182         matcher->knnMatch(desc_feed, desc_static, matches, k);
00183 
00184         std::vector<cv::DMatch> good_matches;
00185 
00186         for(const auto m : matches)
00187                 if(m[0].distance < m[1].distance * dist_check)
00188                         good_matches.push_back(m[0]);
00189 
00190         cv::drawMatches(in_feed, vec_feed, in_static, vec_static, good_matches, out);
00191 }
00192 
00193 void FlannMatching::homography(std::vector<cv::KeyPoint> aruco_, std::vector<cv::KeyPoint> feed_, std::vector<cv::DMatch> match_vector, cv::Mat aruco_img, cv::Mat matches_mat)
00194 {
00195         std::vector<cv::Point2f> aruco_2f, feed_2f;
00196         
00197         for(int i = 0; i<match_vector.size(); ++i)
00198         {
00199                 aruco_2f.push_back(aruco_[match_vector[i].queryIdx].pt);
00200                 feed_2f.push_back(feed_[match_vector[i].trainIdx].pt);
00201         }
00202 
00203         cv::Mat h_mat = cv::findHomography(aruco_2f, feed_2f, CV_RANSAC );
00204 
00205         std::vector<cv::Point2f>aruco_corners(4), feed_corners(4);
00206         aruco_corners[0] = cv::Point2f(0,0);
00207         aruco_corners[1] = cv::Point2f(matches_mat.cols, 0);
00208         aruco_corners[2] = cv::Point2f(matches_mat.cols, matches_mat.rows);
00209         aruco_corners[3] = cv::Point2f(0, matches_mat.rows);
00210 
00211         cv::perspectiveTransform(aruco_corners, feed_corners, h_mat);
00212 
00213         cv::line(matches_mat, feed_corners[0] + cv::Point2f(aruco_img.cols, 0), feed_corners[1] + cv::Point2f(aruco_img.rows), cv::Scalar(0,255,0), 4);
00214         cv::line(matches_mat, feed_corners[1] + cv::Point2f(aruco_img.cols, 0), feed_corners[2] + cv::Point2f(aruco_img.rows), cv::Scalar(0,255,0), 4);
00215         cv::line(matches_mat, feed_corners[2] + cv::Point2f(aruco_img.cols, 0), feed_corners[3] + cv::Point2f(aruco_img.rows), cv::Scalar(0,255,0), 4);
00216         cv::line(matches_mat, feed_corners[3] + cv::Point2f(aruco_img.cols, 0), feed_corners[0] + cv::Point2f(aruco_img.rows), cv::Scalar(0,255,0), 4);
00217 }
00218 
00219 int main(int argc, char** argv)
00220 {
00221         ros::init(argc, argv, "FlannMatching");
00222 
00223         ros::NodeHandle nh;
00224 
00225         FlannMatching fm(nh);
00226 
00227         ros::spin();
00228 }


opencv_tut
Author(s): Job van Dieten
autogenerated on Fri Aug 26 2016 13:20:16