00001 #include <stdio.h>
00002 #include <iostream>
00003 #include <cstdio>
00004 #include <boost/filesystem.hpp>
00005
00006 #include <image_transport/image_transport.h>
00007 #include <cv_bridge/cv_bridge.h>
00008 #include <sensor_msgs/image_encodings.h>
00009
00010 #include "opencv2/core/core.hpp"
00011 #include "opencv2/features2d/features2d.hpp"
00012 #include "opencv2/highgui/highgui.hpp"
00013 #include "opencv2/calib3d/calib3d.hpp"
00014 #include "opencv2/nonfree/nonfree.hpp"
00015
00016 #include "opencv2/objdetect/objdetect.hpp"
00017 #include "opencv2/imgproc/imgproc.hpp"
00018
00019 #include "ros/ros.h"
00020 #include "std_msgs/String.h"
00021
00022 #include "bwi_scavenger/ObjectDetection.h"
00023
00024 using namespace cv;
00025
00026 cv_bridge::CvImageConstPtr cv_ptr;
00027 Mat frame;
00028
00029 std::string file, name, directory;
00030 std::string default_dir = "/home/bwi/shiqi/";
00031
00032
00033 void callback(const sensor_msgs::ImageConstPtr& msg)
00034 {
00035 cv_ptr = cv_bridge::toCvShare(msg, sensor_msgs::image_encodings::BGR8);
00036 frame = cv_ptr->image;
00037 }
00038
00039
00040 bool callback_detection(bwi_scavenger::ObjectDetection::Request &req,
00041 bwi_scavenger::ObjectDetection::Response &res) {
00042
00043 file = req.path_to_template;
00044 Mat img_object = imread(file, CV_LOAD_IMAGE_GRAYSCALE );
00045 if(! img_object.data )
00046 ROS_ERROR("No template image is provided for object detection");
00047
00048 cv_ptr.reset (new cv_bridge::CvImage);
00049
00050
00051 int minHessian = 400;
00052 SurfFeatureDetector detector( minHessian );
00053 std::vector<KeyPoint> keypoints_object, keypoints_frame;
00054
00055 detector.detect( img_object, keypoints_object );
00056
00057
00058 SurfDescriptorExtractor extractor;
00059 Mat descriptors_object, descriptors_frame;
00060
00061 extractor.compute( img_object, keypoints_object, descriptors_object );
00062
00063
00064 FlannBasedMatcher matcher;
00065 std::vector< DMatch > matches;
00066
00067
00068
00069 int cnt = 0;
00070
00071 ros::param::param<std::string>("~name", name, "NAME");
00072
00073 while (ros::ok()) {
00074
00075 ros::spinOnce();
00076
00077 if (frame.empty()) {
00078 ROS_WARN("frame empty");
00079 ros::Duration(0.1).sleep();
00080 ros::spinOnce();
00081 continue;
00082 }
00083
00084 detector.detect(frame, keypoints_frame);
00085 extractor.compute(frame, keypoints_frame, descriptors_frame);
00086
00087 matcher.match(descriptors_object, descriptors_frame, matches);
00088
00089
00090 double max_dist = 0; double min_dist = 100;
00091
00092 for( int i = 0; i < descriptors_object.rows; i++ )
00093 { double dist = matches[i].distance;
00094 if( dist < min_dist ) min_dist = dist;
00095 if( dist > max_dist ) max_dist = dist;
00096 }
00097
00098
00099
00100
00101 std::vector< DMatch > good_matches;
00102
00103 for( int i = 0; i < descriptors_object.rows; i++ )
00104 { if( matches[i].distance < 3*min_dist )
00105 { good_matches.push_back( matches[i]); }
00106 }
00107
00108 Mat img_matches;
00109 drawMatches( img_object, keypoints_object, frame, keypoints_frame,
00110 good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
00111 vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
00112
00113
00114 std::vector<Point2f> obj;
00115 std::vector<Point2f> scene;
00116
00117 for( int i = 0; i < good_matches.size(); i++ )
00118 {
00119
00120 obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
00121 scene.push_back( keypoints_frame[ good_matches[i].trainIdx ].pt );
00122 }
00123
00124 if (obj.size() < 4 || scene.size() < 4)
00125 continue;
00126
00127 Mat H = findHomography( obj, scene, CV_RANSAC );
00128
00129
00130 std::vector<Point2f> obj_corners(4);
00131 obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( img_object.cols, 0 );
00132 obj_corners[2] = cvPoint( img_object.cols, img_object.rows );
00133 obj_corners[3] = cvPoint( 0, img_object.rows );
00134 std::vector<Point2f> scene_corners(4);
00135
00136 perspectiveTransform( obj_corners, scene_corners, H);
00137
00138
00139 line( img_matches, scene_corners[0] + Point2f( img_object.cols, 0),
00140 scene_corners[1] + Point2f( img_object.cols, 0),
00141 Scalar(0, 255, 0), 4 );
00142 line( img_matches, scene_corners[1] + Point2f( img_object.cols, 0),
00143 scene_corners[2] + Point2f( img_object.cols, 0),
00144 Scalar( 0, 255, 0), 4 );
00145 line( img_matches, scene_corners[2] + Point2f( img_object.cols, 0),
00146 scene_corners[3] + Point2f( img_object.cols, 0),
00147 Scalar( 0, 255, 0), 4 );
00148 line( img_matches, scene_corners[3] + Point2f( img_object.cols, 0),
00149 scene_corners[0] + Point2f( img_object.cols, 0),
00150 Scalar( 0, 255, 0), 4 );
00151
00152 float dis = 0.0;
00153 dis += norm( (scene_corners[0] + Point2f( img_object.cols, 0)) -
00154 (scene_corners[1] + Point2f( img_object.cols, 0)) );
00155 dis += norm( (scene_corners[1] + Point2f( img_object.cols, 0)) -
00156 (scene_corners[2] + Point2f( img_object.cols, 0)) );
00157 dis += norm( (scene_corners[2] + Point2f( img_object.cols, 0)) -
00158 (scene_corners[3] + Point2f( img_object.cols, 0)) );
00159 dis += norm( (scene_corners[3] + Point2f( img_object.cols, 0)) -
00160 (scene_corners[0] + Point2f( img_object.cols, 0)) );
00161
00162
00163
00164 if (dis > 500)
00165 cnt++;
00166 else
00167 cnt = 0;
00168
00169 ros::param::param<std::string>("~directory", directory, default_dir);
00170 if (boost::filesystem::is_directory(directory) == false)
00171 boost::filesystem::create_directory(directory);
00172 std::string file_object = directory + "object_matched.jpg";
00173 if (cnt >= 5) {
00174 imwrite(file_object, frame);
00175 res.path_to_image = file_object;
00176 return true;
00177 }
00178
00179 imshow( "WindowName", img_matches );
00180 waitKey(1);
00181
00182 }
00183
00184 destroyAllWindows();
00185
00186 return true;
00187 }
00188
00189 int main(int argc, char **argv) {
00190
00191 ros::init(argc, argv, "object_detection_server");
00192 ros::NodeHandle nh;
00193
00194
00195 ros::Subscriber sub = nh.subscribe("/nav_kinect/rgb/image_color", 1, callback);
00196 ros::ServiceServer service = nh.advertiseService("object_detection_service",
00197 callback_detection);
00198
00199 ros::Rate r(10);
00200 ros::Duration(2.0).sleep();
00201
00202 ros::spin();
00203
00204 return true;
00205 }