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 "rviz_interaction_tools/image_overlay.h"
00031 #include "rviz_interaction_tools/image_tools.h"
00032 #include "rviz_interaction_tools/unique_string_manager.h"
00033
00034 #include <sensor_msgs/image_encodings.h>
00035
00036 #include <vector>
00037
00038 #include <OGRE/OgreSceneNode.h>
00039 #include <OGRE/OgreRectangle2D.h>
00040 #include <OGRE/OgreMaterialManager.h>
00041 #include <OGRE/OgreTextureManager.h>
00042 #include <OGRE/OgreTechnique.h>
00043
00044 using namespace Ogre;
00045
00046 namespace rviz_interaction_tools
00047 {
00048
00049 ImageOverlay::ImageOverlay( Ogre::SceneNode* scene_root, unsigned char render_queue_group ) :
00050 scene_root_(scene_root),
00051 new_image_(false),
00052 width_(0),
00053 height_(0)
00054 {
00055
00056 Ogre::PixelFormat format = Ogre::PF_BYTE_RGB;
00057 std::vector<unsigned char> empty_buffer;
00058
00059 empty_buffer.assign(100 * 100 * 3, 0);
00060 void* data_ptr = (void*) &empty_buffer[0];
00061 uint32_t data_size = empty_buffer.size();
00062
00063 Ogre::DataStreamPtr pixel_stream;
00064 pixel_stream.bind(new Ogre::MemoryDataStream(data_ptr, data_size));
00065
00066 try
00067 {
00068 empty_image_.loadRawData(pixel_stream, 100, 100, 1, format, 1, 0);
00069 } catch (Ogre::Exception& e)
00070 {
00071 ROS_ERROR("Error loading image: %s", e.what());
00072 }
00073
00074 UniqueStringManager unique_string_mgr;
00075
00076 resource_group_name_ = unique_string_mgr.unique("rviz_interaction_tools::ImageOverlay");
00077 Ogre::ResourceGroupManager::getSingleton().createResourceGroup(resource_group_name_);
00078 Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup(resource_group_name_);
00079
00080
00081 texture_ = Ogre::TextureManager::getSingleton().loadImage(
00082 unique_string_mgr.unique("ImageOverlayTexture"),
00083 resource_group_name_, empty_image_,
00084 Ogre::TEX_TYPE_2D, 0);
00085
00086
00087 texture_material_ = Ogre::MaterialManager::getSingleton().create(
00088 unique_string_mgr.unique("ImageOverlayMaterial"),
00089 resource_group_name_);
00090
00091 Ogre::TextureUnitState* texture_unit =
00092 texture_material_->getTechnique(0)->getPass(0)->createTextureUnitState();
00093 texture_unit->setTextureName(texture_->getName());
00094 texture_unit->setTextureFiltering(Ogre::TFO_NONE);
00095
00096 texture_material_->setSceneBlending(Ogre::SBT_REPLACE);
00097 texture_material_->setDepthWriteEnabled(false);
00098 texture_material_->setReceiveShadows(false);
00099 texture_material_->setDepthCheckEnabled(false);
00100 texture_material_->getTechnique(0)->setLightingEnabled(false);
00101 texture_material_->setCullingMode(Ogre::CULL_NONE);
00102
00103 image_rect_ = new Ogre::Rectangle2D(true);
00104
00105 image_rect_->setRenderQueueGroup(render_queue_group);
00106 image_rect_->setCorners(-1.0f, 1.0f, 1.0f, -1.0f);
00107 image_rect_->setMaterial(texture_material_->getName());
00108 image_rect_->setQueryFlags(0);
00109
00110 Ogre::AxisAlignedBox aabInf;
00111 aabInf.setInfinite();
00112 image_rect_->setBoundingBox(aabInf);
00113
00114 scene_root_->attachObject(image_rect_);
00115 }
00116
00117 ImageOverlay::~ImageOverlay()
00118 {
00119 Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup(resource_group_name_);
00120 scene_root_->detachObject(image_rect_);
00121 delete image_rect_;
00122 }
00123
00124 bool ImageOverlay::setImage( const sensor_msgs::Image &image,
00125 const stereo_msgs::DisparityImage &disparity_image )
00126 {
00127 boost::mutex::scoped_lock lock(mutex_);
00128
00129 if (!setImageNoLock(image))
00130 {
00131 return false;
00132 }
00133
00134 if ((image.width != disparity_image.image.width) || (image.height
00135 != disparity_image.image.height))
00136 {
00137 ROS_ERROR("Size mismatch between image (%i x %i) and disparity image (%i x %i)!",
00138 image.width, image.height, disparity_image.image.width, disparity_image.image.height );
00139 return false;
00140 }
00141
00142
00143 for (unsigned int i = 0; i < image.height; i++)
00144 {
00145 for (unsigned int j = 0; j < image.width; j++)
00146 {
00147 unsigned int adr = i * image.width + j;
00148 if (!rviz_interaction_tools::hasDisparityValue(disparity_image, i, j))
00149 {
00150 if (image_buffer_[3 * adr + 0] < 215)
00151 image_buffer_[3 * adr + 0] += 40;
00152 else
00153 image_buffer_[3 * adr + 0] = 255;
00154 if (image_buffer_[3 * adr + 1] > 200)
00155 image_buffer_[3 * adr + 1] = 200;
00156 if (image_buffer_[3 * adr + 2] > 200)
00157 image_buffer_[3 * adr + 2] = 200;
00158 }
00159 }
00160 }
00161
00162 new_image_ = true;
00163
00164 return true;
00165 }
00166
00167 bool ImageOverlay::setImage( const sensor_msgs::Image &image )
00168 {
00169 boost::mutex::scoped_lock lock(mutex_);
00170
00171 if (!setImageNoLock(image))
00172 {
00173 return false;
00174 }
00175
00176 new_image_ = true;
00177 return true;
00178 }
00179
00180 bool ImageOverlay::setImageNoLock( const sensor_msgs::Image &image )
00181 {
00182 width_ = image.width;
00183 height_ = image.height;
00184
00185
00186 image_buffer_.resize(3 * width_ * height_, 0);
00187
00188 if (image.encoding == sensor_msgs::image_encodings::MONO8)
00189 {
00190 for (unsigned int i = 0; i < image.height; i++)
00191 {
00192 for (unsigned int j = 0; j < image.width; j++)
00193 {
00194 unsigned int adr = i * image.width + j;
00195 image_buffer_[3 * adr + 0] = image.data[adr];
00196 image_buffer_[3 * adr + 1] = image.data[adr];
00197 image_buffer_[3 * adr + 2] = image.data[adr];
00198 }
00199 }
00200 }
00201 else if (image.encoding == sensor_msgs::image_encodings::BGR8)
00202 {
00203 for (unsigned int i = 0; i < image.height; i++)
00204 {
00205 for (unsigned int j = 0; j < image.width; j++)
00206 {
00207 unsigned int adr = i * image.width + j;
00208 unsigned int adr2 = i * image.step + j*3;
00209 image_buffer_[3 * adr + 0] = image.data[adr2 + 2];
00210 image_buffer_[3 * adr + 1] = image.data[adr2 + 1];
00211 image_buffer_[3 * adr + 2] = image.data[adr2 + 0];
00212 }
00213 }
00214 }
00215 else if (image.encoding == sensor_msgs::image_encodings::RGB8)
00216 {
00217 image_buffer_ = image.data;
00218 }
00219 else
00220 {
00221 ROS_ERROR("ImageDisplay only supports MONO8, RGB8 and BGR8 images");
00222 return false;
00223 }
00224
00225 return true;
00226 }
00227
00228 bool ImageOverlay::setImage( unsigned char *rgb_data, int width, int height )
00229 {
00230 boost::mutex::scoped_lock lock(mutex_);
00231
00232 if (width <= 0 || height <= 0)
00233 {
00234 ROS_ERROR( "Image dimensions must be > 0" );
00235 return false;
00236 }
00237
00238 width_ = width;
00239 height_ = height;
00240
00241 image_buffer_.resize(width * height * 3, 0);
00242 memcpy(&image_buffer_[0], rgb_data, width * height * 3);
00243
00244 return true;
00245 }
00246
00247 bool ImageOverlay::update()
00248 {
00249 boost::mutex::scoped_lock lock(mutex_);
00250
00251 if (!new_image_ || !width_ || image_buffer_.size() != unsigned(width_
00252 * height_ * 3))
00253 {
00254 return false;
00255 }
00256
00257 Ogre::PixelFormat format = Ogre::PF_BYTE_RGB;
00258
00259 void* data_ptr = (void*) &image_buffer_[0];
00260 uint32_t data_size = image_buffer_.size();
00261
00262 Ogre::DataStreamPtr pixel_stream;
00263 pixel_stream.bind(new Ogre::MemoryDataStream(data_ptr, data_size));
00264
00265 Ogre::Image ogre_image;
00266
00267 try
00268 {
00269 ogre_image.loadRawData(pixel_stream, width_, height_, 1, format, 1, 0);
00270 } catch (Ogre::Exception& e)
00271 {
00272 ROS_ERROR("Error loading image: %s", e.what());
00273 return false;
00274 }
00275
00276 texture_->unload();
00277 texture_->loadImage(ogre_image);
00278
00279 return true;
00280 }
00281
00282 void ImageOverlay::clear()
00283 {
00284 boost::mutex::scoped_lock lock(mutex_);
00285
00286 texture_->unload();
00287
00288 new_image_ = false;
00289 }
00290
00291 int ImageOverlay::getWidth()
00292 {
00293 boost::mutex::scoped_lock lock(mutex_);
00294 int w = width_;
00295 return w;
00296 }
00297
00298 int ImageOverlay::getHeight()
00299 {
00300 boost::mutex::scoped_lock lock(mutex_);
00301 int h = height_;
00302 return h;
00303 }
00304
00305 }