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
00036
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
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
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 }