adding_images_nodelet.cpp
Go to the documentation of this file.
00001 // -*- mode: c++ -*-
00002 /*********************************************************************
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) JSK, 2016 Lab
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the JSK Lab nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *********************************************************************/
00035 
00036 // https://github.com/opencv/opencv/tree/2.4/samples/cpp/tutorial_code/ImgProc/AddingImages.cpp
00041 #include <opencv2/opencv.hpp>
00042 #include <cv_bridge/cv_bridge.h>
00043 #include <sensor_msgs/image_encodings.h>
00044 #include <sensor_msgs/CameraInfo.h>
00045 #include <dynamic_reconfigure/server.h>
00046 
00047 #include <image_transport/image_transport.h>
00048 #include <image_transport/subscriber_filter.h>
00049 
00050 #include <message_filters/subscriber.h>
00051 #include <message_filters/synchronizer.h>
00052 #include <message_filters/sync_policies/exact_time.h>
00053 #include <message_filters/sync_policies/approximate_time.h>
00054 
00055 #include "opencv_apps/AddingImagesConfig.h"
00056 #include "opencv_apps/nodelet.h"
00057 
00058 namespace adding_images {
00059   class AddingImagesNodelet : public opencv_apps::Nodelet {
00060   private:
00061     boost::shared_ptr<image_transport::ImageTransport> it_;
00062 
00063     typedef message_filters::sync_policies::ExactTime<
00064       sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo> SyncPolicyWithCameraInfo;
00065     typedef message_filters::sync_policies::ApproximateTime<
00066       sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo> ApproxSyncPolicyWithCameraInfo;
00067     typedef message_filters::sync_policies::ExactTime<
00068       sensor_msgs::Image, sensor_msgs::Image> SyncPolicy;
00069     typedef message_filters::sync_policies::ApproximateTime<
00070       sensor_msgs::Image, sensor_msgs::Image> ApproxSyncPolicy;
00071 
00073     // Dynamic Reconfigure
00075     typedef adding_images::AddingImagesConfig Config;
00076     typedef dynamic_reconfigure::Server<Config> ReconfigureServer;
00077     Config config_;
00078     boost::shared_ptr<ReconfigureServer> reconfigure_server_;
00079 
00080     bool debug_view_;
00081     ros::Time prev_stamp_;
00082 
00083     std::string window_name_;
00084 
00085     image_transport::SubscriberFilter sub_image1_, sub_image2_;
00086     image_transport::Publisher img_pub_;
00087     message_filters::Subscriber<sensor_msgs::CameraInfo> sub_camera_info_;
00088     boost::shared_ptr<message_filters::Synchronizer<SyncPolicyWithCameraInfo> > sync_with_info_;
00089     boost::shared_ptr<message_filters::Synchronizer<ApproxSyncPolicyWithCameraInfo> > async_with_info_;
00090     boost::shared_ptr<message_filters::Synchronizer<SyncPolicy> > sync_;
00091     boost::shared_ptr<message_filters::Synchronizer<ApproxSyncPolicy> > async_;
00092     boost::mutex mutex_;
00093 
00094     bool approximate_sync_;
00095     double alpha_;
00096     double beta_;
00097     double gamma_;
00098 
00099     void imageCallbackWithInfo(
00100       const sensor_msgs::ImageConstPtr& msg1,
00101       const sensor_msgs::ImageConstPtr& msg2,
00102       const sensor_msgs::CameraInfoConstPtr& cam_info) {
00103       do_work(msg1, msg2, cam_info->header.frame_id);
00104     }
00105 
00106     void imageCallback(const sensor_msgs::ImageConstPtr& msg1,
00107                        const sensor_msgs::ImageConstPtr& msg2) {
00108       do_work(msg1, msg2, msg1->header.frame_id);
00109     }
00110 
00111     void subscribe() {
00112       NODELET_DEBUG("Subscribing to image topic.");
00113       sub_image1_.subscribe(*it_, "image1", 3);
00114       sub_image2_.subscribe(*it_, "image2", 3);
00115       sub_camera_info_.subscribe(*nh_, "camera_info", 3);
00116       if (config_.use_camera_info) {
00117         if (approximate_sync_) {
00118           async_with_info_ = boost::make_shared<
00119             message_filters::Synchronizer<ApproxSyncPolicyWithCameraInfo> >(100);
00120           async_with_info_->connectInput(sub_image1_, sub_image2_, sub_camera_info_);
00121           async_with_info_->registerCallback(boost::bind(
00122             &AddingImagesNodelet::imageCallbackWithInfo, this, _1, _2, _3));
00123         } else {
00124           sync_with_info_ =
00125             boost::make_shared<message_filters::Synchronizer<SyncPolicyWithCameraInfo> >(100);
00126           sync_with_info_->connectInput(sub_image1_, sub_image2_, sub_camera_info_);
00127           sync_with_info_->registerCallback(boost::bind(
00128             &AddingImagesNodelet::imageCallbackWithInfo, this, _1, _2, _3));
00129         }
00130       } else {
00131         if (approximate_sync_) {
00132           async_ = boost::make_shared<
00133             message_filters::Synchronizer<ApproxSyncPolicy> >(100);
00134           async_->connectInput(sub_image1_, sub_image2_);
00135           async_->registerCallback(
00136             boost::bind(&AddingImagesNodelet::imageCallback, this, _1, _2));
00137         } else {
00138           sync_ =
00139             boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
00140           sync_->connectInput(sub_image1_, sub_image2_);
00141           sync_->registerCallback(
00142             boost::bind(&AddingImagesNodelet::imageCallback, this, _1, _2));
00143         }
00144       }
00145     }
00146 
00147     void unsubscribe() {
00148       NODELET_DEBUG("Unsubscribing from image topic.");
00149       sub_image1_.unsubscribe();
00150       sub_image2_.unsubscribe();
00151       sub_camera_info_.unsubscribe();
00152     }
00153 
00154     void reconfigureCallback(Config& config, uint32_t level) {
00155       boost::mutex::scoped_lock lock(mutex_);
00156       config_ = config;
00157       alpha_ = config.alpha;
00158       if ( config.auto_beta ) {
00159         beta_ = 1.0 - alpha_;
00160         config.beta = beta_;
00161       } else {
00162         beta_ = config.beta;
00163       }
00164       gamma_ = config.gamma;
00165     }
00166 
00167     void do_work(const sensor_msgs::Image::ConstPtr& image_msg1,
00168                  const sensor_msgs::Image::ConstPtr& image_msg2,
00169                  const std::string input_frame_from_msg) {
00170         boost::mutex::scoped_lock lock(mutex_);
00171       // Work on the image.
00172       try {
00173         cv::Mat image1 =
00174           cv_bridge::toCvShare(image_msg1, image_msg1->encoding)->image;
00175         cv::Mat image2 =
00176           cv_bridge::toCvShare(image_msg2, image_msg1->encoding)->image;
00177         if (cv_bridge::getCvType(image_msg1->encoding) != cv_bridge::getCvType(image_msg2->encoding)) {
00178           NODELET_ERROR("Encoding of input images must be same type: %s, %s",
00179                         image_msg1->encoding.c_str(), image_msg2->encoding.c_str());
00180           return;
00181         }
00182 
00183         cv::Mat result_image;
00184         cv::addWeighted(image1, alpha_, image2, beta_, gamma_, result_image);
00185         //-- Show what you got
00186         sensor_msgs::ImagePtr image_msg3 = cv_bridge::CvImage(image_msg1->header,
00187                                                               image_msg1->encoding,
00188                                                               result_image).toImageMsg();
00189         if (debug_view_) {
00190           cv::namedWindow(window_name_, cv::WINDOW_AUTOSIZE);
00191 #ifdef CV_BRIDGE_CVT_COLOR_FOR_DISPLAY_IS_NOT_SUPPORTED
00192           cv::imshow(window_name_, result_image);
00193 #else
00194 #ifdef CV_BRIDGE_CVT_COLOR_FOR_DISPLAY_OPTION_IS_NOT_SUPPORTED
00195           cv::imshow(window_name_, cv_bridge::cvtColorForDisplay(cv_bridge::toCvShare(image_msg3, image_msg3->encoding))->image);
00196 #else
00197           cv_bridge::CvtColorForDisplayOptions options;
00198           if (sensor_msgs::image_encodings::bitDepth(image_msg1->encoding) == 32 ||
00199               sensor_msgs::image_encodings::bitDepth(image_msg1->encoding) == 64) {
00200             // float or double image
00201             options.do_dynamic_scaling = true;
00202           }
00203           cv::imshow(window_name_, cv_bridge::cvtColorForDisplay(cv_bridge::toCvShare(image_msg3), "", options)->image);
00204 #endif
00205 #endif
00206           int c = cv::waitKey(1);
00207         }
00208         img_pub_.publish(image_msg3);
00209 
00210       } catch (cv::Exception& e) {
00211         NODELET_ERROR("Image processing error: %s %s %s %i", e.err.c_str(),
00212                       e.func.c_str(), e.file.c_str(), e.line);
00213       }
00214 
00215       prev_stamp_ = image_msg1->header.stamp;
00216     }
00217 
00218   public:
00219     virtual void onInit() {
00220       Nodelet::onInit();
00221       it_ = boost::shared_ptr<image_transport::ImageTransport>(
00222         new image_transport::ImageTransport(*nh_));
00223 
00224       pnh_->param("debug_view", debug_view_, false);
00225       if (debug_view_) {
00226         always_subscribe_ = true;
00227       }
00228       prev_stamp_ = ros::Time(0, 0);
00229 
00230       window_name_ = "AddingImages Demo";
00232       // Dynamic Reconfigure
00234       reconfigure_server_ =
00235         boost::make_shared<dynamic_reconfigure::Server<Config> >(*pnh_);
00236       dynamic_reconfigure::Server<Config>::CallbackType f =
00237         boost::bind(&AddingImagesNodelet::reconfigureCallback, this, _1, _2);
00238       reconfigure_server_->setCallback(f);
00239 
00240       pnh_->param("approximate_sync", approximate_sync_, true);
00241       img_pub_ = advertiseImage(*pnh_, "image", 1);
00242       onInitPostProcess();
00243     }
00244   };
00245 }
00246 
00247 #include <pluginlib/class_list_macros.h>
00248 PLUGINLIB_EXPORT_CLASS(adding_images::AddingImagesNodelet, nodelet::Nodelet);


opencv_apps
Author(s): Kei Okada
autogenerated on Tue May 2 2017 02:58:58