demo_main.cpp
Go to the documentation of this file.
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   // convert sensor_msgs::Images to cv::Mats
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); // 32FC1
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   // run & time Match()
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   // run & time FrameToCloud()
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   // alternatively, you can call Match to directly return a vector of object_clouds as well:
00080   // matcher.Match(rgb_ptr->image, depth_ptr->image, &object_clouds);
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   // annotates rgb_ptr->image & publish it
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   // concatenate the vector of pointClouds into a single one & publish it
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; // head_camera_rgb_optical_frame
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   // Load template from stdin
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   // fetch CameraInfo
00154   demor.camera_info = ros::topic::waitForMessage<sensor_msgs::CameraInfo>("cam_info");
00155 
00156   ROS_INFO("received camear_info...");
00157 
00158   // setup the matcher
00159   demor.matcher.set_template(templ);
00160   demor.matcher.set_cam_model(demor.camera_info);
00161 
00162   // setup published topics
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   // ApproximateTime takes a queue size as its constructor argument, hence SyncPolicy(10)
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 }


custom_landmark_2d
Author(s):
autogenerated on Thu Jun 6 2019 18:35:43