9 #ifndef CObservation3DRangeScan_project3D_impl_H
10 #define CObservation3DRangeScan_project3D_impl_H
18 template <
class POINTMAP>
20 const int H,
const int W,
const float* kys,
const float* kzs,
23 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
25 template <
class POINTMAP>
27 const int H,
const int W,
const float* kys,
const float* kzs,
30 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
33 template <
class POINTMAP>
51 const size_t WH = W * H;
60 pca.setDimensions(H,W);
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 = 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);
322 const Eigen::Matrix<float, 4, 4> HM =
326 Eigen::Matrix<float, 4, 1> pt, pt_transf;
329 const size_t nPts = pca.size();
330 for (
size_t i = 0; i < nPts; i++)
332 pca.getPointXYZ(i, pt[0], pt[1], pt[2]);
334 pca.setPointXYZ(i, pt_transf[0], pt_transf[1], pt_transf[2]);
340 template <
class POINTMAP>
342 const int H,
const int W,
const float* kys,
const float* kzs,
345 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
351 for (
int r = 0;
r < H;
r++)
352 for (
int c = 0;
c < W;
c++)
354 const float D = rangeImage.coeff(
r,
c);
359 pca.setInvalidPoint(idx);
365 pca.setPointXYZ(idx, D , *kys++ * D , *kzs++ * D );
374 template <
class POINTMAP>
376 const int H,
const int W,
const float* kys,
const float* kzs,
379 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
385 const int W_4 = W >> 2;
388 const __m128 D_zeros = _mm_set_ps(.0f, .0f, .0f, .0f);
389 const __m128 xormask =
391 ? _mm_cmpneq_ps(D_zeros, D_zeros)
396 for (
int r = 0;
r < H;
r++)
399 &rangeImage.coeffRef(
r, 0);
400 const float* Dgt_ptr =
404 const float* Dlt_ptr =
409 for (
int c = 0;
c < W_4;
c++)
411 const __m128 D = _mm_load_ps(D_ptr);
412 const __m128 nz_mask = _mm_cmpgt_ps(D, D_zeros);
413 __m128 valid_range_mask;
416 valid_range_mask = nz_mask;
424 const __m128 Dmin = _mm_load_ps(Dgt_ptr);
425 valid_range_mask = _mm_and_ps(
426 _mm_cmpgt_ps(D, Dmin), _mm_cmpgt_ps(Dmin, D_zeros));
430 const __m128 Dmax = _mm_load_ps(Dlt_ptr);
431 valid_range_mask = _mm_and_ps(
432 _mm_cmplt_ps(D, Dmax), _mm_cmpgt_ps(Dmax, D_zeros));
434 valid_range_mask = _mm_and_ps(
435 valid_range_mask, nz_mask);
441 const __m128 Dmin = _mm_load_ps(Dgt_ptr);
442 const __m128 Dmax = _mm_load_ps(Dlt_ptr);
444 const __m128 gt_mask = _mm_cmpgt_ps(D, Dmin);
445 const __m128 lt_mask = _mm_and_ps(
446 _mm_cmplt_ps(D, Dmax), nz_mask);
448 _mm_and_ps(gt_mask, lt_mask);
449 valid_range_mask = _mm_xor_ps(valid_range_mask, xormask);
451 valid_range_mask = _mm_or_ps(
452 valid_range_mask, _mm_and_ps(
453 _mm_cmpeq_ps(Dmin, D_zeros),
454 _mm_cmpeq_ps(Dmax, D_zeros)));
456 valid_range_mask = _mm_and_ps(valid_range_mask, nz_mask);
459 const int valid_range_maski = _mm_movemask_epi8(
460 _mm_castps_si128(valid_range_mask));
461 if (valid_range_maski != 0)
463 const __m128 KY = _mm_load_ps(kys);
464 const __m128 KZ = _mm_load_ps(kzs);
466 _mm_storeu_ps(xs, D);
467 _mm_storeu_ps(ys, _mm_mul_ps(KY, D));
468 _mm_storeu_ps(zs, _mm_mul_ps(KZ, D));
470 for (
int q = 0;
q < 4;
q++)
471 if ((valid_range_maski & (1 << (
q * 4))) != 0)
473 pca.setPointXYZ(idx, xs[
q], ys[
q], zs[
q]);
474 idxs_x[idx] = (
c << 2) +
q;
478 else if (!MAKE_DENSE)
480 pca.setInvalidPoint(idx);
484 else if (!MAKE_DENSE)
486 for (
int q = 0;
q < 4;
q++)
488 pca.setInvalidPoint(idx);
493 if (Dgt_ptr) Dgt_ptr += 4;
494 if (Dlt_ptr) Dlt_ptr += 4;
#define MRPT_MAX_ALIGN_BYTES
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,...
size_t getHeight() const override
Returns the height of the image in pixels.
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
size_t getWidth() const override
Returns the width of the image in pixels.
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).
double cx() const
Get the value of the principal point x-coordinate (in pixels).
double cy() const
Get the value of the principal point y-coordinate (in pixels).
A numeric matrix of compile-time fixed size.
This class is a "CSerializable" wrapper for "CMatrixFloat".
Declares a class derived from "CObservation" that encapsules a 3D range scan measurement,...
void resizePoints3DVectors(const size_t nPoints)
Use this method instead of resizing all three points3D_x, points3D_y & points3D_z to allow the usage ...
static TCached3DProjTables & get_3dproj_lut()
3D point cloud projection look-up-table
std::vector< uint16_t > points3D_idxs_x
If hasPoints3D=true, the (x,y) pixel coordinates for each (X,Y,Z) point in points3D_x,...
mrpt::img::TCamera cameraParams
Projection parameters of the depth camera.
bool hasIntensityImage
true means the field intensityImage contains valid data
mrpt::poses::CPose3D relativePoseIntensityWRTDepth
Relative pose of the intensity camera wrt the depth camera (which is the coordinates origin for this ...
bool doDepthAndIntensityCamerasCoincide() const
Return true if relativePoseIntensityWRTDepth equals the pure rotation (0,0,0,-90deg,...
std::vector< uint16_t > points3D_idxs_y
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
mrpt::math::CMatrix rangeImage
If hasRangeImage=true, a matrix of floats with the range data as captured by the camera (in meters)
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot.
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...
An adapter to different kinds of point cloud object.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
void getRotationMatrix(mrpt::math::CMatrixDouble33 &ROT) const
Get the 3x3 rotation matrix.
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...
MATRIX44 getHomogeneousMatrixVal() const
Returns the corresponding 4x4 homogeneous transformation matrix for the point(translation) or pose (t...
#define ASSERT_EQUAL_(__A, __B)
Assert comparing two values, reporting their actual values upon failure.
#define ASSERT_(f)
Defines an assertion mechanism.
GLdouble GLdouble GLdouble r
GLdouble GLdouble GLdouble GLdouble q
int round(const T value)
Returns the closer integer (int) to x.
This base provides a set of functions for maths stuff.
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...
void do_project_3d_pointcloud(const int H, const int W, const float *kys, const float *kzs, const mrpt::math::CMatrix &rangeImage, mrpt::opengl::PointCloudAdapter< POINTMAP > &pca, std::vector< uint16_t > &idxs_x, std::vector< uint16_t > &idxs_y, const mrpt::obs::TRangeImageFilterParams &filterParams, bool MAKE_DENSE)
void do_project_3d_pointcloud_SSE2(const int H, const int W, const float *kys, const float *kzs, const mrpt::math::CMatrix &rangeImage, mrpt::opengl::PointCloudAdapter< POINTMAP > &pca, std::vector< uint16_t > &idxs_x, std::vector< uint16_t > &idxs_y, const mrpt::obs::TRangeImageFilterParams &filterParams, bool MAKE_DENSE)
void project3DPointsFromDepthImageInto(mrpt::obs::CObservation3DRangeScan &src_obs, POINTMAP &dest_pointcloud, const mrpt::obs::T3DPointsProjectionParams &projectParams, const mrpt::obs::TRangeImageFilterParams &filterParams)
mrpt::math::CVectorFloat Kys
mrpt::math::CVectorFloat Kzs
mrpt::img::TCamera prev_camParams
Used in CObservation3DRangeScan::project3DPointsFromDepthImageInto()
bool MAKE_ORGANIZED
(Default:false) set to true if you want an organized point cloud
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 takeIntoAccountSensorPoseOnRobot
(Default: false) If false, local (sensor-centric) coordinates of points are generated.
bool MAKE_DENSE
(Default:true) set to false if your point cloud can contain undefined values
bool USE_SSE2
(Default:true) If possible, use SSE2 optimized code.
const mrpt::poses::CPose3D * robotPoseInTheWorld
(Default: nullptr) Read takeIntoAccountSensorPoseOnRobot
Mainly for internal use within CObservation3DRangeScan::project3DPointsFromDepthImageInto()
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.
Used in CObservation3DRangeScan::project3DPointsFromDepthImageInto()
bool rangeCheckBetween
Only used if both rangeMask_min and rangeMask_max are present.
const mrpt::math::CMatrix * rangeMask_min
(Default: nullptr) If provided, each data range will be tested to be greater-than (rangeMask_min) or ...
const mrpt::math::CMatrix * rangeMask_max