6 #include <opencv2/imgproc.hpp>
13 struct __attribute__((packed))
Rgb
23 RowView(
const std::uint8_t *
const data)
24 : data(reinterpret_cast<const T *>(data))
28 const T &getColumn(
const std::size_t column)
const noexcept
33 inline const T &operator[] (
const std::size_t column)
const noexcept
35 return getColumn(column);
44 ImageView(
const std::uint8_t *
const data,
const std::size_t step)
50 inline RowView<T> getRow(
const std::size_t row)
const noexcept
52 return RowView<T>(data + row * step);
55 inline RowView<T> operator[] (
const std::size_t row)
const noexcept
60 const std::uint8_t *data;
72 sensor_msgs::PointCloud
astra_ros::toPointCloud(
const sensor_msgs::Image &rgb,
const sensor_msgs::Image ®istered_depth,
const sensor_msgs::CameraInfo &camera_info,
const std::function<
bool (
const std::size_t x,
const std::size_t y)> &mask)
79 const double fx = camera_info.K[0];
80 const double fy = camera_info.K[4];
81 const double cx = camera_info.K[2];
82 const double cy = camera_info.K[5];
84 if (rgb.encoding !=
RGB8)
86 throw std::runtime_error(
"Expected RGB image to be RGB8 encoded");
89 if (registered_depth.encoding !=
MONO16)
91 throw std::runtime_error(
"Expected registered depth image to be MONO16 encoded");
94 if (rgb.height != registered_depth.height || rgb.width != registered_depth.width)
97 o <<
"Size mismatch. RGB image was (" << rgb.width <<
", " << rgb.height <<
")"
98 <<
", but registered depth image was (" << registered_depth.width <<
", " << registered_depth.height <<
")";
100 throw std::runtime_error(o.str());
103 if (rgb.height * rgb.step != rgb.data.size())
105 throw std::runtime_error(
"RGB image is malformed. height * step != size");
108 if (registered_depth.height * registered_depth.step != registered_depth.data.size())
110 throw std::runtime_error(
"Registered depth image is malformed. height * step != size");
113 const std::size_t rgb_pixel_size = bitDepth(rgb.encoding) * numChannels(rgb.encoding);
114 const std::size_t depth_pixel_size = bitDepth(rgb.encoding) * numChannels(rgb.encoding);
119 sensor_msgs::ChannelFloat32 rgb_channel;
120 rgb_channel.name =
"rgb";
122 sensor_msgs::PointCloud ret;
124 const ImageView<Rgb> rgb_view(rgb.data.data(), rgb.step);
125 const ImageView<std::uint16_t> depth_view(registered_depth.data.data(), registered_depth.step);
127 for (std::size_t y = 0; y < rgb.height; ++y)
129 const RowView<Rgb> rgb_row_view = rgb_view[y];
130 const RowView<std::uint16_t> depth_row_view = depth_view[y];
132 for (std::size_t x = 0; x < rgb.width; ++x)
135 if (!mask(x, y))
continue;
137 std::uint16_t depth_pixel = depth_row_view[x];
140 if (!depth_pixel)
continue;
144 #ifdef ASTRA_ROS_BIG_ENDIAN
145 const bool swap_bytes = !registered_depth.is_bigendian;
147 const bool swap_bytes = registered_depth.is_bigendian;
152 depth_pixel = ((depth_pixel & 0x00FF) << 8) | ((depth_pixel & 0xFF00) << 0);
155 const double depth_meters = depth_pixel / 1000.0;
157 const double dx = x - cx;
160 const double dy = y - cy;
162 const double dx_over_z = dx / fx;
163 const double dy_over_z = dy / fy;
165 const double dx_over_z2 = dx_over_z * dx_over_z;
166 const double dy_over_z2 = dy_over_z * dy_over_z;
168 geometry_msgs::Point32 point;
169 point.z = depth_meters / sqrt(1.0 + dx_over_z2 + dy_over_z2);
170 point.x = dx_over_z * point.z;
171 point.y = dy_over_z * point.z;
175 ret.points.push_back(point);
177 const Rgb &pixel = rgb_row_view[x];
181 const std::uint32_t rgb_data = (pixel.
r << 16) | (pixel.
g << 8) | (pixel.
b << 0);
182 rgb_channel.values.push_back(*
reinterpret_cast<const float *
>(&rgb_data));
186 ret.channels.push_back(rgb_channel);