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_image_util/blend_images_util.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 swri_image_util::blendImages(
00163 cv_base_image->image,
00164 cv_top_image->image,
00165 alpha_,
00166 mask_color_,
00167 blended);
00168 }
00169 else
00170 {
00171 swri_image_util::blendImages(
00172 cv_base_image->image,
00173 cv_top_image->image,
00174 alpha_,
00175 blended);
00176 }
00177
00178
00179 cv_bridge::CvImagePtr cv_blended = boost::make_shared<cv_bridge::CvImage>();
00180 cv_blended->image = blended;
00181 cv_blended->encoding = cv_base_image->encoding;
00182 cv_blended->header = cv_base_image->header;
00183
00184 image_pub_.publish(cv_blended->toImageMsg());
00185 }
00186 }
00187
00188
00189 #include <pluginlib/class_list_macros.h>
00190 PLUGINLIB_DECLARE_CLASS(
00191 swri_image_util,
00192 blend_images,
00193 swri_image_util::BlendImagesNodelet,
00194 nodelet::Nodelet)