ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
PointCloudIO.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <Logging.h>
11 #include <benchmark/benchmark.h>
12 #include <ecvPointCloud.h>
13 
14 namespace cloudViewer {
15 namespace benchmarks {
16 
19 
20 namespace {
21 
22 template <class T>
23 double AverageDistance(const std::vector<T> &a, const std::vector<T> &b) {
24  if (a.size() != b.size()) {
25  utility::LogError("vectors different size {} {}", a.size(), b.size());
26  }
27  if (a.size() == 0) {
28  return 0.;
29  }
30  double total = 0;
31  for (size_t i = 0; i < a.size(); ++i) {
32  total += (a[i] - b[i]).norm();
33  }
34  return total / a.size();
35 }
36 
37 enum class IsAscii : bool { BINARY = false, ASCII = true };
38 enum class Compressed : bool { UNCOMPRESSED = false, COMPRESSED = true };
39 enum class Compare : uint32_t {
40  // Points are always compared
41  NONE = 0,
42  NORMALS = 1 << 0,
43  COLORS = 1 << 1,
44  NORMALS_AND_COLORS = NORMALS | COLORS
45 };
46 struct ReadWritePCArgs {
47  std::string filename;
48  IsAscii write_ascii;
49  Compressed compressed;
50  Compare compare;
51 };
52 std::vector<ReadWritePCArgs> g_pc_args({
53  // PCD has ASCII, BINARY, and BINARY_COMPRESSED
54  {"testau.pcd", IsAscii::ASCII, Compressed::UNCOMPRESSED,
55  Compare::NORMALS_AND_COLORS}, // 0
56  {"testbu.pcd", IsAscii::BINARY, Compressed::UNCOMPRESSED,
57  Compare::NORMALS_AND_COLORS}, // 1
58  {"testbc.pcd", IsAscii::BINARY, Compressed::COMPRESSED,
59  Compare::NORMALS_AND_COLORS}, // 2
60  {"testb.ply", IsAscii::BINARY, Compressed::UNCOMPRESSED,
61  Compare::NORMALS_AND_COLORS}, // 3
62  {"testa.ply", IsAscii::ASCII, Compressed::UNCOMPRESSED,
63  Compare::NORMALS_AND_COLORS}, // 4
64  {"test.pts", IsAscii::BINARY, Compressed::UNCOMPRESSED,
65  Compare::COLORS}, // 5
66  {"test.xyz", IsAscii::BINARY, Compressed::UNCOMPRESSED,
67  Compare::NONE}, // 6
68  {"test.xyzn", IsAscii::BINARY, Compressed::UNCOMPRESSED,
69  Compare::NORMALS}, // 7
70  {"test.xyzrgb", IsAscii::BINARY, Compressed::UNCOMPRESSED,
71  Compare::COLORS}, // 8
72 });
73 
74 class TestPCGrid0 {
75  ccPointCloud pc_;
76  int size_ = 0;
77  const bool print_progress = false;
78 
79 public:
80  void Setup(int size) {
81  if (size_ == size) return;
82  utility::LogInfo("setup PCGrid size={}", size);
83  pc_.clear();
84 
85  size_ = size;
86  for (int i = 0; i < size; ++i) {
87  // provide somewhat random numbers everywhere, so compression
88  // doesn't get a free pass
89  pc_.addEigenPoint({std::sin(i * .8969920581) * 1000.,
90  std::sin(i * .3898546778) * 1000.,
91  std::sin(i * .2509962463) * 1000.});
92  pc_.addEigenNorm({std::sin(i * .4472367685),
93  std::sin(i * .9698787116),
94  std::sin(i * .7072878517)});
95  // color needs to be [0,1]
96  pc_.addEigenColor({std::fmod(i * .4241490710, 1.0),
97  std::fmod(i * .6468026221, 1.0),
98  std::fmod(i * .5376722873, 1.0)});
99  }
100  }
101 
102  void WriteRead(int pc_args_id) {
103  const auto &args = g_pc_args[pc_args_id];
104  const auto &pc = pc_;
105  // we loose some precision when saving generated data
106  if (!WritePointCloud(args.filename, pc,
107  {bool(args.write_ascii), bool(args.compressed),
108  print_progress})) {
109  utility::LogError("Failed to write to {}", args.filename);
110  }
111  ccPointCloud pc2;
112  if (!ReadPointCloud(args.filename, pc2,
113  {"auto", false, false, print_progress})) {
114  utility::LogError("Failed to read from {}", args.filename);
115  }
116  auto CheckLE = [](double a, double b) {
117  if (a <= b) return;
118  utility::LogError("Error too high: {} {}", a, b);
119  };
120 
121  const double pointsMaxError =
122  1e-3; //.ply ascii has the highest error, others <1e-4
123  CheckLE(AverageDistance(pc.getEigenPoints(), pc2.getEigenPoints()),
124  pointsMaxError);
125  if (int(args.compare) & int(Compare::NORMALS)) {
126  const double normalsMaxError =
127  1e-6; //.ply ascii has the highest error, others <1e-7
128  CheckLE(AverageDistance(pc.getEigenNormals(),
129  pc2.getEigenNormals()),
130  normalsMaxError);
131  }
132  if (int(args.compare) & int(Compare::COLORS)) {
133  const double colorsMaxError =
134  1e-2; // colors are saved as uint8_t[3] in a lot of formats
135  CheckLE(AverageDistance(pc.getEigenColors(), pc2.getEigenColors()),
136  colorsMaxError);
137  }
138  }
139 };
140 // reuse the same instance so we don't recreate the point cloud every time
141 TestPCGrid0 test_pc_grid0;
142 
143 } // namespace
144 
145 static void BM_TestPCGrid0(::benchmark::State &state) {
146  // state.range(n) are arguments that are passed to us
147  int pc_args_id = state.range(0);
148  int size = state.range(1);
149  test_pc_grid0.Setup(size);
150  for (auto _ : state) {
151  test_pc_grid0.WriteRead(pc_args_id);
152  }
153 }
154 static void BM_TestPCGrid0_Args(benchmark::internal::Benchmark *b) {
155  for (int j = 4 * 1024; j <= 256 * 1024; j *= 8) {
156  for (int i = 0; i < int(g_pc_args.size()); ++i) {
157  b->Args({i, j});
158  }
159  }
160 }
161 
163 
164 } // namespace benchmarks
165 } // namespace cloudViewer
Compare compare
IsAscii write_ascii
Compressed compressed
std::string filename
int size
int64_t size_
Definition: FilePLY.cpp:37
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void addEigenNorm(const Eigen::Vector3d &N)
std::vector< Eigen::Vector3d > getEigenColors() const
void addEigenColor(const Eigen::Vector3d &color)
void clear() override
Clears the entity from all its points and features.
std::vector< Eigen::Vector3d > getEigenNormals() const
void addEigenPoint(const Eigen::Vector3d &point)
std::vector< Eigen::Vector3d > getEigenPoints() const
#define LogInfo(...)
Definition: Logging.h:81
#define LogError(...)
Definition: Logging.h:60
BENCHMARK(BM_TestKDTreeLine0) -> Args({1<< 5, 1<< 10}) ->Args({1<< 9, 1<< 11})
static void BM_TestPCGrid0_Args(benchmark::internal::Benchmark *b)
static void BM_TestPCGrid0(::benchmark::State &state)
bool ReadPointCloud(const std::string &filename, ccPointCloud &pointcloud, const ReadPointCloudOption &params)
bool WritePointCloud(const std::string &filename, const ccPointCloud &pointcloud, const WritePointCloudOption &params)
bool WritePointCloud(const std::string &filename, const geometry::PointCloud &pointcloud, bool write_ascii, bool compressed, bool print_progress)
bool ReadPointCloud(const std::string &filename, geometry::PointCloud &pointcloud, const std::string &file_format, bool remove_nan_points, bool remove_infinite_points, bool print_progress)
Generic file read and write utility for python interface.