Point Cloud Library (PCL)  1.9.1-dev
texture_mapping.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $Id$
37  *
38  */
39 
40 #pragma once
41 
42 #include <pcl/pcl_macros.h>
43 #include <pcl/surface/reconstruction.h>
44 #include <pcl/common/transforms.h>
45 #include <pcl/TextureMesh.h>
46 
47 
48 namespace pcl
49 {
50  namespace texture_mapping
51  {
52 
53  /** \brief Structure to store camera pose and focal length.
54  *
55  * One can assign a value to focal_length, to be used along
56  * both camera axes or, optionally, axis-specific values
57  * (focal_length_w and focal_length_h). Optionally, one can
58  * also specify center-of-focus using parameters
59  * center_w and center_h. If the center-of-focus is not
60  * specified, it will be set to the geometric center of
61  * the camera, as defined by the width and height parameters.
62  */
63  struct Camera
64  {
66  center_w (-1), center_h (-1), height (), width () {}
67  Eigen::Affine3f pose;
68  double focal_length;
69  double focal_length_w; // optional
70  double focal_length_h; // optinoal
71  double center_w; // optional
72  double center_h; // optional
73  double height;
74  double width;
75  std::string texture_file;
76 
78  };
79 
80  /** \brief Structure that links a uv coordinate to its 3D point and face.
81  */
82  struct UvIndex
83  {
84  UvIndex () : idx_cloud (), idx_face () {}
85  int idx_cloud; // Index of the PointXYZ in the camera's cloud
86  int idx_face; // Face corresponding to that projection
87  };
88 
89  using CameraVector = std::vector<Camera, Eigen::aligned_allocator<Camera> >;
90 
91  }
92 
93  /** \brief The texture mapping algorithm
94  * \author Khai Tran, Raphael Favier
95  * \ingroup surface
96  */
97  template<typename PointInT>
99  {
100  public:
101 
102  using Ptr = boost::shared_ptr<TextureMapping<PointInT> >;
103  using ConstPtr = boost::shared_ptr<const TextureMapping<PointInT> >;
104 
106  using PointCloudPtr = typename PointCloud::Ptr;
108 
110  using OctreePtr = typename Octree::Ptr;
112 
115 
116  /** \brief Constructor. */
118  f_ ()
119  {
120  }
121 
122  /** \brief Destructor. */
124  {
125  }
126 
127  /** \brief Set mesh scale control
128  * \param[in] f
129  */
130  inline void
131  setF (float f)
132  {
133  f_ = f;
134  }
135 
136  /** \brief Set vector field
137  * \param[in] x data point x
138  * \param[in] y data point y
139  * \param[in] z data point z
140  */
141  inline void
142  setVectorField (float x, float y, float z)
143  {
144  vector_field_ = Eigen::Vector3f (x, y, z);
145  // normalize vector field
146  vector_field_ /= std::sqrt (vector_field_.dot (vector_field_));
147  }
148 
149  /** \brief Set texture files
150  * \param[in] tex_files list of texture files
151  */
152  inline void
153  setTextureFiles (std::vector<std::string> tex_files)
154  {
155  tex_files_ = tex_files;
156  }
157 
158  /** \brief Set texture materials
159  * \param[in] tex_material texture material
160  */
161  inline void
163  {
164  tex_material_ = tex_material;
165  }
166 
167  /** \brief Map texture to a mesh synthesis algorithm
168  * \param[in] tex_mesh texture mesh
169  */
170  void
171  mapTexture2Mesh (pcl::TextureMesh &tex_mesh);
172 
173  /** \brief Map texture to a mesh UV mapping
174  * \param[in] tex_mesh texture mesh
175  */
176  void
177  mapTexture2MeshUV (pcl::TextureMesh &tex_mesh);
178 
179  /** \brief Map textures acquired from a set of cameras onto a mesh.
180  * \details With UV mapping, the mesh must be divided into NbCamera + 1 sub-meshes.
181  * Each sub-mesh corresponding to the faces visible by one camera. The last submesh containing all non-visible faces
182  * \param[in] tex_mesh texture mesh
183  * \param[in] cams cameras used for UV mapping
184  */
185  void
186  mapMultipleTexturesToMeshUV (pcl::TextureMesh &tex_mesh,
188 
189  /** \brief computes UV coordinates of point, observed by one particular camera
190  * \param[in] pt XYZ point to project on camera plane
191  * \param[in] cam the camera used for projection
192  * \param[out] UV_coordinates the resulting uv coordinates. Set to (-1.0,-1.0) if the point is not visible by the camera
193  * \returns false if the point is not visible by the camera
194  */
195  inline bool
196  getPointUVCoordinates (const PointInT &pt, const Camera &cam, Eigen::Vector2f &UV_coordinates)
197  {
198  // if the point is in front of the camera
199  if (pt.z > 0)
200  {
201  // compute image center and dimension
202  double sizeX = cam.width;
203  double sizeY = cam.height;
204  double cx, cy;
205  if (cam.center_w > 0)
206  cx = cam.center_w;
207  else
208  cx = (sizeX) / 2.0;
209  if (cam.center_h > 0)
210  cy = cam.center_h;
211  else
212  cy = (sizeY) / 2.0;
213 
214  double focal_x, focal_y;
215  if (cam.focal_length_w > 0)
216  focal_x = cam.focal_length_w;
217  else
218  focal_x = cam.focal_length;
219  if (cam.focal_length_h>0)
220  focal_y = cam.focal_length_h;
221  else
222  focal_y = cam.focal_length;
223 
224  // project point on image frame
225  UV_coordinates[0] = static_cast<float> ((focal_x * (pt.x / pt.z) + cx) / sizeX); //horizontal
226  UV_coordinates[1] = 1.0f - static_cast<float> (((focal_y * (pt.y / pt.z) + cy) / sizeY)); //vertical
227 
228  // point is visible!
229  if (UV_coordinates[0] >= 0.0 && UV_coordinates[0] <= 1.0 && UV_coordinates[1] >= 0.0 && UV_coordinates[1]
230  <= 1.0)
231  return (true);
232  }
233 
234  // point is NOT visible by the camera
235  UV_coordinates[0] = -1.0;
236  UV_coordinates[1] = -1.0;
237  return (false);
238  }
239 
240  /** \brief Check if a point is occluded using raycasting on octree.
241  * \param[in] pt XYZ from which the ray will start (toward the camera)
242  * \param[in] octree the octree used for raycasting. It must be initialized with a cloud transformed into the camera's frame
243  * \returns true if the point is occluded.
244  */
245  inline bool
246  isPointOccluded (const PointInT &pt, const OctreePtr octree);
247 
248  /** \brief Remove occluded points from a point cloud
249  * \param[in] input_cloud the cloud on which to perform occlusion detection
250  * \param[out] filtered_cloud resulting cloud, containing only visible points
251  * \param[in] octree_voxel_size octree resolution (in meters)
252  * \param[out] visible_indices will contain indices of visible points
253  * \param[out] occluded_indices will contain indices of occluded points
254  */
255  void
256  removeOccludedPoints (const PointCloudPtr &input_cloud,
257  PointCloudPtr &filtered_cloud, const double octree_voxel_size,
258  std::vector<int> &visible_indices, std::vector<int> &occluded_indices);
259 
260  /** \brief Remove occluded points from a textureMesh
261  * \param[in] tex_mesh input mesh, on witch to perform occlusion detection
262  * \param[out] cleaned_mesh resulting mesh, containing only visible points
263  * \param[in] octree_voxel_size octree resolution (in meters)
264  */
265  void
266  removeOccludedPoints (const pcl::TextureMesh &tex_mesh, pcl::TextureMesh &cleaned_mesh, const double octree_voxel_size);
267 
268 
269  /** \brief Remove occluded points from a textureMesh
270  * \param[in] tex_mesh input mesh, on witch to perform occlusion detection
271  * \param[out] filtered_cloud resulting cloud, containing only visible points
272  * \param[in] octree_voxel_size octree resolution (in meters)
273  */
274  void
275  removeOccludedPoints (const pcl::TextureMesh &tex_mesh, PointCloudPtr &filtered_cloud, const double octree_voxel_size);
276 
277 
278  /** \brief Segment faces by camera visibility. Point-based segmentation.
279  * \details With N camera, faces will be arranged into N+1 groups: 1 for each camera, plus 1 for faces not visible from any camera.
280  * \param[in] tex_mesh input mesh that needs sorting. Must contain only 1 sub-mesh.
281  * \param[in] sorted_mesh resulting mesh, will contain nbCamera + 1 sub-mesh.
282  * \param[in] cameras vector containing the cameras used for texture mapping.
283  * \param[in] octree_voxel_size octree resolution (in meters)
284  * \param[out] visible_pts cloud containing only visible points
285  */
286  int
287  sortFacesByCamera (pcl::TextureMesh &tex_mesh,
288  pcl::TextureMesh &sorted_mesh,
289  const pcl::texture_mapping::CameraVector &cameras,
290  const double octree_voxel_size, PointCloud &visible_pts);
291 
292  /** \brief Colors a point cloud, depending on its occlusions.
293  * \details If showNbOcclusions is set to True, each point is colored depending on the number of points occluding it.
294  * Else, each point is given a different a 0 value is not occluded, 1 if occluded.
295  * By default, the number of occlusions is bounded to 4.
296  * \param[in] input_cloud input cloud on which occlusions will be computed.
297  * \param[out] colored_cloud resulting colored cloud showing the number of occlusions per point.
298  * \param[in] octree_voxel_size octree resolution (in meters).
299  * \param[in] show_nb_occlusions If false, color information will only represent.
300  * \param[in] max_occlusions Limit the number of occlusions per point.
301  */
302  void
303  showOcclusions (const PointCloudPtr &input_cloud,
305  const double octree_voxel_size,
306  const bool show_nb_occlusions = true,
307  const int max_occlusions = 4);
308 
309  /** \brief Colors the point cloud of a Mesh, depending on its occlusions.
310  * \details If showNbOcclusions is set to True, each point is colored depending on the number of points occluding it.
311  * Else, each point is given a different a 0 value is not occluded, 1 if occluded.
312  * By default, the number of occlusions is bounded to 4.
313  * \param[in] tex_mesh input mesh on which occlusions will be computed.
314  * \param[out] colored_cloud resulting colored cloud showing the number of occlusions per point.
315  * \param[in] octree_voxel_size octree resolution (in meters).
316  * \param[in] show_nb_occlusions If false, color information will only represent.
317  * \param[in] max_occlusions Limit the number of occlusions per point.
318  */
319  void
320  showOcclusions (pcl::TextureMesh &tex_mesh,
322  double octree_voxel_size,
323  bool show_nb_occlusions = true,
324  int max_occlusions = 4);
325 
326  /** \brief Segment and texture faces by camera visibility. Face-based segmentation.
327  * \details With N camera, faces will be arranged into N+1 groups: 1 for each camera, plus 1 for faces not visible from any camera.
328  * The mesh will also contain uv coordinates for each face
329  * \param mesh input mesh that needs sorting. Should contain only 1 sub-mesh.
330  * \param[in] cameras vector containing the cameras used for texture mapping.
331  */
332  void
333  textureMeshwithMultipleCameras (pcl::TextureMesh &mesh,
334  const pcl::texture_mapping::CameraVector &cameras);
335 
336  protected:
337  /** \brief mesh scale control. */
338  float f_;
339 
340  /** \brief vector field */
341  Eigen::Vector3f vector_field_;
342 
343  /** \brief list of texture files */
344  std::vector<std::string> tex_files_;
345 
346  /** \brief list of texture materials */
348 
349  /** \brief Map texture to a face
350  * \param[in] p1 the first point
351  * \param[in] p2 the second point
352  * \param[in] p3 the third point
353  */
354  std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> >
355  mapTexture2Face (const Eigen::Vector3f &p1, const Eigen::Vector3f &p2, const Eigen::Vector3f &p3);
356 
357  /** \brief Returns the circumcenter of a triangle and the circle's radius.
358  * \details see http://en.wikipedia.org/wiki/Circumcenter for formulas.
359  * \param[in] p1 first point of the triangle.
360  * \param[in] p2 second point of the triangle.
361  * \param[in] p3 third point of the triangle.
362  * \param[out] circumcenter resulting circumcenter
363  * \param[out] radius the radius of the circumscribed circle.
364  */
365  inline void
366  getTriangleCircumcenterAndSize (const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, pcl::PointXY &circumcenter, double &radius);
367 
368 
369  /** \brief Returns the centroid of a triangle and the corresponding circumscribed circle's radius.
370  * \details yield a tighter circle than getTriangleCircumcenterAndSize.
371  * \param[in] p1 first point of the triangle.
372  * \param[in] p2 second point of the triangle.
373  * \param[in] p3 third point of the triangle.
374  * \param[out] circumcenter resulting circumcenter
375  * \param[out] radius the radius of the circumscribed circle.
376  */
377  inline void
378  getTriangleCircumcscribedCircleCentroid ( const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, pcl::PointXY &circumcenter, double &radius);
379 
380 
381  /** \brief computes UV coordinates of point, observed by one particular camera
382  * \param[in] pt XYZ point to project on camera plane
383  * \param[in] cam the camera used for projection
384  * \param[out] UV_coordinates the resulting UV coordinates. Set to (-1.0,-1.0) if the point is not visible by the camera
385  * \returns false if the point is not visible by the camera
386  */
387  inline bool
388  getPointUVCoordinates (const PointInT &pt, const Camera &cam, pcl::PointXY &UV_coordinates);
389 
390  /** \brief Returns true if all the vertices of one face are projected on the camera's image plane.
391  * \param[in] camera camera on which to project the face.
392  * \param[in] p1 first point of the face.
393  * \param[in] p2 second point of the face.
394  * \param[in] p3 third point of the face.
395  * \param[out] proj1 UV coordinates corresponding to p1.
396  * \param[out] proj2 UV coordinates corresponding to p2.
397  * \param[out] proj3 UV coordinates corresponding to p3.
398  */
399  inline bool
400  isFaceProjected (const Camera &camera,
401  const PointInT &p1, const PointInT &p2, const PointInT &p3,
402  pcl::PointXY &proj1, pcl::PointXY &proj2, pcl::PointXY &proj3);
403 
404  /** \brief Returns True if a point lays within a triangle
405  * \details see http://www.blackpawn.com/texts/pointinpoly/default.html
406  * \param[in] p1 first point of the triangle.
407  * \param[in] p2 second point of the triangle.
408  * \param[in] p3 third point of the triangle.
409  * \param[in] pt the querry point.
410  */
411  inline bool
412  checkPointInsideTriangle (const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, const pcl::PointXY &pt);
413 
414  /** \brief Class get name method. */
415  std::string
416  getClassName () const
417  {
418  return ("TextureMapping");
419  }
420 
421  public:
423  };
424 }
boost::shared_ptr< TextureMapping< PointInT > > Ptr
The texture mapping algorithm.
~TextureMapping()
Destructor.
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:45
boost::shared_ptr< const TextureMapping< PointInT > > ConstPtr
boost::shared_ptr< OctreePointCloudSearch< PointT, LeafContainerT, BranchContainerT > > Ptr
Definition: octree_search.h:68
void setTextureFiles(std::vector< std::string > tex_files)
Set texture files.
#define PCL_MAKE_ALIGNED_OPERATOR_NEW
Macro to signal a class requires a custom allocator.
Definition: pcl_macros.h:344
bool getPointUVCoordinates(const PointInT &pt, const Camera &cam, Eigen::Vector2f &UV_coordinates)
computes UV coordinates of point, observed by one particular camera
A 2D point structure representing Euclidean xy coordinates.
TextureMapping()
Constructor.
Eigen::Vector3f vector_field_
vector field
void setVectorField(float x, float y, float z)
Set vector field.
typename Octree::ConstPtr OctreeConstPtr
boost::shared_ptr< PointCloud< PointT > > Ptr
Definition: point_cloud.h:429
Structure to store camera pose and focal length.
boost::shared_ptr< const OctreePointCloudSearch< PointT, LeafContainerT, BranchContainerT > > ConstPtr
Definition: octree_search.h:69
typename Octree::Ptr OctreePtr
std::vector< Camera, Eigen::aligned_allocator< Camera > > CameraVector
Structure that links a uv coordinate to its 3D point and face.
void setF(float f)
Set mesh scale control.
float f_
mesh scale control.
void setTextureMaterials(TexMaterial tex_material)
Set texture materials.
typename PointCloud::Ptr PointCloudPtr
Octree pointcloud search class
Definition: octree_search.h:56
boost::shared_ptr< const PointCloud< PointT > > ConstPtr
Definition: point_cloud.h:430
typename PointCloud::ConstPtr PointCloudConstPtr
std::string getClassName() const
Class get name method.
std::vector< std::string > tex_files_
list of texture files
TexMaterial tex_material_
list of texture materials