13 #include <Eigen/Dense> 19 template <
class POINTMAP>
21 const int H,
const int W,
const float* kys,
const float* kzs,
24 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
27 template <
class POINTMAP>
29 const int H,
const int W,
const float* kys,
const float* kzs,
32 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
35 template <
typename POINTMAP,
bool isDepth>
55 for (
int r = 0;
r < H;
r++)
56 for (
int c = 0;
c < W;
c++)
61 const float Ky = (r_cx -
c) * r_fx_inv;
62 const float Kz = (r_cy -
r) * r_fy_inv;
65 isDepth ? D : D / std::sqrt(1 + Ky * Ky + Kz * Kz),
77 template <
typename POINTMAP,
bool isDepth>
85 const size_t WH = W * H;
100 for (
int r = 0;
r < H;
r++)
101 for (
int c = 0;
c < W;
c++)
103 *kys++ = (r_cx -
c) * r_fx_inv;
104 *kzs++ = (r_cy -
r) * r_fy_inv;
125 if ((W & 0x07) == 0 && pp.
USE_SSE2 && DECIM == 1)
136 template <
class POINTMAP>
154 const size_t WH = W * H;
171 range2XYZ_LUT<POINTMAP, true>(pca, src_obs, pp, fp, H, W);
173 range2XYZ<POINTMAP, true>(pca, src_obs, fp, H, W);
176 range2XYZ<POINTMAP, false>(pca, src_obs, fp, H, W);
183 (W % DECIM) == 0 && (H % DECIM == 0),
184 "Width/Height are not an exact multiple of decimation");
185 const int Wd = W / DECIM;
186 const int Hd = H / DECIM;
188 const size_t WHd = Wd * Hd;
195 "Decimation only available if range_is_depth && PROJ3D_USE_LUT");
196 range2XYZ_LUT<POINTMAP, true>(pca, src_obs, pp, fp, H, W, DECIM);
202 if constexpr (pca.HAS_RGB)
217 const bool isDirectCorresp =
227 if (!isDirectCorresp)
246 const size_t nPts = pca.size();
249 const auto img_stride = iimg.getRowStride();
250 for (
size_t i = 0; i < nPts; i++)
255 bool pointWithinImage =
false;
258 pointWithinImage =
true;
268 i, pt_wrt_depth[0], pt_wrt_depth[1], pt_wrt_depth[2]);
269 pt_wrt_color = T_inv * pt_wrt_depth;
275 cx + fx * pt_wrt_color[0] / pt_wrt_color[2]);
277 cy + fy * pt_wrt_color[1] / pt_wrt_color[2]);
278 pointWithinImage = img_idx_x >= 0 && img_idx_x < imgW &&
279 img_idx_y >= 0 && img_idx_y < imgH;
283 if (pointWithinImage)
285 if (hasColorIntensityImg)
288 img_stride * img_idx_y + 3 * img_idx_x;
289 pCol.
R = img_data[px_idx + 2];
290 pCol.
G = img_data[px_idx + 1];
291 pCol.
B = img_data[px_idx + 0];
295 const auto px_idx = img_stride * img_idx_y + img_idx_x;
296 pCol.
R = pCol.
G = pCol.
B = img_data[px_idx];
301 pCol.
R = pCol.
G = pCol.
B = 255;
304 pca.setPointRGBu8(i, pCol.
R, pCol.
G, pCol.
B);
331 const size_t nPts = pca.size();
332 for (
size_t i = 0; i < nPts; i++)
334 pca.getPointXYZ(i, pt[0], pt[1], pt[2]);
336 pca.setPointXYZ(i, pt_transf[0], pt_transf[1], pt_transf[2]);
342 template <
class POINTMAP>
344 const int H,
const int W,
const float* kys,
const float* kzs,
347 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
356 for (
int r = 0;
r < H;
r++)
357 for (
int c = 0;
c < W;
c++)
359 const float D = rangeImage.
coeff(
r,
c);
361 const auto ky = *kys++, kz = *kzs++;
364 if (MAKE_ORGANIZED) pca.setInvalidPoint(idx++);
367 pca.setPointXYZ(idx, D , ky * D , kz * D );
375 const int Hd = H / DECIM, Wd = W / DECIM;
377 for (
int rd = 0; rd < Hd; rd++)
378 for (
int cd = 0; cd < Wd; cd++)
380 bool valid_pt =
false;
381 float min_d = std::numeric_limits<float>::max();
382 for (
int rb = 0; rb < DECIM; rb++)
383 for (
int cb = 0; cb < DECIM; cb++)
385 const auto r = rd * DECIM + rb,
c = cd * DECIM + cb;
386 const float D = rangeImage.
coeff(
r,
c);
390 if (D < min_d) min_d = D;
395 if (MAKE_ORGANIZED) pca.setInvalidPoint(idx++);
398 const auto eq_r = rd * DECIM + DECIM / 2,
399 eq_c = cd * DECIM + DECIM / 2;
400 const auto ky = kys[eq_c + eq_r * W], kz = kzs[eq_c + eq_r * W];
402 idx, min_d , ky * min_d , kz * min_d );
412 template <
class POINTMAP>
414 const int H,
const int W,
const float* kys,
const float* kzs,
417 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
423 const int W_4 = W >> 2;
425 alignas(MRPT_MAX_STATIC_ALIGN_BYTES)
float xs[4], ys[4], zs[4];
426 const __m128 D_zeros = _mm_set_ps(.0f, .0f, .0f, .0f);
427 const __m128 xormask =
433 for (
int r = 0;
r < H;
r++)
435 const float* D_ptr = &rangeImage(
r, 0);
436 const float* Dgt_ptr =
438 const float* Dlt_ptr =
441 for (
int c = 0;
c < W_4;
c++)
443 const __m128 D = _mm_load_ps(D_ptr);
444 const __m128 nz_mask = _mm_cmpgt_ps(D, D_zeros);
445 __m128 valid_range_mask;
448 valid_range_mask = nz_mask;
456 const __m128 Dmin = _mm_load_ps(Dgt_ptr);
457 valid_range_mask = _mm_and_ps(
458 _mm_cmpgt_ps(D, Dmin), _mm_cmpgt_ps(Dmin, D_zeros));
462 const __m128 Dmax = _mm_load_ps(Dlt_ptr);
463 valid_range_mask = _mm_and_ps(
464 _mm_cmplt_ps(D, Dmax), _mm_cmpgt_ps(Dmax, D_zeros));
466 valid_range_mask = _mm_and_ps(
467 valid_range_mask, nz_mask);
473 const __m128 Dmin = _mm_load_ps(Dgt_ptr);
474 const __m128 Dmax = _mm_load_ps(Dlt_ptr);
476 const __m128 gt_mask = _mm_cmpgt_ps(D, Dmin);
477 const __m128 lt_mask = _mm_and_ps(
478 _mm_cmplt_ps(D, Dmax), nz_mask);
480 _mm_and_ps(gt_mask, lt_mask);
481 valid_range_mask = _mm_xor_ps(valid_range_mask, xormask);
483 valid_range_mask = _mm_or_ps(
484 valid_range_mask, _mm_and_ps(
485 _mm_cmpeq_ps(Dmin, D_zeros),
486 _mm_cmpeq_ps(Dmax, D_zeros)));
488 valid_range_mask = _mm_and_ps(valid_range_mask, nz_mask);
491 const int valid_range_maski = _mm_movemask_epi8(
492 _mm_castps_si128(valid_range_mask));
493 if (valid_range_maski != 0)
495 const __m128 KY = _mm_load_ps(kys);
496 const __m128 KZ = _mm_load_ps(kzs);
498 _mm_storeu_ps(xs, D);
499 _mm_storeu_ps(ys, _mm_mul_ps(KY, D));
500 _mm_storeu_ps(zs, _mm_mul_ps(KZ, D));
502 for (
int q = 0;
q < 4;
q++)
503 if ((valid_range_maski & (1 << (
q * 4))) != 0)
505 pca.setPointXYZ(idx, xs[
q], ys[
q], zs[
q]);
506 idxs_x[idx] = (
c << 2) +
q;
510 else if (MAKE_ORGANIZED)
512 pca.setInvalidPoint(idx);
516 else if (MAKE_ORGANIZED)
518 for (
int q = 0;
q < 4;
q++)
520 pca.setInvalidPoint(idx);
525 if (Dgt_ptr) Dgt_ptr += 4;
526 if (Dlt_ptr) Dlt_ptr += 4;
mrpt::img::TCamera cameraParams
Projection parameters of the depth camera.
Mainly for internal use within CObservation3DRangeScan::project3DPointsFromDepthImageInto() ...
uint8_t decimation
(Default:1) If !=1, split the range image in blocks of DxD (D=decimation), and only generates one poi...
void resizePoints3DVectors(const size_t nPoints)
Use this method instead of resizing all three points3D_x, points3D_y & points3D_z to allow the usage ...
const mrpt::poses::CPose3D * robotPoseInTheWorld
(Default: nullptr) Read takeIntoAccountSensorPoseOnRobot
double fx() const
Get the value of the focal length x-value (in pixels).
mrpt::math::CVectorFixedDouble< 3 > m_coords
The translation vector [x,y,z] access directly or with x(), y(), z() setter/getter methods...
const T * ptrLine(unsigned int row) const
Returns a pointer to the first pixel of the given line.
An adapter to different kinds of point cloud object.
GLdouble GLdouble GLdouble GLdouble q
std::vector< uint16_t > points3D_idxs_x
If hasPoints3D=true, the (x,y) pixel coordinates for each (X,Y,Z) point in points3D_x, points3D_y, points3D_z.
mrpt::math::CMatrixF rangeImage
If hasRangeImage=true, a matrix of floats with the range data as captured by the camera (in meters) ...
void insertMatrix(const int row_start, const int col_start, const OTHERMATVEC &submat)
Copies the given input submatrix/vector into this matrix/vector, starting at the given top-left coord...
double fy() const
Get the value of the focal length y-value (in pixels).
Declares a class derived from "CObservation" that encapsules a 3D range scan measurement, as from a time-of-flight range camera or any other RGBD sensor.
void range2XYZ(mrpt::opengl::PointCloudAdapter< POINTMAP > &pca, mrpt::obs::CObservation3DRangeScan &src_obs, const mrpt::obs::TRangeImageFilterParams &fp, const int H, const int W)
size_t getHeight() const override
Returns the height of the image in pixels.
void do_project_3d_pointcloud_SSE2(const int H, const int W, const float *kys, const float *kzs, const mrpt::math::CMatrixF &rangeImage, mrpt::opengl::PointCloudAdapter< POINTMAP > &pca, std::vector< uint16_t > &idxs_x, std::vector< uint16_t > &idxs_y, const mrpt::obs::TRangeImageFilterParams &fp, bool MAKE_ORGANIZED)
Used in CObservation3DRangeScan::project3DPointsFromDepthImageInto()
const mrpt::math::CMatrixF * rangeMask_max
#define ASSERT_(f)
Defines an assertion mechanism.
This base provides a set of functions for maths stuff.
size_t getWidth() const override
Returns the width of the image in pixels.
mrpt::poses::CPose3D relativePoseIntensityWRTDepth
Relative pose of the intensity camera wrt the depth camera (which is the coordinates origin for this ...
double cy() const
Get the value of the principal point y-coordinate (in pixels).
An adapter to different kinds of point cloud object.
std::vector< uint16_t > points3D_idxs_y
void composeFrom(const CPose3D &A, const CPose3D &B)
Makes "this = A (+) B"; this method is slightly more efficient than "this= A + B;" since it avoids th...
#define ASSERT_EQUAL_(__A, __B)
Assert comparing two values, reporting their actual values upon failure.
void project3DPointsFromDepthImageInto(mrpt::obs::CObservation3DRangeScan &src_obs, POINTMAP &dest_pointcloud, const mrpt::obs::T3DPointsProjectionParams &projectParams, const mrpt::obs::TRangeImageFilterParams &filterParams)
mrpt::img::TCamera prev_camParams
mrpt::img::CImage intensityImage
If hasIntensityImage=true, a color or gray-level intensity image of the same size than "rangeImage"...
bool hasRangeImage
true means the field rangeImage contains valid data
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
const mrpt::math::CMatrixF * rangeMask_min
(Default: nullptr) If provided, each data range will be tested to be greater-than (rangeMask_min) or ...
size_type rows() const
Number of rows in the matrix.
size_type cols() const
Number of columns in the matrix.
void range2XYZ_LUT(mrpt::opengl::PointCloudAdapter< POINTMAP > &pca, mrpt::obs::CObservation3DRangeScan &src_obs, const mrpt::obs::T3DPointsProjectionParams &pp, const mrpt::obs::TRangeImageFilterParams &fp, const int H, const int W, const int DECIM=1)
const Scalar & coeff(int r, int c) const
bool USE_SSE2
(Default:true) If possible, use SSE2 optimized code.
double cx() const
Get the value of the principal point x-coordinate (in pixels).
This class is a "CSerializable" wrapper for "CMatrixFloat".
mrpt::aligned_std_vector< float > Kys
bool MAKE_ORGANIZED
(Default:false) set to true if you want an organized point cloud
GLdouble GLdouble GLdouble r
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot.
void homogeneousMatrixInverse(const MATRIXLIKE1 &M, MATRIXLIKE2 &out_inverse_M)
Efficiently compute the inverse of a 4x4 homogeneous matrix by only transposing the rotation 3x3 part...
CMatrixFixed< float, ROWS, COLS > cast_float() const
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
static TCached3DProjTables & get_3dproj_lut()
3D point cloud projection look-up-table
Used in CObservation3DRangeScan::project3DPointsFromDepthImageInto()
bool hasIntensityImage
true means the field intensityImage contains valid data
void do_project_3d_pointcloud(const int H, const int W, const float *kys, const float *kzs, const mrpt::math::CMatrixF &rangeImage, mrpt::opengl::PointCloudAdapter< POINTMAP > &pca, std::vector< uint16_t > &idxs_x, std::vector< uint16_t > &idxs_y, const mrpt::obs::TRangeImageFilterParams &fp, bool MAKE_ORGANIZED, const int DECIM)
bool PROJ3D_USE_LUT
(Default:true) [Only used when range_is_depth=true] Whether to use a Look-up-table (LUT) to speed up ...
bool doDepthAndIntensityCamerasCoincide() const
Return true if relativePoseIntensityWRTDepth equals the pure rotation (0,0,0,-90deg,0,-90deg) (with a small comparison epsilon)
MATRIX44 getHomogeneousMatrixVal() const
Returns the corresponding 4x4 homogeneous transformation matrix for the point(translation) or pose (t...
void getRotationMatrix(mrpt::math::CMatrixDouble33 &ROT) const
Get the 3x3 rotation matrix.
mrpt::img::TCamera cameraParamsIntensity
Projection parameters of the intensity (graylevel or RGB) camera.
bool range_is_depth
true: Kinect-like ranges: entries of rangeImage are distances along the +X axis; false: Ranges in ran...
mrpt::aligned_std_vector< float > Kzs
bool takeIntoAccountSensorPoseOnRobot
(Default: false) If false, local (sensor-centric) coordinates of points are generated.
bool do_range_filter(size_t r, size_t c, const float D) const
Returns true if the point (r,c) with depth D passes all filters.
bool rangeCheckBetween
Only used if both rangeMask_min and rangeMask_max are present.
int round(const T value)
Returns the closer integer (int) to x.