Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpRBDenseDepthTracker.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 */
30
31#include <visp3/rbt/vpRBDenseDepthTracker.h>
32#include <visp3/core/vpMeterPixelConversion.h>
33#include <visp3/core/vpDisplay.h>
34#include <visp3/core/vpUniRand.h>
35
36#ifdef VISP_HAVE_OPENMP
37#include <omp.h>
38#endif
40
41// #define VISP_DEBUG_RB_DEPTH_DENSE_TRACKER 1
42
43void fastProjection(const vpHomogeneousMatrix &oTc, double X, double Y, double Z, std::array<double, 3> &p)
44{
45 const double *T = oTc.data;
46 p[0] = (T[0] * X + T[1] * Y + T[2] * Z + T[3]);
47 p[1] = (T[4] * X + T[5] * Y + T[6] * Z + T[7]);
48 p[2] = (T[8] * X + T[9] * Y + T[10] * Z + T[11]);
49}
50
51double dotProd3(const vpColVector &a, const std::array<double, 3> &b)
52{
53 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
54}
55
57{
58 const vpImage<float> &depthMap = frame.depth;
59 const vpImage<float> &renderDepth = frame.renders.depth;
60 const vpRect bb = frame.renders.boundingBox;
61 const vpHomogeneousMatrix &cMo = frame.renders.cMo;
62 const vpRotationMatrix cRo = cMo.getRotationMatrix();
63 const vpHomogeneousMatrix oMc = cMo.inverse();
64 const vpTranslationVector co = oMc.getTranslationVector(); // Position of the camera in object frame
65 const bool useMask = m_useMask && frame.hasMask();
66
67
68 m_depthPoints.clear();
69 m_depthPoints.reserve(static_cast<size_t>(bb.getArea() / (m_step * m_step * 2)));
70
71 std::vector<std::vector<vpDepthPoint>> pointsPerThread;
72
73#ifdef VISP_HAVE_OPENMP
74#pragma omp parallel
75#endif
76 {
77#ifdef VISP_HAVE_OPENMP
78#pragma omp single
79 {
80 unsigned int numThreads = omp_get_num_threads();
81 pointsPerThread.resize(numThreads);
82 }
83#else
84 {
85 pointsPerThread.resize(1);
86 }
87#endif
88
89#ifdef VISP_HAVE_OPENMP
90 unsigned int threadIdx = omp_get_thread_num();
91#else
92 unsigned int threadIdx = 0;
93#endif
94 vpDepthPoint point;
95 vpColVector cameraRay(3);
96#ifdef VISP_HAVE_OPENMP
97 std::vector<vpDepthPoint> localPoints;
98 localPoints.reserve(m_depthPoints.capacity() / omp_get_num_threads());
99#else
100 // Just reference the global vector, no need to add to it later on
101 std::vector<vpDepthPoint> &localPoints = m_depthPoints;
102#endif
103
104#ifdef VISP_HAVE_OPENMP
105#pragma omp for
106#endif
107 for (auto i = static_cast<int>(bb.getTop()); i < static_cast<int>(bb.getBottom()); i += m_step) {
108 for (auto j = static_cast<int>(bb.getLeft()); j < static_cast<int>(bb.getRight()); j += m_step) {
109 const double Z = renderDepth[i][j];
110 const double currZ = depthMap[i][j];
111
112 if (Z > 0.f && currZ > 0.f) {
113 if (useMask && frame.mask[i][j] < m_minMaskConfidence) {
114 continue;
115 }
116 double x = 0.0, y = 0.0;
117 vpPixelMeterConversion::convertPointWithoutDistortion(frame.cam, j, i, x, y);
118 //vpColVector objectNormal({ frame.renders.normals[i][j].R, frame.renders.normals[i][j].G, frame.renders.normals[i][j].B });
119 point.objectNormal[0] = frame.renders.normals[i][j].R;
120 point.objectNormal[1] = frame.renders.normals[i][j].G;
121 point.objectNormal[2] = frame.renders.normals[i][j].B;
122
123 bool invalidNormal = false;
124 for (unsigned int oi = 0; oi < 3; ++oi) {
125 if (!vpMath::isFinite(point.objectNormal[oi]) || abs(point.objectNormal[oi]) > 1.0) {
126 invalidNormal = true;
127 }
128 }
129
130 if (invalidNormal) {
131 continue;
132 }
133
134 fastProjection(oMc, x * Z, y * Z, Z, point.oX);
135
136 cameraRay = { co[0] - point.oX[0], co[1] - point.oX[1], co[2] - point.oX[2] };
137 cameraRay.normalize();
138
139 if (acos(dotProd3(cameraRay, point.objectNormal)) > vpMath::rad(85.0)) {
140 continue;
141 }
142
143 point.pixelPos[0] = i;
144 point.pixelPos[1] = j;
145
146 point.observation[0] = x * currZ;
147 point.observation[1] = y * currZ;
148 point.observation[2] = currZ;
149
150 localPoints.push_back(point);
151 }
152 }
153 }
154
155 pointsPerThread[threadIdx] = std::move(localPoints);
156 }
157 for (const std::vector<vpDepthPoint> &points: pointsPerThread) {
158 m_depthPoints.insert(m_depthPoints.end(), std::make_move_iterator(points.begin()), std::make_move_iterator(points.end()));
159 }
160 if (m_maxFeatures > 0 && m_depthPoints.size() > m_maxFeatures) {
161 vpUniRand rand(421);
162 std::vector<size_t> indices = rand.sampleWithoutReplacement(m_maxFeatures, m_depthPoints.size());
163 std::vector<vpDepthPoint> finalPoints;
164 for (size_t index : indices) {
165 finalPoints.push_back(m_depthPoints[index]);
166 }
167 std::swap(m_depthPoints, finalPoints);
168 }
169
171
172 if (m_depthPoints.size() > 0) {
173 m_error.resize(static_cast<unsigned int>(m_depthPoints.size()), false);
174 m_weights.resize(static_cast<unsigned int>(m_depthPoints.size()), false);
175 m_weighted_error.resize(static_cast<unsigned int>(m_depthPoints.size()), false);
176 m_L.resize(static_cast<unsigned int>(m_depthPoints.size()), 6, false, false);
177 m_cov.resize(6, 6, false, false);
178 m_covWeightDiag.resize(static_cast<unsigned int>(m_depthPoints.size()), false);
179 m_numFeatures = m_L.getRows();
180 }
181 else {
182 m_numFeatures = 0;
183 }
184}
185
186void vpRBDenseDepthTracker::computeVVSIter(const vpRBFeatureTrackerInput &frame, const vpHomogeneousMatrix &cMo, unsigned int /*iteration*/)
187{
188 const unsigned int minBBSamples = (frame.renders.boundingBox.getArea() / (m_step * m_step));
189
190 const unsigned int minNumFeatures = m_maxFeatures > 0 ? std::min(m_maxFeatures * 0.05, minBBSamples * 0.05) : minBBSamples * 0.05;
191
192 if (m_numFeatures < minNumFeatures) {
193 m_numFeatures = 0;
194 m_LTL = 0;
195 m_LTR = 0;
196 m_error = 0;
197 m_weights = 1.0;
198 m_weighted_error = 0.0;
199 m_cov = 0.0;
200 m_covWeightDiag = 0.0;
201 return;
202 }
203
204 m_depthPointSet.updateAndErrorAndInteractionMatrix(frame.cam, cMo, frame.depth, m_error, m_L);
205
206 m_robust.setMinMedianAbsoluteDeviation((frame.renders.zFar - frame.renders.zNear) * 0.01);
208
210}
211
213 const vpImage<vpRGBa> &/*IRGB*/, const vpImage<unsigned char> &depth) const
214{
215 switch (m_displayType) {
216 case DT_SIMPLE:
217 {
218 for (unsigned int i = 0; i < m_depthPoints.size(); ++i) {
219 vpColor c(0, 255, 0);
220 vpDisplay::displayPoint(depth, m_depthPoints[i].pixelPos[0], m_depthPoints[i].pixelPos[1], c, 1);
221 }
222 break;
223 }
224 case DT_WEIGHT:
225 {
226 for (unsigned int i = 0; i < m_depthPoints.size(); ++i) {
227 vpColor c(0, static_cast<unsigned char>(m_weights[i] * 255), 0);
228 vpDisplay::displayPoint(depth, m_depthPoints[i].pixelPos[0], m_depthPoints[i].pixelPos[1], c, 1);
229 }
230 break;
231 }
232 case DT_ERROR:
233 {
234 double maxError = m_error.getMaxValue();
235 for (unsigned int i = 0; i < m_depthPoints.size(); ++i) {
236 vpColor c(static_cast<unsigned int>((m_error[i] / maxError) * 255), 0, 0);
237 vpDisplay::displayPoint(depth, m_depthPoints[i].pixelPos[0], m_depthPoints[i].pixelPos[1], c, 1);
238 }
239 break;
240 }
242 {
243 double maxError = m_error.getMaxValue();
244 for (unsigned int i = 0; i < m_depthPoints.size(); ++i) {
245 vpColor c(static_cast<unsigned int>((m_error[i] / maxError) * 255.0), static_cast<unsigned char>(m_weights[i] * 255), 0);
246 vpDisplay::displayPoint(depth, m_depthPoints[i].pixelPos[0], m_depthPoints[i].pixelPos[1], c, 1);
247 }
248 break;
249 }
250 default:
251 throw vpException(vpException::notImplementedError, "Depth tracker display type is invalid or not implemented");
252 }
253}
254
255END_VISP_NAMESPACE
Type * data
Address of the first element of the data array.
Definition vpArray2D.h:149
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
vpColVector & normalize()
Class to define RGB colors available for display functionalities.
Definition vpColor.h:157
static void displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ notImplementedError
Not implemented.
Definition vpException.h:69
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpTranslationVector getTranslationVector() const
Definition of the vpImage class member functions.
Definition vpImage.h:131
static double rad(double deg)
Definition vpMath.h:129
static bool isFinite(double value)
Definition vpMath.cpp:198
void display(const vpCameraParameters &cam, const vpImage< unsigned char > &I, const vpImage< vpRGBa > &IRGB, const vpImage< unsigned char > &depth) const VP_OVERRIDE
std::vector< vpDepthPoint > m_depthPoints
void computeVVSIter(const vpRBFeatureTrackerInput &frame, const vpHomogeneousMatrix &cMo, unsigned int iteration) VP_OVERRIDE
void extractFeatures(const vpRBFeatureTrackerInput &frame, const vpRBFeatureTrackerInput &previousFrame, const vpHomogeneousMatrix &cMo) VP_OVERRIDE
Extract features from the frame data and the current pose estimate.
All the data related to a single tracking frame. This contains both the input data (from a real camer...
vpImage< float > mask
depth image, 0 sized if depth is not available
vpImage< float > depth
RGB image, 0 sized if RGB is not available.
vpRBRenderData renders
camera parameters
void updateOptimizerTerms(const vpHomogeneousMatrix &cMo)
vpColVector m_weights
Weighted VS error.
vpMatrix m_LTL
Error jacobian (In VS terms, the interaction matrix).
vpColVector m_covWeightDiag
Covariance matrix.
vpColVector m_LTR
Left side of the Gauss newton minimization.
unsigned m_numFeatures
Error weights.
vpColVector m_weighted_error
Raw VS Error vector.
vpMatrix m_cov
Right side of the Gauss Newton minimization.
Defines a rectangle in the plane.
Definition vpRect.h:79
double getArea() const
Definition vpRect.h:91
@ TUKEY
Tukey influence function.
Definition vpRobust.h:89
Implementation of a rotation matrix and operations on such kind of matrices.
Class that consider the case of a translation vector.
Class for generating random numbers with uniform probability density.
Definition vpUniRand.h:127
std::vector< size_t > sampleWithoutReplacement(size_t count, size_t vectorSize)
double zNear
Binary image indicating whether a given pixel is part of the silhouette.
vpImage< float > depth
Image containing the per-pixel normal vector (RGB, in object space).
vpHomogeneousMatrix cMo
vpImage< vpRGBf > normals