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/surface/reconstruction.h>
43 #include <pcl/common/transforms.h>
44 #include <pcl/TextureMesh.h>
45 
46 
47 namespace pcl
48 {
49  namespace texture_mapping
50  {
51 
52  /** \brief Structure to store camera pose and focal length.
53  *
54  * One can assign a value to focal_length, to be used along
55  * both camera axes or, optionally, axis-specific values
56  * (focal_length_w and focal_length_h). Optionally, one can
57  * also specify center-of-focus using parameters
58  * center_w and center_h. If the center-of-focus is not
59  * specified, it will be set to the geometric center of
60  * the camera, as defined by the width and height parameters.
61  */
62  struct Camera
63  {
65  center_w (-1), center_h (-1), height (), width () {}
66  Eigen::Affine3f pose;
67  double focal_length;
68  double focal_length_w; // optional
69  double focal_length_h; // optinoal
70  double center_w; // optional
71  double center_h; // optional
72  double height;
73  double width;
74  std::string texture_file;
75 
76  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
77  };
78 
79  /** \brief Structure that links a uv coordinate to its 3D point and face.
80  */
81  struct UvIndex
82  {
83  UvIndex () : idx_cloud (), idx_face () {}
84  int idx_cloud; // Index of the PointXYZ in the camera's cloud
85  int idx_face; // Face corresponding to that projection
86  };
87 
88  typedef std::vector<Camera, Eigen::aligned_allocator<Camera> > CameraVector;
89 
90  }
91 
92  /** \brief The texture mapping algorithm
93  * \author Khai Tran, Raphael Favier
94  * \ingroup surface
95  */
96  template<typename PointInT>
98  {
99  public:
100 
101  typedef boost::shared_ptr< TextureMapping < PointInT > > Ptr;
102  typedef boost::shared_ptr< const TextureMapping < PointInT > > ConstPtr;
103 
105  typedef typename PointCloud::Ptr PointCloudPtr;
107 
109  typedef typename Octree::Ptr OctreePtr;
111 
114 
115  /** \brief Constructor. */
117  f_ ()
118  {
119  }
120 
121  /** \brief Destructor. */
123  {
124  }
125 
126  /** \brief Set mesh scale control
127  * \param[in] f
128  */
129  inline void
130  setF (float f)
131  {
132  f_ = f;
133  }
134 
135  /** \brief Set vector field
136  * \param[in] x data point x
137  * \param[in] y data point y
138  * \param[in] z data point z
139  */
140  inline void
141  setVectorField (float x, float y, float z)
142  {
143  vector_field_ = Eigen::Vector3f (x, y, z);
144  // normalize vector field
145  vector_field_ /= std::sqrt (vector_field_.dot (vector_field_));
146  }
147 
148  /** \brief Set texture files
149  * \param[in] tex_files list of texture files
150  */
151  inline void
152  setTextureFiles (std::vector<std::string> tex_files)
153  {
154  tex_files_ = tex_files;
155  }
156 
157  /** \brief Set texture materials
158  * \param[in] tex_material texture material
159  */
160  inline void
162  {
163  tex_material_ = tex_material;
164  }
165 
166  /** \brief Map texture to a mesh synthesis algorithm
167  * \param[in] tex_mesh texture mesh
168  */
169  void
170  mapTexture2Mesh (pcl::TextureMesh &tex_mesh);
171 
172  /** \brief Map texture to a mesh UV mapping
173  * \param[in] tex_mesh texture mesh
174  */
175  void
176  mapTexture2MeshUV (pcl::TextureMesh &tex_mesh);
177 
178  /** \brief Map textures acquired from a set of cameras onto a mesh.
179  * \details With UV mapping, the mesh must be divided into NbCamera + 1 sub-meshes.
180  * Each sub-mesh corresponding to the faces visible by one camera. The last submesh containing all non-visible faces
181  * \param[in] tex_mesh texture mesh
182  * \param[in] cams cameras used for UV mapping
183  */
184  void
185  mapMultipleTexturesToMeshUV (pcl::TextureMesh &tex_mesh,
187 
188  /** \brief computes UV coordinates of point, observed by one particular camera
189  * \param[in] pt XYZ point to project on camera plane
190  * \param[in] cam the camera used for projection
191  * \param[out] UV_coordinates the resulting uv coordinates. Set to (-1.0,-1.0) if the point is not visible by the camera
192  * \returns false if the point is not visible by the camera
193  */
194  inline bool
195  getPointUVCoordinates (const PointInT &pt, const Camera &cam, Eigen::Vector2f &UV_coordinates)
196  {
197  // if the point is in front of the camera
198  if (pt.z > 0)
199  {
200  // compute image center and dimension
201  double sizeX = cam.width;
202  double sizeY = cam.height;
203  double cx, cy;
204  if (cam.center_w > 0)
205  cx = cam.center_w;
206  else
207  cx = (sizeX) / 2.0;
208  if (cam.center_h > 0)
209  cy = cam.center_h;
210  else
211  cy = (sizeY) / 2.0;
212 
213  double focal_x, focal_y;
214  if (cam.focal_length_w > 0)
215  focal_x = cam.focal_length_w;
216  else
217  focal_x = cam.focal_length;
218  if (cam.focal_length_h>0)
219  focal_y = cam.focal_length_h;
220  else
221  focal_y = cam.focal_length;
222 
223  // project point on image frame
224  UV_coordinates[0] = static_cast<float> ((focal_x * (pt.x / pt.z) + cx) / sizeX); //horizontal
225  UV_coordinates[1] = 1.0f - static_cast<float> (((focal_y * (pt.y / pt.z) + cy) / sizeY)); //vertical
226 
227  // point is visible!
228  if (UV_coordinates[0] >= 0.0 && UV_coordinates[0] <= 1.0 && UV_coordinates[1] >= 0.0 && UV_coordinates[1]
229  <= 1.0)
230  return (true);
231  }
232 
233  // point is NOT visible by the camera
234  UV_coordinates[0] = -1.0;
235  UV_coordinates[1] = -1.0;
236  return (false);
237  }
238 
239  /** \brief Check if a point is occluded using raycasting on octree.
240  * \param[in] pt XYZ from which the ray will start (toward the camera)
241  * \param[in] octree the octree used for raycasting. It must be initialized with a cloud transformed into the camera's frame
242  * \returns true if the point is occluded.
243  */
244  inline bool
245  isPointOccluded (const PointInT &pt, const OctreePtr octree);
246 
247  /** \brief Remove occluded points from a point cloud
248  * \param[in] input_cloud the cloud on which to perform occlusion detection
249  * \param[out] filtered_cloud resulting cloud, containing only visible points
250  * \param[in] octree_voxel_size octree resolution (in meters)
251  * \param[out] visible_indices will contain indices of visible points
252  * \param[out] occluded_indices will contain indices of occluded points
253  */
254  void
255  removeOccludedPoints (const PointCloudPtr &input_cloud,
256  PointCloudPtr &filtered_cloud, const double octree_voxel_size,
257  std::vector<int> &visible_indices, std::vector<int> &occluded_indices);
258 
259  /** \brief Remove occluded points from a textureMesh
260  * \param[in] tex_mesh input mesh, on witch to perform occlusion detection
261  * \param[out] cleaned_mesh resulting mesh, containing only visible points
262  * \param[in] octree_voxel_size octree resolution (in meters)
263  */
264  void
265  removeOccludedPoints (const pcl::TextureMesh &tex_mesh, pcl::TextureMesh &cleaned_mesh, const double octree_voxel_size);
266 
267 
268  /** \brief Remove occluded points from a textureMesh
269  * \param[in] tex_mesh input mesh, on witch to perform occlusion detection
270  * \param[out] filtered_cloud resulting cloud, containing only visible points
271  * \param[in] octree_voxel_size octree resolution (in meters)
272  */
273  void
274  removeOccludedPoints (const pcl::TextureMesh &tex_mesh, PointCloudPtr &filtered_cloud, const double octree_voxel_size);
275 
276 
277  /** \brief Segment faces by camera visibility. Point-based segmentation.
278  * \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.
279  * \param[in] tex_mesh input mesh that needs sorting. Must contain only 1 sub-mesh.
280  * \param[in] sorted_mesh resulting mesh, will contain nbCamera + 1 sub-mesh.
281  * \param[in] cameras vector containing the cameras used for texture mapping.
282  * \param[in] octree_voxel_size octree resolution (in meters)
283  * \param[out] visible_pts cloud containing only visible points
284  */
285  int
286  sortFacesByCamera (pcl::TextureMesh &tex_mesh,
287  pcl::TextureMesh &sorted_mesh,
288  const pcl::texture_mapping::CameraVector &cameras,
289  const double octree_voxel_size, PointCloud &visible_pts);
290 
291  /** \brief Colors a point cloud, depending on its occlusions.
292  * \details If showNbOcclusions is set to True, each point is colored depending on the number of points occluding it.
293  * Else, each point is given a different a 0 value is not occluded, 1 if occluded.
294  * By default, the number of occlusions is bounded to 4.
295  * \param[in] input_cloud input cloud on which occlusions will be computed.
296  * \param[out] colored_cloud resulting colored cloud showing the number of occlusions per point.
297  * \param[in] octree_voxel_size octree resolution (in meters).
298  * \param[in] show_nb_occlusions If false, color information will only represent.
299  * \param[in] max_occlusions Limit the number of occlusions per point.
300  */
301  void
302  showOcclusions (const PointCloudPtr &input_cloud,
304  const double octree_voxel_size,
305  const bool show_nb_occlusions = true,
306  const int max_occlusions = 4);
307 
308  /** \brief Colors the point cloud of a Mesh, depending on its occlusions.
309  * \details If showNbOcclusions is set to True, each point is colored depending on the number of points occluding it.
310  * Else, each point is given a different a 0 value is not occluded, 1 if occluded.
311  * By default, the number of occlusions is bounded to 4.
312  * \param[in] tex_mesh input mesh on which occlusions will be computed.
313  * \param[out] colored_cloud resulting colored cloud showing the number of occlusions per point.
314  * \param[in] octree_voxel_size octree resolution (in meters).
315  * \param[in] show_nb_occlusions If false, color information will only represent.
316  * \param[in] max_occlusions Limit the number of occlusions per point.
317  */
318  void
319  showOcclusions (pcl::TextureMesh &tex_mesh,
321  double octree_voxel_size,
322  bool show_nb_occlusions = true,
323  int max_occlusions = 4);
324 
325  /** \brief Segment and texture faces by camera visibility. Face-based segmentation.
326  * \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.
327  * The mesh will also contain uv coordinates for each face
328  * \param mesh input mesh that needs sorting. Should contain only 1 sub-mesh.
329  * \param[in] cameras vector containing the cameras used for texture mapping.
330  */
331  void
332  textureMeshwithMultipleCameras (pcl::TextureMesh &mesh,
333  const pcl::texture_mapping::CameraVector &cameras);
334 
335  protected:
336  /** \brief mesh scale control. */
337  float f_;
338 
339  /** \brief vector field */
340  Eigen::Vector3f vector_field_;
341 
342  /** \brief list of texture files */
343  std::vector<std::string> tex_files_;
344 
345  /** \brief list of texture materials */
347 
348  /** \brief Map texture to a face
349  * \param[in] p1 the first point
350  * \param[in] p2 the second point
351  * \param[in] p3 the third point
352  */
353  std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> >
354  mapTexture2Face (const Eigen::Vector3f &p1, const Eigen::Vector3f &p2, const Eigen::Vector3f &p3);
355 
356  /** \brief Returns the circumcenter of a triangle and the circle's radius.
357  * \details see http://en.wikipedia.org/wiki/Circumcenter for formulas.
358  * \param[in] p1 first point of the triangle.
359  * \param[in] p2 second point of the triangle.
360  * \param[in] p3 third point of the triangle.
361  * \param[out] circumcenter resulting circumcenter
362  * \param[out] radius the radius of the circumscribed circle.
363  */
364  inline void
365  getTriangleCircumcenterAndSize (const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, pcl::PointXY &circumcenter, double &radius);
366 
367 
368  /** \brief Returns the centroid of a triangle and the corresponding circumscribed circle's radius.
369  * \details yield a tighter circle than getTriangleCircumcenterAndSize.
370  * \param[in] p1 first point of the triangle.
371  * \param[in] p2 second point of the triangle.
372  * \param[in] p3 third point of the triangle.
373  * \param[out] circumcenter resulting circumcenter
374  * \param[out] radius the radius of the circumscribed circle.
375  */
376  inline void
377  getTriangleCircumcscribedCircleCentroid ( const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, pcl::PointXY &circumcenter, double &radius);
378 
379 
380  /** \brief computes UV coordinates of point, observed by one particular camera
381  * \param[in] pt XYZ point to project on camera plane
382  * \param[in] cam the camera used for projection
383  * \param[out] UV_coordinates the resulting UV coordinates. Set to (-1.0,-1.0) if the point is not visible by the camera
384  * \returns false if the point is not visible by the camera
385  */
386  inline bool
387  getPointUVCoordinates (const PointInT &pt, const Camera &cam, pcl::PointXY &UV_coordinates);
388 
389  /** \brief Returns true if all the vertices of one face are projected on the camera's image plane.
390  * \param[in] camera camera on which to project the face.
391  * \param[in] p1 first point of the face.
392  * \param[in] p2 second point of the face.
393  * \param[in] p3 third point of the face.
394  * \param[out] proj1 UV coordinates corresponding to p1.
395  * \param[out] proj2 UV coordinates corresponding to p2.
396  * \param[out] proj3 UV coordinates corresponding to p3.
397  */
398  inline bool
399  isFaceProjected (const Camera &camera,
400  const PointInT &p1, const PointInT &p2, const PointInT &p3,
401  pcl::PointXY &proj1, pcl::PointXY &proj2, pcl::PointXY &proj3);
402 
403  /** \brief Returns True if a point lays within a triangle
404  * \details see http://www.blackpawn.com/texts/pointinpoly/default.html
405  * \param[in] p1 first point of the triangle.
406  * \param[in] p2 second point of the triangle.
407  * \param[in] p3 third point of the triangle.
408  * \param[in] pt the querry point.
409  */
410  inline bool
411  checkPointInsideTriangle (const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, const pcl::PointXY &pt);
412 
413  /** \brief Class get name method. */
414  std::string
415  getClassName () const
416  {
417  return ("TextureMapping");
418  }
419 
420  public:
421  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
422  };
423 }
The texture mapping algorithm.
pcl::PointCloud< PointInT > PointCloud
~TextureMapping()
Destructor.
std::vector< Camera, Eigen::aligned_allocator< Camera > > CameraVector
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:44
pcl::texture_mapping::Camera Camera
void setTextureFiles(std::vector< std::string > tex_files)
Set texture files.
PointCloud::ConstPtr PointCloudConstPtr
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.
boost::shared_ptr< PointCloud< PointInT > > Ptr
Definition: point_cloud.h:427
pcl::octree::OctreePointCloudSearch< PointInT > Octree
boost::shared_ptr< OctreePointCloudSearch< PointT, LeafContainerT, BranchContainerT > > Ptr
Definition: octree_search.h:68
TextureMapping()
Constructor.
Eigen::Vector3f vector_field_
vector field
void setVectorField(float x, float y, float z)
Set vector field.
boost::shared_ptr< const TextureMapping< PointInT > > ConstPtr
boost::shared_ptr< const PointCloud< PointInT > > ConstPtr
Definition: point_cloud.h:428
Structure to store camera pose and focal length.
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.
boost::shared_ptr< TextureMapping< PointInT > > Ptr
void setTextureMaterials(TexMaterial tex_material)
Set texture materials.
pcl::texture_mapping::UvIndex UvIndex
Octree::ConstPtr OctreeConstPtr
Octree pointcloud search class
Definition: octree_search.h:56
PointCloud::Ptr PointCloudPtr
std::string getClassName() const
Class get name method.
std::vector< std::string > tex_files_
list of texture files
boost::shared_ptr< const OctreePointCloudSearch< PointT, LeafContainerT, BranchContainerT > > ConstPtr
Definition: octree_search.h:69
TexMaterial tex_material_
list of texture materials