40 #include <opencv2/core/core_c.h> 41 #include <opencv2/imgproc/types_c.h> 42 #include <pcl/search/kdtree.h> 43 #include <pcl/surface/gp3.h> 44 #include <pcl/features/normal_3d_omp.h> 45 #include <pcl/surface/mls.h> 47 #include <pcl/features/integral_image_normal.h> 50 #include <pcl/surface/vtk_smoothing/vtk_mesh_quadric_decimation.h> 53 #if PCL_VERSION_COMPARE(<, 1, 8, 0) 56 #include <pcl/surface/organized_fast_mesh.h> 57 #include <pcl/surface/impl/marching_cubes.hpp> 58 #include <pcl/surface/impl/organized_fast_mesh.hpp> 59 #include <pcl/impl/instantiate.hpp> 60 #include <pcl/point_types.h> 63 PCL_INSTANTIATE(OrganizedFastMesh, (pcl::PointXYZRGBNormal))
65 #include <pcl/features/impl/normal_3d_omp.hpp> 66 #if PCL_VERSION_COMPARE(<=, 1, 8, 0) 67 #ifdef PCL_ONLY_CORE_POINT_TYPES 68 PCL_INSTANTIATE_PRODUCT(NormalEstimationOMP, ((pcl::PointXYZRGB))((pcl::Normal)))
80 const std::vector<pcl::Vertices> & polygons,
82 std::vector<std::set<int> > & neighbors,
83 std::vector<std::set<int> > & vertexToPolygons)
85 vertexToPolygons = std::vector<std::set<int> >(cloudSize);
86 neighbors = std::vector<std::set<int> >(polygons.size());
88 for(
unsigned int i=0; i<polygons.size(); ++i)
90 std::set<int>
vertices(polygons[i].
vertices.begin(), polygons[i].vertices.end());
92 for(
unsigned int j=0; j<polygons[i].vertices.size(); ++j)
94 int v = polygons[i].vertices.at(j);
95 for(std::set<int>::iterator iter=vertexToPolygons[v].begin(); iter!=vertexToPolygons[v].end(); ++iter)
97 int numSharedVertices = 0;
98 for(
unsigned int k=0; k<polygons.at(*iter).vertices.size() && numSharedVertices<2; ++k)
105 if(numSharedVertices >= 2)
107 neighbors[*iter].insert(i);
108 neighbors[i].insert(*iter);
111 vertexToPolygons[v].insert(i);
117 const std::vector<std::set<int> > & neighborPolygons,
120 std::set<int> polygonsChecked;
122 std::list<std::list<int> > clusters;
124 for(
unsigned int i=0; i<neighborPolygons.size(); ++i)
126 if(polygonsChecked.find(i) == polygonsChecked.end())
128 std::list<int> currentCluster;
129 currentCluster.push_back(i);
130 polygonsChecked.insert(i);
132 for(std::list<int>::iterator iter=currentCluster.begin(); iter!=currentCluster.end(); ++iter)
135 std::set<int> neighbors = neighborPolygons[*iter];
136 for(std::set<int>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
138 if(polygonsChecked.insert(*jter).second)
140 currentCluster.push_back(*jter);
144 if((
int)currentCluster.size() > minClusterSize)
146 clusters.push_back(currentCluster);
154 const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
155 double angleTolerance,
157 int trianglePixelSize,
158 const Eigen::Vector3f & viewpoint)
160 UDEBUG(
"size=%d angle=%f quad=%d triangleSize=%d", (
int)cloud->size(), angleTolerance, quad?1:0, trianglePixelSize);
161 UASSERT(cloud->is_dense ==
false);
162 UASSERT(cloud->width > 1 && cloud->height > 1);
167 ofm.setInputCloud (cloud);
171 std::vector<pcl::Vertices>
vertices;
172 ofm.reconstruct (vertices);
177 std::vector<pcl::Vertices> output(vertices.size());
178 for(
unsigned int i=0; i<vertices.size(); ++i)
180 output[i].vertices.resize(4);
181 output[i].vertices[0] = vertices[i].vertices[0];
182 output[i].vertices[3] = vertices[i].vertices[1];
183 output[i].vertices[2] = vertices[i].vertices[2];
184 output[i].vertices[1] = vertices[i].vertices[3];
192 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
193 double angleTolerance,
195 int trianglePixelSize,
196 const Eigen::Vector3f & viewpoint)
198 UDEBUG(
"size=%d angle=%f quad=%d triangleSize=%d", (
int)cloud->size(), angleTolerance, quad?1:0, trianglePixelSize);
199 UASSERT(cloud->is_dense ==
false);
200 UASSERT(cloud->width > 1 && cloud->height > 1);
205 ofm.setInputCloud (cloud);
209 std::vector<pcl::Vertices>
vertices;
210 ofm.reconstruct (vertices);
215 std::vector<pcl::Vertices> output(vertices.size());
216 for(
unsigned int i=0; i<vertices.size(); ++i)
218 output[i].vertices.resize(4);
219 output[i].vertices[0] = vertices[i].vertices[0];
220 output[i].vertices[3] = vertices[i].vertices[1];
221 output[i].vertices[2] = vertices[i].vertices[2];
222 output[i].vertices[1] = vertices[i].vertices[3];
230 const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
231 double angleTolerance,
233 int trianglePixelSize,
234 const Eigen::Vector3f & viewpoint)
236 UDEBUG(
"size=%d angle=%f quad=%d triangleSize=%d", (
int)cloud->size(), angleTolerance, quad?1:0, trianglePixelSize);
237 UASSERT(cloud->is_dense ==
false);
238 UASSERT(cloud->width > 1 && cloud->height > 1);
243 ofm.setInputCloud (cloud);
247 std::vector<pcl::Vertices>
vertices;
248 ofm.reconstruct (vertices);
253 std::vector<pcl::Vertices> output(vertices.size());
254 for(
unsigned int i=0; i<vertices.size(); ++i)
256 output[i].vertices.resize(4);
257 output[i].vertices[0] = vertices[i].vertices[0];
258 output[i].vertices[3] = vertices[i].vertices[1];
259 output[i].vertices[2] = vertices[i].vertices[2];
260 output[i].vertices[1] = vertices[i].vertices[3];
269 pcl::PointCloud<pcl::PointXYZRGBNormal> & cloudA,
270 std::vector<pcl::Vertices> & polygonsA,
271 const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloudB,
272 const std::vector<pcl::Vertices> & polygonsB)
274 UDEBUG(
"cloudA=%d polygonsA=%d cloudB=%d polygonsB=%d", (
int)cloudA.size(), (int)polygonsA.size(), (int)cloudB.size(), (int)polygonsB.size());
275 UASSERT(!cloudA.isOrganized() && !cloudB.isOrganized());
277 int sizeA = (int)cloudA.size();
280 int sizePolygonsA = (int)polygonsA.size();
281 polygonsA.resize(sizePolygonsA+polygonsB.size());
283 for(
unsigned int i=0; i<polygonsB.size(); ++i)
285 pcl::Vertices
vertices = polygonsB[i];
286 for(
unsigned int j=0; j<vertices.vertices.size(); ++j)
288 vertices.vertices[j] += sizeA;
290 polygonsA[i+sizePolygonsA] =
vertices;
295 pcl::PointCloud<pcl::PointXYZRGB> & cloudA,
296 std::vector<pcl::Vertices> & polygonsA,
297 const pcl::PointCloud<pcl::PointXYZRGB> & cloudB,
298 const std::vector<pcl::Vertices> & polygonsB)
300 UDEBUG(
"cloudA=%d polygonsA=%d cloudB=%d polygonsB=%d", (
int)cloudA.size(), (int)polygonsA.size(), (int)cloudB.size(), (int)polygonsB.size());
301 UASSERT(!cloudA.isOrganized() && !cloudB.isOrganized());
303 int sizeA = (int)cloudA.size();
306 int sizePolygonsA = (int)polygonsA.size();
307 polygonsA.resize(sizePolygonsA+polygonsB.size());
309 for(
unsigned int i=0; i<polygonsB.size(); ++i)
311 pcl::Vertices
vertices = polygonsB[i];
312 for(
unsigned int j=0; j<vertices.vertices.size(); ++j)
314 vertices.vertices[j] += sizeA;
316 polygonsA[i+sizePolygonsA] =
vertices;
321 const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud,
322 const std::vector<pcl::Vertices> & polygons,
323 pcl::PointCloud<pcl::PointXYZRGBNormal> & outputCloud,
324 std::vector<pcl::Vertices> & outputPolygons)
326 UDEBUG(
"size=%d polygons=%d", (
int)cloud.size(), (int)polygons.size());
327 std::map<int, int> addedVertices;
328 std::vector<int> output;
329 output.resize(cloud.size());
330 outputCloud.resize(cloud.size());
331 outputCloud.is_dense =
true;
332 outputPolygons.resize(polygons.size());
334 for(
unsigned int i=0; i<polygons.size(); ++i)
336 pcl::Vertices & v = outputPolygons[i];
337 v.vertices.resize(polygons[i].
vertices.size());
338 for(
unsigned int j=0; j<polygons[i].vertices.size(); ++j)
340 std::map<int, int>::iterator iter = addedVertices.find(polygons[i].
vertices[j]);
341 if(iter == addedVertices.end())
343 outputCloud[oi] = cloud.at(polygons[i].
vertices[j]);
344 addedVertices.insert(std::make_pair(polygons[i].
vertices[j], oi));
345 output[oi] = polygons[i].vertices[j];
346 v.vertices[j] = oi++;
350 v.vertices[j] = iter->second;
354 outputCloud.resize(oi);
361 const pcl::PointCloud<pcl::PointXYZRGB> & cloud,
362 const std::vector<pcl::Vertices> & polygons,
363 pcl::PointCloud<pcl::PointXYZRGB> & outputCloud,
364 std::vector<pcl::Vertices> & outputPolygons)
366 UDEBUG(
"size=%d polygons=%d", (
int)cloud.size(), (int)polygons.size());
367 std::map<int, int> addedVertices;
368 std::vector<int> output;
369 output.resize(cloud.size());
370 outputCloud.resize(cloud.size());
371 outputCloud.is_dense =
true;
372 outputPolygons.resize(polygons.size());
374 for(
unsigned int i=0; i<polygons.size(); ++i)
376 pcl::Vertices & v = outputPolygons[i];
377 v.vertices.resize(polygons[i].
vertices.size());
378 for(
unsigned int j=0; j<polygons[i].vertices.size(); ++j)
380 std::map<int, int>::iterator iter = addedVertices.find(polygons[i].
vertices[j]);
381 if(iter == addedVertices.end())
383 outputCloud[oi] = cloud.at(polygons[i].
vertices[j]);
384 addedVertices.insert(std::make_pair(polygons[i].
vertices[j], oi));
385 output[oi] = polygons[i].vertices[j];
386 v.vertices[j] = oi++;
390 v.vertices[j] = iter->second;
394 outputCloud.resize(oi);
401 const pcl::PointCloud<pcl::PointXYZRGB> & cloud,
402 const std::vector<pcl::Vertices> & polygons,
403 pcl::PointCloud<pcl::PointXYZRGB> & outputCloud,
404 std::vector<pcl::Vertices> & outputPolygons)
406 UDEBUG(
"size=%d polygons=%d", (
int)cloud.size(), (int)polygons.size());
407 std::map<int, int> addedVertices;
408 std::vector<int> output;
409 output.resize(cloud.size());
410 outputCloud.resize(cloud.size());
411 outputCloud.is_dense =
true;
412 std::vector<int> organizedToDense(cloud.size(), -1);
415 for(
unsigned int i=0; i<cloud.size(); ++i)
419 outputCloud.at(oi) = cloud.at(i);
421 organizedToDense[i] = oi;
425 outputCloud.resize(oi);
429 outputPolygons = polygons;
430 for(
unsigned int i=0; i<outputPolygons.size(); ++i)
432 pcl::Vertices & v = outputPolygons[i];
433 for(
unsigned int j=0; j<v.vertices.size(); ++j)
435 UASSERT(organizedToDense[v.vertices[j]] >= 0);
436 v.vertices[j] = organizedToDense[v.vertices[j]];
444 const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud,
445 const std::vector<pcl::Vertices> & polygons,
448 bool keepLatestInRadius)
450 UDEBUG(
"size=%d polygons=%d radius=%f angle=%f keepLatest=%d",
451 (
int)cloud->size(), (int)polygons.size(), radius,
angle, keepLatestInRadius?1:0);
452 std::vector<pcl::Vertices> outputPolygons;
453 pcl::KdTreeFLANN<pcl::PointXYZRGBNormal>::Ptr kdtree(
new pcl::KdTreeFLANN<pcl::PointXYZRGBNormal>);
454 kdtree->setInputCloud(cloud);
456 std::map<int, int> verticesDone;
457 outputPolygons = polygons;
458 for(
unsigned int i=0; i<outputPolygons.size(); ++i)
460 pcl::Vertices & polygon = outputPolygons[i];
461 for(
unsigned int j=0; j<polygon.vertices.size(); ++j)
463 std::map<int, int>::iterator iter = verticesDone.find(polygon.vertices[j]);
464 if(iter != verticesDone.end())
466 polygon.vertices[j] = iter->second;
471 std::vector<float> kDistances;
472 kdtree->radiusSearch(polygon.vertices[j], radius, kIndices, kDistances);
476 for(
unsigned int z=0; z<kIndices.size(); ++z)
480 reference = kIndices[z];
482 else if(keepLatestInRadius)
484 if(kIndices[z] < reference)
486 reference = kIndices[z];
491 if(kIndices[z] > reference)
493 reference = kIndices[z];
499 for(
unsigned int z=0; z<kIndices.size(); ++z)
501 verticesDone.insert(std::make_pair(kIndices[j], reference));
503 polygon.vertices[j] = reference;
508 verticesDone.insert(std::make_pair(polygon.vertices[j], polygon.vertices[j]));
513 return outputPolygons;
518 std::vector<pcl::Vertices> output(polygons.size());
520 for(
unsigned int i=0; i<polygons.size(); ++i)
523 for(
unsigned int j=0; j<polygons[i].vertices.size(); ++j)
525 if(polygons[i].
vertices[j] == polygons[i].
vertices[(j+1)%polygons[i].vertices.size()])
533 output[oi++] = polygons[i];
541 const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloudWithNormals,
542 float gp3SearchRadius,
544 int gp3MaximumNearestNeighbors,
545 float gp3MaximumSurfaceAngle,
546 float gp3MinimumAngle,
547 float gp3MaximumAngle,
548 bool gp3NormalConsistency)
553 pcl::search::KdTree<pcl::PointXYZRGBNormal>::Ptr tree2 (
new pcl::search::KdTree<pcl::PointXYZRGBNormal>);
554 tree2->setInputCloud (cloudWithNormalsNoNaN);
557 pcl::GreedyProjectionTriangulation<pcl::PointXYZRGBNormal> gp3;
558 pcl::PolygonMesh::Ptr mesh(
new pcl::PolygonMesh);
561 gp3.setSearchRadius (gp3SearchRadius);
565 gp3.setMaximumNearestNeighbors (gp3MaximumNearestNeighbors);
566 gp3.setMaximumSurfaceAngle(gp3MaximumSurfaceAngle);
567 gp3.setMinimumAngle(gp3MinimumAngle);
568 gp3.setMaximumAngle(gp3MaximumAngle);
569 gp3.setNormalConsistency(gp3NormalConsistency);
570 gp3.setConsistentVertexOrdering(gp3NormalConsistency);
573 gp3.setInputCloud (cloudWithNormalsNoNaN);
574 gp3.setSearchMethod (tree2);
575 gp3.reconstruct (*mesh);
584 const std::map<int, Transform> & poses,
585 const std::map<
int, std::vector<CameraModel> > & cameraModels,
586 const std::map<int, cv::Mat> & cameraDepths,
587 const std::vector<float> & roiRatios)
589 UASSERT_MSG(poses.size() == cameraModels.size(),
uFormat(
"%d vs %d", (
int)poses.size(), (int)cameraModels.size()).c_str());
590 UASSERT(roiRatios.empty() || roiRatios.size() == 4);
592 std::map<int, Transform>::const_iterator poseIter=poses.begin();
593 std::map<int, std::vector<CameraModel> >::const_iterator modelIter=cameraModels.begin();
594 for(; poseIter!=poses.end(); ++poseIter, ++modelIter)
596 UASSERT(poseIter->first == modelIter->first);
598 std::map<int, cv::Mat>::const_iterator depthIter = cameraDepths.find(poseIter->first);
601 for(
unsigned int i=0; i<modelIter->second.size(); ++i)
605 UASSERT(!modelIter->second[i].localTransform().isNull() && !poseIter->second.isNull());
606 Transform t = poseIter->second*modelIter->second[i].localTransform();
608 cam.
pose = t.toEigen3f();
610 if(modelIter->second[i].imageHeight() <=0 || modelIter->second[i].imageWidth() <=0)
612 UERROR(
"Should have camera models with width/height set to create texture cameras!");
616 UASSERT(modelIter->second[i].fx()>0 && modelIter->second[i].imageHeight()>0 && modelIter->second[i].imageWidth()>0);
618 cam.
height=modelIter->second[i].imageHeight();
619 cam.
width=modelIter->second[i].imageWidth();
620 if(modelIter->second.size() == 1)
628 if(!roiRatios.empty())
631 cam.
roi[0] = cam.
width * roiRatios[0];
633 cam.
roi[2] = cam.
width * (1.0 - roiRatios[1]) - cam.
roi[0];
634 cam.
roi[3] = cam.
height * (1.0 - roiRatios[3]) - cam.
roi[1];
637 if(depthIter != cameraDepths.end() && !depthIter->second.empty())
639 UASSERT(depthIter->second.type() == CV_32FC1 || depthIter->second.type() == CV_16UC1);
640 UASSERT(depthIter->second.cols % modelIter->second.size() == 0);
641 int subWidth = depthIter->second.cols/(modelIter->second.size());
642 cam.
depth = cv::Mat(depthIter->second, cv::Range(0, depthIter->second.rows), cv::Range(subWidth*i, subWidth*(i+1)));
648 UDEBUG(
"cam.pose=%s", t.prettyPrint().c_str());
650 cameras.push_back(cam);
657 const pcl::PolygonMesh::Ptr & mesh,
658 const std::map<int, Transform> & poses,
659 const std::map<int, CameraModel> & cameraModels,
660 const std::map<int, cv::Mat> & cameraDepths,
665 const std::vector<float> & roiRatios,
667 std::vector<std::map<int, pcl::PointXY> > * vertexToPixels)
669 std::map<int, std::vector<CameraModel> > cameraSubModels;
670 for(std::map<int, CameraModel>::const_iterator iter=cameraModels.begin(); iter!=cameraModels.end(); ++iter)
672 std::vector<CameraModel> models;
673 models.push_back(iter->second);
674 cameraSubModels.insert(std::make_pair(iter->first, models));
692 const pcl::PolygonMesh::Ptr & mesh,
693 const std::map<int, Transform> & poses,
694 const std::map<
int, std::vector<CameraModel> > & cameraModels,
695 const std::map<int, cv::Mat> & cameraDepths,
700 const std::vector<float> & roiRatios,
702 std::vector<std::map<int, pcl::PointXY> > * vertexToPixels)
704 UASSERT(mesh->polygons.size());
705 pcl::TextureMesh::Ptr textureMesh(
new pcl::TextureMesh);
706 textureMesh->cloud = mesh->cloud;
707 textureMesh->tex_polygons.push_back(mesh->polygons);
722 textureMesh->tex_materials.resize (cameras.size () + 1);
723 for(
unsigned int i = 0 ; i <= cameras.size() ; ++i)
725 pcl::TexMaterial mesh_material;
726 mesh_material.tex_Ka.r = 0.2f;
727 mesh_material.tex_Ka.g = 0.2f;
728 mesh_material.tex_Ka.b = 0.2f;
730 mesh_material.tex_Kd.r = 0.8f;
731 mesh_material.tex_Kd.g = 0.8f;
732 mesh_material.tex_Kd.b = 0.8f;
734 mesh_material.tex_Ks.r = 1.0f;
735 mesh_material.tex_Ks.g = 1.0f;
736 mesh_material.tex_Ks.b = 1.0f;
738 mesh_material.tex_d = 1.0f;
739 mesh_material.tex_Ns = 75.0f;
740 mesh_material.tex_illum = 2;
742 std::stringstream tex_name;
743 tex_name <<
"material_" << i;
744 tex_name >> mesh_material.tex_name;
746 if(i < cameras.size ())
748 mesh_material.tex_file = cameras[i].texture_file;
752 mesh_material.tex_file =
"occluded";
755 textureMesh->tex_materials[i] = mesh_material;
762 if(maxDepthError > 0.0
f)
770 bool hasNormals =
false;
771 bool hasColors =
false;
772 for(
unsigned int i=0; i<textureMesh->cloud.fields.size(); ++i)
774 if(textureMesh->cloud.fields[i].name.compare(
"normal_x") == 0)
778 else if(textureMesh->cloud.fields[i].name.compare(
"rgb") == 0)
788 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud (
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
789 pcl::fromPCLPointCloud2(mesh->cloud, *cloud);
791 for(
unsigned int i=0; i<mesh->polygons.size(); ++i)
793 pcl::Vertices & v = mesh->polygons[i];
796 cloud->at(v.vertices[1]).x - cloud->at(v.vertices[0]).x,
797 cloud->at(v.vertices[1]).y - cloud->at(v.vertices[0]).y,
798 cloud->at(v.vertices[1]).z - cloud->at(v.vertices[0]).z);
799 int last = v.vertices.size()-1;
801 cloud->at(v.vertices[last]).x - cloud->at(v.vertices[0]).x,
802 cloud->at(v.vertices[last]).y - cloud->at(v.vertices[0]).y,
803 cloud->at(v.vertices[last]).z - cloud->at(v.vertices[0]).z);
804 Eigen::Vector3f normal = v0.cross(v1);
807 for(
unsigned int j=0; j<v.vertices.size(); ++j)
809 cloud->at(v.vertices[j]).normal_x = normal[0];
810 cloud->at(v.vertices[j]).normal_y = normal[1];
811 cloud->at(v.vertices[j]).normal_z = normal[2];
814 pcl::toPCLPointCloud2 (*cloud, textureMesh->cloud);
818 pcl::PointCloud<pcl::PointNormal>::Ptr cloud (
new pcl::PointCloud<pcl::PointNormal>);
819 pcl::fromPCLPointCloud2(mesh->cloud, *cloud);
821 for(
unsigned int i=0; i<mesh->polygons.size(); ++i)
823 pcl::Vertices & v = mesh->polygons[i];
826 cloud->at(v.vertices[1]).x - cloud->at(v.vertices[0]).x,
827 cloud->at(v.vertices[1]).y - cloud->at(v.vertices[0]).y,
828 cloud->at(v.vertices[1]).z - cloud->at(v.vertices[0]).z);
829 int last = v.vertices.size()-1;
831 cloud->at(v.vertices[last]).x - cloud->at(v.vertices[0]).x,
832 cloud->at(v.vertices[last]).y - cloud->at(v.vertices[0]).y,
833 cloud->at(v.vertices[last]).z - cloud->at(v.vertices[0]).z);
834 Eigen::Vector3f normal = v0.cross(v1);
837 for(
unsigned int j=0; j<v.vertices.size(); ++j)
839 cloud->at(v.vertices[j]).normal_x = normal[0];
840 cloud->at(v.vertices[j]).normal_y = normal[1];
841 cloud->at(v.vertices[j]).normal_z = normal[2];
844 pcl::toPCLPointCloud2 (*cloud, textureMesh->cloud);
852 pcl::TextureMesh & textureMesh,
855 UDEBUG(
"minClusterSize=%d", minClusterSize);
857 if(textureMesh.tex_coordinates.size())
860 textureMesh.tex_coordinates.pop_back();
861 textureMesh.tex_polygons.pop_back();
862 textureMesh.tex_materials.pop_back();
864 if(minClusterSize!=0)
867 unsigned int totalSize = 0;
868 for(
unsigned int t=0; t<textureMesh.tex_polygons.size(); ++t)
870 totalSize+=textureMesh.tex_polygons[t].size();
872 std::vector<pcl::Vertices> allPolygons(totalSize);
874 for(
unsigned int t=0; t<textureMesh.tex_polygons.size(); ++t)
876 for(
unsigned int i=0; i<textureMesh.tex_polygons[t].size(); ++i)
878 allPolygons[oi++] = textureMesh.tex_polygons[t][i];
883 std::vector<std::set<int> > neighbors;
884 std::vector<std::set<int> > vertexToPolygons;
886 (
int)textureMesh.cloud.data.size()/textureMesh.cloud.point_step,
892 minClusterSize<0?0:minClusterSize);
894 std::set<int> validPolygons;
895 if(minClusterSize < 0)
898 std::list<std::list<int> >::iterator biggestClusterIndex = clusters.end();
899 unsigned int biggestClusterSize = 0;
900 for(std::list<std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
902 if(iter->size() > biggestClusterSize)
904 biggestClusterIndex = iter;
905 biggestClusterSize = iter->size();
908 if(biggestClusterIndex != clusters.end())
910 for(std::list<int>::iterator jter=biggestClusterIndex->begin(); jter!=biggestClusterIndex->end(); ++jter)
912 validPolygons.insert(*jter);
918 for(std::list<std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
920 for(std::list<int>::iterator jter=iter->begin(); jter!=iter->end(); ++jter)
922 validPolygons.insert(*jter);
927 if(validPolygons.size() == 0)
929 UWARN(
"All %d polygons filtered after polygon cluster filtering. Cluster minimum size is %d.",totalSize, minClusterSize);
933 unsigned int allPolygonsIndex = 0;
934 for(
unsigned int t=0; t<textureMesh.tex_polygons.size(); ++t)
936 std::vector<pcl::Vertices> filteredPolygons(textureMesh.tex_polygons[t].size());
937 #if PCL_VERSION_COMPARE(>=, 1, 8, 0) 938 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > filteredCoordinates(textureMesh.tex_coordinates[t].size());
940 std::vector<Eigen::Vector2f> filteredCoordinates(textureMesh.tex_coordinates[t].size());
943 if(textureMesh.tex_polygons[t].size())
945 UASSERT_MSG(allPolygonsIndex < allPolygons.size(),
uFormat(
"%d vs %d", (
int)allPolygonsIndex, (
int)allPolygons.size()).c_str());
948 std::vector<unsigned int> polygonToCoord(textureMesh.tex_polygons[t].size());
949 unsigned int totalCoord = 0;
950 for(
unsigned int i=0; i<textureMesh.tex_polygons[t].size(); ++i)
952 polygonToCoord[i] = totalCoord;
953 totalCoord+=textureMesh.tex_polygons[t][i].vertices.size();
955 UASSERT_MSG(totalCoord == textureMesh.tex_coordinates[t].size(),
uFormat(
"%d vs %d", totalCoord, (
int)textureMesh.tex_coordinates[t].size()).c_str());
959 for(
unsigned int i=0; i<textureMesh.tex_polygons[t].size(); ++i)
961 if(validPolygons.find(allPolygonsIndex) != validPolygons.end())
963 filteredPolygons[oi] = textureMesh.tex_polygons[t].at(i);
964 for(
unsigned int j=0; j<filteredPolygons[oi].vertices.size(); ++j)
966 UASSERT(polygonToCoord[i] < textureMesh.tex_coordinates[t].size());
967 filteredCoordinates[ci] = textureMesh.tex_coordinates[t][polygonToCoord[i]+j];
974 filteredPolygons.resize(oi);
975 filteredCoordinates.resize(ci);
976 textureMesh.tex_polygons[t] = filteredPolygons;
977 textureMesh.tex_coordinates[t] = filteredCoordinates;
986 pcl::TextureMesh::Ptr output(
new pcl::TextureMesh);
987 std::map<std::string, int> addedMaterials;
988 for(std::list<pcl::TextureMesh::Ptr>::const_iterator iter = meshes.begin(); iter!=meshes.end(); ++iter)
990 if((*iter)->cloud.point_step &&
991 (*iter)->cloud.data.size()/(*iter)->cloud.point_step &&
992 (*iter)->tex_polygons.size() &&
993 (*iter)->tex_coordinates.size())
996 int polygonStep = output->cloud.height * output->cloud.width;
997 pcl::PCLPointCloud2 tmp;
998 pcl::concatenatePointCloud(output->cloud, iter->get()->cloud, tmp);
1001 UASSERT((*iter)->tex_polygons.size() == (*iter)->tex_coordinates.size() &&
1002 (*iter)->tex_polygons.size() == (*iter)->tex_materials.size());
1004 int materialCount = (*iter)->tex_polygons.size();
1005 for(
int i=0; i<materialCount; ++i)
1007 std::map<std::string, int>::iterator jter = addedMaterials.find((*iter)->tex_materials[i].tex_file);
1009 if(jter != addedMaterials.end())
1011 index = jter->second;
1015 addedMaterials.insert(std::make_pair((*iter)->tex_materials[i].tex_file, output->tex_materials.size()));
1016 index = output->tex_materials.size();
1017 output->tex_materials.push_back((*iter)->tex_materials[i]);
1018 output->tex_materials.back().tex_name =
uFormat(
"material_%d", index);
1019 output->tex_polygons.resize(output->tex_polygons.size() + 1);
1020 output->tex_coordinates.resize(output->tex_coordinates.size() + 1);
1024 int oi = output->tex_polygons[index].size();
1025 output->tex_polygons[index].resize(output->tex_polygons[index].size() + (*iter)->tex_polygons[i].size());
1026 for(
unsigned int j=0; j<(*iter)->tex_polygons[i].size(); ++j)
1028 pcl::Vertices polygon = (*iter)->tex_polygons[i][j];
1029 for(
unsigned int k=0; k<polygon.vertices.size(); ++k)
1031 polygon.vertices[k] += polygonStep;
1033 output->tex_polygons[index][oi+j] = polygon;
1037 oi = output->tex_coordinates[index].size();
1038 output->tex_coordinates[index].resize(output->tex_coordinates[index].size() + (*iter)->tex_coordinates[i].size());
1039 for(
unsigned int j=0; j<(*iter)->tex_coordinates[i].size(); ++j)
1041 output->tex_coordinates[index][oi+j] = (*iter)->tex_coordinates[i][j];
1050 return b == 0 ? a :
gcd(b, a % b);
1055 UASSERT(textureSize>0 && imageSize.width>0 && imageSize.height>0);
1061 for(
unsigned int i=0; i<mesh.tex_materials.size(); ++i)
1063 if(mesh.tex_polygons.size())
1070 int w = imageSize.width;
1071 int h = imageSize.height;
1075 UDEBUG(
"w=%d h=%d g=%d a=%d b=%d", w, h, g, a, b);
1078 float factor = 0.1f;
1081 while((colCount*rowCount)*maxTextures < materials || (factor == 0.1
f || scale > 1.0
f))
1086 scale = float(textureSize)/float(w*b*factor);
1088 colCount = float(textureSize)/(scale*float(w));
1089 rowCount = float(textureSize)/(scale*float(h));
1092 int outputTextures = (materials / (colCount*rowCount)) + (materials % (colCount*rowCount) > 0?1:0);
1093 UDEBUG(
"materials=%d col=%d row=%d output textures=%d factor=%f scale=%f", materials, colCount, rowCount, outputTextures, factor-epsilon, scale);
1095 UASSERT(mesh.tex_coordinates.size() == mesh.tex_materials.size() && mesh.tex_polygons.size() == mesh.tex_materials.size());
1098 std::vector<int> totalPolygons(outputTextures, 0);
1099 std::vector<int> totalCoordinates(outputTextures, 0);
1101 for(
unsigned int i=0; i<mesh.tex_materials.size(); ++i)
1103 if(mesh.tex_polygons[i].size())
1105 int indexMaterial = count / (colCount*rowCount);
1106 UASSERT(indexMaterial < outputTextures);
1108 totalPolygons[indexMaterial]+=mesh.tex_polygons[i].size();
1109 totalCoordinates[indexMaterial]+=mesh.tex_coordinates[i].size();
1115 pcl::TextureMesh outputMesh;
1120 float scaledHeight = float(
int(scale*
float(h)))/float(textureSize);
1121 float scaledWidth = float(
int(scale*
float(w)))/float(textureSize);
1122 float lowerBorderSize = 1.0f - scaledHeight*float(rowCount);
1123 UDEBUG(
"scaledWidth=%f scaledHeight=%f lowerBorderSize=%f", scaledWidth, scaledHeight, lowerBorderSize);
1126 materialsKept->resize(mesh.tex_materials.size(),
false);
1128 for(
unsigned int t=0; t<mesh.tex_materials.size(); ++t)
1130 if(mesh.tex_polygons[t].size())
1132 int indexMaterial = ti / (colCount*rowCount);
1133 UASSERT(indexMaterial < outputTextures);
1134 if((
int)outputMesh.tex_polygons.size() <= indexMaterial)
1136 std::vector<pcl::Vertices> newPolygons(totalPolygons[indexMaterial]);
1137 #if PCL_VERSION_COMPARE(>=, 1, 8, 0) 1138 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > newCoordinates(totalCoordinates[indexMaterial]);
1140 std::vector<Eigen::Vector2f> newCoordinates(totalCoordinates[indexMaterial]);
1142 outputMesh.tex_polygons.push_back(newPolygons);
1143 outputMesh.tex_coordinates.push_back(newCoordinates);
1149 int row = (ti/colCount) % rowCount;
1150 int col = ti%colCount;
1151 float offsetU = scaledWidth * float(col);
1152 float offsetV = scaledHeight * float((rowCount - 1) - row) + lowerBorderSize;
1155 for(
unsigned int i=0; i<mesh.tex_polygons[t].size(); ++i)
1157 UASSERT(pi < (
int)outputMesh.tex_polygons[indexMaterial].size());
1158 outputMesh.tex_polygons[indexMaterial][pi++] = mesh.tex_polygons[t].at(i);
1161 for(
unsigned int i=0; i<mesh.tex_coordinates[t].size(); ++i)
1163 const Eigen::Vector2f & v = mesh.tex_coordinates[t].at(i);
1164 if(v[0] >= 0 && v[1] >=0)
1166 outputMesh.tex_coordinates[indexMaterial][ci][0] = v[0]*scaledWidth + offsetU;
1167 outputMesh.tex_coordinates[indexMaterial][ci][1] = v[1]*scaledHeight + offsetV;
1171 outputMesh.tex_coordinates[indexMaterial][ci] = v;
1178 materialsKept->at(t) =
true;
1182 pcl::TexMaterial m = mesh.tex_materials.front();
1183 mesh.tex_materials.clear();
1184 for(
int i=0; i<outputTextures; ++i)
1186 m.tex_file =
"texture";
1187 m.tex_name =
"material";
1188 if(outputTextures > 1)
1194 mesh.tex_materials.push_back(m);
1196 mesh.tex_coordinates = outputMesh.tex_coordinates;
1197 mesh.tex_polygons = outputMesh.tex_polygons;
1203 std::vector<std::vector<unsigned int> > polygonsOut(polygons.size());
1204 for(
unsigned int p=0; p<polygons.size(); ++p)
1206 polygonsOut[p] = polygons[p].vertices;
1210 std::vector<std::vector<std::vector<unsigned int> > >
convertPolygonsFromPCL(
const std::vector<std::vector<pcl::Vertices> > & tex_polygons)
1212 std::vector<std::vector<std::vector<unsigned int> > > polygonsOut(tex_polygons.size());
1213 for(
unsigned int t=0; t<tex_polygons.size(); ++t)
1215 polygonsOut[t].resize(tex_polygons[t].size());
1216 for(
unsigned int p=0; p<tex_polygons[t].size(); ++p)
1218 polygonsOut[t][p] = tex_polygons[t][p].vertices;
1225 std::vector<pcl::Vertices> polygonsOut(polygons.size());
1226 for(
unsigned int p=0; p<polygons.size(); ++p)
1228 polygonsOut[p].vertices = polygons[p];
1232 std::vector<std::vector<pcl::Vertices> >
convertPolygonsToPCL(
const std::vector<std::vector<std::vector<unsigned int> > > & tex_polygons)
1234 std::vector<std::vector<pcl::Vertices> > polygonsOut(tex_polygons.size());
1235 for(
unsigned int t=0; t<tex_polygons.size(); ++t)
1237 polygonsOut[t].resize(tex_polygons[t].size());
1238 for(
unsigned int p=0; p<tex_polygons[t].size(); ++p)
1240 polygonsOut[t][p].vertices = tex_polygons[t][p];
1247 const cv::Mat & cloudMat,
1248 const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
1249 #
if PCL_VERSION_COMPARE(>=, 1, 8, 0)
1250 const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
1252 const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
1257 pcl::TextureMesh::Ptr textureMesh(
new pcl::TextureMesh);
1259 if(cloudMat.channels() <= 3)
1262 pcl::toPCLPointCloud2(*cloud, textureMesh->cloud);
1264 else if(cloudMat.channels() == 4)
1267 pcl::toPCLPointCloud2(*cloud, textureMesh->cloud);
1269 else if(cloudMat.channels() == 6)
1272 pcl::toPCLPointCloud2(*cloud, textureMesh->cloud);
1274 else if(cloudMat.channels() == 7)
1277 pcl::toPCLPointCloud2(*cloud, textureMesh->cloud);
1280 if(textureMesh->cloud.data.size() && polygons.size())
1282 textureMesh->tex_polygons.resize(polygons.size());
1283 for(
unsigned int t=0; t<polygons.size(); ++t)
1285 textureMesh->tex_polygons[t].resize(polygons[t].size());
1286 for(
unsigned int p=0; p<polygons[t].size(); ++p)
1288 textureMesh->tex_polygons[t][p].vertices = polygons[t][p];
1292 if(!texCoords.empty() && !textures.empty())
1294 textureMesh->tex_coordinates = texCoords;
1296 textureMesh->tex_materials.resize (textureMesh->tex_coordinates.size());
1297 for(
unsigned int i = 0 ; i < textureMesh->tex_coordinates.size() ; ++i)
1299 pcl::TexMaterial mesh_material;
1300 mesh_material.tex_Ka.r = 0.2f;
1301 mesh_material.tex_Ka.g = 0.2f;
1302 mesh_material.tex_Ka.b = 0.2f;
1304 mesh_material.tex_Kd.r = 0.8f;
1305 mesh_material.tex_Kd.g = 0.8f;
1306 mesh_material.tex_Kd.b = 0.8f;
1308 mesh_material.tex_Ks.r = 1.0f;
1309 mesh_material.tex_Ks.g = 1.0f;
1310 mesh_material.tex_Ks.b = 1.0f;
1312 mesh_material.tex_d = 1.0f;
1313 mesh_material.tex_Ns = 75.0f;
1314 mesh_material.tex_illum = 2;
1316 std::stringstream tex_name;
1317 tex_name <<
"material_" << i;
1318 tex_name >> mesh_material.tex_name;
1320 mesh_material.tex_file =
uFormat(
"%d", i);
1322 textureMesh->tex_materials[i] = mesh_material;
1325 if(mergeTextures && textures.cols/textures.rows > 1)
1327 UASSERT(textures.cols % textures.rows == 0 && textures.cols/textures.rows == (
int)textureMesh->tex_coordinates.size());
1328 std::vector<bool> materialsKept;
1330 cv::Size imageSize(textures.rows, textures.rows);
1331 int imageType = textures.type();
1333 if(scale && textureMesh->tex_materials.size() == 1)
1335 int cols = float(textures.rows)/(scale*imageSize.width);
1336 int rows = float(textures.rows)/(scale*imageSize.height);
1338 cv::Mat mergedTextures = cv::Mat(textures.rows, textures.rows, imageType,
cv::Scalar::all(255));
1341 cv::Size resizedImageSize(
int(imageSize.width*scale),
int(imageSize.height*scale));
1343 for(
int i=0; i<(int)materialsKept.size(); ++i)
1345 if(materialsKept.at(i))
1347 int u = oi%cols * resizedImageSize.width;
1348 int v = ((oi/cols) % rows ) * resizedImageSize.height;
1349 UASSERT(u < textures.rows-resizedImageSize.width);
1350 UASSERT(v < textures.rows-resizedImageSize.height);
1352 cv::Mat resizedImage;
1353 cv::resize(textures(
cv::Range::all(), cv::Range(i*textures.rows, (i+1)*textures.rows)), resizedImage, resizedImageSize, 0.0f, 0.0f, cv::INTER_AREA);
1355 UASSERT(resizedImage.type() == mergedTextures.type());
1356 resizedImage.copyTo(mergedTextures(cv::Rect(u, v, resizedImage.cols, resizedImage.rows)));
1361 textures = mergedTextures;
1370 const cv::Mat & cloudMat,
1371 const std::vector<std::vector<unsigned int> > & polygons)
1373 pcl::PolygonMesh::Ptr polygonMesh(
new pcl::PolygonMesh);
1375 if(cloudMat.channels() <= 3)
1378 pcl::toPCLPointCloud2(*cloud, polygonMesh->cloud);
1380 else if(cloudMat.channels() == 4)
1383 pcl::toPCLPointCloud2(*cloud, polygonMesh->cloud);
1385 else if(cloudMat.channels() == 6)
1388 pcl::toPCLPointCloud2(*cloud, polygonMesh->cloud);
1390 else if(cloudMat.channels() == 7)
1393 pcl::toPCLPointCloud2(*cloud, polygonMesh->cloud);
1396 if(polygonMesh->cloud.data.size() && polygons.size())
1398 polygonMesh->polygons.resize(polygons.size());
1399 for(
unsigned int p=0; p<polygons.size(); ++p)
1401 polygonMesh->polygons[p].vertices = polygons[p];
1409 return double(v)*double(v);
1413 pcl::TextureMesh & mesh,
1414 const std::map<int, cv::Mat> & images,
1415 const std::map<int, CameraModel> & calibrations,
1420 const std::vector<std::map<int, pcl::PointXY> > & vertexToPixels,
1421 bool gainCompensation,
1425 int blendingDecimation,
1426 int brightnessContrastRatioLow,
1427 int brightnessContrastRatioHigh,
1431 std::map<int, std::vector<CameraModel> > calibVectors;
1432 for(std::map<int, CameraModel>::const_iterator iter=calibrations.begin(); iter!=calibrations.end(); ++iter)
1434 std::vector<CameraModel> m;
1435 m.push_back(iter->second);
1436 calibVectors.insert(std::make_pair(iter->first, m));
1451 brightnessContrastRatioLow,
1452 brightnessContrastRatioHigh,
1457 pcl::TextureMesh & mesh,
1458 const std::map<int, cv::Mat> & images,
1459 const std::map<
int, std::vector<CameraModel> > & calibrations,
1464 const std::vector<std::map<int, pcl::PointXY> > & vertexToPixels,
1465 bool gainCompensation,
1469 int blendingDecimation,
1470 int brightnessContrastRatioLow,
1471 int brightnessContrastRatioHigh,
1476 UASSERT(textureSize%256 == 0);
1477 UDEBUG(
"textureSize = %d", textureSize);
1478 cv::Mat globalTextures;
1479 if(mesh.tex_materials.size() > 1)
1481 std::vector<std::pair<int, int> > textures(mesh.tex_materials.size(), std::pair<int, int>(-1,-1));
1483 const int imageType=CV_8UC3;
1486 for(
unsigned int i=0; i<mesh.tex_materials.size(); ++i)
1488 std::list<std::string> texFileSplit =
uSplit(mesh.tex_materials[i].tex_file,
'_');
1489 if(!mesh.tex_materials[i].tex_file.empty() &&
1490 mesh.tex_polygons[i].size() &&
1493 textures[i].first =
uStr2Int(texFileSplit.front());
1494 if(texFileSplit.size() == 2 &&
1497 textures[i].second =
uStr2Int(texFileSplit.back());
1500 int textureId = textures[i].first;
1501 if(imageSize.width == 0 || imageSize.height == 0)
1503 if(images.find(textureId) != images.end() &&
1504 !images.find(textureId)->second.empty() &&
1505 calibrations.find(textureId) != calibrations.end())
1507 const std::vector<CameraModel> & models = calibrations.find(textureId)->second;
1509 if( models[0].imageHeight()>0 &&
1510 models[0].imageWidth()>0)
1512 imageSize = models[0].imageSize();
1514 else if(images.find(textureId)!=images.end())
1517 cv::Mat image = images.find(textureId)->second;
1518 if(image.rows == 1 && image.type() == CV_8UC1)
1523 imageSize = image.size();
1526 imageSize.width/=models.size();
1535 if(models.size()>=1 &&
1536 models[0].imageHeight()>0 &&
1537 models[0].imageWidth()>0)
1539 imageSize = models[0].imageSize();
1551 imageSize = image.size();
1560 std::vector<CameraModel> models;
1563 if(models.size()>=1 &&
1564 models[0].imageHeight()>0 &&
1565 models[0].imageWidth()>0)
1567 imageSize = models[0].imageSize();
1577 dbDriver->
getNodeData(textureId, data,
true,
false,
false,
false);
1581 imageSize = image.size();
1590 else if(mesh.tex_polygons[i].size() && mesh.tex_materials[i].tex_file.compare(
"occluded")!=0)
1592 UWARN(
"Failed parsing texture file name: %s", mesh.tex_materials[i].tex_file.c_str());
1595 UDEBUG(
"textures=%d imageSize=%dx%d", (
int)textures.size(), imageSize.height, imageSize.width);
1596 if(textures.size() && imageSize.height>0 && imageSize.width>0)
1600 std::vector<bool> materialsKept;
1602 if(scale && mesh.tex_materials.size())
1604 int materials = (int)mesh.tex_materials.size();
1605 int cols = float(textureSize)/(scale*imageSize.width);
1606 int rows = float(textureSize)/(scale*imageSize.height);
1608 globalTextures = cv::Mat(textureSize, materials*textureSize, imageType,
cv::Scalar::all(255));
1609 cv::Mat globalTextureMasks = cv::Mat(textureSize, materials*textureSize, CV_8UC1,
cv::Scalar::all(0));
1612 cv::Mat previousImage;
1613 int previousTextureId = 0;
1614 std::vector<CameraModel> previousCameraModels;
1617 cv::Mat emptyImage(
int(imageSize.height*scale),
int(imageSize.width*scale), imageType,
cv::Scalar::all(255));
1618 cv::Mat emptyImageMask(
int(imageSize.height*scale),
int(imageSize.width*scale), CV_8UC1,
cv::Scalar::all(255));
1620 std::vector<cv::Point2i> imageOrigin(textures.size());
1621 std::vector<int> newCamIndex(textures.size(), -1);
1622 for(
int t=0; t<(int)textures.size(); ++t)
1624 if(materialsKept.at(t))
1626 int indexMaterial = oi / (cols*rows);
1627 UASSERT(indexMaterial < materials);
1629 newCamIndex[t] = oi;
1630 int u = oi%cols * emptyImage.cols;
1631 int v = ((oi/cols) % rows ) * emptyImage.rows;
1632 UASSERT_MSG(u < textureSize-emptyImage.cols,
uFormat(
"u=%d textureSize=%d emptyImage.cols=%d", u, textureSize, emptyImage.cols).c_str());
1633 UASSERT_MSG(v < textureSize-emptyImage.rows,
uFormat(
"v=%d textureSize=%d emptyImage.rows=%d", v, textureSize, emptyImage.rows).c_str());
1634 imageOrigin[t].x = u;
1635 imageOrigin[t].y = v;
1636 if(textures[t].first>=0)
1639 std::vector<CameraModel> models;
1641 if(textures[t].first == previousTextureId)
1643 image = previousImage;
1644 models = previousCameraModels;
1648 if(images.find(textures[t].first) != images.end() &&
1649 !images.find(textures[t].first)->second.empty() &&
1650 calibrations.find(textures[t].first) != calibrations.end())
1652 image = images.find(textures[t].first)->second;
1653 if(image.rows == 1 && image.type() == CV_8UC1)
1657 models = calibrations.find(textures[t].first)->second;
1668 dbDriver->
getNodeData(textures[t].first, data,
true,
false,
false,
false);
1671 dbDriver->
getCalibration(textures[t].first, models, stereoModel);
1674 previousImage = image;
1675 previousCameraModels = models;
1676 previousTextureId = textures[t].first;
1681 if(textures[t].second>=0)
1683 UASSERT(textures[t].second < (
int)models.size());
1684 int width = image.cols/models.size();
1685 image = image.colRange(width*textures[t].second, width*(textures[t].second+1));
1688 cv::Mat resizedImage;
1689 cv::resize(image, resizedImage, emptyImage.size(), 0.0f, 0.0f, cv::INTER_AREA);
1690 UASSERT(resizedImage.type() == CV_8UC1 || resizedImage.type() == CV_8UC3);
1691 if(resizedImage.type() == CV_8UC1)
1693 cv::Mat resizedImageColor;
1694 cv::cvtColor(resizedImage, resizedImageColor, CV_GRAY2BGR);
1695 resizedImage = resizedImageColor;
1697 UASSERT(resizedImage.type() == globalTextures.type());
1698 resizedImage.copyTo(globalTextures(cv::Rect(u+indexMaterial*globalTextures.rows, v, resizedImage.cols, resizedImage.rows)));
1699 emptyImageMask.copyTo(globalTextureMasks(cv::Rect(u+indexMaterial*globalTextureMasks.rows, v, resizedImage.cols, resizedImage.rows)));
1703 emptyImage.copyTo(globalTextures(cv::Rect(u+indexMaterial*globalTextures.rows, v, emptyImage.cols, emptyImage.rows)));
1714 state->
callback(
uFormat(
"Assembled texture %d/%d.", t+1, (
int)textures.size()));
1719 if(vertexToPixels.size())
1724 if(gainCompensation)
1730 const int num_images =
static_cast<int>(oi);
1731 cv::Mat_<int> N(num_images, num_images); N.setTo(0);
1732 cv::Mat_<double> I(num_images, num_images); I.setTo(0);
1734 cv::Mat_<double> IR(num_images, num_images); IR.setTo(0);
1735 cv::Mat_<double> IG(num_images, num_images); IG.setTo(0);
1736 cv::Mat_<double> IB(num_images, num_images); IB.setTo(0);
1739 for(
unsigned int p=0; p<vertexToPixels.size(); ++p)
1741 for(std::map<int, pcl::PointXY>::const_iterator iter=vertexToPixels[p].begin(); iter!=vertexToPixels[p].end(); ++iter)
1743 if(materialsKept.at(iter->first))
1745 N(newCamIndex[iter->first], newCamIndex[iter->first]) +=1;
1747 std::map<int, pcl::PointXY>::const_iterator jter=iter;
1750 for(; jter!=vertexToPixels[p].end(); ++jter, ++k)
1752 if(materialsKept.at(jter->first))
1754 int i = newCamIndex[iter->first];
1755 int j = newCamIndex[jter->first];
1760 int indexMaterial = i / (cols*rows);
1763 int ui = iter->second.x*emptyImage.cols + imageOrigin[iter->first].x;
1764 int vi = (1.0-iter->second.y)*emptyImage.rows + imageOrigin[iter->first].y;
1765 int uj = jter->second.x*emptyImage.cols + imageOrigin[jter->first].x;
1766 int vj = (1.0-jter->second.y)*emptyImage.rows + imageOrigin[jter->first].y;
1767 cv::Vec3b * pt1 = globalTextures.ptr<cv::Vec3b>(vi,ui+indexMaterial*globalTextures.rows);
1768 cv::Vec3b * pt2 = globalTextures.ptr<cv::Vec3b>(vj,uj+indexMaterial*globalTextures.rows);
1770 I(i, j) +=
std::sqrt(static_cast<double>(
sqr(pt1->val[0]) +
sqr(pt1->val[1]) +
sqr(pt1->val[2])));
1771 I(j, i) +=
std::sqrt(static_cast<double>(
sqr(pt2->val[0]) +
sqr(pt2->val[1]) +
sqr(pt2->val[2])));
1773 IR(i, j) +=
static_cast<double>(pt1->val[2]);
1774 IR(j, i) +=
static_cast<double>(pt2->val[2]);
1775 IG(i, j) +=
static_cast<double>(pt1->val[1]);
1776 IG(j, i) +=
static_cast<double>(pt2->val[1]);
1777 IB(i, j) +=
static_cast<double>(pt1->val[0]);
1778 IB(j, i) +=
static_cast<double>(pt2->val[0]);
1785 for(
int i=0; i<num_images; ++i)
1787 for(
int j=i; j<num_images; ++j)
1801 IR(i, j) /= N(i, j);
1802 IR(j, i) /= N(j, i);
1803 IG(i, j) /= N(i, j);
1804 IG(j, i) /= N(j, i);
1805 IB(i, j) /= N(i, j);
1806 IB(j, i) /= N(j, i);
1811 cv::Mat_<double> A(num_images, num_images); A.setTo(0);
1812 cv::Mat_<double> b(num_images, 1); b.setTo(0);
1813 cv::Mat_<double> AR(num_images, num_images); AR.setTo(0);
1814 cv::Mat_<double> AG(num_images, num_images); AG.setTo(0);
1815 cv::Mat_<double> AB(num_images, num_images); AB.setTo(0);
1816 double alpha = 0.01;
1817 double beta = gainBeta;
1818 for (
int i = 0; i < num_images; ++i)
1820 for (
int j = 0; j < num_images; ++j)
1822 b(i, 0) += beta * N(i, j);
1823 A(i, i) += beta * N(i, j);
1824 AR(i, i) += beta * N(i, j);
1825 AG(i, i) += beta * N(i, j);
1826 AB(i, i) += beta * N(i, j);
1827 if (j == i)
continue;
1828 A(i, i) += 2 * alpha * I(i, j) * I(i, j) * N(i, j);
1829 A(i, j) -= 2 * alpha * I(i, j) * I(j, i) * N(i, j);
1831 AR(i, i) += 2 * alpha * IR(i, j) * IR(i, j) * N(i, j);
1832 AR(i, j) -= 2 * alpha * IR(i, j) * IR(j, i) * N(i, j);
1834 AG(i, i) += 2 * alpha * IG(i, j) * IG(i, j) * N(i, j);
1835 AG(i, j) -= 2 * alpha * IG(i, j) * IG(j, i) * N(i, j);
1837 AB(i, i) += 2 * alpha * IB(i, j) * IB(i, j) * N(i, j);
1838 AB(i, j) -= 2 * alpha * IB(i, j) * IB(j, i) * N(i, j);
1842 cv::Mat_<double> gainsGray, gainsR, gainsG, gainsB;
1843 cv::solve(A, b, gainsGray);
1845 cv::solve(AR, b, gainsR);
1846 cv::solve(AG, b, gainsG);
1847 cv::solve(AB, b, gainsB);
1849 cv::Mat_<double> gains(gainsGray.rows, 4);
1850 gainsGray.copyTo(gains.col(0));
1851 gainsR.copyTo(gains.col(1));
1852 gainsG.copyTo(gains.col(2));
1853 gainsB.copyTo(gains.col(3));
1855 for(
int t=0; t<(int)textures.size(); ++t)
1858 if(materialsKept.at(t))
1860 int u = imageOrigin[t].x;
1861 int v = imageOrigin[t].y;
1863 UDEBUG(
"Gain cam%d = %f", newCamIndex[t], gainsGray(newCamIndex[t], 0));
1865 int indexMaterial = newCamIndex[t] / (cols*rows);
1866 cv::Mat roi = globalTextures(cv::Rect(u+indexMaterial*globalTextures.rows, v, emptyImage.cols, emptyImage.rows));
1868 std::vector<cv::Mat> channels;
1869 cv::split(roi, channels);
1872 cv::multiply(channels[0], gains(newCamIndex[t], gainRGB?3:0), channels[0]);
1873 cv::multiply(channels[1], gains(newCamIndex[t], gainRGB?2:0), channels[1]);
1874 cv::multiply(channels[2], gains(newCamIndex[t], gainRGB?1:0), channels[2]);
1876 cv::merge(channels, roi);
1888 if(blendingDecimation <= 0)
1891 std::vector<float> edgeLengths;
1892 if(mesh.tex_coordinates.size() && mesh.tex_coordinates[0].size())
1894 UASSERT(mesh.tex_polygons.size() && mesh.tex_polygons[0].size() && mesh.tex_polygons[0][0].vertices.size());
1895 int polygonSize = mesh.tex_polygons[0][0].vertices.size();
1896 UDEBUG(
"polygon size=%d", polygonSize);
1898 for(
unsigned int k=0; k<mesh.tex_coordinates.size(); ++k)
1900 for(
unsigned int i=0; i<mesh.tex_coordinates[k].size(); i+=polygonSize)
1902 for(
int j=0; j<polygonSize; ++j)
1904 const Eigen::Vector2f & uc1 = mesh.tex_coordinates[k][i + j];
1905 const Eigen::Vector2f & uc2 = mesh.tex_coordinates[k][i + (j+1)%polygonSize];
1906 Eigen::Vector2f edge = (uc1-uc2)*textureSize;
1907 edgeLengths.push_back(fabs(edge[0]));
1908 edgeLengths.push_back(fabs(edge[1]));
1912 float edgeLength = 0.0f;
1913 if(edgeLengths.size())
1915 std::sort(edgeLengths.begin(), edgeLengths.end());
1916 float m =
uMean(edgeLengths.data(), edgeLengths.size());
1918 edgeLength = m+stddev;
1919 decimation = 1 << 6;
1920 for(
int i=1; i<=6; ++i)
1922 if(
float(1 << i) >= edgeLength)
1924 decimation = 1 << i;
1930 UDEBUG(
"edge length=%f decimation=%d", edgeLength, decimation);
1935 if(blendingDecimation > 1)
1937 UASSERT(textureSize % blendingDecimation == 0);
1939 decimation = blendingDecimation;
1940 UDEBUG(
"decimation=%d", decimation);
1943 std::vector<cv::Mat> blendGains(materials);
1944 for(
int i=0; i<materials;++i)
1946 blendGains[i] = cv::Mat(globalTextures.rows/decimation, globalTextures.rows/decimation, CV_32FC3,
cv::Scalar::all(1.0f));
1949 for(
unsigned int p=0; p<vertexToPixels.size(); ++p)
1951 if(vertexToPixels[p].size() > 1)
1953 std::vector<float> gainsB(vertexToPixels[p].size());
1954 std::vector<float> gainsG(vertexToPixels[p].size());
1955 std::vector<float> gainsR(vertexToPixels[p].size());
1956 float sumWeight = 0.0f;
1958 for(std::map<int, pcl::PointXY>::const_iterator iter=vertexToPixels[p].begin(); iter!=vertexToPixels[p].end(); ++iter)
1960 if(materialsKept.at(iter->first))
1962 int u = iter->second.x*emptyImage.cols + imageOrigin[iter->first].x;
1963 int v = (1.0-iter->second.y)*emptyImage.rows + imageOrigin[iter->first].y;
1964 float x = iter->second.x - 0.5f;
1965 float y = iter->second.y - 0.5f;
1966 float weight = 0.7f -
sqrt(x*x+y*y);
1971 int indexMaterial = newCamIndex[iter->first] / (cols*rows);
1972 cv::Vec3b * pt = globalTextures.ptr<cv::Vec3b>(v,u+indexMaterial*globalTextures.rows);
1973 gainsB[k] =
static_cast<double>(pt->val[0]) * weight;
1974 gainsG[k] =
static_cast<double>(pt->val[1]) * weight;
1975 gainsR[k] =
static_cast<double>(pt->val[2]) * weight;
1976 sumWeight += weight;
1986 float targetColor[3];
1987 targetColor[0] =
uSum(gainsB.data(), gainsB.size()) / sumWeight;
1988 targetColor[1] =
uSum(gainsG.data(), gainsG.size()) / sumWeight;
1989 targetColor[2] =
uSum(gainsR.data(), gainsR.size()) / sumWeight;
1990 for(std::map<int, pcl::PointXY>::const_iterator iter=vertexToPixels[p].begin(); iter!=vertexToPixels[p].end(); ++iter)
1992 if(materialsKept.at(iter->first))
1994 int u = iter->second.x*emptyImage.cols + imageOrigin[iter->first].x;
1995 int v = (1.0-iter->second.y)*emptyImage.rows + imageOrigin[iter->first].y;
1996 int indexMaterial = newCamIndex[iter->first] / (cols*rows);
1997 cv::Vec3b * pt = globalTextures.ptr<cv::Vec3b>(v,u+indexMaterial*globalTextures.rows);
1998 float gB = targetColor[0]/(pt->val[0]==0?1.0f:pt->val[0]);
1999 float gG = targetColor[1]/(pt->val[1]==0?1.0f:pt->val[1]);
2000 float gR = targetColor[2]/(pt->val[2]==0?1.0f:pt->val[2]);
2001 cv::Vec3f * ptr = blendGains[indexMaterial].ptr<cv::Vec3f>(v/decimation, u/decimation);
2002 ptr->val[0] = (gB>1.3f)?1.3
f:(gB<0.7
f)?0.7f:gB;
2003 ptr->val[1] = (gG>1.3f)?1.3
f:(gG<0.7
f)?0.7f:gG;
2004 ptr->val[2] = (gR>1.3f)?1.3
f:(gR<0.7
f)?0.7f:gR;
2011 for(
int i=0; i<materials; ++i)
2023 cv::Mat globalTexturesROI = globalTextures(
cv::Range::all(), cv::Range(i*globalTextures.rows, (i+1)*globalTextures.rows));
2025 cv::blur(blendGains[i], dst, cv::Size(3,3));
2026 cv::resize(dst, blendGains[i], globalTexturesROI.size(), 0, 0, cv::INTER_LINEAR);
2036 cv::multiply(globalTexturesROI, blendGains[i], globalTexturesROI, 1.0, CV_8UC3);
2046 if(brightnessContrastRatioLow > 0 || brightnessContrastRatioHigh > 0)
2048 for(
int i=0; i<materials; ++i)
2050 cv::Mat globalTexturesROI = globalTextures(
cv::Range::all(), cv::Range(i*globalTextures.rows, (i+1)*globalTextures.rows));
2051 cv::Mat globalTextureMasksROI = globalTextureMasks(
cv::Range::all(), cv::Range(i*globalTextureMasks.rows, (i+1)*globalTextureMasks.rows));
2054 std::vector<cv::Mat> images;
2055 images.push_back(globalTexturesROI);
2056 if (brightnessContrastRatioLow > 0)
2060 globalTextureMasksROI,
2061 (
float)brightnessContrastRatioLow,
2064 if (brightnessContrastRatioHigh > 0)
2068 globalTextureMasksROI,
2070 (
float)brightnessContrastRatioHigh));
2079 globalTextureMasksROI,
2080 (
float)brightnessContrastRatioLow,
2081 (
float)brightnessContrastRatioHigh).copyTo(globalTexturesROI);
2089 UDEBUG(
"globalTextures=%d", globalTextures.cols?globalTextures.cols / globalTextures.rows:0);
2090 return globalTextures;
2099 for (
unsigned int t = 0; t < textureMesh.tex_coordinates.size(); ++t)
2101 if(textureMesh.tex_polygons[t].size())
2103 pcl::PointCloud<pcl::PointXYZ>::Ptr originalCloud(
new pcl::PointCloud<pcl::PointXYZ>);
2104 pcl::fromPCLPointCloud2(textureMesh.cloud, *originalCloud);
2107 unsigned int nPoints = textureMesh.tex_coordinates[t].size();
2108 UASSERT(nPoints == textureMesh.tex_polygons[t].size()*textureMesh.tex_polygons[t][0].vertices.size());
2110 pcl::PointCloud<pcl::PointXYZ>::Ptr newCloud(
new pcl::PointCloud<pcl::PointXYZ>);
2111 newCloud->resize(nPoints);
2113 unsigned int oi = 0;
2114 for (
unsigned int i = 0; i < textureMesh.tex_polygons[t].size(); ++i)
2116 pcl::Vertices &
vertices = textureMesh.tex_polygons[t][i];
2118 for(
unsigned int j=0; j<vertices.vertices.size(); ++j)
2120 UASSERT(oi < newCloud->size());
2121 UASSERT_MSG(vertices.vertices[j] < originalCloud->size(),
uFormat(
"%d vs %d", vertices.vertices[j], (
int)originalCloud->size()).c_str());
2122 newCloud->at(oi) = originalCloud->at(vertices.vertices[j]);
2123 vertices.vertices[j] = oi;
2127 pcl::toPCLPointCloud2(*newCloud, textureMesh.cloud);
2142 pcl::PointCloud<pcl::Normal>::Ptr normals;
2159 if(laserScan.
is2d())
2176 if(laserScan.
is2d())
2191 template<
typename Po
intT>
2193 const typename pcl::PointCloud<PointT>::Ptr & cloud,
2194 const pcl::IndicesPtr & indices,
2197 const Eigen::Vector3f & viewPoint)
2199 typename pcl::search::KdTree<PointT>::Ptr
tree (
new pcl::search::KdTree<PointT>);
2202 tree->setInputCloud(cloud, indices);
2206 tree->setInputCloud (cloud);
2211 pcl::NormalEstimationOMP<PointT, pcl::Normal> n;
2213 pcl::NormalEstimation<PointT, pcl::Normal> n;
2215 pcl::PointCloud<pcl::Normal>::Ptr normals (
new pcl::PointCloud<pcl::Normal>);
2216 n.setInputCloud (cloud);
2222 n.setSearchMethod (tree);
2223 n.setKSearch (searchK);
2224 n.setRadiusSearch (searchRadius);
2225 n.setViewPoint(viewPoint[0], viewPoint[1], viewPoint[2]);
2226 n.compute (*normals);
2231 const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
2234 const Eigen::Vector3f & viewPoint)
2236 pcl::IndicesPtr indices(
new std::vector<int>);
2237 return computeNormals(cloud, indices, searchK, searchRadius, viewPoint);
2240 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
2243 const Eigen::Vector3f & viewPoint)
2245 pcl::IndicesPtr indices(
new std::vector<int>);
2246 return computeNormals(cloud, indices, searchK, searchRadius, viewPoint);
2249 const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
2252 const Eigen::Vector3f & viewPoint)
2254 pcl::IndicesPtr indices(
new std::vector<int>);
2255 return computeNormals(cloud, indices, searchK, searchRadius, viewPoint);
2258 const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
2259 const pcl::IndicesPtr & indices,
2262 const Eigen::Vector3f & viewPoint)
2264 return computeNormalsImpl<pcl::PointXYZ>(cloud, indices, searchK, searchRadius, viewPoint);
2267 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
2268 const pcl::IndicesPtr & indices,
2271 const Eigen::Vector3f & viewPoint)
2273 return computeNormalsImpl<pcl::PointXYZRGB>(cloud, indices, searchK, searchRadius, viewPoint);
2276 const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
2277 const pcl::IndicesPtr & indices,
2280 const Eigen::Vector3f & viewPoint)
2282 return computeNormalsImpl<pcl::PointXYZI>(cloud, indices, searchK, searchRadius, viewPoint);
2285 template<
typename Po
intT>
2287 const typename pcl::PointCloud<PointT>::Ptr & cloud,
2290 const Eigen::Vector3f & viewPoint)
2292 UASSERT(searchK>0 || searchRadius>0.0
f);
2293 pcl::PointCloud<pcl::Normal>::Ptr normals (
new pcl::PointCloud<pcl::Normal>);
2295 typename pcl::search::KdTree<PointT>::Ptr
tree (
new pcl::search::KdTree<PointT>);
2296 tree->setInputCloud (cloud);
2298 normals->resize(cloud->size());
2300 float bad_point = std::numeric_limits<float>::quiet_NaN ();
2303 for(
unsigned int i=0; i<cloud->size(); ++i)
2305 const PointT & pt = cloud->at(i);
2306 std::vector<Eigen::Vector3f> neighborNormals;
2307 Eigen::Vector3f direction;
2308 direction[0] = viewPoint[0] - pt.x;
2309 direction[1] = viewPoint[1] - pt.y;
2310 direction[2] = viewPoint[2] - pt.z;
2312 std::vector<int> k_indices;
2313 std::vector<float> k_sqr_distances;
2314 if(searchRadius>0.0
f)
2316 tree->radiusSearch(cloud->at(i), searchRadius, k_indices, k_sqr_distances, searchK);
2320 tree->nearestKSearch(cloud->at(i), searchK, k_indices, k_sqr_distances);
2323 for(
unsigned int j=0; j<k_indices.size(); ++j)
2325 if(k_indices.at(j) != (int)i)
2327 const PointT & pt2 = cloud->at(k_indices.at(j));
2328 Eigen::Vector3f v(pt2.x-pt.x, pt2.y - pt.y, pt2.z - pt.z);
2329 Eigen::Vector3f up = v.cross(direction);
2330 Eigen::Vector3f n = up.cross(v);
2332 neighborNormals.push_back(n);
2336 if(neighborNormals.empty())
2338 normals->at(i).normal_x = bad_point;
2339 normals->at(i).normal_y = bad_point;
2340 normals->at(i).normal_z = bad_point;
2344 Eigen::Vector3f meanNormal(0,0,0);
2345 for(
unsigned int j=0; j<neighborNormals.size(); ++j)
2347 meanNormal+=neighborNormals[j];
2349 meanNormal /= (float)neighborNormals.size();
2350 meanNormal.normalize();
2351 normals->at(i).normal_x = meanNormal[0];
2352 normals->at(i).normal_y = meanNormal[1];
2353 normals->at(i).normal_z = meanNormal[2];
2360 const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
2363 const Eigen::Vector3f & viewPoint)
2365 return computeNormals2DImpl<pcl::PointXYZ>(cloud, searchK, searchRadius, viewPoint);
2368 const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
2371 const Eigen::Vector3f & viewPoint)
2373 return computeNormals2DImpl<pcl::PointXYZI>(cloud, searchK, searchRadius, viewPoint);
2376 template<
typename Po
intT>
2378 const typename pcl::PointCloud<PointT>::Ptr & cloud,
2381 const Eigen::Vector3f & viewPoint)
2384 pcl::PointCloud<pcl::Normal>::Ptr normals (
new pcl::PointCloud<pcl::Normal>);
2386 normals->resize(cloud->size());
2387 searchRadius *= searchRadius;
2389 float bad_point = std::numeric_limits<float>::quiet_NaN ();
2392 for(
int i=0; i<(int)cloud->size(); ++i)
2400 if(hi>=(
int)cloud->size())
2402 hi=(int)cloud->size()-1;
2406 const PointT & pt = cloud->at(i);
2407 std::vector<Eigen::Vector3f> neighborNormals;
2408 Eigen::Vector3f direction;
2409 direction[0] = viewPoint[0] - cloud->at(i).x;
2410 direction[1] = viewPoint[1] - cloud->at(i).y;
2411 direction[2] = viewPoint[2] - cloud->at(i).z;
2412 for(
int j=i-1; j>=li; --j)
2414 const PointT & pt2 = cloud->at(j);
2415 Eigen::Vector3f vd(pt2.x-pt.x, pt2.y - pt.y, pt2.z - pt.z);
2416 if(searchRadius<=0.0
f || (vd[0]*vd[0] + vd[1]*vd[1] + vd[2]*vd[2]) < searchRadius)
2418 Eigen::Vector3f v(pt2.x-pt.x, pt2.y - pt.y, pt2.z - pt.z);
2419 Eigen::Vector3f up = v.cross(direction);
2420 Eigen::Vector3f n = up.cross(v);
2422 neighborNormals.push_back(n);
2429 for(
int j=i+1; j<=hi; ++j)
2431 const PointT & pt2 = cloud->at(j);
2432 Eigen::Vector3f vd(pt2.x-pt.x, pt2.y - pt.y, pt2.z - pt.z);
2433 if(searchRadius<=0.0
f || (vd[0]*vd[0] + vd[1]*vd[1] + vd[2]*vd[2]) < searchRadius)
2435 Eigen::Vector3f v(pt2.x-pt.x, pt2.y - pt.y, pt2.z - pt.z);
2436 Eigen::Vector3f up = v[2]==0.0f?Eigen::Vector3f(0,0,1):v.cross(direction);
2437 Eigen::Vector3f n = up.cross(v);
2439 neighborNormals.push_back(n);
2447 if(neighborNormals.empty())
2449 normals->at(i).normal_x = bad_point;
2450 normals->at(i).normal_y = bad_point;
2451 normals->at(i).normal_z = bad_point;
2455 Eigen::Vector3f meanNormal(0,0,0);
2456 for(
unsigned int j=0; j<neighborNormals.size(); ++j)
2458 meanNormal+=neighborNormals[j];
2460 meanNormal /= (float)neighborNormals.size();
2461 meanNormal.normalize();
2462 normals->at(i).normal_x = meanNormal[0];
2463 normals->at(i).normal_y = meanNormal[1];
2464 normals->at(i).normal_z = meanNormal[2];
2472 const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
2475 const Eigen::Vector3f & viewPoint)
2477 return computeFastOrganizedNormals2DImpl<pcl::PointXYZ>(cloud, searchK, searchRadius, viewPoint);
2480 const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
2483 const Eigen::Vector3f & viewPoint)
2485 return computeFastOrganizedNormals2DImpl<pcl::PointXYZI>(cloud, searchK, searchRadius, viewPoint);
2489 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
2490 float maxDepthChangeFactor,
2491 float normalSmoothingSize,
2492 const Eigen::Vector3f & viewPoint)
2494 pcl::IndicesPtr indices(
new std::vector<int>);
2498 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
2499 const pcl::IndicesPtr & indices,
2500 float maxDepthChangeFactor,
2501 float normalSmoothingSize,
2502 const Eigen::Vector3f & viewPoint)
2504 UASSERT(cloud->isOrganized());
2506 pcl::search::KdTree<pcl::PointXYZRGB>::Ptr
tree (
new pcl::search::KdTree<pcl::PointXYZRGB>);
2509 tree->setInputCloud(cloud, indices);
2513 tree->setInputCloud (cloud);
2517 pcl::PointCloud<pcl::Normal>::Ptr normals (
new pcl::PointCloud<pcl::Normal>);
2518 pcl::IntegralImageNormalEstimation<pcl::PointXYZRGB, pcl::Normal> ne;
2519 ne.setNormalEstimationMethod (ne.AVERAGE_3D_GRADIENT);
2520 ne.setMaxDepthChangeFactor(maxDepthChangeFactor);
2521 ne.setNormalSmoothingSize(normalSmoothingSize);
2522 ne.setBorderPolicy(ne.BORDER_POLICY_MIRROR);
2523 ne.setInputCloud(cloud);
2529 ne.setSearchMethod(tree);
2530 ne.setViewPoint(viewPoint[0], viewPoint[1], viewPoint[2]);
2531 ne.compute(*normals);
2538 cv::Mat * pcaEigenVectors,
2539 cv::Mat * pcaEigenValues)
2544 int sz =
static_cast<int>(scan.
size()*2);
2545 bool is2d = scan.
is2d();
2546 cv::Mat data_normals = cv::Mat::zeros(sz, is2d?2:3, CV_32FC1);
2557 for (
int i = 0; i < scan.
size(); ++i)
2559 const float * ptrScan = scan.
data().ptr<
float>(0, i);
2565 float * ptr = data_normals.ptr<
float>(oi++, 0);
2566 ptr[0] = ptrScan[2];
2567 ptr[1] = ptrScan[3];
2574 float * ptr = data_normals.ptr<
float>(oi++, 0);
2575 ptr[0] = ptrScan[3];
2576 ptr[1] = ptrScan[4];
2577 ptr[2] = ptrScan[5];
2583 cv::PCA pca_analysis(cv::Mat(data_normals, cv::Range(0, oi*2)), cv::Mat(), CV_PCA_DATA_AS_ROW);
2587 *pcaEigenVectors = pca_analysis.eigenvectors;
2591 *pcaEigenValues = pca_analysis.eigenvalues;
2595 return pca_analysis.eigenvalues.at<
float>(0, is2d?1:2)*(is2d?2.0
f:3.0
f);
2600 UERROR(
"Scan doesn't have normals!");
2606 const pcl::PointCloud<pcl::PointNormal> & cloud,
2608 cv::Mat * pcaEigenVectors,
2609 cv::Mat * pcaEigenValues)
2612 int sz =
static_cast<int>(cloud.size()*2);
2613 cv::Mat data_normals = cv::Mat::zeros(sz, is2d?2:3, CV_32FC1);
2615 for (
unsigned int i = 0; i < cloud.size(); ++i)
2617 const pcl::PointNormal & pt = cloud.at(i);
2620 float * ptr = data_normals.ptr<
float>(oi++, 0);
2621 ptr[0] = pt.normal_x;
2622 ptr[1] = pt.normal_y;
2625 ptr[2] = pt.normal_z;
2631 cv::PCA pca_analysis(cv::Mat(data_normals, cv::Range(0, oi*2)), cv::Mat(), CV_PCA_DATA_AS_ROW);
2635 *pcaEigenVectors = pca_analysis.eigenvectors;
2639 *pcaEigenValues = pca_analysis.eigenvalues;
2643 return pca_analysis.eigenvalues.at<
float>(0, is2d?1:2)*(is2d?2.0
f:3.0
f);
2649 const pcl::PointCloud<pcl::Normal> & normals,
2651 cv::Mat * pcaEigenVectors,
2652 cv::Mat * pcaEigenValues)
2655 int sz =
static_cast<int>(normals.size()*2);
2656 cv::Mat data_normals = cv::Mat::zeros(sz, is2d?2:3, CV_32FC1);
2658 for (
unsigned int i = 0; i < normals.size(); ++i)
2660 const pcl::Normal & pt = normals.at(i);
2663 float * ptr = data_normals.ptr<
float>(oi++, 0);
2664 ptr[0] = pt.normal_x;
2665 ptr[1] = pt.normal_y;
2668 ptr[2] = pt.normal_z;
2674 cv::PCA pca_analysis(cv::Mat(data_normals, cv::Range(0, oi*2)), cv::Mat(), CV_PCA_DATA_AS_ROW);
2678 *pcaEigenVectors = pca_analysis.eigenvectors;
2682 *pcaEigenValues = pca_analysis.eigenvalues;
2686 return pca_analysis.eigenvalues.at<
float>(0, is2d?1:2)*(is2d?2.0
f:3.0
f);
2692 const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud,
2694 cv::Mat * pcaEigenVectors,
2695 cv::Mat * pcaEigenValues)
2698 int sz =
static_cast<int>(cloud.size()*2);
2699 cv::Mat data_normals = cv::Mat::zeros(sz, is2d?2:3, CV_32FC1);
2701 for (
unsigned int i = 0; i < cloud.size(); ++i)
2703 const pcl::PointXYZRGBNormal & pt = cloud.at(i);
2706 float * ptr = data_normals.ptr<
float>(oi++, 0);
2707 ptr[0] = pt.normal_x;
2708 ptr[1] = pt.normal_y;
2711 ptr[2] = pt.normal_z;
2717 cv::PCA pca_analysis(cv::Mat(data_normals, cv::Range(0, oi*2)), cv::Mat(), CV_PCA_DATA_AS_ROW);
2721 *pcaEigenVectors = pca_analysis.eigenvectors;
2725 *pcaEigenValues = pca_analysis.eigenvalues;
2729 return pca_analysis.eigenvalues.at<
float>(0, is2d?1:2)*(is2d?2.0
f:3.0
f);
2734 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr
mls(
2735 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
2737 int polygonialOrder,
2738 int upsamplingMethod,
2739 float upsamplingRadius,
2740 float upsamplingStep,
2742 float dilationVoxelSize,
2743 int dilationIterations)
2745 pcl::IndicesPtr indices(
new std::vector<int>);
2755 dilationIterations);
2758 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr
mls(
2759 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
2760 const pcl::IndicesPtr & indices,
2762 int polygonialOrder,
2763 int upsamplingMethod,
2764 float upsamplingRadius,
2765 float upsamplingStep,
2767 float dilationVoxelSize,
2768 int dilationIterations)
2770 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud_with_normals(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
2771 pcl::search::KdTree<pcl::PointXYZRGB>::Ptr
tree (
new pcl::search::KdTree<pcl::PointXYZRGB>);
2774 tree->setInputCloud (cloud, indices);
2778 tree->setInputCloud (cloud);
2782 pcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGBNormal>
mls;
2785 mls.setComputeNormals (
true);
2786 if(polygonialOrder > 0)
2788 mls.setPolynomialFit (
true);
2789 mls.setPolynomialOrder(polygonialOrder);
2793 mls.setPolynomialFit (
false);
2795 UASSERT(upsamplingMethod >= mls.NONE &&
2796 upsamplingMethod <= mls.VOXEL_GRID_DILATION);
2797 mls.setUpsamplingMethod((pcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGBNormal>::UpsamplingMethod)upsamplingMethod);
2798 mls.setSearchRadius(searchRadius);
2799 mls.setUpsamplingRadius(upsamplingRadius);
2800 mls.setUpsamplingStepSize(upsamplingStep);
2801 mls.setPointDensity(pointDensity);
2802 mls.setDilationVoxelSize(dilationVoxelSize);
2803 mls.setDilationIterations(dilationIterations);
2806 mls.setInputCloud (cloud);
2809 mls.setIndices(indices);
2811 mls.setSearchMethod (tree);
2812 mls.process (*cloud_with_normals);
2815 for(
unsigned int i=0; i<cloud_with_normals->size(); ++i)
2817 Eigen::Vector3f normal(cloud_with_normals->at(i).normal_x, cloud_with_normals->at(i).normal_y, cloud_with_normals->at(i).normal_z);
2819 cloud_with_normals->at(i).normal_x = normal[0];
2820 cloud_with_normals->at(i).normal_y = normal[1];
2821 cloud_with_normals->at(i).normal_z = normal[2];
2824 return cloud_with_normals;
2829 const Eigen::Vector3f & viewpoint,
2830 bool forceGroundNormalsUp)
2837 cv::Mat output = scan.
data().clone();
2838 for(
int i=0; i<scan.
size(); ++i)
2840 float * ptr = output.ptr<
float>(0, i);
2843 Eigen::Vector3f v = viewpoint - Eigen::Vector3f(ptr[0], ptr[1], ptr[2]);
2844 Eigen::Vector3f n(ptr[nx], ptr[ny], ptr[nz]);
2846 float result = v.dot(n);
2848 || (forceGroundNormalsUp && ptr[nz] < -0.8 && ptr[2] < viewpoint[3]))
2863 pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
2864 const Eigen::Vector3f & viewpoint,
2865 bool forceGroundNormalsUp)
2867 for(
unsigned int i=0; i<cloud->size(); ++i)
2869 pcl::PointXYZ normal(cloud->points[i].normal_x, cloud->points[i].normal_y, cloud->points[i].normal_z);
2872 Eigen::Vector3f v = viewpoint - cloud->points[i].getVector3fMap();
2873 Eigen::Vector3f n(normal.x, normal.y, normal.z);
2875 float result = v.dot(n);
2877 || (forceGroundNormalsUp && normal.z < -0.8 && cloud->points[i].z < viewpoint[3]))
2880 cloud->points[i].normal_x *= -1.0f;
2881 cloud->points[i].normal_y *= -1.0f;
2882 cloud->points[i].normal_z *= -1.0f;
2889 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
2890 const Eigen::Vector3f & viewpoint,
2891 bool forceGroundNormalsUp)
2893 for(
unsigned int i=0; i<cloud->size(); ++i)
2895 pcl::PointXYZ normal(cloud->points[i].normal_x, cloud->points[i].normal_y, cloud->points[i].normal_z);
2898 Eigen::Vector3f v = viewpoint - cloud->points[i].getVector3fMap();
2899 Eigen::Vector3f n(normal.x, normal.y, normal.z);
2901 float result = v.dot(n);
2903 || (forceGroundNormalsUp && normal.z < -0.8 && cloud->points[i].z < viewpoint[3]))
2906 cloud->points[i].normal_x *= -1.0f;
2907 cloud->points[i].normal_y *= -1.0f;
2908 cloud->points[i].normal_z *= -1.0f;
2915 const std::map<int, Transform> & poses,
2916 const pcl::PointCloud<pcl::PointXYZ>::Ptr & rawCloud,
2917 const std::vector<int> & rawCameraIndices,
2918 pcl::PointCloud<pcl::PointNormal>::Ptr & cloud)
2920 if(poses.size() && rawCloud->size() && rawCloud->size() == rawCameraIndices.size() && cloud->size())
2922 pcl::search::KdTree<pcl::PointXYZ>::Ptr rawTree (
new pcl::search::KdTree<pcl::PointXYZ>);
2923 rawTree->setInputCloud (rawCloud);
2925 for(
unsigned int i=0; i<cloud->size(); ++i)
2927 pcl::PointXYZ normal(cloud->points[i].normal_x, cloud->points[i].normal_y, cloud->points[i].normal_z);
2930 std::vector<int> indices;
2931 std::vector<float> dist;
2932 rawTree->nearestKSearch(pcl::PointXYZ(cloud->points[i].x, cloud->points[i].y, cloud->points[i].z), 1, indices, dist);
2934 if(indices.size() && indices[0]>=0)
2936 Transform p = poses.at(rawCameraIndices[indices[0]]);
2937 pcl::PointXYZ viewpoint(p.
x(), p.
y(), p.
z());
2938 Eigen::Vector3f v = viewpoint.getVector3fMap() - cloud->points[i].getVector3fMap();
2940 Eigen::Vector3f n(normal.x, normal.y, normal.z);
2942 float result = v.dot(n);
2946 cloud->points[i].normal_x *= -1.0f;
2947 cloud->points[i].normal_y *= -1.0f;
2948 cloud->points[i].normal_z *= -1.0f;
2953 UWARN(
"Not found camera viewpoint for point %d", i);
2961 const std::map<int, Transform> & poses,
2962 const pcl::PointCloud<pcl::PointXYZ>::Ptr & rawCloud,
2963 const std::vector<int> & rawCameraIndices,
2964 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud)
2966 UASSERT(rawCloud.get() && cloud.get());
2967 UDEBUG(
"poses=%d, rawCloud=%d, rawCameraIndices=%d, cloud=%d", (
int)poses.size(), (int)rawCloud->size(), (int)rawCameraIndices.size(), (int)cloud->size());
2968 if(poses.size() && rawCloud->size() && rawCloud->size() == rawCameraIndices.size() && cloud->size())
2970 pcl::search::KdTree<pcl::PointXYZ>::Ptr rawTree (
new pcl::search::KdTree<pcl::PointXYZ>);
2971 rawTree->setInputCloud (rawCloud);
2972 for(
unsigned int i=0; i<cloud->size(); ++i)
2974 pcl::PointXYZ normal(cloud->points[i].normal_x, cloud->points[i].normal_y, cloud->points[i].normal_z);
2977 std::vector<int> indices;
2978 std::vector<float> dist;
2979 rawTree->nearestKSearch(pcl::PointXYZ(cloud->points[i].x, cloud->points[i].y, cloud->points[i].z), 1, indices, dist);
2980 if(indices.size() && indices[0]>=0)
2982 UASSERT_MSG(indices[0]<(
int)rawCameraIndices.size(),
uFormat(
"indices[0]=%d rawCameraIndices.size()=%d", indices[0], (
int)rawCameraIndices.size()).c_str());
2984 Transform p = poses.at(rawCameraIndices[indices[0]]);
2985 pcl::PointXYZ viewpoint(p.
x(), p.
y(), p.
z());
2986 Eigen::Vector3f v = viewpoint.getVector3fMap() - cloud->points[i].getVector3fMap();
2988 Eigen::Vector3f n(normal.x, normal.y, normal.z);
2990 float result = v.dot(n);
2994 cloud->points[i].normal_x *= -1.0f;
2995 cloud->points[i].normal_y *= -1.0f;
2996 cloud->points[i].normal_z *= -1.0f;
3001 UWARN(
"Not found camera viewpoint for point %d!?", i);
3008 pcl::PolygonMesh::Ptr
meshDecimation(
const pcl::PolygonMesh::Ptr & mesh,
float factor)
3010 pcl::PolygonMesh::Ptr output(
new pcl::PolygonMesh);
3012 pcl::MeshQuadricDecimationVTK mqd;
3013 mqd.setTargetReductionFactor(factor);
3014 mqd.setInputMesh(mesh);
3015 mqd.process (*output);
3017 UWARN(
"RTAB-Map is not built with VTK module so mesh decimation cannot be used!");
bool uIsInteger(const std::string &str, bool checkForSign=true)
int UTILITE_EXP uStr2Int(const std::string &str)
LaserScan RTABMAP_EXP laserScanFromPointCloud(const pcl::PCLPointCloud2 &cloud, bool filterNaNs=true)
std::vector< int > RTABMAP_EXP filterNaNPointsFromMesh(const pcl::PointCloud< pcl::PointXYZRGB > &cloud, const std::vector< pcl::Vertices > &polygons, pcl::PointCloud< pcl::PointXYZRGB > &outputCloud, std::vector< pcl::Vertices > &outputPolygons)
T uVariance(const T *v, unsigned int size, T meanV)
bool RTABMAP_EXP isFinite(const cv::Point3f &pt)
cv::Mat RTABMAP_EXP mergeTextures(pcl::TextureMesh &mesh, const std::map< int, cv::Mat > &images, const std::map< int, CameraModel > &calibrations, const Memory *memory=0, const DBDriver *dbDriver=0, int textureSize=4096, int textureCount=1, const std::vector< std::map< int, pcl::PointXY > > &vertexToPixels=std::vector< std::map< int, pcl::PointXY > >(), bool gainCompensation=true, float gainBeta=10.0f, bool gainRGB=true, bool blending=true, int blendingDecimation=0, int brightnessContrastRatioLow=0, int brightnessContrastRatioHigh=0, bool exposureFusion=false, const ProgressState *state=0)
void setViewpoint(const Eigen::Vector3f &viewpoint)
Set the viewpoint from where the input point cloud has been acquired.
rtabmap::CameraThread * cam
void uncompressDataConst(cv::Mat *imageRaw, cv::Mat *depthOrRightRaw, LaserScan *laserScanRaw=0, cv::Mat *userDataRaw=0, cv::Mat *groundCellsRaw=0, cv::Mat *obstacleCellsRaw=0, cv::Mat *emptyCellsRaw=0) const
T uMean(const T *v, unsigned int size)
pcl::TextureMesh::Ptr RTABMAP_EXP concatenateTextureMeshes(const std::list< pcl::TextureMesh::Ptr > &meshes)
pcl::PointCloud< pcl::Normal >::Ptr computeNormals2DImpl(const typename pcl::PointCloud< PointT >::Ptr &cloud, int searchK, float searchRadius, const Eigen::Vector3f &viewPoint)
const cv::Size & imageSize() const
const cv::Mat & data() const
pcl::PointCloud< pcl::Normal >::Ptr RTABMAP_EXP computeNormals2D(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, int searchK=5, float searchRadius=0.0f, const Eigen::Vector3f &viewPoint=Eigen::Vector3f(0, 0, 0))
pcl::TextureMesh::Ptr RTABMAP_EXP createTextureMesh(const pcl::PolygonMesh::Ptr &mesh, const std::map< int, Transform > &poses, const std::map< int, CameraModel > &cameraModels, const std::map< int, cv::Mat > &cameraDepths, float maxDistance=0.0f, float maxDepthError=0.0f, float maxAngle=0.0f, int minClusterSize=50, const std::vector< float > &roiRatios=std::vector< float >(), const ProgressState *state=0, std::vector< std::map< int, pcl::PointXY > > *vertexToPixels=0)
void setTriangulationType(TriangulationType type)
Set the triangulation type (see TriangulationType)
Simple triangulation/surface reconstruction for organized point clouds. Neighboring points (pixels in...
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)
std::vector< pcl::Vertices > RTABMAP_EXP filterCloseVerticesFromMesh(const pcl::PointCloud< pcl::PointXYZRGBNormal >::Ptr cloud, const std::vector< pcl::Vertices > &polygons, float radius, float angle, bool keepLatestInRadius)
const float maxDepthError
pcl::PointCloud< pcl::PointXYZRGBNormal >::Ptr RTABMAP_EXP laserScanToPointCloudRGBNormal(const LaserScan &laserScan, const Transform &transform=Transform(), unsigned char r=255, unsigned char g=255, unsigned char b=255)
pcl::PointCloud< pcl::Normal >::Ptr computeNormalsImpl(const typename pcl::PointCloud< PointT >::Ptr &cloud, const pcl::IndicesPtr &indices, int searchK, float searchRadius, const Eigen::Vector3f &viewPoint)
std::vector< int > RTABMAP_EXP filterNotUsedVerticesFromMesh(const pcl::PointCloud< pcl::PointXYZRGBNormal > &cloud, const std::vector< pcl::Vertices > &polygons, pcl::PointCloud< pcl::PointXYZRGBNormal > &outputCloud, std::vector< pcl::Vertices > &outputPolygons)
The texture mapping algorithm.
void setAngleTolerance(float angle_tolerance)
Set the angle tolerance used for checking whether or not an edge is occluded. Standard values are 5de...
GLM_FUNC_DECL bool all(vecType< bool, P > const &v)
static const float vertices[]
void getNodeData(int signatureId, SensorData &data, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const
void setMinClusterSize(int size)
pcl::PointCloud< pcl::Normal >::Ptr RTABMAP_EXP computeFastOrganizedNormals(const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &cloud, float maxDepthChangeFactor=0.02f, float normalSmoothingSize=10.0f, const Eigen::Vector3f &viewPoint=Eigen::Vector3f(0, 0, 0))
GLM_FUNC_DECL genType::row_type row(genType const &m, length_t const &index)
int getNormalsOffset() const
Basic mathematics functions.
GLM_FUNC_DECL T angle(detail::tquat< T, P > const &x)
Some conversion functions.
pcl::PointCloud< pcl::Normal >::Ptr computeFastOrganizedNormals2DImpl(const typename pcl::PointCloud< PointT >::Ptr &cloud, int searchK, float searchRadius, const Eigen::Vector3f &viewPoint)
pcl::PointCloud< pcl::Normal >::Ptr RTABMAP_EXP computeFastOrganizedNormals2D(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, int searchK=5, float searchRadius=0.0f, const Eigen::Vector3f &viewPoint=Eigen::Vector3f(0, 0, 0))
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP laserScanToPointCloud(const LaserScan &laserScan, const Transform &transform=Transform())
std::vector< std::vector< unsigned int > > RTABMAP_EXP convertPolygonsFromPCL(const std::vector< pcl::Vertices > &polygons)
std::list< std::string > uSplit(const std::string &str, char separator= ' ')
std::vector< double > roi
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud< pcl::PointXYZ > &cloud, const Transform &transform=Transform(), bool filterNaNs=true)
pcl::PointCloud< pcl::PointXYZRGBNormal >::Ptr RTABMAP_EXP mls(const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &cloud, float searchRadius=0.0f, int polygonialOrder=2, int upsamplingMethod=0, float upsamplingRadius=0.0f, float upsamplingStep=0.0f, int pointDensity=0, float dilationVoxelSize=1.0f, int dilationIterations=0)
bool uIsFinite(const T &value)
pcl::texture_mapping::CameraVector createTextureCameras(const std::map< int, Transform > &poses, const std::map< int, std::vector< CameraModel > > &cameraModels, const std::map< int, cv::Mat > &cameraDepths, const std::vector< float > &roiRatios)
#define UASSERT(condition)
Structure to store camera pose and focal length.
virtual bool callback(const std::string &msg) const
std::vector< pcl::Vertices > RTABMAP_EXP convertPolygonsToPCL(const std::vector< std::vector< unsigned int > > &polygons)
const CameraModel & left() const
std::list< std::list< int > > RTABMAP_EXP clusterPolygons(const std::vector< std::set< int > > &neighborPolygons, int minClusterSize=0)
void setTrianglePixelSize(int triangle_size)
Set the edge length (in pixels) used for constructing the fixed mesh.
pcl::PolygonMesh::Ptr RTABMAP_EXP meshDecimation(const pcl::PolygonMesh::Ptr &mesh, float factor)
void RTABMAP_EXP appendMesh(pcl::PointCloud< pcl::PointXYZRGBNormal > &cloudA, std::vector< pcl::Vertices > &polygonsA, const pcl::PointCloud< pcl::PointXYZRGBNormal > &cloudB, const std::vector< pcl::Vertices > &polygonsB)
#define UASSERT_MSG(condition, msg_str)
cv::Mat RTABMAP_EXP brightnessAndContrastAuto(const cv::Mat &src, const cv::Mat &mask, float clipLowHistPercent=0, float clipHighHistPercent=0)
Automatic brightness and contrast optimization with optional histogram clipping.
GLM_FUNC_DECL genType pi()
bool getCalibration(int signatureId, std::vector< CameraModel > &models, StereoCameraModel &stereoModel) const
cv::Mat RTABMAP_EXP computeNormals(const cv::Mat &laserScan, int searchK, float searchRadius)
pcl::TextureMesh::Ptr RTABMAP_EXP assembleTextureMesh(const cv::Mat &cloudMat, const std::vector< std::vector< std::vector< unsigned int > > > &polygons, const std::vector< std::vector< Eigen::Vector2f > > &texCoords, cv::Mat &textures, bool mergeTextures=false)
Transform localTransform() const
void setMaxDepthError(float maxDepthError)
SensorData getSignatureDataConst(int locationId, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const
pcl::PolygonMesh::Ptr RTABMAP_EXP createMesh(const pcl::PointCloud< pcl::PointXYZRGBNormal >::Ptr &cloudWithNormals, float gp3SearchRadius=0.025, float gp3Mu=2.5, int gp3MaximumNearestNeighbors=100, float gp3MaximumSurfaceAngle=M_PI/4, float gp3MinimumAngle=M_PI/18, float gp3MaximumAngle=2 *M_PI/3, bool gp3NormalConsistency=true)
std::vector< pcl::Vertices > RTABMAP_EXP organizedFastMesh(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, double angleTolerance, bool quad, int trianglePixelSize, const Eigen::Vector3f &viewpoint=Eigen::Vector3f(0, 0, 0))
void RTABMAP_EXP concatenateTextureMaterials(pcl::TextureMesh &mesh, const cv::Size &imageSize, int textureSize, int maxTextures, float &scale, std::vector< bool > *materialsKept=0)
bool uContains(const std::list< V > &list, const V &value)
RecoveryProgressState state
cv::Mat RTABMAP_EXP exposureFusion(const std::vector< cv::Mat > &images)
void RTABMAP_EXP adjustNormalsToViewPoints(const std::map< int, Transform > &poses, const pcl::PointCloud< pcl::PointXYZ >::Ptr &rawCloud, const std::vector< int > &rawCameraIndices, pcl::PointCloud< pcl::PointNormal >::Ptr &cloud)
void RTABMAP_EXP fixTextureMeshForVisualization(pcl::TextureMesh &textureMesh)
float RTABMAP_EXP computeNormalsComplexity(const LaserScan &scan, cv::Mat *pcaEigenVectors=0, cv::Mat *pcaEigenValues=0)
const std::vector< CameraModel > & cameraModels() const
std::vector< pcl::Vertices > RTABMAP_EXP filterInvalidPolygons(const std::vector< pcl::Vertices > &polygons)
void RTABMAP_EXP cleanTextureMesh(pcl::TextureMesh &textureMesh, int minClusterSize)
pcl::PointCloud< pcl::PointNormal >::Ptr RTABMAP_EXP laserScanToPointCloudNormal(const LaserScan &laserScan, const Transform &transform=Transform())
LaserScan RTABMAP_EXP adjustNormalsToViewPoint(const LaserScan &scan, const Eigen::Vector3f &viewpoint, bool forceGroundNormalsUp)
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...
ULogger class and convenient macros.
const StereoCameraModel & stereoCameraModel() const
void setMaxAngle(float maxAngle)
pcl::PointCloud< pcl::PointNormal >::Ptr RTABMAP_EXP removeNaNNormalsFromPointCloud(const pcl::PointCloud< pcl::PointNormal >::Ptr &cloud)
void setMaxDistance(float maxDistance)
static const GLushort kIndices[]
pcl::PointCloud< pcl::PointXYZI >::Ptr RTABMAP_EXP laserScanToPointCloudI(const LaserScan &laserScan, const Transform &transform=Transform(), float intensity=0.0f)
T uSum(const std::list< T > &list)
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::string UTILITE_EXP uNumber2Str(unsigned int number)
static LaserScan backwardCompatibility(const cv::Mat &oldScanFormat, int maxPoints=0, int maxRange=0, const Transform &localTransform=Transform::getIdentity())
pcl::PointCloud< pcl::PointXYZRGB >::Ptr RTABMAP_EXP laserScanToPointCloudRGB(const LaserScan &laserScan, const Transform &transform=Transform(), unsigned char r=255, unsigned char g=255, unsigned char b=255)
bool hasIntensity() const
cv::Mat RTABMAP_EXP uncompressImage(const cv::Mat &bytes)
pcl::PolygonMesh::Ptr RTABMAP_EXP assemblePolygonMesh(const cv::Mat &cloudMat, const std::vector< std::vector< unsigned int > > &polygons)