Main MRPT website > C++ reference for MRPT 1.5.6
CObservation3DRangeScan_project3D_impl.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +---------------------------------------------------------------------------+ */
9 #ifndef CObservation3DRangeScan_project3D_impl_H
10 #define CObservation3DRangeScan_project3D_impl_H
11 
12 #include <mrpt/utils/round.h> // round()
13 
14 namespace mrpt {
15 namespace obs {
16 namespace detail {
17  // Auxiliary functions which implement SSE-optimized proyection of 3D point cloud:
18  template <class POINTMAP> 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);
19  template <class POINTMAP> 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);
20 
21  template <class POINTMAP>
24  POINTMAP & dest_pointcloud,
25  const mrpt::obs::T3DPointsProjectionParams & projectParams,
26  const mrpt::obs::TRangeImageFilterParams &filterParams)
27  {
28  using namespace mrpt::math;
29 
30  if (!src_obs.hasRangeImage) return;
31 
32  mrpt::utils::PointCloudAdapter<POINTMAP> pca(dest_pointcloud);
33 
34  // ------------------------------------------------------------
35  // Stage 1/3: Create 3D point cloud local coordinates
36  // ------------------------------------------------------------
37  const int W = src_obs.rangeImage.cols();
38  const int H = src_obs.rangeImage.rows();
39  ASSERT_(W!=0 && H!=0);
40  const size_t WH = W*H;
41 
42  src_obs.resizePoints3DVectors(WH); // This is to make sure points3D_idxs_{x,y} have the expected sizes.
43  pca.resize(WH); // Reserve memory for 3D points. It will be later resized again to the actual number of valid points
44 
45  if (src_obs.range_is_depth)
46  {
47  // range_is_depth = true
48 
49  // Use cached tables?
50  if (projectParams.PROJ3D_USE_LUT)
51  {
52  // Use LUT:
53  if (src_obs.m_3dproj_lut.prev_camParams!=src_obs.cameraParams || WH!=size_t(src_obs.m_3dproj_lut.Kys.size()))
54  {
55  src_obs.m_3dproj_lut.prev_camParams = src_obs.cameraParams;
56  src_obs.m_3dproj_lut.Kys.resize(WH);
57  src_obs.m_3dproj_lut.Kzs.resize(WH);
58 
59  const float r_cx = src_obs.cameraParams.cx();
60  const float r_cy = src_obs.cameraParams.cy();
61  const float r_fx_inv = 1.0f/src_obs.cameraParams.fx();
62  const float r_fy_inv = 1.0f/src_obs.cameraParams.fy();
63 
64  float *kys = &src_obs.m_3dproj_lut.Kys[0];
65  float *kzs = &src_obs.m_3dproj_lut.Kzs[0];
66  for (int r=0;r<H;r++)
67  for (int c=0;c<W;c++)
68  {
69  *kys++ = (r_cx - c) * r_fx_inv;
70  *kzs++ = (r_cy - r) * r_fy_inv;
71  }
72  } // end update LUT.
73 
74  ASSERT_EQUAL_(WH,size_t(src_obs.m_3dproj_lut.Kys.size()))
75  ASSERT_EQUAL_(WH,size_t(src_obs.m_3dproj_lut.Kzs.size()))
76  float *kys = &src_obs.m_3dproj_lut.Kys[0];
77  float *kzs = &src_obs.m_3dproj_lut.Kzs[0];
78 
79  if (filterParams.rangeMask_min) { // sanity check:
80  ASSERT_EQUAL_(filterParams.rangeMask_min->cols(), src_obs.rangeImage.cols());
81  ASSERT_EQUAL_(filterParams.rangeMask_min->rows(), src_obs.rangeImage.rows());
82  }
83  if (filterParams.rangeMask_max) { // sanity check:
84  ASSERT_EQUAL_(filterParams.rangeMask_max->cols(), src_obs.rangeImage.cols());
85  ASSERT_EQUAL_(filterParams.rangeMask_max->rows(), src_obs.rangeImage.rows());
86  }
87  #if MRPT_HAS_SSE2
88  if ((W & 0x07)==0 && projectParams.USE_SSE2)
89  do_project_3d_pointcloud_SSE2(H,W,kys,kzs,src_obs.rangeImage,pca, src_obs.points3D_idxs_x, src_obs.points3D_idxs_y, filterParams, projectParams.MAKE_DENSE);
90  else do_project_3d_pointcloud(H,W,kys,kzs,src_obs.rangeImage,pca, src_obs.points3D_idxs_x, src_obs.points3D_idxs_y, filterParams, projectParams.MAKE_DENSE); // if image width is not 8*N, use standard method
91  #else
92  do_project_3d_pointcloud(H,W,kys,kzs,src_obs.rangeImage,pca,src_obs.points3D_idxs_x, src_obs.points3D_idxs_y,filterParams, projectParams.MAKE_DENSE);
93  #endif
94  }
95  else
96  {
97  // Without LUT:
98  const float r_cx = src_obs.cameraParams.cx();
99  const float r_cy = src_obs.cameraParams.cy();
100  const float r_fx_inv = 1.0f/src_obs.cameraParams.fx();
101  const float r_fy_inv = 1.0f/src_obs.cameraParams.fy();
102  TRangeImageFilter rif(filterParams);
103  size_t idx=0;
104  for (int r=0;r<H;r++)
105  for (int c=0;c<W;c++)
106  {
107  const float D = src_obs.rangeImage.coeff(r,c);
108  if (rif.do_range_filter(r,c,D))
109  {
110  const float Kz = (r_cy - r) * r_fy_inv;
111  const float Ky = (r_cx - c) * r_fx_inv;
112  pca.setPointXYZ(idx,
113  D, // x
114  Ky * D, // y
115  Kz * D // z
116  );
117  src_obs.points3D_idxs_x[idx]=c;
118  src_obs.points3D_idxs_y[idx]=r;
119  ++idx;
120  }
121  }
122  pca.resize(idx); // Actual number of valid pts
123  }
124  }
125  else
126  {
127  /* range_is_depth = false :
128  * Ky = (r_cx - c)/r_fx
129  * Kz = (r_cy - r)/r_fy
130  *
131  * x(i) = rangeImage(r,c) / sqrt( 1 + Ky^2 + Kz^2 )
132  * y(i) = Ky * x(i)
133  * z(i) = Kz * x(i)
134  */
135  const float r_cx = src_obs.cameraParams.cx();
136  const float r_cy = src_obs.cameraParams.cy();
137  const float r_fx_inv = 1.0f/src_obs.cameraParams.fx();
138  const float r_fy_inv = 1.0f/src_obs.cameraParams.fy();
139  TRangeImageFilter rif(filterParams);
140  size_t idx=0;
141  for (int r=0;r<H;r++)
142  for (int c=0;c<W;c++)
143  {
144  const float D = src_obs.rangeImage.coeff(r,c);
145  if (rif.do_range_filter(r,c,D))
146  {
147  const float Ky = (r_cx - c) * r_fx_inv;
148  const float Kz = (r_cy - r) * r_fy_inv;
149  pca.setPointXYZ(idx,
150  D / std::sqrt(1+Ky*Ky+Kz*Kz), // x
151  Ky * D, // y
152  Kz * D // z
153  );
154  src_obs.points3D_idxs_x[idx]=c;
155  src_obs.points3D_idxs_y[idx]=r;
156  ++idx;
157  }
158  }
159  pca.resize(idx); // Actual number of valid pts
160  }
161 
162  // -------------------------------------------------------------
163  // Stage 2/3: Project local points into RGB image to get colors
164  // -------------------------------------------------------------
165  if (src_obs.hasIntensityImage)
166  {
167  const int imgW = src_obs.intensityImage.getWidth();
168  const int imgH = src_obs.intensityImage.getHeight();
169  const bool hasColorIntensityImg = src_obs.intensityImage.isColor();
170 
171  const float cx = src_obs.cameraParamsIntensity.cx();
172  const float cy = src_obs.cameraParamsIntensity.cy();
173  const float fx = src_obs.cameraParamsIntensity.fx();
174  const float fy = src_obs.cameraParamsIntensity.fy();
175 
176  // Unless we are in a special case (both depth & RGB images coincide)...
177  const bool isDirectCorresp = src_obs.doDepthAndIntensityCamerasCoincide();
178 
179  // ...precompute the inverse of the pose transformation out of the loop,
180  // store as a 4x4 homogeneous matrix to exploit SSE optimizations below:
182  if (!isDirectCorresp)
183  {
188  R_inv,t_inv);
189 
190  T_inv(3,3)=1;
191  T_inv.block<3,3>(0,0)=R_inv.cast<float>();
192  T_inv.block<3,1>(0,3)=t_inv.cast<float>();
193  }
194 
195  Eigen::Matrix<float,4,1> pt_wrt_color, pt_wrt_depth;
196  pt_wrt_depth[3]=1;
197 
198  mrpt::utils::TColor pCol;
199 
200  // For each local point:
201  const size_t nPts = pca.size();
202  for (size_t i=0;i<nPts;i++)
203  {
204  int img_idx_x, img_idx_y; // projected pixel coordinates, in the RGB image plane
205  bool pointWithinImage = false;
206  if (isDirectCorresp)
207  {
208  pointWithinImage=true;
209  img_idx_x = src_obs.points3D_idxs_x[i];
210  img_idx_y = src_obs.points3D_idxs_y[i];
211  }
212  else
213  {
214  // Project point, which is now in "pca" in local coordinates wrt the depth camera, into the intensity camera:
215  pca.getPointXYZ(i,pt_wrt_depth[0],pt_wrt_depth[1],pt_wrt_depth[2]);
216  pt_wrt_color.noalias() = T_inv*pt_wrt_depth;
217 
218  // Project to image plane:
219  if (pt_wrt_color[2]) {
220  img_idx_x = mrpt::utils::round( cx + fx * pt_wrt_color[0]/pt_wrt_color[2] );
221  img_idx_y = mrpt::utils::round( cy + fy * pt_wrt_color[1]/pt_wrt_color[2] );
222  pointWithinImage=
223  img_idx_x>=0 && img_idx_x<imgW &&
224  img_idx_y>=0 && img_idx_y<imgH;
225  }
226  }
227 
228  if (pointWithinImage)
229  {
230  if (hasColorIntensityImg) {
231  const uint8_t *c= src_obs.intensityImage.get_unsafe(img_idx_x, img_idx_y, 0);
232  pCol.R = c[2];
233  pCol.G = c[1];
234  pCol.B = c[0];
235  }
236  else{
237  uint8_t c= *src_obs.intensityImage.get_unsafe(img_idx_x, img_idx_y, 0);
238  pCol.R = pCol.G = pCol.B = c;
239  }
240  }
241  else
242  {
243  pCol.R = pCol.G = pCol.B = 255;
244  }
245  // Set color:
246  pca.setPointRGBu8(i,pCol.R,pCol.G,pCol.B);
247  } // end for each point
248  } // end if src_obs has intensity image
249 
250  // ...
251 
252  // ------------------------------------------------------------
253  // Stage 3/3: Apply 6D transformations
254  // ------------------------------------------------------------
255  if (projectParams.takeIntoAccountSensorPoseOnRobot || projectParams.robotPoseInTheWorld)
256  {
257  mrpt::poses::CPose3D transf_to_apply; // Either ROBOTPOSE or ROBOTPOSE(+)SENSORPOSE or SENSORPOSE
258  if (projectParams.takeIntoAccountSensorPoseOnRobot)
259  transf_to_apply = src_obs.sensorPose;
260  if (projectParams.robotPoseInTheWorld)
261  transf_to_apply.composeFrom(*projectParams.robotPoseInTheWorld, mrpt::poses::CPose3D(transf_to_apply));
262 
263  const mrpt::math::CMatrixFixedNumeric<float,4,4> HM = transf_to_apply.getHomogeneousMatrixVal().cast<float>();
264  Eigen::Matrix<float,4,1> pt, pt_transf;
265  pt[3]=1;
266 
267  const size_t nPts = pca.size();
268  for (size_t i=0;i<nPts;i++)
269  {
270  pca.getPointXYZ(i,pt[0],pt[1],pt[2]);
271  pt_transf.noalias() = HM*pt;
272  pca.setPointXYZ(i,pt_transf[0],pt_transf[1],pt_transf[2]);
273  }
274  }
275  } // end of project3DPointsFromDepthImageInto
276 
277  // Auxiliary functions which implement proyection of 3D point clouds:
278  template <class POINTMAP>
279  inline 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 &fp, bool MAKE_DENSE)
280  {
281  TRangeImageFilter rif(fp);
282  // Preconditions: minRangeMask() has the right size
283  size_t idx=0;
284  for (int r=0;r<H;r++)
285  for (int c=0;c<W;c++)
286  {
287  const float D = rangeImage.coeff(r,c);
288  if (!rif.do_range_filter(r,c,D)){
289  if (!MAKE_DENSE)
290  {
291  pca.setInvalidPoint(idx);
292  ++idx;
293  }
294  continue;
295  }
296 
297  pca.setPointXYZ(idx, D /*x*/, *kys++ * D /*y*/, *kzs++ * D /*z*/);
298  idxs_x[idx]=c;
299  idxs_y[idx]=r;
300  ++idx;
301  }
302  pca.resize(idx);
303  }
304 
305  // Auxiliary functions which implement proyection of 3D point clouds:
306  template <class POINTMAP>
307  inline 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)
308  {
309  #if MRPT_HAS_SSE2
310  // Preconditions: minRangeMask() has the right size
311  // Use optimized version:
312  const int W_4 = W >> 2; // /=4 , since we process 4 values at a time.
313  size_t idx=0;
314  MRPT_ALIGN16 float xs[4],ys[4],zs[4];
315  const __m128 D_zeros = _mm_set_ps(.0f,.0f,.0f,.0f);
316  const __m128 xormask = (filterParams.rangeCheckBetween) ?
317  _mm_cmpneq_ps(D_zeros,D_zeros) : // want points BETWEEN min and max to be valid
318  _mm_cmpeq_ps(D_zeros,D_zeros); // want points OUTSIDE of min and max to be valid
319  for (int r=0;r<H;r++)
320  {
321  const float *D_ptr = &rangeImage.coeffRef(r,0); // Matrices are 16-aligned
322  const float *Dgt_ptr = !filterParams.rangeMask_min ? NULL : &filterParams.rangeMask_min->coeffRef(r,0);
323  const float *Dlt_ptr = !filterParams.rangeMask_max ? NULL : &filterParams.rangeMask_max->coeffRef(r,0);
324 
325  for (int c=0;c<W_4;c++)
326  {
327  const __m128 D = _mm_load_ps(D_ptr);
328  const __m128 nz_mask = _mm_cmpgt_ps(D, D_zeros);
329  __m128 valid_range_mask;
330  if (!filterParams.rangeMask_min && !filterParams.rangeMask_max)
331  { // No filter: just skip D=0 points
332  valid_range_mask = nz_mask;
333  }
334  else
335  {
336  if (!filterParams.rangeMask_min || !filterParams.rangeMask_max)
337  { // Only one filter
338  if (filterParams.rangeMask_min)
339  {
340  const __m128 Dmin = _mm_load_ps(Dgt_ptr);
341  valid_range_mask = _mm_and_ps(_mm_cmpgt_ps(D, Dmin ), _mm_cmpgt_ps(Dmin, D_zeros));
342  }
343  else
344  {
345  const __m128 Dmax = _mm_load_ps(Dlt_ptr);
346  valid_range_mask = _mm_and_ps(_mm_cmplt_ps(D, Dmax ), _mm_cmpgt_ps(Dmax, D_zeros));
347  }
348  valid_range_mask = _mm_and_ps(valid_range_mask, nz_mask ); // Filter out D=0 points
349  }
350  else
351  {
352  // We have both: D>Dmin and D<Dmax conditions, with XOR to optionally invert the selection:
353  const __m128 Dmin = _mm_load_ps(Dgt_ptr);
354  const __m128 Dmax = _mm_load_ps(Dlt_ptr);
355 
356  const __m128 gt_mask = _mm_cmpgt_ps(D, Dmin );
357  const __m128 lt_mask = _mm_and_ps( _mm_cmplt_ps(D, Dmax), nz_mask ); // skip points at zero
358  valid_range_mask = _mm_and_ps(gt_mask, lt_mask ); // (D>Dmin && D<Dmax)
359  valid_range_mask = _mm_xor_ps(valid_range_mask, xormask );
360  // Add the case of D_min & D_max = 0 (no filtering)
361  valid_range_mask = _mm_or_ps(valid_range_mask, _mm_and_ps(_mm_cmpeq_ps(Dmin,D_zeros),_mm_cmpeq_ps(Dmax,D_zeros)) );
362  // Finally, ensure no invalid ranges get thru:
363  valid_range_mask = _mm_and_ps(valid_range_mask, nz_mask );
364  }
365  }
366  const int valid_range_maski = _mm_movemask_epi8(_mm_castps_si128(valid_range_mask)); // 0x{f|0}{f|0}{f|0}{f|0}
367  if (valid_range_maski!=0) // Any of the 4 values is valid?
368  {
369  const __m128 KY = _mm_load_ps(kys);
370  const __m128 KZ = _mm_load_ps(kzs);
371 
372  _mm_storeu_ps(xs , D);
373  _mm_storeu_ps(ys , _mm_mul_ps(KY,D));
374  _mm_storeu_ps(zs , _mm_mul_ps(KZ,D));
375 
376  for (int q=0;q<4;q++)
377  if ((valid_range_maski & (1<<(q*4))) !=0) {
378  pca.setPointXYZ(idx,xs[q],ys[q],zs[q]);
379  idxs_x[idx]=(c<<2)+q;
380  idxs_y[idx]=r;
381  ++idx;
382  }
383  else if (!MAKE_DENSE)
384  {
385  pca.setInvalidPoint(idx);
386  ++idx;
387  }
388  }
389  else if (!MAKE_DENSE)
390  {
391  for( int q=0; q<4; q++)
392  {
393  pca.setInvalidPoint(idx);
394  ++idx;
395  }
396  }
397  D_ptr+=4;
398  if (Dgt_ptr) Dgt_ptr+=4;
399  if (Dlt_ptr) Dlt_ptr+=4;
400  kys+=4;
401  kzs+=4;
402  }
403  }
404  pca.resize(idx);
405  #endif
406  }
407 
408 } // End of namespace
409 } // End of namespace
410 } // End of namespace
411 #endif
#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: NULL) Read takeIntoAccountSensorPoseOnRobot
mrpt::utils::TCamera cameraParamsIntensity
Projection parameters of the intensity (graylevel or RGB) camera.
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:3626
double cy() const
Get the value of the principal point y-coordinate (in pixels).
Definition: TCamera.h:156
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: NULL) If provided, each data range will be tested to be greater-than (rangeMask_min) or les...
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) ...
unsigned char uint8_t
Definition: rptypes.h:43
mrpt::utils::TCamera cameraParams
Projection parameters of the depth camera.
double fx() const
Get the value of the focal length x-value (in pixels).
Definition: TCamera.h:158
double fy() const
Get the value of the focal length y-value (in pixels).
Definition: TCamera.h:160
A numeric matrix of compile-time fixed size.
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
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
//!< If hasPoints3D=true, the (x,y) pixel coordinates for each (X,Y,Z) point in points3D_x, points3D_y, points3D_z
mrpt::math::CArrayDouble< 3 > m_coords
The translation vector [x,y,z] access directly or with x(), y(), z() setter/getter methods...
Definition: CPose3D.h:81
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...
Definition: CPose3D.cpp:595
mrpt::math::CMatrixDouble44 getHomogeneousMatrixVal() const
Definition: CPose3D.h:173
const GLubyte * c
Definition: glext.h:5590
void project3DPointsFromDepthImageInto(mrpt::obs::CObservation3DRangeScan &src_obs, POINTMAP &dest_pointcloud, const mrpt::obs::T3DPointsProjectionParams &projectParams, const mrpt::obs::TRangeImageFilterParams &filterParams)
A RGB color - 8bit.
Definition: TColor.h:26
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)
double cx() const
Get the value of the principal point x-coordinate (in pixels).
Definition: TCamera.h:154
static TCached3DProjTables m_3dproj_lut
3D point cloud projection look-up-table
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
Definition: glext.h:3618
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).
Definition: CPose3D.h:72
Used in CObservation3DRangeScan::project3DPointsFromDepthImageInto()
bool hasIntensityImage
true means the field intensityImage contains valid data
#define ASSERT_(f)
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:26
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.
Definition: CImage.cpp:898
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.
Definition: CImage.cpp:491
An adapter to different kinds of point cloud object.
Definition: adapters.h:38
void getRotationMatrix(mrpt::math::CMatrixDouble33 &ROT) const
Get the 3x3 rotation matrix.
Definition: CPose3D.h:176
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".
Definition: CMatrix.h:30
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)
size_t getWidth() const MRPT_OVERRIDE
Returns the width of the image in pixels.
Definition: CImage.cpp:855
#define MRPT_ALIGN16
bool takeIntoAccountSensorPoseOnRobot
(Default: false) If false, local (sensor-centric) coordinates of points are generated. Otherwise, points are transformed with sensorPose. Furthermore, if provided, those coordinates are transformed with robotPoseInTheWorld
size_t getHeight() const MRPT_OVERRIDE
Returns the height of the image in pixels.
Definition: CImage.cpp:884
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.



Page generated by Doxygen 1.8.14 for MRPT 1.5.6 Git: 4c65e8431 Tue Apr 24 08:18:17 2018 +0200 at lun oct 28 01:35:26 CET 2019