9 #ifndef CObservation3DRangeScan_project3D_impl_H 10 #define CObservation3DRangeScan_project3D_impl_H 22 template <
class POINTMAP>
24 const int H,
const int W,
const float* kys,
const float* kzs,
27 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
29 template <
class POINTMAP>
31 const int H,
const int W,
const float* kys,
const float* kzs,
34 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
37 template <
class POINTMAP>
55 const size_t WH = W * H;
85 for (
int r = 0;
r < H;
r++)
86 for (
int c = 0;
c < W;
c++)
88 *kys++ = (r_cx -
c) * r_fx_inv;
89 *kzs++ = (r_cy -
r) * r_fy_inv;
117 if ((W & 0x07) == 0 && projectParams.
USE_SSE2)
145 for (
int r = 0;
r < H;
r++)
146 for (
int c = 0;
c < W;
c++)
151 const float Kz = (r_cy -
r) * r_fy_inv;
152 const float Ky = (r_cx -
c) * r_fx_inv;
183 for (
int r = 0;
r < H;
r++)
184 for (
int c = 0;
c < W;
c++)
189 const float Ky = (r_cx -
c) * r_fx_inv;
190 const float Kz = (r_cy -
r) * r_fy_inv;
193 D / std::sqrt(1 + Ky * Ky + Kz * Kz),
220 const bool isDirectCorresp =
227 if (!isDirectCorresp)
236 T_inv.block<3, 3>(0, 0) = R_inv.cast<
float>();
237 T_inv.block<3, 1>(0, 3) = t_inv.cast<
float>();
240 Eigen::Matrix<float, 4, 1> pt_wrt_color, pt_wrt_depth;
246 const size_t nPts = pca.size();
247 for (
size_t i = 0; i < nPts; i++)
249 int img_idx_x, img_idx_y;
251 bool pointWithinImage =
false;
254 pointWithinImage =
true;
263 i, pt_wrt_depth[0], pt_wrt_depth[1], pt_wrt_depth[2]);
264 pt_wrt_color.noalias() = T_inv * pt_wrt_depth;
270 cx + fx * pt_wrt_color[0] / pt_wrt_color[2]);
272 cy + fy * pt_wrt_color[1] / pt_wrt_color[2]);
273 pointWithinImage = img_idx_x >= 0 && img_idx_x < imgW &&
274 img_idx_y >= 0 && img_idx_y < imgH;
278 if (pointWithinImage)
280 if (hasColorIntensityImg)
283 img_idx_x, img_idx_y, 0);
291 img_idx_x, img_idx_y, 0);
292 pCol.
R = pCol.
G = pCol.
B =
c;
297 pCol.
R = pCol.
G = pCol.
B = 255;
300 pca.setPointRGBu8(i, pCol.
R, pCol.
G, pCol.
B);
324 Eigen::Matrix<float, 4, 1> pt, pt_transf;
327 const size_t nPts = pca.size();
328 for (
size_t i = 0; i < nPts; i++)
330 pca.getPointXYZ(i, pt[0], pt[1], pt[2]);
331 pt_transf.noalias() = HM * pt;
332 pca.setPointXYZ(i, pt_transf[0], pt_transf[1], pt_transf[2]);
338 template <
class POINTMAP>
340 const int H,
const int W,
const float* kys,
const float* kzs,
343 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
349 for (
int r = 0;
r < H;
r++)
350 for (
int c = 0;
c < W;
c++)
352 const float D = rangeImage.coeff(
r,
c);
357 pca.setInvalidPoint(idx);
363 pca.setPointXYZ(idx, D , *kys++ * D , *kzs++ * D );
372 template <
class POINTMAP>
374 const int H,
const int W,
const float* kys,
const float* kzs,
377 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
383 const int W_4 = W >> 2;
385 alignas(16)
float xs[4], ys[4], zs[4];
386 const __m128 D_zeros = _mm_set_ps(.0f, .0f, .0f, .0f);
387 const __m128 xormask =
389 ? _mm_cmpneq_ps(D_zeros, D_zeros)
394 for (
int r = 0;
r < H;
r++)
397 &rangeImage.coeffRef(
r, 0);
398 const float* Dgt_ptr =
402 const float* Dlt_ptr =
407 for (
int c = 0;
c < W_4;
c++)
409 const __m128 D = _mm_load_ps(D_ptr);
410 const __m128 nz_mask = _mm_cmpgt_ps(D, D_zeros);
411 __m128 valid_range_mask;
414 valid_range_mask = nz_mask;
422 const __m128 Dmin = _mm_load_ps(Dgt_ptr);
423 valid_range_mask = _mm_and_ps(
424 _mm_cmpgt_ps(D, Dmin), _mm_cmpgt_ps(Dmin, D_zeros));
428 const __m128 Dmax = _mm_load_ps(Dlt_ptr);
429 valid_range_mask = _mm_and_ps(
430 _mm_cmplt_ps(D, Dmax), _mm_cmpgt_ps(Dmax, D_zeros));
432 valid_range_mask = _mm_and_ps(
433 valid_range_mask, nz_mask);
439 const __m128 Dmin = _mm_load_ps(Dgt_ptr);
440 const __m128 Dmax = _mm_load_ps(Dlt_ptr);
442 const __m128 gt_mask = _mm_cmpgt_ps(D, Dmin);
443 const __m128 lt_mask = _mm_and_ps(
444 _mm_cmplt_ps(D, Dmax), nz_mask);
446 _mm_and_ps(gt_mask, lt_mask);
447 valid_range_mask = _mm_xor_ps(valid_range_mask, xormask);
449 valid_range_mask = _mm_or_ps(
450 valid_range_mask, _mm_and_ps(
451 _mm_cmpeq_ps(Dmin, D_zeros),
452 _mm_cmpeq_ps(Dmax, D_zeros)));
454 valid_range_mask = _mm_and_ps(valid_range_mask, nz_mask);
457 const int valid_range_maski = _mm_movemask_epi8(
458 _mm_castps_si128(valid_range_mask));
459 if (valid_range_maski != 0)
461 const __m128 KY = _mm_load_ps(kys);
462 const __m128 KZ = _mm_load_ps(kzs);
464 _mm_storeu_ps(xs, D);
465 _mm_storeu_ps(ys, _mm_mul_ps(KY, D));
466 _mm_storeu_ps(zs, _mm_mul_ps(KZ, D));
468 for (
int q = 0;
q < 4;
q++)
469 if ((valid_range_maski & (1 << (
q * 4))) != 0)
471 pca.setPointXYZ(idx, xs[
q], ys[
q], zs[
q]);
472 idxs_x[idx] = (
c << 2) +
q;
476 else if (!MAKE_DENSE)
478 pca.setInvalidPoint(idx);
482 else if (!MAKE_DENSE)
484 for (
int q = 0;
q < 4;
q++)
486 pca.setInvalidPoint(idx);
491 if (Dgt_ptr) Dgt_ptr += 4;
492 if (Dlt_ptr) Dlt_ptr += 4;
#define ASSERT_EQUAL_(__A, __B)
Mainly for internal use within CObservation3DRangeScan::project3DPointsFromDepthImageInto() ...
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
mrpt::utils::TCamera cameraParamsIntensity
Projection parameters of the intensity (graylevel or RGB) camera.
mrpt::math::CVectorFloat Kzs
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.
double cy() const
Get the value of the principal point y-coordinate (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.
const mrpt::math::CMatrix * rangeMask_min
(Default: nullptr) If provided, each data range will be tested to be greater-than (rangeMask_min) or ...
Used in CObservation3DRangeScan::project3DPointsFromDepthImageInto()
mrpt::math::CMatrix rangeImage
If hasRangeImage=true, a matrix of floats with the range data as captured by the camera (in meters) ...
mrpt::utils::TCamera cameraParams
Projection parameters of the depth camera.
double fx() const
Get the value of the focal length x-value (in pixels).
double fy() const
Get the value of the focal length y-value (in pixels).
A numeric matrix of compile-time fixed size.
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 ...
std::vector< uint16_t > points3D_idxs_y
mrpt::math::CArrayDouble< 3 > m_coords
The translation vector [x,y,z] access directly or with x(), y(), z() setter/getter methods...
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...
mrpt::math::CMatrixDouble44 getHomogeneousMatrixVal() const
void project3DPointsFromDepthImageInto(mrpt::obs::CObservation3DRangeScan &src_obs, POINTMAP &dest_pointcloud, const mrpt::obs::T3DPointsProjectionParams &projectParams, const mrpt::obs::TRangeImageFilterParams &filterParams)
size_t getHeight() const override
Returns the height of the image in pixels.
bool hasRangeImage
true means the field rangeImage contains valid data
An adapter to different kinds of point cloud object.
void do_project_3d_pointcloud_SSE2(const int H, const int W, const float *kys, const float *kzs, const mrpt::math::CMatrix &rangeImage, mrpt::utils::PointCloudAdapter< POINTMAP > &pca, std::vector< uint16_t > &idxs_x, std::vector< uint16_t > &idxs_y, const mrpt::obs::TRangeImageFilterParams &filterParams, bool MAKE_DENSE)
mrpt::math::CVectorFloat Kys
double cx() const
Get the value of the principal point x-coordinate (in pixels).
bool USE_SSE2
(Default:true) If possible, use SSE2 optimized code.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
GLdouble GLdouble GLdouble r
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot.
const mrpt::math::CMatrix * rangeMask_max
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...
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
int round(const T value)
Returns the closer integer (int) to x.
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)
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
unsigned char * get_unsafe(unsigned int col, unsigned int row, unsigned int channel=0) const
Access to pixels without checking boundaries - Use normally the () operator better, which checks the coordinates.
An adapter to different kinds of point cloud object.
void getRotationMatrix(mrpt::math::CMatrixDouble33 &ROT) const
Get the 3x3 rotation matrix.
bool MAKE_DENSE
(Default:true) set to false if you want to preserve the organization of the point cloud ...
mrpt::utils::CImage intensityImage
If hasIntensityImage=true, a color or gray-level intensity image of the same size than "rangeImage"...
This class is a "CSerializable" wrapper for "CMatrixFloat".
bool range_is_depth
true: Kinect-like ranges: entries of rangeImage are distances along the +X axis; false: Ranges in ran...
void do_project_3d_pointcloud(const int H, const int W, const float *kys, const float *kzs, const mrpt::math::CMatrix &rangeImage, mrpt::utils::PointCloudAdapter< POINTMAP > &pca, std::vector< uint16_t > &idxs_x, std::vector< uint16_t > &idxs_y, const mrpt::obs::TRangeImageFilterParams &filterParams, bool MAKE_DENSE)
bool takeIntoAccountSensorPoseOnRobot
(Default: false) If false, local (sensor-centric) coordinates of points are generated.
mrpt::utils::TCamera prev_camParams
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.