QualityEvaluator_RangeImageSimilarity.cpp
Go to the documentation of this file.
1 /* -------------------------------------------------------------------------
2  * A repertory of multi primitive-to-primitive (MP2P) ICP algorithms in C++
3  * Copyright (C) 2018-2024 Jose Luis Blanco, University of Almeria
4  * See LICENSE for license information.
5  * ------------------------------------------------------------------------- */
14 #include <mrpt/gui/CDisplayWindow.h>
15 #include <mrpt/img/TPixelCoord.h>
16 #include <mrpt/io/vector_loadsave.h>
17 
19  QualityEvaluator_RangeImageSimilarity, QualityEvaluator, mp2p_icp)
20 
21 using namespace mp2p_icp;
22 
24  const mrpt::containers::yaml& params)
25 {
26  rangeCamera.ncols = params["ncols"].as<uint32_t>();
27  rangeCamera.nrows = params["nrows"].as<uint32_t>();
28 
29  rangeCamera.cx(params["cx"].as<double>());
30  rangeCamera.cy(params["cy"].as<double>());
31  rangeCamera.fx(params["fx"].as<double>());
32  rangeCamera.fy(params["fy"].as<double>());
33 
34  MCP_LOAD_OPT(params, sigma);
35  MCP_LOAD_OPT(params, penalty_not_visible);
36 
37  MCP_LOAD_OPT(params, debug_show_all_in_window);
38  MCP_LOAD_OPT(params, debug_save_all_matrices);
39 }
40 
42  const metric_map_t& pcGlobal, const metric_map_t& pcLocal,
43  const mrpt::poses::CPose3D& localPose,
44  [[maybe_unused]] const Pairings& pairingsFromICP) const
45 {
46  // See Figure 3 of IROS2017 paper:
47  // "Analyzing the Quality of Matched 3D Point Clouds of Objects"
48  // Igor Bogoslavskyi, Cyrill Stachniss
49 
50  const auto& p1 = *pcGlobal.point_layer(metric_map_t::PT_LAYER_RAW);
51  const auto& p2 = *pcLocal.point_layer(metric_map_t::PT_LAYER_RAW);
52 
53  const auto I11 = projectPoints(p1);
54  const auto I12 = projectPoints(p1, localPose);
55  const auto I22 = projectPoints(p2);
56  const auto I21 = projectPoints(p2, -localPose);
57 
58  auto s1 = scores(I11, I21);
59  auto s2 = scores(I12, I22);
60 
61  const size_t nScores = s1.size() + s2.size();
62 
63  double sum = .0;
64  for (double v : s1) sum += v;
65  for (double v : s2) sum += v;
66 
67  const double finalScore = nScores > 0 ? sum / nScores : .0;
68 
69  // ----- Debug ----------
71  {
72  mrpt::gui::CDisplayWindow win_11("I11", 400, 300);
73  mrpt::gui::CDisplayWindow win_12("I12", 400, 300);
74  mrpt::gui::CDisplayWindow win_21("I21", 400, 300);
75  mrpt::gui::CDisplayWindow win_22("I22", 400, 300);
76  win_11.setPos(5, 5);
77  win_12.setPos(410 + 5, 5);
78  win_21.setPos(5, 310 + 5);
79  win_22.setPos(410 + 5, 310 + 5);
80  mrpt::img::CImage im11, im12, im21, im22;
81  im11.setFromMatrix(I11, false);
82  win_11.showImage(im11);
83  im12.setFromMatrix(I12, false);
84  win_12.showImage(im12);
85  im21.setFromMatrix(I21, false);
86  win_21.showImage(im21);
87  im22.setFromMatrix(I22, false);
88  win_22.showImage(im22);
89  win_11.waitForKey();
90  }
92  {
93  static std::atomic_int iv = 0;
94  const int i = iv++;
95  I11.saveToTextFile(mrpt::format("I11_%05i.txt", i));
96  I22.saveToTextFile(mrpt::format("I22_%05i.txt", i));
97  I12.saveToTextFile(mrpt::format("I12_%05i.txt", i));
98  I21.saveToTextFile(mrpt::format("I21_%05i.txt", i));
99 
100  mrpt::io::vectorToTextFile(s1, mrpt::format("I1_scores_%05i.txt", i));
101  mrpt::io::vectorToTextFile(s2, mrpt::format("I2_scores_%05i.txt", i));
102  }
103 
104  Result r;
105  r.quality = finalScore;
106  return r;
107 }
108 
109 // Adapted from mrpt::vision::pinhole::projectPoint_with_distortion()
110 // 3-claused BSD
111 static void projectPoint(
112  const mrpt::math::TPoint3D& P, const mrpt::img::TCamera& params,
113  double& pixel_x, double& pixel_y)
114 {
115  /* Pinhole model.
116  *
117  * Point reference Pixel/camera reference
118  *
119  * +Z ^ / +Z
120  * | / /
121  * | / +X /
122  * +Y |/ /
123  * <-----+ +-----------> +X
124  * |
125  * |
126  * V +Y
127  *
128  */
129  const double x = -P.y / P.x;
130  const double y = -P.z / P.x;
131 
132  pixel_x = params.cx() + params.fx() * x;
133  pixel_y = params.cy() + params.fy() * y;
134 }
135 
137  const mrpt::maps::CPointsMap& pts,
138  const std::optional<mrpt::poses::CPose3D>& relativePose) const
139 {
140  const auto& rc = rangeCamera;
141 
142  mrpt::math::CMatrixDouble I(rc.nrows, rc.ncols);
143  I.setZero(); // range=0 means "invalid"
144 
145  const auto& xs = pts.getPointsBufferRef_x();
146  const auto& ys = pts.getPointsBufferRef_y();
147  const auto& zs = pts.getPointsBufferRef_z();
148 
149  const auto nPoints = xs.size();
150  size_t nValidPoints = 0;
151  for (size_t i = 0; i < nPoints; i++)
152  {
153  mrpt::math::TPoint3D p(xs[i], ys[i], zs[i]);
154  if (relativePose) p = relativePose->composePoint(p);
155 
156  double px, py;
157  projectPoint(p, rc, px, py);
158  int pixx = static_cast<int>(px);
159  int pixy = static_cast<int>(py);
160 
161  // Out of range
162  if (pixx < 0 || pixy < 0 || pixx >= int(rc.ncols) ||
163  pixy >= int(rc.nrows))
164  continue;
165 
166  const double newRange = p.norm();
167  double& storedRange = I(pixy, pixx);
168 
169  if (storedRange == 0 || newRange < storedRange) storedRange = newRange;
170 
171  nValidPoints++;
172  }
173 
174  // std::cout << "Points: " << nValidPoints << "/" << nPoints << "\n";
175 
176  return I;
177 }
178 
179 static double phi(double x) { return std::erf(x / std::sqrt(2)); }
180 static double errorForMismatch(const double x) { return 1.0 - phi(x); }
181 static double errorForMismatch(const double DeltaRange, const double sigma)
182 {
183  const double x = std::abs(DeltaRange / sigma);
184  return errorForMismatch(x);
185 }
186 
188  const mrpt::math::CMatrixDouble& m1,
189  const mrpt::math::CMatrixDouble& m2) const
190 {
191  ASSERT_EQUAL_(m1.rows(), m2.rows());
192  ASSERT_EQUAL_(m1.cols(), m2.cols());
193 
194  std::vector<double> scores;
195  scores.reserve(m1.rows() * m1.cols() / 4);
196 
197  const size_t N = m1.rows() * m1.cols();
198  for (size_t i = 0; i < N; i++)
199  {
200  const double r1 = m1.data()[i];
201  const double r2 = m2.data()[i];
202 
203  if (r1 == 0 && r2 == 0) continue;
204 
205  double val;
206  if (r1 == 0 || r2 == 0)
207  {
208  // Maximum error:
210  }
211  else
212  {
213  // Maximum error:
214  val = errorForMismatch(r1 - r2, sigma);
215  }
216  // printf("r1=%f r2=%f -> val=%f\n", r1, r2, val);
217  scores.push_back(val);
218  }
219 
220  return scores;
221 }
mp2p_icp::QualityEvaluator_RangeImageSimilarity::evaluate
Result evaluate(const metric_map_t &pcGlobal, const metric_map_t &pcLocal, const mrpt::poses::CPose3D &localPose, const Pairings &pairingsFromICP) const override
Definition: QualityEvaluator_RangeImageSimilarity.cpp:41
mp2p_icp
Definition: covariance.h:17
mp2p_icp::QualityEvaluator_RangeImageSimilarity::initialize
void initialize(const mrpt::containers::yaml &params) override
Definition: QualityEvaluator_RangeImageSimilarity.cpp:23
mp2p_icp::QualityEvaluator::Result
Definition: QualityEvaluator.h:34
mp2p_icp::Pairings
Definition: Pairings.h:94
test.x
x
Definition: test.py:4
mp2p_icp::QualityEvaluator_RangeImageSimilarity::sigma
double sigma
Definition: QualityEvaluator_RangeImageSimilarity.h:67
mp2p_icp::metric_map_t::PT_LAYER_RAW
constexpr static const char * PT_LAYER_RAW
Definition: metricmap.h:57
mp2p_icp::QualityEvaluator_RangeImageSimilarity::projectPoints
mrpt::math::CMatrixDouble projectPoints(const mrpt::maps::CPointsMap &pts, const std::optional< mrpt::poses::CPose3D > &relativePose=std::nullopt) const
Definition: QualityEvaluator_RangeImageSimilarity.cpp:136
mp2p_icp::QualityEvaluator_RangeImageSimilarity::debug_show_all_in_window
bool debug_show_all_in_window
Definition: QualityEvaluator_RangeImageSimilarity.h:72
mp2p_icp::QualityEvaluator_RangeImageSimilarity::rangeCamera
mrpt::img::TCamera rangeCamera
Definition: QualityEvaluator_RangeImageSimilarity.h:65
phi
static double phi(double x)
Definition: QualityEvaluator_RangeImageSimilarity.cpp:179
mp2p_icp::QualityEvaluator_RangeImageSimilarity::debug_save_all_matrices
bool debug_save_all_matrices
Definition: QualityEvaluator_RangeImageSimilarity.h:73
mp2p_icp::QualityEvaluator::Result::quality
double quality
The resulting quality measure, in the range [0,1].
Definition: QualityEvaluator.h:37
projectPoint
static void projectPoint(const mrpt::math::TPoint3D &P, const mrpt::img::TCamera &params, double &pixel_x, double &pixel_y)
Definition: QualityEvaluator_RangeImageSimilarity.cpp:111
mp2p_icp::metric_map_t::point_layer
mrpt::maps::CPointsMap::Ptr point_layer(const layer_name_t &name) const
Definition: metricmap.cpp:633
errorForMismatch
static double errorForMismatch(const double x)
Definition: QualityEvaluator_RangeImageSimilarity.cpp:180
IMPLEMENTS_MRPT_OBJECT
IMPLEMENTS_MRPT_OBJECT(QualityEvaluator_RangeImageSimilarity, QualityEvaluator, mp2p_icp) using namespace mp2p_icp
PointMatcherSupport::Parametrizable
The superclass of classes that are constructed using generic parameters. This class provides the para...
Definition: Parametrizable.h:98
mp2p_icp::QualityEvaluator_RangeImageSimilarity::penalty_not_visible
double penalty_not_visible
!< Uncertainty of depth ranges [meters]
Definition: QualityEvaluator_RangeImageSimilarity.h:70
mp2p_icp::metric_map_t
Generic container of pointcloud(s), extracted features and other maps.
Definition: metricmap.h:48
mp2p_icp::QualityEvaluator_RangeImageSimilarity::scores
std::vector< double > scores(const mrpt::math::CMatrixDouble &m1, const mrpt::math::CMatrixDouble &m2) const
Definition: QualityEvaluator_RangeImageSimilarity.cpp:187
QualityEvaluator_RangeImageSimilarity.h
Matching quality evaluator from paper [Bogoslavskyi,IROS2017].


mp2p_icp
Author(s): Jose-Luis Blanco-Claraco
autogenerated on Tue Jul 2 2024 02:47:25