31#include <visp3/rbt/vpPointMap.h>
33#ifdef VISP_HAVE_OPENMP
37#define VP_RB_POINT_MAP_DEBUG 0
44 for (
unsigned int i = 0; i < indices.
getRows(); ++i) {
45 unsigned idx = indices[i][0];
46 X[i][0] = m_X[idx][0];
47 X[i][1] = m_X[idx][1];
48 X[i][2] = m_X[idx][2];
54 cX.
resize(m_X.getRows(), 3,
false,
false);
60 for (
unsigned int i = 0; i < m_X.getRows(); ++i) {
70 for (
unsigned int i = 0; i < indices.
getRows(); ++i) {
71 unsigned idx = indices[i][0];
72 X[i][0] = m_X[idx][0];
73 X[i][1] = m_X[idx][1];
74 X[i][2] = m_X[idx][2];
83 for (
unsigned int i = 0; i < indices.
getRows(); ++i) {
94 for (
unsigned int i = 0; i < cX.
getRows(); ++i) {
95 xs[i][0] = cX[i][0] / cX[i][2];
96 xs[i][1] = cX[i][1] / cX[i][2];
107 for (
unsigned int i = 0; i < xs.
getRows(); ++i) {
108 vpMeterPixelConversion::convertPointWithoutDistortion(cam, xs[i][0], xs[i][1], uvs[i][0], uvs[i][1]);
114 for (
unsigned int i = 0; i < cX.
getRows(); ++i) {
115 const double u = uvs[i][0], v = uvs[i][1];
116 const double Z = cX[i][2];
117 if (u < 0 || v < 0 || u >= w || v >= h) {
120 if (fabs(Z - expectedZ[i]) > m_maxDepthErrorVisible) {
123 indices.push_back(i);
132 vpMatrix cX(m_X.getRows(), m_X.getCols());
133 vpMatrix cN(m_normals.getRows(), m_normals.getCols());
139 if (m_normals.getRows() > 0) {
143 std::vector<std::vector<int>> indicesPerThread;
144 const double normalThreshold =
vpMath::rad(180 - m_normalThresholdVisible);
146#ifdef VISP_HAVE_OPENMP
151#ifdef VISP_HAVE_OPENMP
154 unsigned int numThreads = omp_get_num_threads();
155 indicesPerThread.resize(numThreads);
159 indicesPerThread.resize(1);
163#ifdef VISP_HAVE_OPENMP
164 unsigned int threadIdx = omp_get_thread_num();
166 unsigned int threadIdx = 0;
168 std::vector<int> localIndices;
171#ifdef VISP_HAVE_OPENMP
172 localIndices.reserve(m_X.getRows() / omp_get_num_threads());
173#pragma omp for nowait
175 for (
int i = 0; i < static_cast<int>(m_X.getRows()); ++i) {
179 const double Z = cX[i][2] + t[2];
183 const double X = cX[i][0] + t[0], Y = cX[i][1] + t[1];
186 if (m_normals.getRows() > 0) {
187 cameraRay = { X, Y, Z };
189 double dotProd = cN[i][0] * cameraRay[0] + cN[i][1] * cameraRay[1] + cN[i][2] * cameraRay[2];
190 double angle = acos(dotProd);
191 if (angle < normalThreshold) {
195 const double x = X / Z, y = Y / Z;
196 vpMeterPixelConversion::convertPointWithoutDistortion(cam, x, y, u, v);
198 if (u < 0 || v < 0 || u >= w || v >= h) {
202 unsigned int uint =
static_cast<unsigned int>(u), vint =
static_cast<unsigned int>(v);
205 if (fabs(Z - depth[vint][uint]) > m_maxDepthErrorVisible) {
208 localIndices.push_back(i);
210 indicesPerThread[threadIdx] = std::move(localIndices);
212 for (
const std::vector<int> &indicesPart: indicesPerThread) {
213 indices.insert(indices.end(), std::make_move_iterator(indicesPart.begin()), std::make_move_iterator(indicesPart.end()));
223 double thresholdSqr =
vpMath::sqr(m_outlierThreshold);
224 for (
unsigned int i = 0; i < uvs.
getRows(); ++i) {
225 const double error =
vpMath::sqr(uvs[i][0] - observations[i][0]) +
vpMath::sqr(uvs[i][1] - observations[i][1]);
226 if (error >= thresholdSqr) {
227 indices.push_back(originalIndices[i][0]);
239 validCandidateIndices.clear();
246 double farEnoughThresholdSq = m_minDistNewPoint * m_minDistNewPoint;
248 std::vector<std::array<double, 3>> validoXList;
249 std::vector<std::array<double, 3>> validoNList;
251 validoXList.reserve(uvs.
getRows());
253 validoNList.reserve(uvs.
getRows());
256 for (
unsigned int i = 0; i < uvs.
getRows(); ++i) {
257 double u = uvs[i][0], v = uvs[i][1];
258 unsigned int uint =
static_cast<unsigned int>(u), vint =
static_cast<unsigned int>(v);
260 if (modelDepth.
getSize() == 0) {
261 Z =
static_cast<double>(depth[vint][uint]);
267 double renderZ = modelDepth[vint][uint];
268 if (renderZ <= 0.f) {
271 if (depth.getSize() > 0 && depth[vint][uint] > 0.f) {
272 Z = depth[vint][uint];
274 if (m_maxDepthErrorCandidate > 0.0 && fabs(renderZ - Z) >= m_maxDepthErrorCandidate) {
281 vpPixelMeterConversion::convertPointWithoutDistortion(cam, u, v, x, y);
289 bool isFarEnoughFromOtherPoints =
true;
290 if (m_minDistNewPoint > 0.0) {
291 for (
unsigned int j = 0; j < m_X.getRows(); ++j) {
293 if (errSq < farEnoughThresholdSq) {
294 isFarEnoughFromOtherPoints =
false;
298 if (isFarEnoughFromOtherPoints) {
299 for (
const std::array<double, 3> &other: validoXList) {
301 if (errSq < farEnoughThresholdSq) {
302 isFarEnoughFromOtherPoints =
false;
309 if (isFarEnoughFromOtherPoints) {
310 validoXList.push_back({ oX[0], oX[1], oX[2] });
311 validCandidateIndices.push_back(originalIndices[i][0]);
313 vpRGBf n = normals[vint][uint];
314 validoNList.push_back({ n.
R, n.
G, n.
B });
319 oXs.
resize(
static_cast<unsigned int>(validoXList.size()), 3,
false,
false);
320 oNs.
resize(
static_cast<unsigned int>(validoNList.size()), 3,
false,
false);
323 for (
const std::array<double, 3> &oX: validoXList) {
330 for (
const std::array<double, 3> &oN: validoNList) {
344vpMatrix removeAndAdd(
const vpMatrix &oldArray,
unsigned int newSize,
const std::vector<int> &removedIndices,
const vpMatrix &rowsToAdd,
unsigned int &numAddedPoints)
346 unsigned int numCols = 3;
348 unsigned int newXIndex = 0;
349 unsigned int oldXIndex = 0;
352 for (
int removedRow : removedIndices) {
353#if VP_RB_POINT_MAP_DEBUG
354 if (removedRow >=
static_cast<int>(oldArray.
getRows())) {
358 unsigned int copiedRows = removedRow - oldXIndex;
359 if (copiedRows > 0) {
360 memcpy(newX[newXIndex], oldArray[oldXIndex], copiedRows * numCols *
sizeof(
double));
361 newXIndex += copiedRows;
363 oldXIndex = removedRow + 1;
366 unsigned int copiedRows = oldArray.
getRows() - oldXIndex;
367 if (copiedRows > 0) {
368 memcpy(newX[newXIndex], oldArray[oldXIndex], copiedRows * numCols *
sizeof(
double));
369 newXIndex += copiedRows;
372 numAddedPoints = std::min(rowsToAdd.
getRows(),
static_cast<unsigned int>(newSize) - newXIndex);
373 memcpy(newX[newXIndex], rowsToAdd[0], numAddedPoints * numCols *
sizeof(
double));
378 std::vector<int> &removedIndices,
unsigned int &numAddedPoints)
380 removedIndices.clear();
384 int newSize = m_X.getRows() - indicesToRemove.
getRows() + pointsToAdd.
getRows();
385 for (
unsigned int i = 0; i < indicesToRemove.
getRows(); ++i) {
386 removedIndices.push_back(indicesToRemove[i][0]);
389 int maxPoints =
static_cast<int>(m_maxPoints);
390 std::sort(removedIndices.begin(), removedIndices.end());
391 if (newSize > maxPoints) {
392 int shouldBeRemoved = newSize - maxPoints;
396 std::vector<int> startingIndices;
397 auto removedIt = removedIndices.begin();
399 int n_rows =
static_cast<int>(m_X.getRows());
400 while ((startingIndices.size() <
static_cast<size_t>(shouldBeRemoved)) && (i < n_rows)) {
401 if (removedIt == removedIndices.end() || i < (*removedIt)) {
402 startingIndices.push_back(i);
410 removedIndices.insert(removedIndices.begin(), startingIndices.begin(), startingIndices.end());
411 std::sort(removedIndices.begin(), removedIndices.end());
414 m_X = removeAndAdd(m_X, newSize, removedIndices, pointsToAdd, numAddedPoints);
415 if (normalsToAdd.
getRows() > 0 || m_normals.getRows() > 0) {
416 m_normals = removeAndAdd(m_normals, newSize, removedIndices, normalsToAdd, numAddedPoints);
418 if (m_normals.getRows() > 0 && m_X.size() != m_normals.size()) {
Implementation of a generic 2D array used as base class for matrices and vectors.
unsigned int getCols() const
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
unsigned int getRows() const
Generic class defining intrinsic camera parameters.
@ perspectiveProjWithoutDistortion
Perspective projection without distortion model.
Implementation of column vector and the associated operations.
vpColVector & normalize()
error that can be emitted by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
@ dimensionError
Bad dimension.
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpRotationMatrix getRotationMatrix() const
vpTranslationVector getTranslationVector() const
Definition of the vpImage class member functions.
unsigned int getSize() const
static double rad(double deg)
static double sqr(double x)
Implementation of a matrix and operations on matrices.
static void mult2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
void getOutliers(const vpArray2D< int > &originalIndices, const vpMatrix &uvs, const vpMatrix &observations, std::vector< int > &indices)
void project(const vpHomogeneousMatrix &cTw, vpMatrix &cX)
void selectValidNewCandidates(const vpCameraParameters &cam, const vpHomogeneousMatrix &cTw, const vpArray2D< int > &originalIndices, const vpMatrix &uvs, const vpImage< float > &modelDepth, const vpImage< float > &depth, const vpImage< vpRGBf > &normals, vpMatrix &oXs, vpMatrix &oNs, std::vector< int > &validCandidateIndices)
void getVisiblePoints(const unsigned int h, const unsigned int w, const vpMatrix &cX, const vpMatrix &uvs, const vpColVector &expectedZ, std::vector< int > &indices)
const vpMatrix & getPoints()
void updatePoints(const vpArray2D< int > &indicesToRemove, const vpMatrix &pointsToAdd, const vpMatrix &normalsToAdd, std::vector< int > &removedIndices, unsigned int &numAddedPoints)
Implementation of a rotation matrix and operations on such kind of matrices.
vpRotationMatrix t() const
vpRotationMatrix inverse() const
Class that consider the case of a translation vector.