38 #ifndef PCL_SURFACE_IMPL_TEXTURE_MAPPING_HPP_ 39 #define PCL_SURFACE_IMPL_TEXTURE_MAPPING_HPP_ 41 #include <pcl/common/distances.h> 43 #include <pcl/search/octree.h> 46 template<
typename Po
intInT> std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> >
48 const Eigen::Vector3f &p1,
49 const Eigen::Vector3f &p2,
50 const Eigen::Vector3f &p3)
52 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > tex_coordinates;
54 Eigen::Vector3f p1p2 (p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]);
55 Eigen::Vector3f p1p3 (p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]);
56 Eigen::Vector3f p2p3 (p3[0] - p2[0], p3[1] - p2[1], p3[2] - p2[2]);
59 p1p2 = p1p2 /
std::sqrt (p1p2.dot (p1p2));
60 p1p3 = p1p3 /
std::sqrt (p1p3.dot (p1p3));
61 p2p3 = p2p3 /
std::sqrt (p2p3.dot (p2p3));
64 Eigen::Vector3f f_normal = p1p2.cross (p1p3);
65 f_normal = f_normal /
std::sqrt (f_normal.dot (f_normal));
68 Eigen::Vector3f f_vector_field = vector_field_ - vector_field_.dot (f_normal) * f_normal;
71 f_vector_field = f_vector_field /
std::sqrt (f_vector_field.dot (f_vector_field));
74 Eigen::Vector2f tp1, tp2, tp3;
76 double alpha =
std::acos (f_vector_field.dot (p1p2));
79 double e1 = (p2 - p3).norm () / f_;
80 double e2 = (p1 - p3).norm () / f_;
81 double e3 = (p1 - p2).norm () / f_;
87 tp2[0] =
static_cast<float> (e3);
91 double cos_p1 = (e2 * e2 + e3 * e3 - e1 * e1) / (2 * e2 * e3);
92 double sin_p1 =
sqrt (1 - (cos_p1 * cos_p1));
94 tp3[0] =
static_cast<float> (cos_p1 * e2);
95 tp3[1] =
static_cast<float> (sin_p1 * e2);
98 Eigen::Vector2f r_tp2, r_tp3;
99 r_tp2[0] =
static_cast<float> (tp2[0] *
std::cos (alpha) - tp2[1] *
std::sin (alpha));
100 r_tp2[1] =
static_cast<float> (tp2[0] *
std::sin (alpha) + tp2[1] *
std::cos (alpha));
102 r_tp3[0] =
static_cast<float> (tp3[0] *
std::cos (alpha) - tp3[1] *
std::sin (alpha));
103 r_tp3[1] =
static_cast<float> (tp3[0] *
std::sin (alpha) + tp3[1] *
std::cos (alpha));
113 float min_x = tp1[0];
114 float min_y = tp1[1];
126 tp1[0] = tp1[0] - min_x;
127 tp2[0] = tp2[0] - min_x;
128 tp3[0] = tp3[0] - min_x;
132 tp1[1] = tp1[1] - min_y;
133 tp2[1] = tp2[1] - min_y;
134 tp3[1] = tp3[1] - min_y;
137 tex_coordinates.push_back (tp1);
138 tex_coordinates.push_back (tp2);
139 tex_coordinates.push_back (tp3);
140 return (tex_coordinates);
144 template<
typename Po
intInT>
void 148 int nr_points = tex_mesh.cloud.width * tex_mesh.cloud.height;
149 int point_size =
static_cast<int> (tex_mesh.cloud.data.size ()) / nr_points;
154 Eigen::Vector3f facet[3];
157 std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >texture_map;
159 for (
size_t m = 0; m < tex_mesh.tex_polygons.size (); ++m)
162 #if PCL_VERSION_COMPARE(>=, 1, 8, 0) 163 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > texture_map_tmp;
165 std::vector<Eigen::Vector2f> texture_map_tmp;
169 for (
size_t i = 0; i < tex_mesh.tex_polygons[m].size (); ++i)
174 for (
size_t j = 0; j < tex_mesh.tex_polygons[m][i].vertices.size (); ++j)
176 idx = tex_mesh.tex_polygons[m][i].vertices[j];
177 memcpy (&x, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[0].offset],
sizeof(
float));
178 memcpy (&y, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[1].offset],
sizeof(
float));
179 memcpy (&z, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[2].offset],
sizeof(
float));
186 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > tex_coordinates = mapTexture2Face (facet[0], facet[1], facet[2]);
187 for (
size_t n = 0; n < tex_coordinates.size (); ++n)
188 texture_map_tmp.push_back (tex_coordinates[n]);
192 std::stringstream tex_name;
193 tex_name <<
"material_" << m;
194 tex_name >> tex_material_.tex_name;
195 tex_material_.tex_file = tex_files_[m];
196 tex_mesh.tex_materials.push_back (tex_material_);
199 tex_mesh.tex_coordinates.push_back (texture_map_tmp);
204 template<
typename Po
intInT>
void 208 int nr_points = tex_mesh.cloud.width * tex_mesh.cloud.height;
209 int point_size =
static_cast<int> (tex_mesh.cloud.data.size ()) / nr_points;
211 float x_lowest = 100000;
213 float y_lowest = 100000;
215 float z_lowest = 100000;
219 for (
int i = 0; i < nr_points; ++i)
221 memcpy (&x_, &tex_mesh.cloud.data[i * point_size + tex_mesh.cloud.fields[0].offset],
sizeof(
float));
222 memcpy (&y_, &tex_mesh.cloud.data[i * point_size + tex_mesh.cloud.fields[1].offset],
sizeof(
float));
223 memcpy (&z_, &tex_mesh.cloud.data[i * point_size + tex_mesh.cloud.fields[2].offset],
sizeof(
float));
242 float x_range = (x_lowest - x_highest) * -1;
243 float x_offset = 0 - x_lowest;
248 float z_range = (z_lowest - z_highest) * -1;
249 float z_offset = 0 - z_lowest;
252 std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >texture_map;
254 for (
size_t m = 0; m < tex_mesh.tex_polygons.size (); ++m)
257 #if PCL_VERSION_COMPARE(>=, 1, 8, 0) 258 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > texture_map_tmp;
260 std::vector<Eigen::Vector2f> texture_map_tmp;
264 for (
size_t i = 0; i < tex_mesh.tex_polygons[m].size (); ++i)
267 Eigen::Vector2f tmp_VT;
268 for (
size_t j = 0; j < tex_mesh.tex_polygons[m][i].vertices.size (); ++j)
270 idx = tex_mesh.tex_polygons[m][i].vertices[j];
271 memcpy (&x_, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[0].offset],
sizeof(
float));
272 memcpy (&y_, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[1].offset],
sizeof(
float));
273 memcpy (&z_, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[2].offset],
sizeof(
float));
276 tmp_VT[0] = (x_ + x_offset) / x_range;
277 tmp_VT[1] = (z_ + z_offset) / z_range;
278 texture_map_tmp.push_back (tmp_VT);
283 std::stringstream tex_name;
284 tex_name <<
"material_" << m;
285 tex_name >> tex_material_.tex_name;
286 tex_material_.tex_file = tex_files_[m];
287 tex_mesh.tex_materials.push_back (tex_material_);
290 tex_mesh.tex_coordinates.push_back (texture_map_tmp);
295 template<
typename Po
intInT>
void 299 if (tex_mesh.tex_polygons.size () != cams.size () + 1)
301 PCL_ERROR (
"The mesh should be divided into nbCamera+1 sub-meshes.\n");
302 PCL_ERROR (
"You provided %d cameras and a mesh containing %d sub-meshes.\n", cams.size (), tex_mesh.tex_polygons.size ());
306 PCL_INFO (
"You provided %d cameras and a mesh containing %d sub-meshes.\n", cams.size (), tex_mesh.tex_polygons.size ());
308 typename pcl::PointCloud<PointInT>::Ptr originalCloud (
new pcl::PointCloud<PointInT>);
309 typename pcl::PointCloud<PointInT>::Ptr camera_transformed_cloud (
new pcl::PointCloud<PointInT>);
312 pcl::fromPCLPointCloud2 (tex_mesh.cloud, *originalCloud);
315 std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > texture_map;
317 for (
size_t m = 0; m < cams.size (); ++m)
320 Camera current_cam = cams[m];
323 Eigen::Affine3f cam_trans = current_cam.
pose;
329 #if PCL_VERSION_COMPARE(>=, 1, 8, 0) 330 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > texture_map_tmp;
332 std::vector<Eigen::Vector2f> texture_map_tmp;
338 for (
size_t i = 0; i < tex_mesh.tex_polygons[m].size (); ++i)
340 Eigen::Vector2f tmp_VT;
342 for (
size_t j = 0; j < tex_mesh.tex_polygons[m][i].vertices.size (); ++j)
345 idx = tex_mesh.tex_polygons[m][i].vertices[j];
346 pt = camera_transformed_cloud->points[idx];
349 getPointUVCoordinates (pt, current_cam, tmp_VT);
350 texture_map_tmp.push_back (tmp_VT);
356 std::stringstream tex_name;
357 tex_name <<
"material_" << m;
358 tex_name >> tex_material_.tex_name;
360 tex_mesh.tex_materials.push_back (tex_material_);
363 tex_mesh.tex_coordinates.push_back (texture_map_tmp);
367 #if PCL_VERSION_COMPARE(>=, 1, 8, 0) 368 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > texture_map_tmp;
370 std::vector<Eigen::Vector2f> texture_map_tmp;
372 for (
size_t i = 0; i < tex_mesh.tex_polygons[cams.size ()].size (); ++i)
373 for (
size_t j = 0; j < tex_mesh.tex_polygons[cams.size ()][i].vertices.size (); ++j)
375 Eigen::Vector2f tmp_VT;
378 texture_map_tmp.push_back (tmp_VT);
381 tex_mesh.tex_coordinates.push_back (texture_map_tmp);
384 std::stringstream tex_name;
385 tex_name <<
"material_" << cams.size ();
386 tex_name >> tex_material_.tex_name;
387 tex_material_.tex_file =
"occluded.jpg";
388 tex_mesh.tex_materials.push_back (tex_material_);
393 template<
typename Po
intInT>
bool 396 Eigen::Vector3f direction;
397 direction (0) = pt.x;
398 direction (1) = pt.y;
399 direction (2) = pt.z;
401 std::vector<int> indices;
404 cloud = octree->getInputCloud();
406 double distance_threshold = octree->getResolution();
409 octree->getIntersectedVoxelIndices(direction, -direction, indices);
411 int nbocc =
static_cast<int> (indices.size ());
412 for (
size_t j = 0; j < indices.size (); j++)
415 if (pt.z * cloud->points[indices[j]].z < 0)
421 if (fabs (cloud->points[indices[j]].z - pt.z) <= distance_threshold)
435 template<
typename Po
intInT>
void 438 const double octree_voxel_size, std::vector<int> &visible_indices,
439 std::vector<int> &occluded_indices)
442 double maxDeltaZ = octree_voxel_size;
447 octree->setInputCloud (input_cloud);
449 octree->defineBoundingBox ();
451 octree->addPointsFromInputCloud ();
453 visible_indices.clear ();
456 Eigen::Vector3f direction;
457 std::vector<int> indices;
458 for (
size_t i = 0; i < input_cloud->points.size (); ++i)
460 direction (0) = input_cloud->points[i].x;
461 direction (1) = input_cloud->points[i].y;
462 direction (2) = input_cloud->points[i].z;
465 octree->getIntersectedVoxelIndices (direction, -direction, indices);
467 int nbocc =
static_cast<int> (indices.size ());
468 for (
size_t j = 0; j < indices.size (); j++)
471 if (input_cloud->points[i].z * input_cloud->points[indices[j]].z < 0)
477 if (fabs (input_cloud->points[indices[j]].z - input_cloud->points[i].z) <= maxDeltaZ)
487 filtered_cloud->points.push_back (input_cloud->points[i]);
488 visible_indices.push_back (static_cast<int> (i));
492 occluded_indices.push_back (static_cast<int> (i));
499 template<
typename Po
intInT>
void 503 cleaned_mesh = tex_mesh;
505 typename pcl::PointCloud<PointInT>::Ptr cloud (
new pcl::PointCloud<PointInT>);
506 typename pcl::PointCloud<PointInT>::Ptr filtered_cloud (
new pcl::PointCloud<PointInT>);
509 pcl::fromPCLPointCloud2 (tex_mesh.cloud, *cloud);
511 std::vector<int> visible, occluded;
512 removeOccludedPoints (cloud, filtered_cloud, octree_voxel_size, visible, occluded);
516 for (
size_t polygons = 0; polygons < cleaned_mesh.tex_polygons.size (); ++polygons)
519 cleaned_mesh.tex_polygons[polygons].clear ();
521 for (
size_t faces = 0; faces < tex_mesh.tex_polygons[polygons].size (); ++faces)
524 bool faceIsVisible =
true;
525 std::vector<int>::iterator it;
528 for (
size_t points = 0; points < tex_mesh.tex_polygons[polygons][faces].vertices.size (); ++points)
530 it = find (occluded.begin (), occluded.end (), tex_mesh.tex_polygons[polygons][faces].vertices[points]);
532 if (it == occluded.end ())
541 faceIsVisible =
false;
547 cleaned_mesh.tex_polygons[polygons].push_back (tex_mesh.tex_polygons[polygons][faces]);
555 template<
typename Po
intInT>
void 557 const double octree_voxel_size)
562 pcl::fromPCLPointCloud2 (tex_mesh.cloud, *cloud);
564 std::vector<int> visible, occluded;
565 removeOccludedPoints (cloud, filtered_cloud, octree_voxel_size, visible, occluded);
570 template<
typename Po
intInT>
int 575 if (tex_mesh.tex_polygons.size () != 1)
577 PCL_ERROR (
"The mesh must contain only 1 sub-mesh!\n");
581 if (cameras.size () == 0)
583 PCL_ERROR (
"Must provide at least one camera info!\n");
588 sorted_mesh = tex_mesh;
590 sorted_mesh.tex_polygons.clear ();
592 typename pcl::PointCloud<PointInT>::Ptr original_cloud (
new pcl::PointCloud<PointInT>);
593 typename pcl::PointCloud<PointInT>::Ptr transformed_cloud (
new pcl::PointCloud<PointInT>);
594 typename pcl::PointCloud<PointInT>::Ptr filtered_cloud (
new pcl::PointCloud<PointInT>);
597 pcl::fromPCLPointCloud2 (tex_mesh.cloud, *original_cloud);
600 for (
size_t cam = 0;
cam < cameras.size (); ++
cam)
603 Eigen::Affine3f cam_trans = cameras[
cam].pose;
609 std::vector<int> visible, occluded;
610 removeOccludedPoints (transformed_cloud, filtered_cloud, octree_voxel_size, visible, occluded);
611 visible_pts = *filtered_cloud;
615 std::vector<pcl::Vertices> visibleFaces_currentCam;
617 for (
size_t faces = 0; faces < tex_mesh.tex_polygons[0].size (); ++faces)
620 bool faceIsVisible =
true;
621 std::vector<int>::iterator it;
624 for (
size_t current_pt_indice = 0; faceIsVisible && current_pt_indice < tex_mesh.tex_polygons[0][faces].vertices.size (); ++current_pt_indice)
627 it = find (occluded.begin (), occluded.end (), tex_mesh.tex_polygons[0][faces].vertices[current_pt_indice]);
629 if (it == occluded.end ())
633 PointInT pt = transformed_cloud->points[tex_mesh.tex_polygons[0][faces].vertices[current_pt_indice]];
634 Eigen::Vector2f dummy_UV;
635 if (!getPointUVCoordinates (pt, cameras[
cam], dummy_UV))
638 faceIsVisible =
false;
643 faceIsVisible =
false;
650 visibleFaces_currentCam.push_back (tex_mesh.tex_polygons[0][faces]);
652 tex_mesh.tex_polygons[0].erase (tex_mesh.tex_polygons[0].begin () + faces);
657 sorted_mesh.tex_polygons.push_back (visibleFaces_currentCam);
662 sorted_mesh.tex_polygons.push_back (tex_mesh.tex_polygons[0]);
667 template<
typename Po
intInT>
void 669 pcl::PointCloud<pcl::PointXYZI>::Ptr &colored_cloud,
670 const double octree_voxel_size,
const bool show_nb_occlusions,
671 const int max_occlusions)
674 double maxDeltaZ = octree_voxel_size * 2.0;
677 pcl::octree::OctreePointCloudSearch<PointInT> *octree;
678 octree =
new pcl::octree::OctreePointCloudSearch<PointInT> (octree_voxel_size);
680 octree->setInputCloud (input_cloud);
682 octree->defineBoundingBox ();
684 octree->addPointsFromInputCloud ();
687 Eigen::Vector3f direction;
689 std::vector<int> indices;
693 std::vector<double> zDist;
694 std::vector<double> ptDist;
696 for (
size_t i = 0; i < input_cloud->points.size (); ++i)
698 direction (0) = input_cloud->points[i].x;
699 pt.x = input_cloud->points[i].x;
700 direction (1) = input_cloud->points[i].y;
701 pt.y = input_cloud->points[i].y;
702 direction (2) = input_cloud->points[i].z;
703 pt.z = input_cloud->points[i].z;
707 int nbocc = octree->getIntersectedVoxelIndices (direction, -direction, indices);
709 nbocc =
static_cast<int> (indices.size ());
712 for (
size_t j = 0; j < indices.size (); j++)
715 if (pt.z * input_cloud->points[indices[j]].z < 0)
719 else if (fabs (input_cloud->points[indices[j]].z - pt.z) <= maxDeltaZ)
726 zDist.push_back (fabs (input_cloud->points[indices[j]].z - pt.z));
727 ptDist.push_back (pcl::euclideanDistance (input_cloud->points[indices[j]], pt));
731 if (show_nb_occlusions)
732 (nbocc <= max_occlusions) ? (pt.intensity = static_cast<float> (nbocc)) : (pt.intensity = static_cast<float> (max_occlusions));
734 (nbocc == 0) ? (pt.intensity = 0) : (pt.intensity = 1);
736 colored_cloud->points.push_back (pt);
739 if (zDist.size () >= 2)
741 std::sort (zDist.begin (), zDist.end ());
742 std::sort (ptDist.begin (), ptDist.end ());
747 template<
typename Po
intInT>
void 749 double octree_voxel_size,
bool show_nb_occlusions,
int max_occlusions)
752 typename pcl::PointCloud<PointInT>::Ptr cloud (
new pcl::PointCloud<PointInT>);
753 pcl::fromPCLPointCloud2 (tex_mesh.cloud, *cloud);
755 showOcclusions (cloud, colored_cloud, octree_voxel_size, show_nb_occlusions, max_occlusions);
759 template<
typename Po
intInT>
void 763 if (mesh.tex_polygons.size () != 1)
766 typename pcl::PointCloud<PointInT>::Ptr mesh_cloud (
new pcl::PointCloud<PointInT>);
768 pcl::fromPCLPointCloud2 (mesh.cloud, *mesh_cloud);
770 std::vector<pcl::Vertices> faces;
772 for (
int current_cam = 0; current_cam < static_cast<int> (cameras.size ()); ++current_cam)
774 PCL_INFO (
"Processing camera %d of %d.\n", current_cam+1, cameras.size ());
777 typename pcl::PointCloud<PointInT>::Ptr camera_cloud (
new pcl::PointCloud<PointInT>);
781 pcl::PointCloud<pcl::PointXY>::Ptr projections (
new pcl::PointCloud<pcl::PointXY>);
782 std::vector<pcl::Vertices>::iterator current_face;
783 std::vector<bool> visibility;
784 visibility.resize (mesh.tex_polygons[current_cam].size ());
785 std::vector<UvIndex> indexes_uv_to_points;
789 pcl::PointXY nan_point;
790 nan_point.x = std::numeric_limits<float>::quiet_NaN ();
791 nan_point.y = std::numeric_limits<float>::quiet_NaN ();
797 for (
int idx_face = 0; idx_face < static_cast<int> (mesh.tex_polygons[current_cam].size ()); ++idx_face)
800 pcl::PointXY uv_coord1;
801 pcl::PointXY uv_coord2;
802 pcl::PointXY uv_coord3;
804 if (isFaceProjected (cameras[current_cam],
805 camera_cloud->points[mesh.tex_polygons[current_cam][idx_face].vertices[0]],
806 camera_cloud->points[mesh.tex_polygons[current_cam][idx_face].vertices[1]],
807 camera_cloud->points[mesh.tex_polygons[current_cam][idx_face].vertices[2]],
815 projections->points.push_back (uv_coord1);
816 projections->points.push_back (uv_coord2);
817 projections->points.push_back (uv_coord3);
821 u1.
idx_cloud = mesh.tex_polygons[current_cam][idx_face].vertices[0];
822 u2.
idx_cloud = mesh.tex_polygons[current_cam][idx_face].vertices[1];
823 u3.
idx_cloud = mesh.tex_polygons[current_cam][idx_face].vertices[2];
825 indexes_uv_to_points.push_back (u1);
826 indexes_uv_to_points.push_back (u2);
827 indexes_uv_to_points.push_back (u3);
830 visibility[idx_face] =
true;
834 projections->points.push_back (nan_point);
835 projections->points.push_back (nan_point);
836 projections->points.push_back (nan_point);
837 indexes_uv_to_points.push_back (u_null);
838 indexes_uv_to_points.push_back (u_null);
839 indexes_uv_to_points.push_back (u_null);
841 visibility[idx_face] =
false;
851 if (visibility.size () - cpt_invisible !=0)
854 pcl::KdTreeFLANN<pcl::PointXY> kdtree;
855 kdtree.setInputCloud (projections);
857 std::vector<int> idxNeighbors;
858 std::vector<float> neighborsSquaredDistance;
862 for (
int idx_pcam = 0 ; idx_pcam <= current_cam ; ++idx_pcam)
865 for (
int idx_face = 0; idx_face < static_cast<int> (mesh.tex_polygons[idx_pcam].size ()); ++idx_face)
868 if (idx_pcam == current_cam && !visibility[idx_face])
877 pcl::PointXY uv_coord1;
878 pcl::PointXY uv_coord2;
879 pcl::PointXY uv_coord3;
881 if (isFaceProjected (cameras[current_cam],
882 camera_cloud->points[mesh.tex_polygons[idx_pcam][idx_face].vertices[0]],
883 camera_cloud->points[mesh.tex_polygons[idx_pcam][idx_face].vertices[1]],
884 camera_cloud->points[mesh.tex_polygons[idx_pcam][idx_face].vertices[2]],
894 getTriangleCircumcscribedCircleCentroid(uv_coord1, uv_coord2, uv_coord3, center, radius);
897 if (kdtree.radiusSearch (center, radius, idxNeighbors, neighborsSquaredDistance) > 0 )
900 for (
size_t i = 0; i < idxNeighbors.size (); ++i)
902 if (
std::max (camera_cloud->points[mesh.tex_polygons[idx_pcam][idx_face].vertices[0]].z,
903 std::max (camera_cloud->points[mesh.tex_polygons[idx_pcam][idx_face].vertices[1]].z,
904 camera_cloud->points[mesh.tex_polygons[idx_pcam][idx_face].vertices[2]].z))
905 < camera_cloud->points[indexes_uv_to_points[idxNeighbors[i]].idx_cloud].z)
908 if (checkPointInsideTriangle(uv_coord1, uv_coord2, uv_coord3, projections->points[idxNeighbors[i]]))
911 visibility[indexes_uv_to_points[idxNeighbors[i]].idx_face] =
false;
926 if (static_cast<int> (mesh.tex_coordinates.size ()) <= current_cam)
928 #if PCL_VERSION_COMPARE(>=, 1, 8, 0) 929 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > dummy_container;
931 std::vector<Eigen::Vector2f> dummy_container;
933 mesh.tex_coordinates.push_back (dummy_container);
935 mesh.tex_coordinates[current_cam].resize (3 * visibility.size ());
937 std::vector<pcl::Vertices> occluded_faces;
938 occluded_faces.resize (visibility.size ());
939 std::vector<pcl::Vertices> visible_faces;
940 visible_faces.resize (visibility.size ());
942 int cpt_occluded_faces = 0;
943 int cpt_visible_faces = 0;
945 for (
size_t idx_face = 0 ; idx_face < visibility.size () ; ++idx_face)
947 if (visibility[idx_face])
950 mesh.tex_coordinates[current_cam][cpt_visible_faces * 3](0) = projections->points[idx_face*3].x;
951 mesh.tex_coordinates[current_cam][cpt_visible_faces * 3](1) = projections->points[idx_face*3].y;
953 mesh.tex_coordinates[current_cam][cpt_visible_faces * 3 + 1](0) = projections->points[idx_face*3 + 1].x;
954 mesh.tex_coordinates[current_cam][cpt_visible_faces * 3 + 1](1) = projections->points[idx_face*3 + 1].y;
956 mesh.tex_coordinates[current_cam][cpt_visible_faces * 3 + 2](0) = projections->points[idx_face*3 + 2].x;
957 mesh.tex_coordinates[current_cam][cpt_visible_faces * 3 + 2](1) = projections->points[idx_face*3 + 2].y;
959 visible_faces[cpt_visible_faces] = mesh.tex_polygons[current_cam][idx_face];
966 occluded_faces[cpt_occluded_faces] = mesh.tex_polygons[current_cam][idx_face];
967 cpt_occluded_faces++;
970 mesh.tex_coordinates[current_cam].resize (cpt_visible_faces*3);
972 occluded_faces.resize (cpt_occluded_faces);
973 mesh.tex_polygons.push_back (occluded_faces);
975 visible_faces.resize (cpt_visible_faces);
976 mesh.tex_polygons[current_cam].clear ();
977 mesh.tex_polygons[current_cam] = visible_faces;
980 for (
int i = 0; i < static_cast<int> (mesh.tex_polygons.size ()); i++)
981 nb_faces += static_cast<int> (mesh.tex_polygons[i].size ());
988 if (mesh.tex_coordinates.size() <= cameras.size ())
990 #if PCL_VERSION_COMPARE(>=, 1, 8, 0) 991 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > dummy_container;
993 std::vector<Eigen::Vector2f> dummy_container;
995 mesh.tex_coordinates.push_back(dummy_container);
999 for(
size_t idx_face = 0 ; idx_face < mesh.tex_polygons[cameras.size()].size() ; ++idx_face)
1001 Eigen::Vector2f UV1, UV2, UV3;
1002 UV1(0) = -1.0; UV1(1) = -1.0;
1003 UV2(0) = -1.0; UV2(1) = -1.0;
1004 UV3(0) = -1.0; UV3(1) = -1.0;
1005 mesh.tex_coordinates[cameras.size()].push_back(UV1);
1006 mesh.tex_coordinates[cameras.size()].push_back(UV2);
1007 mesh.tex_coordinates[cameras.size()].push_back(UV3);
1019 const pcl::PointXY & uv1,
1020 const pcl::PointXY & uv2,
1021 const pcl::PointXY & uv3,
1022 const pcl::PointXY & center) :
1042 bool ptInTriangle(
const pcl::PointXY & p0,
const pcl::PointXY & p1,
const pcl::PointXY & p2,
const pcl::PointXY & p) {
1043 float A = 1/2 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
1044 float sign = A < 0 ? -1 : 1;
1045 float s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign;
1046 float t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign;
1048 return s > 0 && t > 0 && (s + t) < 2 * A * sign;
1052 template<
typename Po
intInT>
bool 1054 pcl::TextureMesh &mesh,
1057 std::vector<std::map<int, pcl::PointXY> > * vertexToPixels)
1060 if (mesh.tex_polygons.size () != 1)
1063 typename pcl::PointCloud<PointInT>::Ptr mesh_cloud (
new pcl::PointCloud<PointInT>);
1065 pcl::fromPCLPointCloud2 (mesh.cloud, *mesh_cloud);
1067 std::vector<pcl::Vertices> faces;
1068 faces.swap(mesh.tex_polygons[0]);
1070 mesh.tex_polygons.clear();
1071 mesh.tex_polygons.resize(cameras.size()+1);
1072 mesh.tex_coordinates.clear();
1073 mesh.tex_coordinates.resize(cameras.size()+1);
1076 std::vector<std::map<int, FaceInfo > > visibleFaces(cameras.size());
1077 std::vector<Eigen::Affine3f> invCamTransform(cameras.size());
1078 std::vector<std::list<int> > faceCameras(faces.size());
1079 UINFO(
"Precompute visible faces per cam (%d faces, %d cams)", (
int)faces.size(), (int)cameras.size());
1080 for (
unsigned int current_cam = 0; current_cam < cameras.size(); ++current_cam)
1082 UDEBUG(
"Texture camera %d...", current_cam);
1084 typename pcl::PointCloud<PointInT>::Ptr camera_cloud (
new pcl::PointCloud<PointInT>);
1087 std::vector<int> visibilityIndices;
1088 visibilityIndices.resize (faces.size ());
1089 pcl::PointCloud<pcl::PointXY>::Ptr projections (
new pcl::PointCloud<pcl::PointXY>);
1090 projections->resize(faces.size()*3);
1091 std::map<float, int> sortedVisibleFaces;
1093 for(
unsigned int idx_face=0; idx_face<faces.size(); ++idx_face)
1095 pcl::Vertices & face = faces[idx_face];
1098 pcl::PointXY & uv_coords1 = projections->at(j);
1099 pcl::PointXY & uv_coords2 = projections->at(j+1);
1100 pcl::PointXY & uv_coords3 = projections->at(j+2);
1101 PointInT & pt0 = camera_cloud->points[face.vertices[0]];
1102 PointInT & pt1 = camera_cloud->points[face.vertices[1]];
1103 PointInT & pt2 = camera_cloud->points[face.vertices[2]];
1104 if (isFaceProjected (cameras[current_cam],
1114 uv_coords2.x - uv_coords1.x,
1115 uv_coords2.y - uv_coords1.y,
1118 uv_coords3.x - uv_coords1.x,
1119 uv_coords3.y - uv_coords1.y,
1121 Eigen::Vector3f normal = v0.cross(v1);
1122 float angle = normal.dot(Eigen::Vector3f(0.0
f,0.0
f,1.0
f));
1125 float angleToCam = 0.0f;
1126 Eigen::Vector3f e0 = Eigen::Vector3f(
1130 Eigen::Vector3f e1 = Eigen::Vector3f(
1134 Eigen::Vector3f e2 = Eigen::Vector3f(
1138 if(facingTheCam && this->max_angle_)
1140 Eigen::Vector3f normal3D;
1141 normal3D = e0.cross(e1);
1142 angleToCam = pcl::getAngle3D(Eigen::Vector4f(normal3D[0], normal3D[1], normal3D[2], 0.0
f), Eigen::Vector4f(0.0
f,0.0
f,-1.0
f,0.0
f));
1146 float e0norm2 = e0[0]*e0[0] + e0[1]*e0[1] + e0[2]*e0[2];
1147 float e1norm2 = e1[0]*e1[0] + e1[1]*e1[1] + e1[2]*e1[2];
1148 float e2norm2 = e2[0]*e2[0] + e2[1]*e2[1] + e2[2]*e2[2];
1151 pcl::PointXY center;
1152 center.x = (uv_coords1.x+uv_coords2.x+uv_coords3.x)/3.0
f;
1153 center.y = (uv_coords1.y+uv_coords2.y+uv_coords3.y)/3.0
f;
1154 visibleFaces[current_cam].insert(visibleFaces[current_cam].end(), std::make_pair(idx_face,
FaceInfo(distanceToCam, angleToCam, longestEdgeSqrd, facingTheCam, uv_coords1, uv_coords2, uv_coords3, center)));
1155 sortedVisibleFaces.insert(std::make_pair(distanceToCam, idx_face));
1156 visibilityIndices[oi] = idx_face;
1160 visibilityIndices.resize(oi);
1161 projections->resize(oi*3);
1162 UASSERT(projections->size() == visibilityIndices.size()*3);
1166 pcl::KdTreeFLANN<pcl::PointXY> kdtree;
1167 kdtree.setInputCloud (projections);
1169 std::vector<int> idxNeighbors;
1170 std::vector<float> neighborsSquaredDistance;
1174 std::set<int> occludedFaces;
1175 for (std::map<float, int>::iterator jter=sortedVisibleFaces.begin(); jter!=sortedVisibleFaces.end(); ++jter)
1178 int idx_face = jter->second;
1180 std::map<int, FaceInfo>::iterator iter= visibleFaces[current_cam].find(idx_face);
1181 UASSERT(iter != visibleFaces[current_cam].end());
1188 pcl::PointXY center;
1193 if (kdtree.radiusSearch (center, radius, idxNeighbors, neighborsSquaredDistance) > 0 )
1196 for (
size_t i = 0; i < idxNeighbors.size (); ++i)
1198 int neighborFaceIndex = idxNeighbors[i]/3;
1202 if (
std::max(camera_cloud->points[faces[idx_face].vertices[0]].z,
1203 std::max (camera_cloud->points[faces[idx_face].vertices[1]].z,
1204 camera_cloud->points[faces[idx_face].vertices[2]].z))
1205 < camera_cloud->points[faces[visibilityIndices[neighborFaceIndex]].vertices[idxNeighbors[i]%3]].z)
1212 occludedFaces.insert(visibilityIndices[neighborFaceIndex]);
1222 for(std::set<int>::iterator iter= occludedFaces.begin(); iter!=occludedFaces.end(); ++iter)
1224 visibleFaces[current_cam].erase(*iter);
1228 int clusterFaces = 0;
1230 std::vector<pcl::Vertices> polygons(visibleFaces[current_cam].size());
1231 std::vector<int> polygon_to_face_index(visibleFaces[current_cam].size());
1233 for(std::map<int, FaceInfo>::iterator iter=visibleFaces[current_cam].begin(); iter!=visibleFaces[current_cam].end(); ++iter)
1235 polygons[oi].vertices.resize(3);
1236 polygons[oi].vertices[0] = faces[iter->first].vertices[0];
1237 polygons[oi].vertices[1] = faces[iter->first].vertices[1];
1238 polygons[oi].vertices[2] = faces[iter->first].vertices[2];
1239 polygon_to_face_index[oi] = iter->first;
1243 std::vector<std::set<int> > neighbors;
1244 std::vector<std::set<int> > vertexToPolygons;
1246 (
int)camera_cloud->size(),
1252 std::set<int> polygonsKept;
1253 for(std::list<std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
1255 for(std::list<int>::iterator jter=iter->begin(); jter!=iter->end(); ++jter)
1257 polygonsKept.insert(polygon_to_face_index[*jter]);
1258 faceCameras[polygon_to_face_index[*jter]].push_back(current_cam);
1262 for(std::map<int, FaceInfo>::iterator iter=visibleFaces[current_cam].begin(); iter!=visibleFaces[current_cam].end();)
1264 if(polygonsKept.find(iter->first) == polygonsKept.end())
1266 visibleFaces[current_cam].erase(iter++);
1275 std::string msg =
uFormat(
"Processed camera %d/%d: %d occluded and %d spurious polygons out of %d", (
int)current_cam+1, (
int)cameras.size(), (int)occludedFaces.size(), clusterFaces, (int)visibilityIndices.size());
1280 UWARN(
"Texturing cancelled!");
1285 std::string msg =
uFormat(
"Texturing %d polygons...", (
int)faces.size());
1290 UWARN(
"Texturing cancelled!");
1296 *vertexToPixels = std::vector<std::map<int, pcl::PointXY> >(mesh_cloud->size());
1298 for(
unsigned int idx_face=0; idx_face<faces.size(); ++idx_face)
1300 if((idx_face+1)%10000 == 0)
1302 UDEBUG(
"face %d/%d", idx_face+1, (
int)faces.size());
1303 if(state && !state->
callback(
uFormat(
"Textured %d/%d of %d polygons", textured, idx_face+1, (
int)faces.size())))
1306 UWARN(
"Texturing cancelled!");
1310 pcl::Vertices & face = faces[idx_face];
1312 int cameraIndex = -1;
1314 bool depthSet =
false;
1315 pcl::PointXY uv_coords[3];
1316 for (std::list<int>::iterator camIter = faceCameras[idx_face].begin(); camIter!=faceCameras[idx_face].end(); ++camIter)
1318 int current_cam = *camIter;
1319 std::map<int, FaceInfo>::iterator iter = visibleFaces[current_cam].find(idx_face);
1320 UASSERT(iter != visibleFaces[current_cam].end());
1321 if (iter->second.facingTheCam && (max_angle_ <=0.0f || iter->second.angle <= max_angle_))
1323 float distanceToCam = iter->second.distance;
1324 float vx = (iter->second.uv_coord1.x+iter->second.uv_coord2.x+ iter->second.uv_coord3.x)/3.0
f-0.5
f;
1325 float vy = (iter->second.uv_coord1.y+iter->second.uv_coord2.y+ iter->second.uv_coord3.y)/3.0
f-0.5
f;
1326 float distanceToCenter = vx*vx+vy*vy;
1328 cv::Mat depth = cameras[current_cam].depth;
1329 bool currentDepthSet =
false;
1330 float maxDepthError = max_depth_error_==0.0f?
std::sqrt(iter->second.longestEdgeSqrd)*2.0f : max_depth_error_;
1331 if(!cameras[current_cam].depth.empty() && maxDepthError > 0.0f)
1333 float d1 = depth.type() == CV_32FC1?
1334 depth.at<
float>((1.0f-iter->second.uv_coord1.y)*depth.rows, iter->second.uv_coord1.x*depth.cols):
1335 float(depth.at<
unsigned short>((1.0f-iter->second.uv_coord1.y)*depth.rows, iter->second.uv_coord1.x*depth.cols))/1000.0f;
1336 float d2 = depth.type() == CV_32FC1?
1337 depth.at<
float>((1.0f-iter->second.uv_coord2.y)*depth.rows, iter->second.uv_coord2.x*depth.cols):
1338 float(depth.at<
unsigned short>((1.0f-iter->second.uv_coord2.y)*depth.rows, iter->second.uv_coord2.x*depth.cols))/1000.0f;
1339 float d3 = depth.type() == CV_32FC1?
1340 depth.at<
float>((1.0f-iter->second.uv_coord3.y)*depth.rows, iter->second.uv_coord3.x*depth.cols):
1341 float(depth.at<
unsigned short>((1.0f-iter->second.uv_coord3.y)*depth.rows, iter->second.uv_coord3.x*depth.cols))/1000.0f;
1349 else if(d1 > 0.0
f &&
std::isfinite(d1) && fabs(d1 - distanceToCam) > maxDepthError)
1354 else if(d2 > 0.0
f &&
std::isfinite(d2) && fabs(d2 - distanceToCam) > maxDepthError)
1359 else if(d3 > 0.0
f &&
std::isfinite(d3) && fabs(d3 - distanceToCam) > maxDepthError)
1368 if(fabs(d1 - distanceToCam) > maxDepthError ||
1369 fabs(d2 - distanceToCam) > maxDepthError ||
1370 fabs(d3 - distanceToCam) > maxDepthError)
1375 currentDepthSet =
true;
1381 vertexToPixels->at(face.vertices[0]).insert(std::make_pair(current_cam, iter->second.uv_coord1));
1382 vertexToPixels->at(face.vertices[1]).insert(std::make_pair(current_cam, iter->second.uv_coord2));
1383 vertexToPixels->at(face.vertices[2]).insert(std::make_pair(current_cam, iter->second.uv_coord3));
1388 if(distanceToCenter <= smallestWeight || (!depthSet && currentDepthSet))
1390 cameraIndex = current_cam;
1391 smallestWeight = distanceToCenter;
1392 uv_coords[0] = iter->second.uv_coord1;
1393 uv_coords[1] = iter->second.uv_coord2;
1394 uv_coords[2] = iter->second.uv_coord3;
1395 if(!depthSet && currentDepthSet)
1403 if(cameraIndex >= 0)
1406 mesh.tex_polygons[cameraIndex].push_back(face);
1407 mesh.tex_coordinates[cameraIndex].push_back(Eigen::Vector2f(uv_coords[0].x, uv_coords[0].y));
1408 mesh.tex_coordinates[cameraIndex].push_back(Eigen::Vector2f(uv_coords[1].x, uv_coords[1].y));
1409 mesh.tex_coordinates[cameraIndex].push_back(Eigen::Vector2f(uv_coords[2].x, uv_coords[2].y));
1413 mesh.tex_polygons[cameras.size()].push_back(face);
1414 mesh.tex_coordinates[cameras.size()].push_back(Eigen::Vector2f(-1.0,-1.0));
1415 mesh.tex_coordinates[cameras.size()].push_back(Eigen::Vector2f(-1.0,-1.0));
1416 mesh.tex_coordinates[cameras.size()].push_back(Eigen::Vector2f(-1.0,-1.0));
1419 UINFO(
"Process %d polygons...done! (%d textured)", (
int)faces.size(), textured);
1425 template<
typename Po
intInT>
inline void 1429 pcl::PointXY ptB, ptC;
1430 ptB.x = p2.x - p1.x; ptB.y = p2.y - p1.y;
1431 ptC.x = p3.x - p1.x; ptC.y = p3.y - p1.y;
1433 double D = 2.0*(ptB.x*ptC.y - ptB.y*ptC.x);
1438 circomcenter.x = p1.x;
1439 circomcenter.y = p1.y;
1444 double bx2 = ptB.x * ptB.x;
1445 double by2 = ptB.y * ptB.y;
1446 double cx2 = ptC.x * ptC.x;
1447 double cy2 = ptC.y * ptC.y;
1450 circomcenter.x =
static_cast<float> (p1.x + (ptC.y*(bx2 + by2) - ptB.y*(cx2 + cy2)) / D);
1451 circomcenter.y =
static_cast<float> (p1.y + (ptB.x*(cx2 + cy2) - ptC.x*(bx2 + by2)) / D);
1454 radius =
sqrt( (circomcenter.x - p1.x)*(circomcenter.x - p1.x) + (circomcenter.y - p1.y)*(circomcenter.y - p1.y));
1458 template<
typename Po
intInT>
inline void 1462 circumcenter.x =
static_cast<float> (p1.x + p2.x + p3.x ) / 3;
1463 circumcenter.y =
static_cast<float> (p1.y + p2.y + p3.y ) / 3;
1464 double r1 = (circumcenter.x - p1.x) * (circumcenter.x - p1.x) + (circumcenter.y - p1.y) * (circumcenter.y - p1.y) ;
1465 double r2 = (circumcenter.x - p2.x) * (circumcenter.x - p2.x) + (circumcenter.y - p2.y) * (circumcenter.y - p2.y) ;
1466 double r3 = (circumcenter.x - p3.x) * (circumcenter.x - p3.x) + (circumcenter.y - p3.y) * (circumcenter.y - p3.y) ;
1474 template<
typename Po
intInT>
inline bool 1477 if (pt.z > 0 && (max_distance_<=0.0f || pt.z<max_distance_))
1480 double sizeX = cam.
width;
1481 double sizeY = cam.
height;
1492 double focal_x, focal_y;
1503 UV_coordinates.x =
static_cast<float> ((focal_x * (pt.x / pt.z) + cx) / sizeX);
1504 UV_coordinates.y =
static_cast<float> ((focal_y * (pt.y / pt.z) + cy) / sizeY);
1506 if(cam.
roi.size() == 4)
1508 if( UV_coordinates.x < cam.
roi[0]/sizeX ||
1509 UV_coordinates.y < cam.
roi[1]/sizeY ||
1510 UV_coordinates.x > (cam.
roi[0]+cam.
roi[2])/sizeX ||
1511 UV_coordinates.y > (cam.
roi[1]+cam.
roi[3])/sizeY)
1514 UV_coordinates.x = -1.0f;
1515 UV_coordinates.y = -1.0f;
1521 if (UV_coordinates.x >= 0.0 && UV_coordinates.x <= 1.0 && UV_coordinates.y >= 0.0 && UV_coordinates.y <= 1.0)
1525 UV_coordinates.y = 1.0f - UV_coordinates.y;
1531 UV_coordinates.x = -1.0f;
1532 UV_coordinates.y = -1.0f;
1537 template<
typename Po
intInT>
inline bool 1541 Eigen::Vector2d v0, v1, v2;
1542 v0(0) = p3.x - p1.x; v0(1) = p3.y - p1.y;
1543 v1(0) = p2.x - p1.x; v1(1) = p2.y - p1.y;
1544 v2(0) = pt.x - p1.x; v2(1) = pt.y - p1.y;
1547 double dot00 = v0.dot(v0);
1548 double dot01 = v0.dot(v1);
1549 double dot02 = v0.dot(v2);
1550 double dot11 = v1.dot(v1);
1551 double dot12 = v1.dot(v2);
1554 double invDenom = 1.0 / (dot00*dot11 - dot01*dot01);
1555 double u = (dot11*dot02 - dot01*dot12) * invDenom;
1556 double v = (dot00*dot12 - dot01*dot02) * invDenom;
1559 return ((u >= 0) && (v >= 0) && (u + v < 1));
1563 template<
typename Po
intInT>
inline bool 1566 return getPointUVCoordinates(p1, camera, proj1)
1568 getPointUVCoordinates(p2, camera, proj2)
1570 getPointUVCoordinates(p3, camera, proj3);
1573 #define PCL_INSTANTIATE_TextureMapping(T) \ 1574 template class PCL_EXPORTS pcl::TextureMapping<T>;
rtabmap::CameraThread * cam
int sortFacesByCamera(pcl::TextureMesh &tex_mesh, pcl::TextureMesh &sorted_mesh, const pcl::texture_mapping::CameraVector &cameras, const double octree_voxel_size, PointCloud &visible_pts)
Segment faces by camera visibility. Point-based segmentation.
bool isFaceProjected(const Camera &camera, const PointInT &p1, const PointInT &p2, const PointInT &p3, pcl::PointXY &proj1, pcl::PointXY &proj2, pcl::PointXY &proj3)
Returns true if all the vertices of one face are projected on the camera's image plane.
GLM_FUNC_DECL bool isfinite(genType const &x)
Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility)...
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP transformPointCloud(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const Transform &transform)
bool textureMeshwithMultipleCameras2(pcl::TextureMesh &mesh, const pcl::texture_mapping::CameraVector &cameras, const rtabmap::ProgressState *callback=0, std::vector< std::map< int, pcl::PointXY > > *vertexToPixels=0)
std::vector< Camera, Eigen::aligned_allocator< Camera > > CameraVector
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
const float maxDepthError
bool isPointOccluded(const PointInT &pt, const OctreePtr octree)
Check if a point is occluded using raycasting on octree.
bool checkPointInsideTriangle(const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, const pcl::PointXY &pt)
Returns True if a point lays within a triangle.
FaceInfo(float d, float a, float edge, bool facingCam, const pcl::PointXY &uv1, const pcl::PointXY &uv2, const pcl::PointXY &uv3, const pcl::PointXY ¢er)
void getTriangleCircumcscribedCircleCentroid(const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, pcl::PointXY &circumcenter, double &radius)
Returns the centroid of a triangle and the corresponding circumscribed circle's radius.
pcl::octree::OctreePointCloudSearch< PointInT > Octree
GLM_FUNC_DECL genType sign(genType const &x)
std::vector< double > roi
#define UASSERT(condition)
GLM_FUNC_DECL genType cos(genType const &angle)
bool ptInTriangle(const pcl::PointXY &p0, const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p)
Structure that links a uv coordinate to its 3D point and face.
Structure to store camera pose and focal length.
virtual bool callback(const std::string &msg) const
GLM_FUNC_DECL genType sin(genType const &angle)
std::list< std::list< int > > RTABMAP_EXP clusterPolygons(const std::vector< std::set< int > > &neighborPolygons, int minClusterSize=0)
pcl::PointCloud< PointInT > PointCloud
void mapTexture2MeshUV(pcl::TextureMesh &tex_mesh)
Map texture to a mesh UV mapping.
PointCloud::Ptr PointCloudPtr
void textureMeshwithMultipleCameras(pcl::TextureMesh &mesh, const pcl::texture_mapping::CameraVector &cameras)
Segment and texture faces by camera visibility. Face-based segmentation.
void mapMultipleTexturesToMeshUV(pcl::TextureMesh &tex_mesh, pcl::texture_mapping::CameraVector &cams)
Map textures acquired from a set of cameras onto a mesh.
void mapTexture2Mesh(pcl::TextureMesh &tex_mesh)
Map texture to a mesh synthesis algorithm.
std::vector< Eigen::Vector2f, Eigen::aligned_allocator< Eigen::Vector2f > > mapTexture2Face(const Eigen::Vector3f &p1, const Eigen::Vector3f &p2, const Eigen::Vector3f &p3)
Map texture to a face.
RecoveryProgressState state
void showOcclusions(const PointCloudPtr &input_cloud, pcl::PointCloud< pcl::PointXYZI >::Ptr &colored_cloud, const double octree_voxel_size, const bool show_nb_occlusions=true, const int max_occlusions=4)
Colors a point cloud, depending on its occlusions.
void getTriangleCircumcenterAndSize(const pcl::PointXY &p1, const pcl::PointXY &p2, const pcl::PointXY &p3, pcl::PointXY &circumcenter, double &radius)
Returns the circumcenter of a triangle and the circle's radius.
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
void removeOccludedPoints(const PointCloudPtr &input_cloud, PointCloudPtr &filtered_cloud, const double octree_voxel_size, std::vector< int > &visible_indices, std::vector< int > &occluded_indices)
Remove occluded points from a point cloud.
void RTABMAP_EXP createPolygonIndexes(const std::vector< pcl::Vertices > &polygons, int cloudSize, std::vector< std::set< int > > &neighborPolygons, std::vector< std::set< int > > &vertexPolygons)
Given a set of polygons, create two indexes: polygons to neighbor polygons and vertices to polygons...
GLM_FUNC_DECL genType acos(genType const &x)
bool getPointUVCoordinates(const PointInT &pt, const Camera &cam, Eigen::Vector2f &UV_coordinates)
computes UV coordinates of point, observed by one particular camera
PointCloud::ConstPtr PointCloudConstPtr
std::string UTILITE_EXP uFormat(const char *fmt,...)