00001 #include <ros/ros.h>
00002 #include <message_filters/subscriber.h>
00003 #include <message_filters/synchronizer.h>
00004 #include <message_filters/sync_policies/approximate_time.h>
00005 #include <sensor_msgs/Image.h>
00006 #include <sensor_msgs/CameraInfo.h>
00007 #include <sensor_msgs/PointCloud2.h>
00008 #include <opencv2/opencv.hpp>
00009 #include <cv_bridge/cv_bridge.h>
00010 #include <pcl_conversions/pcl_conversions.h>
00011 #include <time.h>
00012
00013 #include <custom_landmark_2d/matcher.h>
00014
00015 typedef pcl::PointXYZRGB PointC;
00016 typedef pcl::PointCloud<pcl::PointXYZRGB> PointCloudC;
00017
00018 using namespace sensor_msgs;
00019 using namespace message_filters;
00020
00021 namespace custom_landmark_2d {
00022
00024 class Demor {
00025 public:
00026 Matcher matcher;
00027 sensor_msgs::CameraInfoConstPtr camera_info;
00028
00029 ros::Publisher cloud_pub;
00030 ros::Publisher matched_scene_pub;
00031
00032 void callback(const sensor_msgs::ImageConstPtr& rgb, const sensor_msgs::ImageConstPtr& depth);
00033 };
00034
00035 void Demor::callback(const sensor_msgs::ImageConstPtr& rgb, const sensor_msgs::ImageConstPtr& depth) {
00036
00037
00038 cv_bridge::CvImagePtr rgb_ptr;
00039 cv_bridge::CvImagePtr depth_ptr;
00040
00041 try {
00042 rgb_ptr = cv_bridge::toCvCopy(rgb, sensor_msgs::image_encodings::BGR8);
00043 depth_ptr = cv_bridge::toCvCopy(depth);
00044 }
00045 catch (cv_bridge::Exception& e) {
00046 ROS_ERROR("cv_bridge exception: %s", e.what());
00047 ros::shutdown();
00048 }
00049
00050 ros::param::param("match_limit", matcher.match_limit, (float) 0.68);
00051
00052
00053 std::vector<Frame> lst;
00054
00055 float start_tick = clock();
00056 bool result = matcher.Match(rgb_ptr->image, &lst);
00057 float end_tick = clock();
00058
00059 ROS_INFO("Match() runtime: %f", (end_tick - start_tick) / CLOCKS_PER_SEC);
00060
00061 if (!result) {
00062 ROS_INFO("no matched objects in 2d rgb scene...\n");
00063 return;
00064 }
00065
00066
00067 start_tick = clock();
00068
00069 std::vector<PointCloudC::Ptr> object_clouds;
00070 PointCloudC::Ptr object_cloud;
00071
00072 for (std::vector<Frame>::iterator it = lst.begin(); it != lst.end(); it++) {
00073 object_cloud = PointCloudC::Ptr(new PointCloudC());
00074
00075 if (matcher.FrameToCloud(rgb_ptr->image, depth_ptr->image, *it, object_cloud)) {
00076 object_clouds.push_back(object_cloud);
00077 }
00078 }
00079
00080
00081 end_tick = clock();
00082
00083 ROS_INFO("%lu calls to FrameToCloud() total runtime: %f\n", lst.size(), (end_tick - start_tick) / CLOCKS_PER_SEC);
00084
00085 if (object_clouds.empty()) {
00086 ROS_INFO("no valid matched object coordinate...\n");
00087 return;
00088 }
00089
00090
00091 ROS_INFO("#matched 2D objects: %lu\n", lst.size());
00092 ROS_INFO("-----------");
00093 for (int i = 0; i < lst.size(); i++) {
00094 Frame& f = lst[i];
00095 std::ostringstream stm;
00096 stm << i;
00097 rectangle( rgb_ptr->image, f.p1, f.p2, cv::Scalar(255, 255, 0), 4, 8, 0 );
00098 putText(rgb_ptr->image, stm.str(), cv::Point(f.p1.x - 10, f.p1.y - 10),
00099 cv::FONT_HERSHEY_COMPLEX_SMALL, 1.5, cv::Scalar(255, 255, 0), 2, CV_AA);
00100 ROS_INFO("frame score: %f, p1 pos: [%d, %d], index: %d", f.score, f.p1.x, f.p1.y, i);
00101 }
00102 ROS_INFO("-----------\n");
00103
00104 matched_scene_pub.publish(rgb_ptr->toImageMsg());
00105
00106
00107 PointCloudC::Ptr pcl_cloud(new PointCloudC());
00108 for (std::vector<PointCloudC::Ptr>::iterator it = object_clouds.begin(); it != object_clouds.end(); it++) {
00109 *pcl_cloud += **it;
00110 }
00111 ROS_INFO("#matched 3D objects: %lu", object_clouds.size());
00112 ROS_INFO("pcl cloud size: %lu\n", pcl_cloud->size());
00113
00114 sensor_msgs::PointCloud2 ros_cloud;
00115 pcl::toROSMsg(*pcl_cloud, ros_cloud);
00116 ros_cloud.header.frame_id = camera_info->header.frame_id;
00117
00118 cloud_pub.publish(ros_cloud);
00119 }
00120
00121 }
00122
00123 void print_usage() {
00124 std::cout << "\n"
00125 << "Listens to two sensor_msgs::Image topics and output an annotated version"
00126 << "of the rgb scene to /image_out as well as a concatenated pointcloud"
00127 << "containing all matched objects to /generated_cloud.\n"
00128 << "\n"
00129 << "Usage: rosrun custom_landmark_2d demo template.jpg rgb:=/topic1 depth:=/topic2 cam_info:=/topic3"
00130 << std::endl;
00131 }
00132
00133 int main(int argc, char** argv) {
00134
00135 if (argc < 5) {
00136 print_usage();
00137 return 1;
00138 }
00139
00140 ros::init(argc, argv, "demo");
00141 ros::NodeHandle nh;
00142
00143
00144 cv::Mat templ = cv::imread( argv[1], 1 );
00145
00146 if ( !templ.data ) {
00147 ROS_ERROR("No template data \n");
00148 return -1;
00149 }
00150
00151 custom_landmark_2d::Demor demor;
00152
00153
00154 demor.camera_info = ros::topic::waitForMessage<sensor_msgs::CameraInfo>("cam_info");
00155
00156 ROS_INFO("received camear_info...");
00157
00158
00159 demor.matcher.set_template(templ);
00160 demor.matcher.set_cam_model(demor.camera_info);
00161
00162
00163 demor.cloud_pub = nh.advertise<sensor_msgs::PointCloud2>("generated_cloud", 1, true);
00164 demor.matched_scene_pub = nh.advertise<sensor_msgs::Image>("image_out", 100);
00165
00166 message_filters::Subscriber<Image> rgb_sub(nh, "rgb", 1);
00167 message_filters::Subscriber<Image> depth_sub(nh, "depth", 1);
00168
00169 typedef sync_policies::ApproximateTime<Image, Image> SyncPolicy;
00170
00171 Synchronizer<SyncPolicy> sync(SyncPolicy(10), rgb_sub, depth_sub);
00172 sync.registerCallback(boost::bind(&custom_landmark_2d::Demor::callback, &demor, _1, _2));
00173
00174 ros::spin();
00175
00176 return 0;
00177 }