Go to the documentation of this file.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 #include <opencv2/core/core.hpp>
00031
00032 #include <ros/ros.h>
00033 #include <cv_bridge/cv_bridge.h>
00034 #include <nodelet/nodelet.h>
00035 #include <image_transport/image_transport.h>
00036 #include <message_filters/subscriber.h>
00037 #include <message_filters/time_synchronizer.h>
00038 #include <message_filters/sync_policies/approximate_time.h>
00039 #include <sensor_msgs/Image.h>
00040 #include <swri_opencv_util/blend.h>
00041
00042 namespace swri_image_util
00043 {
00044 const double DEFAULT_ALPHA_LEVEL = 0.5;
00045 const cv::Scalar NO_MASK = cv::Scalar(-1, -1, -1);
00046
00047
00048 class BlendImagesNodelet : public nodelet::Nodelet
00049 {
00050 public:
00051 BlendImagesNodelet();
00052 ~BlendImagesNodelet();
00053 private:
00054
00055
00056
00057 typedef message_filters::sync_policies::ApproximateTime<
00058 sensor_msgs::Image, sensor_msgs::Image> ApproximateTimePolicy;
00059 typedef message_filters::Synchronizer<ApproximateTimePolicy>
00060 ApproximateTimeSync;
00061
00062 virtual void onInit();
00063
00064 void imageCallback(
00065 const sensor_msgs::ImageConstPtr &base_image,
00066 const sensor_msgs::ImageConstPtr &top_image);
00067
00068 double alpha_;
00069
00070 cv::Scalar mask_color_;
00071
00072 image_transport::Publisher image_pub_;
00073
00074 message_filters::Subscriber<sensor_msgs::Image> base_image_sub_;
00075 message_filters::Subscriber<sensor_msgs::Image> top_image_sub_;
00076
00077
00078 boost::shared_ptr<ApproximateTimeSync> image_sync_;
00079 };
00080
00081 BlendImagesNodelet::BlendImagesNodelet() :
00082 alpha_(DEFAULT_ALPHA_LEVEL),
00083 mask_color_(NO_MASK)
00084 {
00085 }
00086
00087 BlendImagesNodelet::~BlendImagesNodelet()
00088 {
00089 }
00090
00091 void BlendImagesNodelet::onInit()
00092 {
00093
00094 ros::NodeHandle& node = getNodeHandle();
00095 ros::NodeHandle& priv = getPrivateNodeHandle();
00096
00097
00098
00099 priv.param("alpha", alpha_, alpha_);
00100
00101
00102 double mask_r;
00103 double mask_g;
00104 double mask_b;
00105 priv.param("mask_r", mask_r, -1.0);
00106 priv.param("mask_g", mask_g, -1.0);
00107 priv.param("mask_b", mask_b, -1.0);
00108
00109
00110 if ((mask_r >= 0) && (mask_g >= 0) && (mask_b >= 0) &&
00111 (mask_r <= 255) && (mask_g <= 255) && (mask_b <= 255))
00112 {
00113 mask_color_ = cv::Scalar(mask_r, mask_g, mask_b);
00114 }
00115 else
00116 {
00117 ROS_ERROR("Mask color components must be in range [0,255]");
00118 ROS_ERROR(" Components were (%f, %f, %f)", mask_r, mask_g, mask_b);
00119 }
00120
00121
00122
00123 image_transport::ImageTransport it(node);
00124 image_pub_ = it.advertise("blended_image", 1);
00125 base_image_sub_.subscribe(node, "base_image", 1);
00126 top_image_sub_.subscribe(node, "top_image", 1);
00127 image_sync_.reset(new ApproximateTimeSync(
00128 ApproximateTimePolicy(10),
00129 base_image_sub_,
00130 top_image_sub_));
00131
00132 image_sync_->registerCallback(boost::bind(
00133 &BlendImagesNodelet::imageCallback,
00134 this,
00135 _1,
00136 _2));
00137 }
00138
00139 void BlendImagesNodelet::imageCallback(
00140 const sensor_msgs::ImageConstPtr& base_image,
00141 const sensor_msgs::ImageConstPtr& top_image)
00142 {
00143
00144
00145
00146 cv_bridge::CvImageConstPtr cv_base_image = cv_bridge::toCvShare(base_image);
00147
00148
00149 cv_bridge::CvImageConstPtr cv_top_image = cv_bridge::toCvShare(
00150 top_image,
00151 base_image->encoding);
00152
00153
00154 cv::Mat blended = cv::Mat::zeros(
00155 cv_base_image->image.rows,
00156 cv_base_image->image.cols,
00157 cv_base_image->image.type());
00158
00159
00160 if (mask_color_ != NO_MASK)
00161 {
00162 cv::Mat mask;
00163 cv::inRange(cv_top_image->image, mask_color_, mask_color_, mask);
00164
00165 blended = swri_opencv_util::overlayColor(
00166 cv_base_image->image,
00167 mask,
00168 mask_color_,
00169 alpha_);
00170 }
00171 else
00172 {
00173 blended = swri_opencv_util::blend(
00174 cv_top_image->image,
00175 cv_base_image->image,
00176 alpha_);
00177 }
00178
00179
00180 cv_bridge::CvImagePtr cv_blended = boost::make_shared<cv_bridge::CvImage>();
00181 cv_blended->image = blended;
00182 cv_blended->encoding = cv_base_image->encoding;
00183 cv_blended->header = cv_base_image->header;
00184
00185 image_pub_.publish(cv_blended->toImageMsg());
00186 }
00187 }
00188
00189
00190 #include <swri_nodelet/class_list_macros.h>
00191 SWRI_NODELET_EXPORT_CLASS(swri_image_util, BlendImagesNodelet)