overlay_image_display.cpp
Go to the documentation of this file.
00001 // -*- mode: c++; -*-
00002 /*********************************************************************
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2014, JSK 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/o2r 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 #include "overlay_image_display.h"
00037 
00038 #include <OGRE/OgreMaterialManager.h>
00039 #include <OGRE/OgreTextureManager.h>
00040 #include <OGRE/OgreTexture.h>
00041 #include <OGRE/OgreHardwarePixelBuffer.h>
00042 #include <OGRE/OgreTechnique.h>
00043 
00044 #include <rviz/uniform_string_stream.h>
00045 #include <cv_bridge/cv_bridge.h>
00046 #include <sensor_msgs/image_encodings.h>
00047 
00048 namespace jsk_rviz_plugins
00049 {
00050 
00051   OverlayImageDisplay::OverlayImageDisplay()
00052     : Display(), width_(128), height_(128), left_(128), top_(128), alpha_(0.8),
00053       is_msg_available_(false), require_update_(false)
00054   {
00055     // setup properties
00056     update_topic_property_ = new rviz::RosTopicProperty(
00057       "Topic", "",
00058       ros::message_traits::datatype<sensor_msgs::Image>(),
00059       "sensor_msgs::Image topic to subscribe to.",
00060       this, SLOT( updateTopic() ));
00061     transport_hint_property_ = new ImageTransportHintsProperty("transport hint",
00062                                                               "transport hint to subscribe topic",
00063                                                               this, SLOT(updateTopic()));
00064     keep_aspect_ratio_property_ = new rviz::BoolProperty("keep aspect ratio", false,
00065                                                          "keep aspect ratio of original image",
00066                                                          this, SLOT(updateKeepAspectRatio()));
00067     width_property_ = new rviz::IntProperty("width", 128,
00068                                             "width of the image window",
00069                                             this, SLOT(updateWidth()));
00070     height_property_ = new rviz::IntProperty("height", 128,
00071                                              "height of the image window",
00072                                              this, SLOT(updateHeight()));
00073     left_property_ = new rviz::IntProperty("left", 128,
00074                                            "left of the image window",
00075                                            this, SLOT(updateLeft()));
00076     top_property_ = new rviz::IntProperty("top", 128,
00077                                           "top of the image window",
00078                                           this, SLOT(updateTop()));
00079     alpha_property_ = new rviz::FloatProperty("alpha", 0.8,
00080                                               "alpha belnding value",
00081                                               this, SLOT(updateAlpha()));
00082   }
00083 
00084   OverlayImageDisplay::~OverlayImageDisplay()
00085   {
00086     delete update_topic_property_;
00087     delete transport_hint_property_;
00088     delete keep_aspect_ratio_property_;
00089     delete width_property_;
00090     delete height_property_;
00091     delete left_property_;
00092     delete top_property_;
00093     delete alpha_property_;
00094   }
00095 
00096   void OverlayImageDisplay::onInitialize()
00097   {
00098     ros::NodeHandle nh;
00099     it_ = std::shared_ptr<image_transport::ImageTransport>(new image_transport::ImageTransport(nh));
00100 
00101     updateWidth();
00102     updateHeight();
00103     updateKeepAspectRatio();
00104     updateTop();
00105     updateLeft();
00106     updateAlpha();
00107     updateTopic();
00108   }
00109 
00110   void OverlayImageDisplay::onEnable()
00111   {
00112     if (overlay_) {
00113       overlay_->show();
00114     }
00115     subscribe();
00116   }
00117   void OverlayImageDisplay::onDisable()
00118   {
00119     if (overlay_) {
00120       overlay_->hide();
00121     }
00122     unsubscribe();
00123   }
00124 
00125   void OverlayImageDisplay::unsubscribe()
00126   {
00127     sub_.shutdown();
00128     // clear clear clear...
00129   }
00130 
00131   void OverlayImageDisplay::subscribe()
00132   {
00133     if (isEnabled()) {
00134       std::string topic_name = update_topic_property_->getTopicStd();
00135 
00136       if (topic_name.length() > 0 && topic_name != "/") {
00137         const image_transport::TransportHints transport_hint =
00138           transport_hint_property_->getTransportHints();
00139         sub_ = it_->subscribe(topic_name, 1, &OverlayImageDisplay::processMessage, this,
00140                               transport_hint);
00141       }
00142     }
00143   }
00144 
00145   void OverlayImageDisplay::processMessage(
00146     const sensor_msgs::Image::ConstPtr& msg)
00147   {
00148     boost::mutex::scoped_lock(mutex_);
00149     msg_ = msg;
00150     is_msg_available_ = true;
00151     require_update_ = true;
00152     if ((width_property_->getInt() < 0) || (height_property_->getInt() < 0) || keep_aspect_ratio_) {
00153       // automatically setup display size
00154       updateWidth();
00155       updateHeight();
00156     }
00157   }
00158 
00159 
00160   void OverlayImageDisplay::update(float wall_dt, float ros_dt)
00161   {
00162     boost::mutex::scoped_lock(mutex_);
00163 
00164     if (!isEnabled()) {
00165       return;
00166     }
00167 
00168     if (require_update_ && is_msg_available_) {
00169       if (!overlay_) {
00170         static int count = 0;
00171         rviz::UniformStringStream ss;
00172         ss << "OverlayImageDisplayObject" << count++;
00173         overlay_.reset(new OverlayObject(ss.str()));
00174         overlay_->show();
00175       }
00176       overlay_->updateTextureSize(msg_->width, msg_->height);
00177       // When aspect_ratio being kept, the size is specified by width;
00178       height_property_->setHidden(keep_aspect_ratio_);
00179       setImageSize();
00180       redraw();
00181       require_update_ = false;
00182     }
00183     if (overlay_) {
00184       overlay_->setDimensions(width_, height_);
00185       overlay_->setPosition(left_, top_);
00186     }
00187   }
00188 
00189   void OverlayImageDisplay::redraw()
00190   {
00191     try
00192     {
00193       if (msg_->width == 0 || msg_->height == 0) {
00194         // image width/height and texture width/height should be same
00195         // but they are not when input image width/height is 0
00196         return;
00197       }
00198       else {
00199         cv::Mat mat;  // mat should be BGRA8 image
00200 
00201         if (msg_->encoding == sensor_msgs::image_encodings::BGRA8 ||
00202             msg_->encoding == sensor_msgs::image_encodings::RGBA8) {
00203           const cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(
00204                   msg_, sensor_msgs::image_encodings::BGRA8);
00205           cv_ptr->image.copyTo(mat);
00206         } else {
00207             // If the image does not have alpha channel, use alpha_ value.
00208             const cv_bridge::CvImagePtr cv_ptr =
00209                     cv_bridge::toCvCopy(msg_, sensor_msgs::image_encodings::BGR8);
00210             const cv::Mat bgr_image = cv_ptr->image;
00211             std::vector<cv::Mat> channels;
00212             // Split BGR image to each channel because cv::merge requires 4 images to create
00213             // B-G-R-A image. The each 4 image represents each channel.
00214             cv::split(bgr_image, channels);
00215             // Create single alpha channel image
00216             const cv::Mat alpha(bgr_image.rows, bgr_image.cols, CV_8UC1,
00217                                 cv::Scalar(alpha_ * 255.0));
00218             channels.push_back(alpha);
00219             cv::merge(channels, mat);
00220         }
00221 
00222         ScopedPixelBuffer buffer = overlay_->getBuffer();
00223         QImage Hud = buffer.getQImage(*overlay_);
00224         // QImage created from ScopedPixelBuffer has no padding between each line.
00225         memcpy(Hud.scanLine(0), mat.data, mat.cols * mat.rows * mat.elemSize());
00226       }
00227     }
00228     catch (cv_bridge::Exception& e)
00229     {
00230       ROS_ERROR("cv_bridge exception: %s", e.what());
00231     }
00232   }
00233 
00234   void OverlayImageDisplay::updateTopic()
00235   {
00236     unsubscribe();
00237     subscribe();
00238   }
00239 
00240   void OverlayImageDisplay::setImageSize()
00241   {
00242     if (width_ == -1) {
00243       if (is_msg_available_) {
00244         width_ = msg_->width;
00245       }
00246       else {
00247         width_ = 128;
00248       }
00249     }
00250 
00251     if (height_ == -1) {
00252       if (is_msg_available_) {
00253         height_ = msg_->height;
00254       }
00255       else {
00256         height_ = 128;
00257       }
00258     }
00259 
00260     if (keep_aspect_ratio_ && is_msg_available_) {
00261       // When aspect_ratio being kept, the size is specified by width;
00262       double aspect_ratio = msg_->height / (double)msg_->width;
00263       int height_from_width = std::ceil(width_ * aspect_ratio);
00264       height_ = height_from_width;
00265     }
00266 
00267   }
00268 
00269   void OverlayImageDisplay::updateWidth()
00270   {
00271     boost::mutex::scoped_lock lock(mutex_);
00272     width_ = width_property_->getInt();
00273     require_update_ = true;
00274   }
00275 
00276   void OverlayImageDisplay::updateHeight()
00277   {
00278     boost::mutex::scoped_lock lock(mutex_);
00279     height_ = height_property_->getInt();
00280     require_update_ = true;
00281   }
00282 
00283   void OverlayImageDisplay::updateTop()
00284   {
00285     boost::mutex::scoped_lock lock(mutex_);
00286     top_ = top_property_->getInt();
00287   }
00288 
00289   void OverlayImageDisplay::updateLeft()
00290   {
00291     boost::mutex::scoped_lock lock(mutex_);
00292     left_ = left_property_->getInt();
00293   }
00294 
00295   void OverlayImageDisplay::updateAlpha()
00296   {
00297     boost::mutex::scoped_lock lock(mutex_);
00298     alpha_ = alpha_property_->getFloat();
00299   }
00300 
00301   void OverlayImageDisplay::updateKeepAspectRatio()
00302   {
00303     boost::mutex::scoped_lock lock(mutex_);
00304     keep_aspect_ratio_ = keep_aspect_ratio_property_->getBool();
00305     require_update_ = true;
00306   }
00307 
00308   bool OverlayImageDisplay::isInRegion(int x, int y)
00309   {
00310     return (top_ < y && top_ + height_ > y &&
00311             left_ < x && left_ + width_ > x);
00312   }
00313 
00314   void OverlayImageDisplay::movePosition(int x, int y)
00315   {
00316     top_ = y;
00317     left_ = x;
00318   }
00319 
00320   void OverlayImageDisplay::setPosition(int x, int y)
00321   {
00322     top_property_->setValue(y);
00323     left_property_->setValue(x);
00324   }
00325 
00326 }
00327 
00328 #include <pluginlib/class_list_macros.h>
00329 PLUGINLIB_EXPORT_CLASS( jsk_rviz_plugins::OverlayImageDisplay, rviz::Display )


jsk_rviz_plugins
Author(s): Kei Okada , Yohei Kakiuchi , Shohei Fujii , Ryohei Ueda
autogenerated on Wed May 1 2019 02:40:22