9 #ifndef CObservation3DRangeScan_project3D_impl_H
10 #define CObservation3DRangeScan_project3D_impl_H
18 template <
class POINTMAP>
void do_project_3d_pointcloud(
const int H,
const int W,
const float *kys,
const float *kzs,
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 &fp,
bool MAKE_DENSE,
const int DECIM);
21 template <
typename POINTMAP,
bool isDepth>
41 for (
int r = 0;
r < H;
r++)
42 for (
int c = 0;
c < W;
c++)
47 const float Ky = (r_cx -
c) * r_fx_inv;
48 const float Kz = (r_cy -
r) * r_fy_inv;
51 isDepth ? D : D / std::sqrt(1 + Ky * Ky + Kz * Kz),
68 template <
typename POINTMAP,
bool isDepth>
76 const size_t WH = W * H;
91 for (
int r = 0;
r < H;
r++)
92 for (
int c = 0;
c < W;
c++)
94 *kys++ = (r_cx -
c) * r_fx_inv;
95 *kzs++ = (r_cy -
r) * r_fy_inv;
116 if ((W & 0x07) == 0 && pp.
USE_SSE2 && DECIM == 1)
127 template <
class POINTMAP>
145 const size_t WH = W * H;
162 range2XYZ_LUT<POINTMAP, true>(pca, src_obs, pp, fp, H, W);
164 range2XYZ<POINTMAP, true>(pca, src_obs, fp, H, W);
167 range2XYZ<POINTMAP, false>(pca, src_obs, fp, H, W);
174 (W % DECIM) == 0 && (H % DECIM == 0),
175 "Width/Height are not an exact multiple of decimation");
176 const int Wd = W / DECIM;
177 const int Hd = H / DECIM;
179 const size_t WHd = Wd * Hd;
186 "Decimation only available if range_is_depth && PROJ3D_USE_LUT");
187 range2XYZ_LUT<POINTMAP, true>(pca, src_obs, pp, fp, H, W, DECIM);
210 if (!isDirectCorresp)
219 T_inv.block<3,3>(0,0)=R_inv.cast<
float>();
220 T_inv.block<3,1>(0,3)=t_inv.cast<
float>();
223 Eigen::Matrix<float,4,1> pt_wrt_color, pt_wrt_depth;
229 const size_t nPts = pca.size();
230 for (
size_t i=0;i<nPts;i++)
232 int img_idx_x, img_idx_y;
233 bool pointWithinImage =
false;
236 pointWithinImage=
true;
243 pca.getPointXYZ(i,pt_wrt_depth[0],pt_wrt_depth[1],pt_wrt_depth[2]);
244 pt_wrt_color.noalias() = T_inv*pt_wrt_depth;
247 if (pt_wrt_color[2]) {
251 img_idx_x>=0 && img_idx_x<imgW &&
252 img_idx_y>=0 && img_idx_y<imgH;
256 if (pointWithinImage)
258 if (hasColorIntensityImg) {
266 pCol.
R = pCol.
G = pCol.
B =
c;
271 pCol.
R = pCol.
G = pCol.
B = 255;
274 pca.setPointRGBu8(i,pCol.
R,pCol.
G,pCol.
B);
292 Eigen::Matrix<float,4,1> pt, pt_transf;
295 const size_t nPts = pca.size();
296 for (
size_t i=0;i<nPts;i++)
298 pca.getPointXYZ(i,pt[0],pt[1],pt[2]);
299 pt_transf.noalias() = HM*pt;
300 pca.setPointXYZ(i,pt_transf[0],pt_transf[1],pt_transf[2]);
306 template <
class POINTMAP>
308 const int H,
const int W,
const float* kys,
const float* kzs,
311 std::vector<uint16_t>& idxs_x, std::vector<uint16_t>& idxs_y,
320 for (
int r = 0;
r < H;
r++)
321 for (
int c = 0;
c < W;
c++)
323 const float D = rangeImage.coeff(
r,
c);
325 const auto ky = *kys++, kz = *kzs++;
328 if (!MAKE_DENSE) pca.setInvalidPoint(idx++);
332 pca.setPointXYZ(idx, D , ky * D , kz * D );
340 const int Hd = H / DECIM, Wd = W / DECIM;
342 for (
int rd = 0; rd < Hd; rd++)
343 for (
int cd = 0; cd < Wd; cd++)
345 bool valid_pt =
false;
346 float min_d = std::numeric_limits<float>::max();
347 for (
int rb = 0; rb < DECIM; rb++)
348 for (
int cb = 0; cb < DECIM; cb++)
350 const auto r = rd * DECIM + rb,
c = cd * DECIM + cb;
351 const float D = rangeImage.coeff(
r,
c);
355 if (D < min_d) min_d = D;
360 rangeImage.coeffRef(
r,
c) = 0;
365 if (!MAKE_DENSE) pca.setInvalidPoint(idx++);
368 const auto eq_r = rd * DECIM + DECIM / 2,
369 eq_c = cd * DECIM + DECIM / 2;
370 const auto ky = kys[eq_c + eq_r * W], kz = kzs[eq_c + eq_r * W];
372 idx, min_d , ky * min_d , kz * min_d );
386 template <
class POINTMAP>
392 const int W_4 = W >> 2;
395 const __m128 D_zeros = _mm_set_ps(.0f,.0f,.0f,.0f);
397 _mm_cmpneq_ps(D_zeros,D_zeros) :
398 _mm_cmpeq_ps(D_zeros,D_zeros);
399 for (
int r=0;
r<H;
r++)
401 const float *D_ptr = &rangeImage.coeffRef(
r,0);
405 for (
int c=0;
c<W_4;
c++)
407 const __m128 D = _mm_load_ps(D_ptr);
408 const __m128 nz_mask = _mm_cmpgt_ps(D, D_zeros);
409 __m128 valid_range_mask;
412 valid_range_mask = nz_mask;
420 const __m128 Dmin = _mm_load_ps(Dgt_ptr);
421 valid_range_mask = _mm_or_ps(
422 _mm_cmpgt_ps(D, Dmin), _mm_cmpeq_ps(Dmin, D_zeros));
426 const __m128 Dmax = _mm_load_ps(Dlt_ptr);
427 valid_range_mask = _mm_or_ps(
428 _mm_cmplt_ps(D, Dmax), _mm_cmpeq_ps(Dmax, D_zeros));
430 valid_range_mask = _mm_and_ps(
431 valid_range_mask, nz_mask);
437 const __m128 Dmin = _mm_load_ps(Dgt_ptr);
438 const __m128 Dmax = _mm_load_ps(Dlt_ptr);
440 const __m128 gt_mask = _mm_or_ps(
441 _mm_cmpgt_ps(D, Dmin), _mm_cmpeq_ps(Dmin, D_zeros));
442 const __m128 lt_mask = _mm_or_ps(
443 _mm_cmplt_ps(D, Dmax), _mm_cmpeq_ps(Dmax, D_zeros));
446 _mm_and_ps(nz_mask, _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(_mm_castps_si128(valid_range_mask));
458 if (valid_range_maski!=0)
460 const __m128 KY = _mm_load_ps(kys);
461 const __m128 KZ = _mm_load_ps(kzs);
463 _mm_storeu_ps(xs , D);
464 _mm_storeu_ps(ys , _mm_mul_ps(KY,D));
465 _mm_storeu_ps(zs , _mm_mul_ps(KZ,D));
467 for (
int q=0;
q<4;
q++)
469 const int actual_c = (
c << 2) +
q;
470 if ((valid_range_maski & (1<<(
q*4))) !=0) {
471 pca.setPointXYZ(idx,xs[
q],ys[
q],zs[
q]);
472 idxs_x[idx]=actual_c;
480 pca.setInvalidPoint(idx);
484 rangeImage.coeffRef(
r, actual_c) = 0;
488 else if (!MAKE_DENSE)
490 for(
int q=0;
q<4;
q++)
492 pca.setInvalidPoint(idx);
494 const int actual_c = (
c << 2) +
q;
496 rangeImage.coeffRef(
r, actual_c) = 0;
500 if (Dgt_ptr) Dgt_ptr+=4;
501 if (Dlt_ptr) Dlt_ptr+=4;
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 ...
mrpt::utils::TCamera cameraParamsIntensity
Projection parameters of the intensity (graylevel or RGB) camera.
std::vector< uint16_t > points3D_idxs_x
mrpt::utils::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
//!< If hasPoints3D=true, the (x,y) pixel coordinates for each (X,Y,Z) point in points3D_x,...
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::utils::CImage intensityImage
If hasIntensityImage=true, a color or gray-level intensity image of the same size than "rangeImage".
static TCached3DProjTables m_3dproj_lut
3D point cloud projection look-up-table
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot.
bool range_is_depth
true: Kinect-like ranges: entries of rangeImage are distances along the +X axis; false: Ranges in ran...
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::CMatrixDouble44 getHomogeneousMatrixVal() const
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...
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,...
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
size_t getHeight() const MRPT_OVERRIDE
Returns the height of the image in pixels.
size_t getWidth() const MRPT_OVERRIDE
Returns the width of the image in pixels.
An adapter to different kinds of point cloud object.
double cx() const
Get the value of the principal point x-coordinate (in pixels).
double fx() const
Get the value of the focal length x-value (in pixels).
double cy() const
Get the value of the principal point y-coordinate (in pixels).
double fy() const
Get the value of the focal length y-value (in pixels).
GLdouble GLdouble GLdouble r
GLdouble GLdouble GLdouble GLdouble q
int round(const T value)
Returns the closer integer (int) to x.
#define ASSERT_EQUAL_(__A, __B)
#define ASSERTMSG_(f, __ERROR_MSG)
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 range2XYZ(mrpt::utils::PointCloudAdapter< POINTMAP > &pca, mrpt::obs::CObservation3DRangeScan &src_obs, const mrpt::obs::TRangeImageFilterParams &fp, const int H, const int W)
void project3DPointsFromDepthImageInto(mrpt::obs::CObservation3DRangeScan &src_obs, POINTMAP &dest_pointcloud, const mrpt::obs::T3DPointsProjectionParams &projectParams, const mrpt::obs::TRangeImageFilterParams &filterParams)
void do_project_3d_pointcloud(const int H, const int W, const float *kys, const float *kzs, 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 &fp, bool MAKE_DENSE, const int DECIM)
void do_project_3d_pointcloud_SSE2(const int H, const int W, const float *kys, const float *kzs, 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 &fp, bool MAKE_DENSE)
void range2XYZ_LUT(mrpt::utils::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)
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
mrpt::utils::TCamera prev_camParams
mrpt::math::CVectorFloat Kys
mrpt::math::CVectorFloat Kzs
Used in CObservation3DRangeScan::project3DPointsFromDepthImageInto()
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 you want to preserve the organization of the point cloud
bool USE_SSE2
(Default:true) If possible, use SSE2 optimized code.
uint8_t decimation
(Default:1) If !=1, split the range image in blocks of DxD (D=decimation), and only generates one poi...
const mrpt::poses::CPose3D * robotPoseInTheWorld
(Default: NULL) 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: NULL) If provided, each data range will be tested to be greater-than (rangeMask_min) or les...
bool mark_invalid_ranges
If enabled, the range pixels of points that do NOT pass the mask filter will be marked as invalid ran...
const mrpt::math::CMatrix * rangeMask_max