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;
mrpt::img::TCamera cameraParams
Projection parameters of the depth camera.
Mainly for internal use within CObservation3DRangeScan::project3DPointsFromDepthImageInto() ...
#define MRPT_MAX_ALIGN_BYTES
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::CVectorFloat Kzs
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.
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.
const mrpt::math::CMatrix * rangeMask_min
(Default: nullptr) If provided, each data range will be tested to be greater-than (rangeMask_min) or ...
size_t getHeight() const override
Returns the height of the image in pixels.
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) ...
#define ASSERT_(f)
Defines an assertion mechanism.
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)
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 ...
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
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...
#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
mrpt::math::CVectorFloat Kys
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).
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.
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
MATRIX44 getHomogeneousMatrixVal() const
Returns the corresponding 4x4 homogeneous transformation matrix for the point(translation) or pose (t...
Used in CObservation3DRangeScan::project3DPointsFromDepthImageInto()
bool hasIntensityImage
true means the field intensityImage contains valid data
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)
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 MAKE_DENSE
(Default:true) set to false if your point cloud can contain undefined values
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_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)
bool takeIntoAccountSensorPoseOnRobot
(Default: false) If false, local (sensor-centric) coordinates of points are generated.
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.
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.