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