Point Cloud Library (PCL)
1.7.0
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2010-2011, Willow Garage, Inc. 00006 * 00007 * All rights reserved. 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 00013 * * Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * * Redistributions in binary form must reproduce the above 00016 * copyright notice, this list of conditions and the following 00017 * disclaimer in the documentation and/or other materials provided 00018 * with the distribution. 00019 * * Neither the name of Willow Garage, Inc. nor the names of its 00020 * contributors may be used to endorse or promote products derived 00021 * from this software without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00026 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00027 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00028 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00029 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00032 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00033 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00034 * POSSIBILITY OF SUCH DAMAGE. 00035 * 00036 * $Id$ 00037 * 00038 */ 00039 00040 #ifndef PCL_SURFACE_TEXTURE_MAPPING_H_ 00041 #define PCL_SURFACE_TEXTURE_MAPPING_H_ 00042 00043 #include <pcl/surface/reconstruction.h> 00044 #include <pcl/common/transforms.h> 00045 #include <pcl/TextureMesh.h> 00046 00047 00048 namespace pcl 00049 { 00050 namespace texture_mapping 00051 { 00052 00053 /** \brief Structure to store camera pose and focal length. */ 00054 struct Camera 00055 { 00056 Camera () : pose (), focal_length (), height (), width (), texture_file () {} 00057 Eigen::Affine3f pose; 00058 double focal_length; 00059 double height; 00060 double width; 00061 std::string texture_file; 00062 00063 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 00064 }; 00065 00066 /** \brief Structure that links a uv coordinate to its 3D point and face. 00067 */ 00068 struct UvIndex 00069 { 00070 UvIndex () : idx_cloud (), idx_face () {} 00071 int idx_cloud; // Index of the PointXYZ in the camera's cloud 00072 int idx_face; // Face corresponding to that projection 00073 }; 00074 00075 typedef std::vector<Camera, Eigen::aligned_allocator<Camera> > CameraVector; 00076 00077 } 00078 00079 /** \brief The texture mapping algorithm 00080 * \author Khai Tran, Raphael Favier 00081 * \ingroup surface 00082 */ 00083 template<typename PointInT> 00084 class TextureMapping 00085 { 00086 public: 00087 00088 typedef boost::shared_ptr< PointInT > Ptr; 00089 typedef boost::shared_ptr< const PointInT > ConstPtr; 00090 00091 typedef pcl::PointCloud<PointInT> PointCloud; 00092 typedef typename PointCloud::Ptr PointCloudPtr; 00093 typedef typename PointCloud::ConstPtr PointCloudConstPtr; 00094 00095 typedef pcl::octree::OctreePointCloudSearch<PointInT> Octree; 00096 typedef typename Octree::Ptr OctreePtr; 00097 typedef typename Octree::ConstPtr OctreeConstPtr; 00098 00099 typedef pcl::texture_mapping::Camera Camera; 00100 typedef pcl::texture_mapping::UvIndex UvIndex; 00101 00102 /** \brief Constructor. */ 00103 TextureMapping () : 00104 f_ (), vector_field_ (), tex_files_ (), tex_material_ () 00105 { 00106 } 00107 00108 /** \brief Destructor. */ 00109 ~TextureMapping () 00110 { 00111 } 00112 00113 /** \brief Set mesh scale control 00114 * \param[in] f 00115 */ 00116 inline void 00117 setF (float f) 00118 { 00119 f_ = f; 00120 } 00121 00122 /** \brief Set vector field 00123 * \param[in] x data point x 00124 * \param[in] y data point y 00125 * \param[in] z data point z 00126 */ 00127 inline void 00128 setVectorField (float x, float y, float z) 00129 { 00130 vector_field_ = Eigen::Vector3f (x, y, z); 00131 // normalize vector field 00132 vector_field_ = vector_field_ / std::sqrt (vector_field_.dot (vector_field_)); 00133 } 00134 00135 /** \brief Set texture files 00136 * \param[in] tex_files list of texture files 00137 */ 00138 inline void 00139 setTextureFiles (std::vector<std::string> tex_files) 00140 { 00141 tex_files_ = tex_files; 00142 } 00143 00144 /** \brief Set texture materials 00145 * \param[in] tex_material texture material 00146 */ 00147 inline void 00148 setTextureMaterials (TexMaterial tex_material) 00149 { 00150 tex_material_ = tex_material; 00151 } 00152 00153 /** \brief Map texture to a mesh synthesis algorithm 00154 * \param[in] tex_mesh texture mesh 00155 */ 00156 void 00157 mapTexture2Mesh (pcl::TextureMesh &tex_mesh); 00158 00159 /** \brief Map texture to a mesh UV mapping 00160 * \param[in] tex_mesh texture mesh 00161 */ 00162 void 00163 mapTexture2MeshUV (pcl::TextureMesh &tex_mesh); 00164 00165 /** \brief Map textures acquired from a set of cameras onto a mesh. 00166 * \details With UV mapping, the mesh must be divided into NbCamera + 1 sub-meshes. 00167 * Each sub-mesh corresponding to the faces visible by one camera. The last submesh containing all non-visible faces 00168 * \param[in] tex_mesh texture mesh 00169 * \param[in] cams cameras used for UV mapping 00170 */ 00171 void 00172 mapMultipleTexturesToMeshUV (pcl::TextureMesh &tex_mesh, 00173 pcl::texture_mapping::CameraVector &cams); 00174 00175 /** \brief computes UV coordinates of point, observed by one particular camera 00176 * \param[in] pt XYZ point to project on camera plane 00177 * \param[in] cam the camera used for projection 00178 * \param[out] UV_coordinates the resulting uv coordinates. Set to (-1.0,-1.0) if the point is not visible by the camera 00179 * \returns false if the point is not visible by the camera 00180 */ 00181 inline bool 00182 getPointUVCoordinates (const pcl::PointXYZ &pt, const Camera &cam, Eigen::Vector2f &UV_coordinates) 00183 { 00184 // if the point is in front of the camera 00185 if (pt.z > 0) 00186 { 00187 // compute image center and dimension 00188 double sizeX = cam.width; 00189 double sizeY = cam.height; 00190 double cx = (sizeX) / 2.0; 00191 double cy = (sizeY) / 2.0; 00192 00193 double focal_x = cam.focal_length; 00194 double focal_y = cam.focal_length; 00195 00196 // project point on image frame 00197 UV_coordinates[0] = static_cast<float> ((focal_x * (pt.x / pt.z) + cx) / sizeX); //horizontal 00198 UV_coordinates[1] = 1.0f - static_cast<float> (((focal_y * (pt.y / pt.z) + cy) / sizeY)); //vertical 00199 00200 // point is visible! 00201 if (UV_coordinates[0] >= 0.0 && UV_coordinates[0] <= 1.0 && UV_coordinates[1] >= 0.0 && UV_coordinates[1] 00202 <= 1.0) 00203 return (true); 00204 } 00205 00206 // point is NOT visible by the camera 00207 UV_coordinates[0] = -1.0; 00208 UV_coordinates[1] = -1.0; 00209 return (false); 00210 } 00211 00212 /** \brief Check if a point is occluded using raycasting on octree. 00213 * \param[in] pt XYZ from which the ray will start (toward the camera) 00214 * \param[in] octree the octree used for raycasting. It must be initialized with a cloud transformed into the camera's frame 00215 * \returns true if the point is occluded. 00216 */ 00217 inline bool 00218 isPointOccluded (const pcl::PointXYZ &pt, const OctreePtr octree); 00219 00220 /** \brief Remove occluded points from a point cloud 00221 * \param[in] input_cloud the cloud on which to perform occlusion detection 00222 * \param[out] filtered_cloud resulting cloud, containing only visible points 00223 * \param[in] octree_voxel_size octree resolution (in meters) 00224 * \param[out] visible_indices will contain indices of visible points 00225 * \param[out] occluded_indices will contain indices of occluded points 00226 */ 00227 void 00228 removeOccludedPoints (const PointCloudPtr &input_cloud, 00229 PointCloudPtr &filtered_cloud, const double octree_voxel_size, 00230 std::vector<int> &visible_indices, std::vector<int> &occluded_indices); 00231 00232 /** \brief Remove occluded points from a textureMesh 00233 * \param[in] tex_mesh input mesh, on witch to perform occlusion detection 00234 * \param[out] cleaned_mesh resulting mesh, containing only visible points 00235 * \param[in] octree_voxel_size octree resolution (in meters) 00236 */ 00237 void 00238 removeOccludedPoints (const pcl::TextureMesh &tex_mesh, pcl::TextureMesh &cleaned_mesh, const double octree_voxel_size); 00239 00240 00241 /** \brief Remove occluded points from a textureMesh 00242 * \param[in] tex_mesh input mesh, on witch to perform occlusion detection 00243 * \param[out] filtered_cloud resulting cloud, containing only visible points 00244 * \param[in] octree_voxel_size octree resolution (in meters) 00245 */ 00246 void 00247 removeOccludedPoints (const pcl::TextureMesh &tex_mesh, PointCloudPtr &filtered_cloud, const double octree_voxel_size); 00248 00249 00250 /** \brief Segment faces by camera visibility. Point-based segmentation. 00251 * \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. 00252 * \param[in] tex_mesh input mesh that needs sorting. Must contain only 1 sub-mesh. 00253 * \param[in] sorted_mesh resulting mesh, will contain nbCamera + 1 sub-mesh. 00254 * \param[in] cameras vector containing the cameras used for texture mapping. 00255 * \param[in] octree_voxel_size octree resolution (in meters) 00256 * \param[out] visible_pts cloud containing only visible points 00257 */ 00258 int 00259 sortFacesByCamera (pcl::TextureMesh &tex_mesh, 00260 pcl::TextureMesh &sorted_mesh, 00261 const pcl::texture_mapping::CameraVector &cameras, 00262 const double octree_voxel_size, PointCloud &visible_pts); 00263 00264 /** \brief Colors a point cloud, depending on its occlusions. 00265 * \details If showNbOcclusions is set to True, each point is colored depending on the number of points occluding it. 00266 * Else, each point is given a different a 0 value is not occluded, 1 if occluded. 00267 * By default, the number of occlusions is bounded to 4. 00268 * \param[in] input_cloud input cloud on which occlusions will be computed. 00269 * \param[out] colored_cloud resulting colored cloud showing the number of occlusions per point. 00270 * \param[in] octree_voxel_size octree resolution (in meters). 00271 * \param[in] show_nb_occlusions If false, color information will only represent. 00272 * \param[in] max_occlusions Limit the number of occlusions per point. 00273 */ 00274 void 00275 showOcclusions (const PointCloudPtr &input_cloud, 00276 pcl::PointCloud<pcl::PointXYZI>::Ptr &colored_cloud, 00277 const double octree_voxel_size, 00278 const bool show_nb_occlusions = true, 00279 const int max_occlusions = 4); 00280 00281 /** \brief Colors the point cloud of a Mesh, depending on its occlusions. 00282 * \details If showNbOcclusions is set to True, each point is colored depending on the number of points occluding it. 00283 * Else, each point is given a different a 0 value is not occluded, 1 if occluded. 00284 * By default, the number of occlusions is bounded to 4. 00285 * \param[in] tex_mesh input mesh on which occlusions will be computed. 00286 * \param[out] colored_cloud resulting colored cloud showing the number of occlusions per point. 00287 * \param[in] octree_voxel_size octree resolution (in meters). 00288 * \param[in] show_nb_occlusions If false, color information will only represent. 00289 * \param[in] max_occlusions Limit the number of occlusions per point. 00290 */ 00291 void 00292 showOcclusions (pcl::TextureMesh &tex_mesh, 00293 pcl::PointCloud<pcl::PointXYZI>::Ptr &colored_cloud, 00294 double octree_voxel_size, 00295 bool show_nb_occlusions = true, 00296 int max_occlusions = 4); 00297 00298 /** \brief Segment and texture faces by camera visibility. Face-based segmentation. 00299 * \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. 00300 * The mesh will also contain uv coordinates for each face 00301 * \param[in/out] tex_mesh input mesh that needs sorting. Should contain only 1 sub-mesh. 00302 * \param[in] cameras vector containing the cameras used for texture mapping. 00303 */ 00304 void 00305 textureMeshwithMultipleCameras (pcl::TextureMesh &mesh, 00306 const pcl::texture_mapping::CameraVector &cameras); 00307 00308 protected: 00309 /** \brief mesh scale control. */ 00310 float f_; 00311 00312 /** \brief vector field */ 00313 Eigen::Vector3f vector_field_; 00314 00315 /** \brief list of texture files */ 00316 std::vector<std::string> tex_files_; 00317 00318 /** \brief list of texture materials */ 00319 TexMaterial tex_material_; 00320 00321 /** \brief Map texture to a face 00322 * \param[in] p1 the first point 00323 * \param[in] p2 the second point 00324 * \param[in] p3 the third point 00325 */ 00326 std::vector<Eigen::Vector2f> 00327 mapTexture2Face (const Eigen::Vector3f &p1, const Eigen::Vector3f &p2, const Eigen::Vector3f &p3); 00328 00329 /** \brief Returns the circumcenter of a triangle and the circle's radius. 00330 * \details see http://en.wikipedia.org/wiki/Circumcenter for formulas. 00331 * \param[in] p1 first point of the triangle. 00332 * \param[in] p2 second point of the triangle. 00333 * \param[in] p3 third point of the triangle. 00334 * \param[out] circumcenter resulting circumcenter 00335 * \param[out] radius the radius of the circumscribed circle. 00336 */ 00337 inline void 00338 getTriangleCircumcenterAndSize (const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, pcl::PointXY &circomcenter, double &radius); 00339 00340 00341 /** \brief Returns the centroid of a triangle and the corresponding circumscribed circle's radius. 00342 * \details yield a tighter circle than getTriangleCircumcenterAndSize. 00343 * \param[in] p1 first point of the triangle. 00344 * \param[in] p2 second point of the triangle. 00345 * \param[in] p3 third point of the triangle. 00346 * \param[out] circumcenter resulting circumcenter 00347 * \param[out] radius the radius of the circumscribed circle. 00348 */ 00349 inline void 00350 getTriangleCircumcscribedCircleCentroid ( const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, pcl::PointXY &circumcenter, double &radius); 00351 00352 00353 /** \brief computes UV coordinates of point, observed by one particular camera 00354 * \param[in] pt XYZ point to project on camera plane 00355 * \param[in] cam the camera used for projection 00356 * \param[out] UV_coordinates the resulting UV coordinates. Set to (-1.0,-1.0) if the point is not visible by the camera 00357 * \returns false if the point is not visible by the camera 00358 */ 00359 inline bool 00360 getPointUVCoordinates (const pcl::PointXYZ &pt, const Camera &cam, pcl::PointXY &UV_coordinates); 00361 00362 /** \brief Returns true if all the vertices of one face are projected on the camera's image plane. 00363 * \param[in] camera camera on which to project the face. 00364 * \param[in] p1 first point of the face. 00365 * \param[in] p2 second point of the face. 00366 * \param[in] p3 third point of the face. 00367 * \param[out] proj1 UV coordinates corresponding to p1. 00368 * \param[out] proj2 UV coordinates corresponding to p2. 00369 * \param[out] proj3 UV coordinates corresponding to p3. 00370 */ 00371 inline bool 00372 isFaceProjected (const Camera &camera, 00373 const pcl::PointXYZ &p1, const pcl::PointXYZ &p2, const pcl::PointXYZ &p3, 00374 pcl::PointXY &proj1, pcl::PointXY &proj2, pcl::PointXY &proj3); 00375 00376 /** \brief Returns True if a point lays within a triangle 00377 * \details see http://www.blackpawn.com/texts/pointinpoly/default.html 00378 * \param[in] p1 first point of the triangle. 00379 * \param[in] p2 second point of the triangle. 00380 * \param[in] p3 third point of the triangle. 00381 * \param[in] pt the querry point. 00382 */ 00383 inline bool 00384 checkPointInsideTriangle (const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, const pcl::PointXY &pt); 00385 00386 /** \brief Class get name method. */ 00387 std::string 00388 getClassName () const 00389 { 00390 return ("TextureMapping"); 00391 } 00392 00393 public: 00394 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 00395 }; 00396 } 00397 00398 #endif /* TEXTURE_MAPPING_H_ */ 00399