texture_point_cloud.cpp
Go to the documentation of this file.
1 // Do not change the order of this block. Otherwise getBinaryData with CV::mat overload will not be recognized
2 #include <cv_bridge/cv_bridge.h>
4 
5 #include <pcl_ros/point_cloud.h>
6 #include <ros/ros.h>
7 #include <sensor_msgs/Image.h>
8 
9 #include <mutex>
10 #include <string>
11 
12 using PointCloud = pcl::PointCloud<pcl::PointXYZ>;
13 using TexturedPointCloud = pcl::PointCloud<pcl::PointXYZRGB>;
14 
20 TexturedPointCloud::Ptr texturePointCloudFromRectifiedImage(cv::Mat const& image,
21  PointCloud::ConstPtr const& pointCloud)
22 {
23  auto texturedPointCloud = boost::make_shared<TexturedPointCloud>();
24 
25  if (static_cast<int>(pointCloud->width) != image.cols || static_cast<int>(pointCloud->height) != image.rows)
26  {
27  ROS_ERROR("The point cloud does not have the same format as the rectified "
28  "image!");
29  return texturedPointCloud;
30  }
31 
32  texturedPointCloud->header.frame_id = pointCloud->header.frame_id;
33  texturedPointCloud->header.stamp = pointCloud->header.stamp;
34 
35  texturedPointCloud->is_dense = pointCloud->is_dense;
36  texturedPointCloud->width = pointCloud->width;
37  texturedPointCloud->height = pointCloud->height;
38  texturedPointCloud->points.resize(texturedPointCloud->width * texturedPointCloud->height);
39 
40  for (size_t x = 0; x < pointCloud->width; x++)
41  {
42  for (size_t y = 0; y < pointCloud->height; y++)
43  {
44  auto& point = texturedPointCloud->at(x, y);
45 
46  point.x = pointCloud->at(x, y).x;
47  point.y = pointCloud->at(x, y).y;
48  point.z = pointCloud->at(x, y).z;
49 
50  if (image.channels() == 3)
51  {
52  cv::Vec3b color = image.at<cv::Vec3b>(y, x);
53  point.b = color.val[0];
54  point.g = color.val[1];
55  point.r = color.val[2];
56  }
57  else
58  {
59  uchar color = image.at<uchar>(y, x);
60  point.r = color;
61  point.g = color;
62  point.b = color;
63  }
64  }
65  }
66 
67  return texturedPointCloud;
68 }
69 
71 {
72 private:
74 
75  std::mutex mutex;
76 
80 
81  sensor_msgs::ImageConstPtr latestImage;
82  PointCloud::ConstPtr latestPointCloud;
83 
84 public:
86  {
87  image_transport::ImageTransport imageTransport(nodeHandle);
88 
89  imageSubscriber = imageTransport.subscribe("image", 10, &TexturingNode::onImageReceived, this);
90  pointCloudSubscriber = nodeHandle.subscribe("point_cloud", 10, &TexturingNode::onPointCloudReceived, this);
91 
92  texturedPointCloudPublisher = nodeHandle.advertise<TexturedPointCloud>("textured_point_cloud", 1);
93  }
94 
95 private:
96  void onImageReceived(sensor_msgs::ImageConstPtr const& image)
97  {
98  std::lock_guard<std::mutex> lock(mutex);
99 
100  latestImage = image;
101  }
102 
103  void onPointCloudReceived(PointCloud::ConstPtr const& pointCloud)
104  {
105  std::lock_guard<std::mutex> lock(mutex);
106 
107  latestPointCloud = pointCloud;
108  texture();
109  }
110 
111  void texture() const
112  {
113  if (!latestImage.get() || !latestPointCloud.get())
114  return;
115 
117  try
118  {
119  image = cv_bridge::toCvShare(latestImage);
120  }
121  catch (cv_bridge::Exception& e)
122  {
123  ROS_ERROR("cv_bridge exception: %s", e.what());
124  }
125 
126  TexturedPointCloud::Ptr texturedPointCloud;
127  texturedPointCloud = texturePointCloudFromRectifiedImage(image->image, latestPointCloud);
128 
129  texturedPointCloudPublisher.publish(texturedPointCloud);
130  }
131 };
132 
133 int main(int argc, char** argv)
134 {
135  ros::init(argc, argv, "texture_point_cloud");
136 
138  ros::spin();
139 
140  return EXIT_SUCCESS;
141 }
sensor_msgs::ImageConstPtr latestImage
PointCloud::ConstPtr latestPointCloud
CvImageConstPtr toCvShare(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
image_transport::Subscriber imageSubscriber
Subscriber subscribe(const std::string &base_topic, uint32_t queue_size, const boost::function< void(const sensor_msgs::ImageConstPtr &)> &callback, const ros::VoidPtr &tracked_object=ros::VoidPtr(), const TransportHints &transport_hints=TransportHints())
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
int main(int argc, char **argv)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
sensor_msgs::PointCloud2 PointCloud
TFSIMD_FORCE_INLINE const tfScalar & y() const
geometry_msgs::TransformStamped t
ros::Subscriber pointCloudSubscriber
ROSCPP_DECL void spin(Spinner &spinner)
void onImageReceived(sensor_msgs::ImageConstPtr const &image)
pcl::PointCloud< pcl::PointXYZRGB > TexturedPointCloud
TFSIMD_FORCE_INLINE const tfScalar & x() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void onPointCloudReceived(PointCloud::ConstPtr const &pointCloud)
TexturedPointCloud::Ptr texturePointCloudFromRectifiedImage(cv::Mat const &image, PointCloud::ConstPtr const &pointCloud)
ros::NodeHandle nodeHandle
ros::Publisher texturedPointCloudPublisher
void texture() const
#define ROS_ERROR(...)


ensenso_camera
Author(s): Ensenso
autogenerated on Thu May 6 2021 02:50:06