39 #ifndef PCL_VISUALIZATION_IMAGE_VISUALIZER_HPP_ 40 #define PCL_VISUALIZATION_IMAGE_VISUALIZER_HPP_ 42 #include <vtkVersion.h> 43 #include <vtkContextActor.h> 44 #include <vtkContextScene.h> 45 #include <vtkImageData.h> 46 #include <vtkImageFlip.h> 47 #include <vtkPointData.h> 48 #include <vtkImageViewer.h> 50 #include <pcl/visualization/common/common.h> 51 #include <pcl/search/organized.h> 54 template <
typename T>
void 57 boost::shared_array<unsigned char> &data)
60 for (
size_t i = 0; i < cloud.
points.size (); ++i)
62 data[j++] = cloud.
points[i].r;
63 data[j++] = cloud.
points[i].g;
64 data[j++] = cloud.
points[i].b;
69 template <
typename T>
void 71 const std::string &layer_id,
77 data_.reset (
new unsigned char[data_size_]);
80 convertRGBCloudToUChar (cloud, data_);
82 return (addRGBImage (data_.get (), cloud.
width, cloud.
height, layer_id, opacity));
86 template <
typename T>
void 88 const std::string &layer_id,
91 addRGBImage<T> (cloud, layer_id, opacity);
96 template <
typename T>
bool 100 double r,
double g,
double b,
101 const std::string &layer_id,
double opacity)
108 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
109 if (am_it == layer_map_.end ())
111 PCL_DEBUG (
"[pcl::visualization::ImageViewer::addMask] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
112 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity,
false);
118 std::vector<float> xy;
119 xy.reserve (mask.
size () * 2);
120 for (
size_t i = 0; i < mask.
size (); ++i)
125 xy.push_back (p_projected.
x);
126 #if ((VTK_MAJOR_VERSION >= 6) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION > 7))) 127 xy.push_back (static_cast<float> (image->
height) - p_projected.
y);
129 xy.push_back (p_projected.
y);
134 points->setColors (static_cast<unsigned char> (r*255.0),
135 static_cast<unsigned char> (g*255.0),
136 static_cast<unsigned char> (b*255.0));
137 points->setOpacity (opacity);
139 am_it->actor->GetScene ()->AddItem (points);
144 template <
typename T>
bool 148 const std::string &layer_id,
double opacity)
150 return (addMask (image, mask, 1.0, 0.0, 0.0, layer_id, opacity));
154 template <
typename T>
bool 158 double r,
double g,
double b,
159 const std::string &layer_id,
double opacity)
166 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
167 if (am_it == layer_map_.end ())
169 PCL_DEBUG (
"[pcl::visualization::ImageViewer::addPlanarPolygon] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
170 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity,
false);
176 std::vector<float> xy;
183 #if ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION <= 7)) 184 xy.push_back (static_cast<float> (image->
height) - p.
y);
191 xy[xy.size () - 2] = xy[0];
192 xy[xy.size () - 1] = xy[1];
195 poly->setColors (static_cast<unsigned char> (r * 255.0),
196 static_cast<unsigned char> (g * 255.0),
197 static_cast<unsigned char> (b * 255.0));
198 poly->setOpacity (opacity);
200 am_it->actor->GetScene ()->AddItem (poly);
206 template <
typename T>
bool 210 const std::string &layer_id,
double opacity)
212 return (addPlanarPolygon (image, polygon, 1.0, 0.0, 0.0, layer_id, opacity));
216 template <
typename T>
bool 221 double r,
double g,
double b,
222 const std::string &layer_id,
double opacity)
229 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
230 if (am_it == layer_map_.end ())
232 PCL_DEBUG (
"[pcl::visualization::ImageViewer::addRectangle] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
233 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity,
false);
240 T p1, p2, p3, p4, p5, p6, p7, p8;
241 p1.x = min_pt.x; p1.y = min_pt.y; p1.z = min_pt.z;
242 p2.x = min_pt.x; p2.y = min_pt.y; p2.z = max_pt.z;
243 p3.x = min_pt.x; p3.y = max_pt.y; p3.z = min_pt.z;
244 p4.x = min_pt.x; p4.y = max_pt.y; p4.z = max_pt.z;
245 p5.x = max_pt.x; p5.y = min_pt.y; p5.z = min_pt.z;
246 p6.x = max_pt.x; p6.y = min_pt.y; p6.z = max_pt.z;
247 p7.x = max_pt.x; p7.y = max_pt.y; p7.z = min_pt.z;
248 p8.x = max_pt.x; p8.y = max_pt.y; p8.z = max_pt.z;
250 std::vector<pcl::PointXY> pp_2d (8);
261 min_pt_2d.
x = min_pt_2d.
y = std::numeric_limits<float>::max ();
262 max_pt_2d.
x = max_pt_2d.
y = -std::numeric_limits<float>::max ();
264 for (
size_t i = 0; i < pp_2d.size (); ++i)
266 if (pp_2d[i].x < min_pt_2d.
x) min_pt_2d.
x = pp_2d[i].x;
267 if (pp_2d[i].y < min_pt_2d.
y) min_pt_2d.
y = pp_2d[i].y;
268 if (pp_2d[i].x > max_pt_2d.
x) max_pt_2d.
x = pp_2d[i].x;
269 if (pp_2d[i].y > max_pt_2d.
y) max_pt_2d.
y = pp_2d[i].y;
271 #if ((VTK_MAJOR_VERSION >= 6) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION > 7))) 272 min_pt_2d.
y = float (image->
height) - min_pt_2d.
y;
273 max_pt_2d.
y = float (image->
height) - max_pt_2d.
y;
277 rect->setColors (static_cast<unsigned char> (255.0 * r),
278 static_cast<unsigned char> (255.0 * g),
279 static_cast<unsigned char> (255.0 * b));
280 rect->setOpacity (opacity);
281 rect->set (min_pt_2d.
x, min_pt_2d.
y, max_pt_2d.
x, max_pt_2d.
y);
282 am_it->actor->GetScene ()->AddItem (rect);
288 template <
typename T>
bool 293 const std::string &layer_id,
double opacity)
295 return (addRectangle<T> (image, min_pt, max_pt, 0.0, 1.0, 0.0, layer_id, opacity));
299 template <
typename T>
bool 303 double r,
double g,
double b,
304 const std::string &layer_id,
double opacity)
311 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
312 if (am_it == layer_map_.end ())
314 PCL_DEBUG (
"[pcl::visualization::ImageViewer::addRectangle] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
315 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity,
false);
321 std::vector<pcl::PointXY> pp_2d (mask.
points.size ());
322 for (
size_t i = 0; i < mask.
points.size (); ++i)
326 min_pt_2d.
x = min_pt_2d.
y = std::numeric_limits<float>::max ();
327 max_pt_2d.
x = max_pt_2d.
y = -std::numeric_limits<float>::max ();
329 for (
size_t i = 0; i < pp_2d.size (); ++i)
331 if (pp_2d[i].x < min_pt_2d.
x) min_pt_2d.
x = pp_2d[i].x;
332 if (pp_2d[i].y < min_pt_2d.
y) min_pt_2d.
y = pp_2d[i].y;
333 if (pp_2d[i].x > max_pt_2d.
x) max_pt_2d.
x = pp_2d[i].x;
334 if (pp_2d[i].y > max_pt_2d.
y) max_pt_2d.
y = pp_2d[i].y;
336 #if ((VTK_MAJOR_VERSION >= 6) ||((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION > 7))) 337 min_pt_2d.
y = float (image->
height) - min_pt_2d.
y;
338 max_pt_2d.
y = float (image->
height) - max_pt_2d.
y;
342 rect->setColors (static_cast<unsigned char> (255.0 * r),
343 static_cast<unsigned char> (255.0 * g),
344 static_cast<unsigned char> (255.0 * b));
345 rect->setOpacity (opacity);
346 rect->set (min_pt_2d.
x, min_pt_2d.
y, max_pt_2d.
x, max_pt_2d.
y);
347 am_it->actor->GetScene ()->AddItem (rect);
353 template <
typename T>
bool 357 const std::string &layer_id,
double opacity)
359 return (addRectangle (image, mask, 0.0, 1.0, 0.0, layer_id, opacity));
363 template <
typename Po
intT>
bool 369 const std::string &layer_id)
371 if (correspondences.empty ())
373 PCL_DEBUG (
"[pcl::visualization::ImageViewer::addCorrespondences] An empty set of correspondences given! Nothing to display.\n");
378 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
379 if (am_it == layer_map_.end ())
381 PCL_DEBUG (
"[pcl::visualization::ImageViewer::addCorrespondences] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
382 am_it = createLayer (layer_id, source_img.
width + target_img.
width, std::max (source_img.
height, target_img.
height), 1.0,
false);
385 int src_size = source_img.
width * source_img.
height * 3;
386 int tgt_size = target_img.
width * target_img.
height * 3;
392 if (data_size_ < static_cast<size_t> (src_size + tgt_size))
394 data_size_ = src_size + tgt_size;
395 data_.reset (
new unsigned char[data_size_]);
400 for (
size_t i = 0; i < std::max (source_img.
height, target_img.
height); ++i)
403 if (i < source_img.
height)
405 for (
size_t k = 0; k < source_img.
width; ++k)
407 data_[j++] = source_img[i * source_img.
width + k].r;
408 data_[j++] = source_img[i * source_img.
width + k].g;
409 data_[j++] = source_img[i * source_img.
width + k].b;
414 memcpy (&data_[j], 0, source_img.
width * 3);
415 j += source_img.
width * 3;
419 if (i < source_img.
height)
421 for (
size_t k = 0; k < target_img.
width; ++k)
423 data_[j++] = target_img[i * source_img.
width + k].r;
424 data_[j++] = target_img[i * source_img.
width + k].g;
425 data_[j++] = target_img[i * source_img.
width + k].b;
430 memcpy (&data_[j], 0, target_img.
width * 3);
431 j += target_img.
width * 3;
435 void* data =
const_cast<void*
> (
reinterpret_cast<const void*
> (data_.get ()));
438 image->SetDimensions (source_img.
width + target_img.
width, std::max (source_img.
height, target_img.
height), 1);
439 #if VTK_MAJOR_VERSION < 6 440 image->SetScalarTypeToUnsignedChar ();
441 image->SetNumberOfScalarComponents (3);
442 image->AllocateScalars ();
444 image->AllocateScalars (VTK_UNSIGNED_CHAR, 3);
446 image->GetPointData ()->GetScalars ()->SetVoidArray (data, data_size_, 1);
448 #if ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION <= 10)) 450 algo_->SetInput (image);
452 image_item->set (0, 0, algo_->GetOutput ());
454 image_item->set (0, 0, image);
455 interactor_style_->adjustCamera (image, ren_);
457 am_it->actor->GetScene ()->AddItem (image_item);
458 image_viewer_->SetSize (image->GetDimensions ()[0], image->GetDimensions ()[1]);
461 for (
size_t i = 0; i < correspondences.size (); i += nth)
465 unsigned char u_r =
static_cast<unsigned char> (255.0 * r);
466 unsigned char u_g =
static_cast<unsigned char> (255.0 * g);
467 unsigned char u_b =
static_cast<unsigned char> (255.0 * b);
469 query_circle->setColors (u_r, u_g, u_b);
471 match_circle->setColors (u_r, u_g, u_b);
473 line->setColors (u_r, u_g, u_b);
475 float query_x = correspondences[i].index_query % source_img.
width;
476 float match_x = correspondences[i].index_match % target_img.
width + source_img.
width;
477 #if ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION > 10)) 478 float query_y = correspondences[i].index_query / source_img.
width;
479 float match_y = correspondences[i].index_match / target_img.
width;
481 float query_y = getSize ()[1] - correspondences[i].index_query / source_img.
width;
482 float match_y = getSize ()[1] - correspondences[i].index_match / target_img.
width;
485 query_circle->set (query_x, query_y, 3.0);
486 match_circle->set (match_x, match_y, 3.0);
487 line->set (query_x, query_y, match_x, match_y);
489 am_it->actor->GetScene ()->AddItem (query_circle);
490 am_it->actor->GetScene ()->AddItem (match_circle);
491 am_it->actor->GetScene ()->AddItem (line);
497 #endif // PCL_VISUALIZATION_IMAGE_VISUALIZER_HPP_ bool projectPoint(const PointT &p, pcl::PointXY &q) const
projects a point into the image
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
pcl::PointCloud< PointT >::VectorType & getContour()
Getter for the contour / boundary.
bool addMask(const typename pcl::PointCloud< T >::ConstPtr &image, const pcl::PointCloud< T > &mask, double r, double g, double b, const std::string &layer_id="image_mask", double opacity=0.5)
Add a generic 2D mask to an image.
void showRGBImage(const unsigned char *data, unsigned width, unsigned height, const std::string &layer_id="rgb_image", double opacity=1.0)
Show a 2D RGB image on screen.
A 2D point structure representing Euclidean xy coordinates.
uint32_t height
The point cloud height (if organized as an image-structure).
PCL_EXPORTS void getRandomColors(double &r, double &g, double &b, double min=0.2, double max=2.8)
Get (good) random values for R/G/B.
bool isOrganized() const
Return whether a dataset is organized (e.g., arranged in a structured grid).
uint32_t width
The point cloud width (if organized as an image-structure).
bool addRectangle(const pcl::PointXY &min_pt, const pcl::PointXY &max_pt, const std::string &layer_id="rectangles", double opacity=1.0)
Add a 2D box and color its edges with a given color.
PlanarPolygon represents a planar (2D) polygon, potentially in a 3D space.
void convertRGBCloudToUChar(const pcl::PointCloud< T > &cloud, boost::shared_array< unsigned char > &data)
Convert the RGB information in a PointCloud<T> to an unsigned char array.
std::vector< pcl::Correspondence, Eigen::aligned_allocator< pcl::Correspondence > > Correspondences
boost::shared_ptr< const PointCloud< PointT > > ConstPtr
bool addPlanarPolygon(const typename pcl::PointCloud< T >::ConstPtr &image, const pcl::PlanarPolygon< T > &polygon, double r, double g, double b, const std::string &layer_id="planar_polygon", double opacity=1.0)
Add a generic 2D planar polygon to an image.
bool showCorrespondences(const pcl::PointCloud< PointT > &source_img, const pcl::PointCloud< PointT > &target_img, const pcl::Correspondences &correspondences, int nth=1, const std::string &layer_id="correspondences")
Add the specified correspondences to the display.
void addRGBImage(const unsigned char *data, unsigned width, unsigned height, const std::string &layer_id="rgb_image", double opacity=1.0)
Add an RGB 2D image layer, but do not render it (use spin/spinOnce to update).
virtual void setInputCloud(const PointCloudConstPtr &cloud, const IndicesConstPtr &indices=IndicesConstPtr())
Provide a pointer to the input data set, if user has focal length he must set it before calling this...
OrganizedNeighbor is a class for optimized nearest neigbhor search in organized point clouds...