38 #ifndef OCTREE_COMPRESSION_HPP
39 #define OCTREE_COMPRESSION_HPP
41 #include <pcl/common/io.h>
42 #include <pcl/compression/entropy_range_coder.h>
53 template<
typename Po
intT,
typename LeafT,
typename BranchT,
typename OctreeT>
void OctreePointCloudCompression<
56 std::ostream& compressed_tree_data_out_arg)
58 auto recent_tree_depth =
59 static_cast<unsigned char> (this->getTreeDepth ());
62 this->setInputCloud (cloud_arg);
65 this->addPointsFromInputCloud ();
68 if (this->leaf_count_>0) {
72 cloud_with_color_ =
false;
73 std::vector<pcl::PCLPointField> fields;
75 rgba_index = pcl::getFieldIndex<PointT> (
"rgb", fields);
78 rgba_index = pcl::getFieldIndex<PointT> (
"rgba", fields);
82 point_color_offset_ =
static_cast<unsigned char> (fields[rgba_index].offset);
83 cloud_with_color_ =
true;
87 cloud_with_color_ &= do_color_encoding_;
91 i_frame_ |= (recent_tree_depth != this->getTreeDepth ());
94 if (i_frame_counter_++==i_frame_rate_)
104 if (!do_voxel_grid_enDecoding_)
106 point_count_data_vector_.clear ();
107 point_count_data_vector_.reserve (cloud_arg->size ());
111 color_coder_.initializeEncoding ();
112 color_coder_.setPointCount (
static_cast<unsigned int> (cloud_arg->size ()));
113 color_coder_.setVoxelCount (
static_cast<unsigned int> (this->leaf_count_));
116 point_coder_.initializeEncoding ();
117 point_coder_.setPointCount (
static_cast<unsigned int> (cloud_arg->size ()));
122 this->serializeTree (binary_tree_data_vector_,
false);
125 this->serializeTree (binary_tree_data_vector_,
true);
129 this->writeFrameHeader (compressed_tree_data_out_arg);
132 this->entropyEncoding (compressed_tree_data_out_arg);
135 this->switchBuffers ();
140 if (b_show_statistics_)
142 float bytes_per_XYZ =
static_cast<float> (compressed_point_data_len_) /
static_cast<float> (point_count_);
143 float bytes_per_color =
static_cast<float> (compressed_color_data_len_) /
static_cast<float> (point_count_);
145 PCL_INFO (
"*** POINTCLOUD ENCODING ***\n");
146 PCL_INFO (
"Frame ID: %d\n", frame_ID_);
148 PCL_INFO (
"Encoding Frame: Intra frame\n");
150 PCL_INFO (
"Encoding Frame: Prediction frame\n");
151 PCL_INFO (
"Number of encoded points: %ld\n", point_count_);
152 PCL_INFO (
"XYZ compression percentage: %f%%\n", bytes_per_XYZ / (3.0f *
sizeof (
float)) * 100.0f);
153 PCL_INFO (
"XYZ bytes per point: %f bytes\n", bytes_per_XYZ);
154 PCL_INFO (
"Color compression percentage: %f%%\n", bytes_per_color / (
sizeof (
int)) * 100.0f);
155 PCL_INFO (
"Color bytes per point: %f bytes\n", bytes_per_color);
156 PCL_INFO (
"Size of uncompressed point cloud: %f kBytes\n",
static_cast<float> (point_count_) * (
sizeof (
int) + 3.0f *
sizeof (
float)) / 1024.0f);
157 PCL_INFO (
"Size of compressed point cloud: %f kBytes\n",
static_cast<float> (compressed_point_data_len_ + compressed_color_data_len_) / 1024.0f);
158 PCL_INFO (
"Total bytes per point: %f bytes\n", bytes_per_XYZ + bytes_per_color);
159 PCL_INFO (
"Total compression percentage: %f%%\n", (bytes_per_XYZ + bytes_per_color) / (
sizeof (
int) + 3.0f *
sizeof (
float)) * 100.0f);
160 PCL_INFO (
"Compression ratio: %f\n\n",
static_cast<float> (
sizeof (
int) + 3.0f *
sizeof (
float)) /
static_cast<float> (bytes_per_XYZ + bytes_per_color));
165 if (b_show_statistics_)
166 PCL_INFO (
"Info: Dropping empty point cloud\n");
168 i_frame_counter_ = 0;
174 template<
typename Po
intT,
typename LeafT,
typename BranchT,
typename OctreeT>
void
176 std::istream& compressed_tree_data_in_arg,
181 syncToHeader(compressed_tree_data_in_arg);
184 this->switchBuffers ();
185 this->setOutputCloud (cloud_arg);
188 cloud_with_color_ =
false;
189 std::vector<pcl::PCLPointField> fields;
191 rgba_index = pcl::getFieldIndex<PointT> (
"rgb", fields);
192 if (rgba_index == -1)
193 rgba_index = pcl::getFieldIndex<PointT> (
"rgba", fields);
196 point_color_offset_ =
static_cast<unsigned char> (fields[rgba_index].offset);
197 cloud_with_color_ =
true;
201 this->readFrameHeader (compressed_tree_data_in_arg);
204 this->entropyDecoding (compressed_tree_data_in_arg);
207 color_coder_.initializeDecoding ();
208 point_coder_.initializeDecoding ();
211 output_->points.clear ();
212 output_->points.reserve (
static_cast<std::size_t
> (point_count_));
216 this->deserializeTree (binary_tree_data_vector_,
false);
219 this->deserializeTree (binary_tree_data_vector_,
true);
223 output_->width = cloud_arg->size ();
224 output_->is_dense =
false;
226 if (b_show_statistics_)
228 float bytes_per_XYZ =
static_cast<float> (compressed_point_data_len_) /
static_cast<float> (point_count_);
229 float bytes_per_color =
static_cast<float> (compressed_color_data_len_) /
static_cast<float> (point_count_);
231 PCL_INFO (
"*** POINTCLOUD DECODING ***\n");
232 PCL_INFO (
"Frame ID: %d\n", frame_ID_);
234 PCL_INFO (
"Decoding Frame: Intra frame\n");
236 PCL_INFO (
"Decoding Frame: Prediction frame\n");
237 PCL_INFO (
"Number of decoded points: %ld\n", point_count_);
238 PCL_INFO (
"XYZ compression percentage: %f%%\n", bytes_per_XYZ / (3.0f *
sizeof (
float)) * 100.0f);
239 PCL_INFO (
"XYZ bytes per point: %f bytes\n", bytes_per_XYZ);
240 PCL_INFO (
"Color compression percentage: %f%%\n", bytes_per_color / (
sizeof (
int)) * 100.0f);
241 PCL_INFO (
"Color bytes per point: %f bytes\n", bytes_per_color);
242 PCL_INFO (
"Size of uncompressed point cloud: %f kBytes\n",
static_cast<float> (point_count_) * (
sizeof (
int) + 3.0f *
sizeof (
float)) / 1024.0f);
243 PCL_INFO (
"Size of compressed point cloud: %f kBytes\n",
static_cast<float> (compressed_point_data_len_ + compressed_color_data_len_) / 1024.0f);
244 PCL_INFO (
"Total bytes per point: %f bytes\n", bytes_per_XYZ + bytes_per_color);
245 PCL_INFO (
"Total compression percentage: %f%%\n", (bytes_per_XYZ + bytes_per_color) / (
sizeof (
int) + 3.0f *
sizeof (
float)) * 100.0f);
246 PCL_INFO (
"Compression ratio: %f\n\n",
static_cast<float> (
sizeof (
int) + 3.0f *
sizeof (
float)) /
static_cast<float> (bytes_per_XYZ + bytes_per_color));
251 template<
typename Po
intT,
typename LeafT,
typename BranchT,
typename OctreeT>
void
254 std::uint64_t binary_tree_data_vector_size;
255 std::uint64_t point_avg_color_data_vector_size;
257 compressed_point_data_len_ = 0;
258 compressed_color_data_len_ = 0;
261 binary_tree_data_vector_size = binary_tree_data_vector_.size ();
262 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&binary_tree_data_vector_size),
sizeof (binary_tree_data_vector_size));
263 compressed_point_data_len_ += entropy_coder_.encodeCharVectorToStream (binary_tree_data_vector_,
264 compressed_tree_data_out_arg);
266 if (cloud_with_color_)
269 std::vector<char>& pointAvgColorDataVector = color_coder_.getAverageDataVector ();
270 point_avg_color_data_vector_size = pointAvgColorDataVector.size ();
271 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&point_avg_color_data_vector_size),
272 sizeof (point_avg_color_data_vector_size));
273 compressed_color_data_len_ += entropy_coder_.encodeCharVectorToStream (pointAvgColorDataVector,
274 compressed_tree_data_out_arg);
277 if (!do_voxel_grid_enDecoding_)
279 std::uint64_t pointCountDataVector_size;
280 std::uint64_t point_diff_data_vector_size;
281 std::uint64_t point_diff_color_data_vector_size;
284 pointCountDataVector_size = point_count_data_vector_.size ();
285 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&pointCountDataVector_size),
sizeof (pointCountDataVector_size));
286 compressed_point_data_len_ += entropy_coder_.encodeIntVectorToStream (point_count_data_vector_,
287 compressed_tree_data_out_arg);
290 std::vector<char>& point_diff_data_vector = point_coder_.getDifferentialDataVector ();
291 point_diff_data_vector_size = point_diff_data_vector.size ();
292 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&point_diff_data_vector_size),
sizeof (point_diff_data_vector_size));
293 compressed_point_data_len_ += entropy_coder_.encodeCharVectorToStream (point_diff_data_vector,
294 compressed_tree_data_out_arg);
295 if (cloud_with_color_)
298 std::vector<char>& point_diff_color_data_vector = color_coder_.getDifferentialDataVector ();
299 point_diff_color_data_vector_size = point_diff_color_data_vector.size ();
300 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&point_diff_color_data_vector_size),
301 sizeof (point_diff_color_data_vector_size));
302 compressed_color_data_len_ += entropy_coder_.encodeCharVectorToStream (point_diff_color_data_vector,
303 compressed_tree_data_out_arg);
307 compressed_tree_data_out_arg.flush ();
311 template<
typename Po
intT,
typename LeafT,
typename BranchT,
typename OctreeT>
void
314 std::uint64_t binary_tree_data_vector_size;
315 std::uint64_t point_avg_color_data_vector_size;
317 compressed_point_data_len_ = 0;
318 compressed_color_data_len_ = 0;
321 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&binary_tree_data_vector_size),
sizeof (binary_tree_data_vector_size));
322 binary_tree_data_vector_.resize (
static_cast<std::size_t
> (binary_tree_data_vector_size));
323 compressed_point_data_len_ += entropy_coder_.decodeStreamToCharVector (compressed_tree_data_in_arg,
324 binary_tree_data_vector_);
326 if (data_with_color_)
329 std::vector<char>& point_avg_color_data_vector = color_coder_.getAverageDataVector ();
330 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&point_avg_color_data_vector_size),
sizeof (point_avg_color_data_vector_size));
331 point_avg_color_data_vector.resize (
static_cast<std::size_t
> (point_avg_color_data_vector_size));
332 compressed_color_data_len_ += entropy_coder_.decodeStreamToCharVector (compressed_tree_data_in_arg,
333 point_avg_color_data_vector);
336 if (!do_voxel_grid_enDecoding_)
338 std::uint64_t point_count_data_vector_size;
339 std::uint64_t point_diff_data_vector_size;
340 std::uint64_t point_diff_color_data_vector_size;
343 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&point_count_data_vector_size),
sizeof (point_count_data_vector_size));
344 point_count_data_vector_.resize (
static_cast<std::size_t
> (point_count_data_vector_size));
345 compressed_point_data_len_ += entropy_coder_.decodeStreamToIntVector (compressed_tree_data_in_arg, point_count_data_vector_);
346 point_count_data_vector_iterator_ = point_count_data_vector_.begin ();
349 std::vector<char>& pointDiffDataVector = point_coder_.getDifferentialDataVector ();
350 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&point_diff_data_vector_size),
sizeof (point_diff_data_vector_size));
351 pointDiffDataVector.resize (
static_cast<std::size_t
> (point_diff_data_vector_size));
352 compressed_point_data_len_ += entropy_coder_.decodeStreamToCharVector (compressed_tree_data_in_arg,
353 pointDiffDataVector);
355 if (data_with_color_)
358 std::vector<char>& pointDiffColorDataVector = color_coder_.getDifferentialDataVector ();
359 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&point_diff_color_data_vector_size),
sizeof (point_diff_color_data_vector_size));
360 pointDiffColorDataVector.resize (
static_cast<std::size_t
> (point_diff_color_data_vector_size));
361 compressed_color_data_len_ += entropy_coder_.decodeStreamToCharVector (compressed_tree_data_in_arg,
362 pointDiffColorDataVector);
368 template<
typename Po
intT,
typename LeafT,
typename BranchT,
typename OctreeT>
void
372 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (frame_header_identifier_), strlen (frame_header_identifier_));
374 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&frame_ID_),
sizeof (frame_ID_));
376 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&i_frame_),
sizeof (i_frame_));
379 double min_x, min_y, min_z, max_x, max_y, max_z;
380 double octree_resolution;
381 unsigned char color_bit_depth;
382 double point_resolution;
385 octree_resolution = this->getResolution ();
386 color_bit_depth = color_coder_.getBitDepth ();
387 point_resolution= point_coder_.getPrecision ();
388 this->getBoundingBox (min_x, min_y, min_z, max_x, max_y, max_z);
391 if (do_voxel_grid_enDecoding_)
392 point_count_ = this->leaf_count_;
394 point_count_ = this->object_count_;
397 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&do_voxel_grid_enDecoding_),
sizeof (do_voxel_grid_enDecoding_));
398 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&cloud_with_color_),
sizeof (cloud_with_color_));
399 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&point_count_),
sizeof (point_count_));
400 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&octree_resolution),
sizeof (octree_resolution));
401 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&color_bit_depth),
sizeof (color_bit_depth));
402 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&point_resolution),
sizeof (point_resolution));
405 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&min_x),
sizeof (min_x));
406 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&min_y),
sizeof (min_y));
407 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&min_z),
sizeof (min_z));
408 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&max_x),
sizeof (max_x));
409 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&max_y),
sizeof (max_y));
410 compressed_tree_data_out_arg.write (
reinterpret_cast<const char*
> (&max_z),
sizeof (max_z));
415 template<
typename Po
intT,
typename LeafT,
typename BranchT,
typename OctreeT>
void
419 unsigned int header_id_pos = 0;
420 while (header_id_pos < strlen (frame_header_identifier_))
423 compressed_tree_data_in_arg.read (
static_cast<char*
> (&readChar),
sizeof (readChar));
424 if (readChar != frame_header_identifier_[header_id_pos++])
425 header_id_pos = (frame_header_identifier_[0]==readChar)?1:0;
430 template<
typename Po
intT,
typename LeafT,
typename BranchT,
typename OctreeT>
void
434 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&frame_ID_),
sizeof (frame_ID_));
435 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
>(&i_frame_),
sizeof (i_frame_));
438 double min_x, min_y, min_z, max_x, max_y, max_z;
439 double octree_resolution;
440 unsigned char color_bit_depth;
441 double point_resolution;
444 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&do_voxel_grid_enDecoding_),
sizeof (do_voxel_grid_enDecoding_));
445 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&data_with_color_),
sizeof (data_with_color_));
446 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&point_count_),
sizeof (point_count_));
447 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&octree_resolution),
sizeof (octree_resolution));
448 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&color_bit_depth),
sizeof (color_bit_depth));
449 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&point_resolution),
sizeof (point_resolution));
452 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&min_x),
sizeof (min_x));
453 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&min_y),
sizeof (min_y));
454 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&min_z),
sizeof (min_z));
455 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&max_x),
sizeof (max_x));
456 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&max_y),
sizeof (max_y));
457 compressed_tree_data_in_arg.read (
reinterpret_cast<char*
> (&max_z),
sizeof (max_z));
461 this->setResolution (octree_resolution);
462 this->defineBoundingBox (min_x, min_y, min_z, max_x, max_y, max_z);
465 color_coder_.setBitDepth (color_bit_depth);
466 point_coder_.setPrecision (
static_cast<float> (point_resolution));
471 template<
typename Po
intT,
typename LeafT,
typename BranchT,
typename OctreeT>
void
473 LeafT &leaf_arg,
const OctreeKey & key_arg)
476 const auto& leafIdx = leaf_arg.getPointIndicesVector();
478 if (!do_voxel_grid_enDecoding_)
480 double lowerVoxelCorner[3];
483 point_count_data_vector_.push_back (
static_cast<int> (leafIdx.size ()));
486 lowerVoxelCorner[0] =
static_cast<double> (key_arg.x) * this->resolution_ + this->min_x_;
487 lowerVoxelCorner[1] =
static_cast<double> (key_arg.y) * this->resolution_ + this->min_y_;
488 lowerVoxelCorner[2] =
static_cast<double> (key_arg.z) * this->resolution_ + this->min_z_;
491 point_coder_.encodePoints (leafIdx, lowerVoxelCorner, this->input_);
493 if (cloud_with_color_)
495 color_coder_.encodePoints (leafIdx, point_color_offset_, this->input_);
499 if (cloud_with_color_)
501 color_coder_.encodeAverageOfPoints (leafIdx, point_color_offset_, this->input_);
506 template<
typename Po
intT,
typename LeafT,
typename BranchT,
typename OctreeT>
void
508 const OctreeKey& key_arg)
512 std::size_t pointCount = 1;
514 if (!do_voxel_grid_enDecoding_)
517 const auto cloudSize = output_->size ();
520 pointCount = *point_count_data_vector_iterator_;
521 point_count_data_vector_iterator_++;
524 for (std::size_t i = 0; i < pointCount; i++)
525 output_->points.push_back (newPoint);
528 double lowerVoxelCorner[3];
529 lowerVoxelCorner[0] =
static_cast<double> (key_arg.x) * this->resolution_ + this->min_x_;
530 lowerVoxelCorner[1] =
static_cast<double> (key_arg.y) * this->resolution_ + this->min_y_;
531 lowerVoxelCorner[2] =
static_cast<double> (key_arg.z) * this->resolution_ + this->min_z_;
534 point_coder_.decodePoints (output_, lowerVoxelCorner, cloudSize, cloudSize + pointCount);
539 newPoint.x =
static_cast<float> ((
static_cast<double> (key_arg.x) + 0.5) * this->resolution_ + this->min_x_);
540 newPoint.y =
static_cast<float> ((
static_cast<double> (key_arg.y) + 0.5) * this->resolution_ + this->min_y_);
541 newPoint.z =
static_cast<float> ((
static_cast<double> (key_arg.z) + 0.5) * this->resolution_ + this->min_z_);
544 output_->points.push_back (newPoint);
547 if (cloud_with_color_)
549 if (data_with_color_)
551 color_coder_.decodePoints (output_, output_->size () - pointCount,
552 output_->size (), point_color_offset_);
555 color_coder_.setDefaultColor (output_, output_->size () - pointCount,
556 output_->size (), point_color_offset_);
void entropyEncoding(std::ostream &compressed_tree_data_out_arg)
Apply entropy encoding to encoded information and output to binary stream.
void syncToHeader(std::istream &compressed_tree_data_in_arg)
Synchronize to frame header.
void readFrameHeader(std::istream &compressed_tree_data_in_arg)
Read frame information to output stream.
void writeFrameHeader(std::ostream &compressed_tree_data_out_arg)
Write frame information to output stream.
typename OctreePointCloud< PointT, LeafT, BranchT, OctreeT >::PointCloudConstPtr PointCloudConstPtr
void entropyDecoding(std::istream &compressed_tree_data_in_arg)
Entropy decoding of input binary stream and output to information vectors.
void decodePointCloud(std::istream &compressed_tree_data_in_arg, PointCloudPtr &cloud_arg)
Decode point cloud from input stream.
void deserializeTreeCallback(LeafT &, const OctreeKey &key_arg) override
Decode leaf nodes information during deserialization.
void serializeTreeCallback(LeafT &leaf_arg, const OctreeKey &key_arg) override
Encode leaf node information during serialization.
typename OctreePointCloud< PointT, LeafT, BranchT, OctreeT >::PointCloudPtr PointCloudPtr
Octree double buffer class
A point structure representing Euclidean xyz coordinates, and the RGB color.