diff --git a/corelib/include/rtabmap/core/ProgressState.h b/corelib/include/rtabmap/core/ProgressState.h new file mode 100644 index 00000000..256a2a3f --- /dev/null +++ b/corelib/include/rtabmap/core/ProgressState.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Universite de Sherbrooke nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef CORELIB_INCLUDE_RTABMAP_CORE_PROGRESSSTATE_H_ +#define CORELIB_INCLUDE_RTABMAP_CORE_PROGRESSSTATE_H_ + + +class ProgressState +{ +public: + virtual bool callback(const std::string & msg) const + { + return true; + } + virtual ~ProgressState(){} +}; + + +#endif /* CORELIB_INCLUDE_RTABMAP_CORE_PROGRESSSTATE_H_ */ diff --git a/corelib/include/rtabmap/core/util3d_surface.h b/corelib/include/rtabmap/core/util3d_surface.h index 3c06abe9..29a626df 100644 --- a/corelib/include/rtabmap/core/util3d_surface.h +++ b/corelib/include/rtabmap/core/util3d_surface.h @@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include @@ -136,7 +137,8 @@ pcl::TextureMesh::Ptr RTABMAP_EXP createTextureMesh( const pcl::PolygonMesh::Ptr & mesh, const std::map & poses, const std::map & cameraModels, - float maxDistance = 0.0f); // max camera distance to polygon to apply texture + float maxDistance = 0.0f, // max camera distance to polygon to apply texture + const ProgressState * state = 0); pcl::PointCloud::Ptr RTABMAP_EXP computeNormals( const pcl::PointCloud::Ptr & cloud, diff --git a/corelib/src/GainCompensator.cpp b/corelib/src/GainCompensator.cpp index 782fa66c..ced27368 100644 --- a/corelib/src/GainCompensator.cpp +++ b/corelib/src/GainCompensator.cpp @@ -305,11 +305,11 @@ void feedImpl( gains = cv::Mat_(); cv::solve(A, b, gains); - //if(ULogger::kDebug) + if(ULogger::kInfo) { for(int i=0; i #include +#include /////////////////////////////////////////////////////////////////////////////////////////////// template std::vector > @@ -1012,17 +1013,20 @@ class FaceInfo { public: FaceInfo(float d, + bool facingCam, const pcl::PointXY & uv1, const pcl::PointXY & uv2, const pcl::PointXY & uv3, const pcl::PointXY & center) : distance(d), + facingTheCam(facingCam), uv_coord1(uv1), uv_coord2(uv2), uv_coord3(uv3), uv_center(center) {} float distance; + bool facingTheCam; pcl::PointXY uv_coord1; pcl::PointXY uv_coord2; pcl::PointXY uv_coord3; @@ -1039,12 +1043,15 @@ bool ptInTriangle(const pcl::PointXY & p0, const pcl::PointXY & p1, const pcl::P } /////////////////////////////////////////////////////////////////////////////////////////////// -template void -pcl::TextureMapping::textureMeshwithMultipleCameras2 (pcl::TextureMesh &mesh, const pcl::texture_mapping::CameraVector &cameras) +template bool +pcl::TextureMapping::textureMeshwithMultipleCameras2 ( + pcl::TextureMesh &mesh, + const pcl::texture_mapping::CameraVector &cameras, + const ProgressState * state) { if (mesh.tex_polygons.size () != 1) - return; + return false; typename pcl::PointCloud::Ptr mesh_cloud (new pcl::PointCloud); @@ -1061,10 +1068,10 @@ pcl::TextureMapping::textureMeshwithMultipleCameras2 (pcl::TextureMesh // pre compute all cam inverse and visibility std::vector > visibleFaces(cameras.size()); std::vector invCamTransform(cameras.size()); - UDEBUG("Precompute visible faces per cam"); + UINFO("Precompute visible faces per cam (%d faces, %d cams)", (int)faces.size(), (int)cameras.size()); for (unsigned int current_cam = 0; current_cam < cameras.size(); ++current_cam) { - UINFO("Processing camera %d...", current_cam); + UDEBUG("Texture camera %d...", current_cam); typename pcl::PointCloud::Ptr camera_cloud (new pcl::PointCloud); pcl::transformPointCloud(*mesh_cloud, *camera_cloud, cameras[current_cam].pose.inverse()); @@ -1072,36 +1079,53 @@ pcl::TextureMapping::textureMeshwithMultipleCameras2 (pcl::TextureMesh std::vector visibilityIndices; visibilityIndices.resize (faces.size ()); pcl::PointCloud::Ptr projections (new pcl::PointCloud); + projections->resize(faces.size()*3); + std::map sortedVisibleFaces; int oi=0; for(unsigned int idx_face=0; idx_faceat(j); + pcl::PointXY & uv_coords2 = projections->at(j+1); + pcl::PointXY & uv_coords3 = projections->at(j+2); PointInT & pt0 = camera_cloud->points[face.vertices[0]]; PointInT & pt1 = camera_cloud->points[face.vertices[1]]; PointInT & pt2 = camera_cloud->points[face.vertices[2]]; - float angle; if (isFaceProjected (cameras[current_cam], pt0, pt1, pt2, - uv_coords[0], - uv_coords[1], - uv_coords[2], - angle)) + uv_coords1, + uv_coords2, + uv_coords3)) { + // check if the polygon is facing the camera, assuming counterclockwise normal + Eigen::Vector3f v0( + pt1.x - pt0.x, + pt1.y - pt0.y, + pt1.z - pt0.z); + Eigen::Vector3f v1( + pt2.x - pt0.x, + pt2.y - pt0.y, + pt2.z - pt0.z); + Eigen::Vector3f normal = v0.cross(v1); + float angle = normal.dot(Eigen::Vector3f(0.0f,0.0f,-1.0f)); + bool facingTheCam = angle>0.0f; + float distanceToCam = std::min(std::min(pt0.z, pt1.z), pt2.z); pcl::PointXY center; - center.x = (uv_coords[0].x+uv_coords[1].x+uv_coords[2].x)/3.0f; - center.y = (uv_coords[0].y+uv_coords[1].y+uv_coords[2].y)/3.0f; - visibleFaces[current_cam].insert(std::make_pair(idx_face, FaceInfo(distanceToCam, uv_coords[0], uv_coords[1], uv_coords[2], center))); - visibilityIndices[oi++] = idx_face; - projections->push_back(uv_coords[0]); - projections->push_back(uv_coords[1]); - projections->push_back(uv_coords[2]); + center.x = (uv_coords1.x+uv_coords2.x+uv_coords3.x)/3.0f; + center.y = (uv_coords1.y+uv_coords2.y+uv_coords3.y)/3.0f; + visibleFaces[current_cam].insert(visibleFaces[current_cam].end(), std::make_pair(idx_face, FaceInfo(distanceToCam, facingTheCam, uv_coords1, uv_coords2, uv_coords3, center))); + sortedVisibleFaces.insert(std::make_pair(distanceToCam, idx_face)); + visibilityIndices[oi] = idx_face; + ++oi; } } visibilityIndices.resize(oi); + projections->resize(oi*3); UASSERT(projections->size() == visibilityIndices.size()*3); //filter occluded polygons @@ -1115,9 +1139,11 @@ pcl::TextureMapping::textureMeshwithMultipleCameras2 (pcl::TextureMesh // then (idx_pcam == current_cam), check for self occlusions. At this stage, we skip faces that were already marked as occluded // project all faces int occludedFaces = 0; - for (unsigned int idx_vis = 0; idx_vis < visibilityIndices.size(); ++idx_vis) + for (std::map::iterator jter=sortedVisibleFaces.begin(); jter!=sortedVisibleFaces.end(); ++jter) + //for (unsigned int idx = 0; idxsecond; + //int idx_face = visibilityIndices[idx]; std::map::iterator iter= visibleFaces[current_cam].find(idx_face); if(iter != visibleFaces[current_cam].end()) { @@ -1210,13 +1236,36 @@ pcl::TextureMapping::textureMeshwithMultipleCameras2 (pcl::TextureMesh } } - UDEBUG("Filtered %d occluded and %d spurious polygons out of %d...", occludedFaces, clusterFaces, (int)visibilityIndices.size()); + std::string msg = uFormat("Processed camera %d/%d: %d occluded and %d spurious polygons out of %d", (int)current_cam+1, (int)cameras.size(), occludedFaces, clusterFaces, (int)visibilityIndices.size()); + UINFO(msg.c_str()); + if(state && !state->callback(msg)) + { + //cancelled! + UWARN("Texturing cancelled!"); + return false; + } } - UDEBUG("Process %d polygons...", (int)faces.size()); + std::string msg = uFormat("Texturing %d polygons...", (int)faces.size()); + UINFO(msg.c_str()); + if(state && !state->callback(msg)) + { + //cancelled! + UWARN("Texturing cancelled!"); + return false; + } for(unsigned int idx_face=0; idx_facecallback("")) + { + //cancelled! + UWARN("Texturing cancelled!"); + return false; + } + } pcl::Vertices & face = faces[idx_face]; int cameraIndex = -1; @@ -1225,7 +1274,7 @@ pcl::TextureMapping::textureMeshwithMultipleCameras2 (pcl::TextureMesh for (unsigned int current_cam = 0; current_cam < cameras.size(); ++current_cam) { std::map::iterator iter = visibleFaces[current_cam].find(idx_face); - if (iter != visibleFaces[current_cam].end()) + if (iter != visibleFaces[current_cam].end() && iter->second.facingTheCam) { float distanceToCam = iter->second.distance; @@ -1244,35 +1293,21 @@ pcl::TextureMapping::textureMeshwithMultipleCameras2 (pcl::TextureMesh if(cameraIndex >= 0) { - if(mesh.tex_polygons[cameraIndex].capacity() < mesh.tex_polygons[cameraIndex].size()+1) - { - mesh.tex_polygons[cameraIndex].reserve(mesh.tex_polygons[cameraIndex].size()+10); - } mesh.tex_polygons[cameraIndex].push_back(face); - if(mesh.tex_coordinates[cameraIndex].capacity() < mesh.tex_coordinates[cameraIndex].size()+3) - { - mesh.tex_coordinates[cameraIndex].reserve(mesh.tex_coordinates[cameraIndex].size()+30); - } mesh.tex_coordinates[cameraIndex].push_back(Eigen::Vector2f(uv_coords[0].x, uv_coords[0].y)); mesh.tex_coordinates[cameraIndex].push_back(Eigen::Vector2f(uv_coords[1].x, uv_coords[1].y)); mesh.tex_coordinates[cameraIndex].push_back(Eigen::Vector2f(uv_coords[2].x, uv_coords[2].y)); } else { - if(mesh.tex_polygons[cameras.size()].capacity() < mesh.tex_polygons[cameras.size()].size()+1) - { - mesh.tex_polygons[cameras.size()].reserve(mesh.tex_polygons[cameras.size()].size()+10); - } mesh.tex_polygons[cameras.size()].push_back(face); - if(mesh.tex_coordinates[cameras.size()].capacity() < mesh.tex_coordinates[cameras.size()].size()+3) - { - mesh.tex_coordinates[cameras.size()].reserve(mesh.tex_coordinates[cameras.size()].size()+30); - } mesh.tex_coordinates[cameras.size()].push_back(Eigen::Vector2f(-1.0,-1.0)); mesh.tex_coordinates[cameras.size()].push_back(Eigen::Vector2f(-1.0,-1.0)); mesh.tex_coordinates[cameras.size()].push_back(Eigen::Vector2f(-1.0,-1.0)); } } + UINFO("Process %d polygons...done!", (int)faces.size()); + return true; } /////////////////////////////////////////////////////////////////////////////////////////////// @@ -1396,28 +1431,13 @@ pcl::TextureMapping::checkPointInsideTriangle(const pcl::PointXY &p1, /////////////////////////////////////////////////////////////////////////////////////////////// template inline bool -pcl::TextureMapping::isFaceProjected (const Camera &camera, const PointInT &p1, const PointInT &p2, const PointInT &p3, pcl::PointXY &proj1, pcl::PointXY &proj2, pcl::PointXY &proj3, float & angle) +pcl::TextureMapping::isFaceProjected (const Camera &camera, const PointInT &p1, const PointInT &p2, const PointInT &p3, pcl::PointXY &proj1, pcl::PointXY &proj2, pcl::PointXY &proj3) { - // check if the polygon is facing the camera, assuming counterclockwise normal - Eigen::Vector3f v0( - p2.x - p1.x, - p2.y - p1.y, - p2.z - p1.z); - Eigen::Vector3f v1( - p3.x - p1.x, - p3.y - p1.y, - p3.z - p1.z); - Eigen::Vector3f normal = v0.cross(v1); - normal.normalize(); - angle = normal.dot(Eigen::Vector3f(0.0f,0.0f,-1.0f)); - - return angle > 0.0f && // toward the camera - (getPointUVCoordinates(p1, camera, proj1) - && - getPointUVCoordinates(p2, camera, proj2) - && - getPointUVCoordinates(p3, camera, proj3) - ); + return getPointUVCoordinates(p1, camera, proj1) + && + getPointUVCoordinates(p2, camera, proj2) + && + getPointUVCoordinates(p3, camera, proj3); } #define PCL_INSTANTIATE_TextureMapping(T) \ diff --git a/corelib/src/pcl18/surface/texture_mapping.h b/corelib/src/pcl18/surface/texture_mapping.h index faa18cb5..199d9c56 100644 --- a/corelib/src/pcl18/surface/texture_mapping.h +++ b/corelib/src/pcl18/surface/texture_mapping.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -341,9 +342,10 @@ namespace pcl void textureMeshwithMultipleCameras (pcl::TextureMesh &mesh, const pcl::texture_mapping::CameraVector &cameras); - void + bool textureMeshwithMultipleCameras2 (pcl::TextureMesh &mesh, - const pcl::texture_mapping::CameraVector &cameras); + const pcl::texture_mapping::CameraVector &cameras, + const ProgressState * callback = 0); protected: /** \brief mesh scale control. */ @@ -414,7 +416,7 @@ namespace pcl inline bool isFaceProjected (const Camera &camera, const PointInT &p1, const PointInT &p2, const PointInT &p3, - pcl::PointXY &proj1, pcl::PointXY &proj2, pcl::PointXY &proj3, float & angle); + pcl::PointXY &proj1, pcl::PointXY &proj2, pcl::PointXY &proj3); /** \brief Returns True if a point lays within a triangle * \details see http://www.blackpawn.com/texts/pointinpoly/default.html diff --git a/corelib/src/util3d_surface.cpp b/corelib/src/util3d_surface.cpp index 47aa3cb0..7b5490d0 100644 --- a/corelib/src/util3d_surface.cpp +++ b/corelib/src/util3d_surface.cpp @@ -607,7 +607,8 @@ pcl::TextureMesh::Ptr createTextureMesh( const pcl::PolygonMesh::Ptr & mesh, const std::map & poses, const std::map & cameraModels, - float maxDistance) + float maxDistance, + const ProgressState * state) { UASSERT(mesh->polygons.size()); pcl::TextureMesh::Ptr textureMesh(new pcl::TextureMesh); @@ -664,87 +665,87 @@ pcl::TextureMesh::Ptr createTextureMesh( // Texture by projection pcl::TextureMapping tm; // TextureMapping object that will perform the sort tm.setMaxDistance(maxDistance); - tm.textureMeshwithMultipleCameras2(*textureMesh, cameras); - - // compute normals for the mesh if not already here - bool hasNormals = false; - bool hasColors = false; - for(unsigned int i=0; icloud.fields.size(); ++i) + if(tm.textureMeshwithMultipleCameras2(*textureMesh, cameras, state)) { - if(textureMesh->cloud.fields[i].name.compare("normal_x") == 0) + // compute normals for the mesh if not already here + bool hasNormals = false; + bool hasColors = false; + for(unsigned int i=0; icloud.fields.size(); ++i) { - hasNormals = true; + if(textureMesh->cloud.fields[i].name.compare("normal_x") == 0) + { + hasNormals = true; + } + else if(textureMesh->cloud.fields[i].name.compare("rgb") == 0) + { + hasColors = true; + } } - else if(textureMesh->cloud.fields[i].name.compare("rgb") == 0) + if(!hasNormals) { - hasColors = true; + // use polygons + if(hasColors) + { + pcl::PointCloud::Ptr cloud (new pcl::PointCloud); + pcl::fromPCLPointCloud2(mesh->cloud, *cloud); + + for(unsigned int i=0; ipolygons.size(); ++i) + { + pcl::Vertices & v = mesh->polygons[i]; + UASSERT(v.vertices.size()>2); + Eigen::Vector3f v0( + cloud->at(v.vertices[1]).x - cloud->at(v.vertices[0]).x, + cloud->at(v.vertices[1]).y - cloud->at(v.vertices[0]).y, + cloud->at(v.vertices[1]).z - cloud->at(v.vertices[0]).z); + int last = v.vertices.size()-1; + Eigen::Vector3f v1( + cloud->at(v.vertices[last]).x - cloud->at(v.vertices[0]).x, + cloud->at(v.vertices[last]).y - cloud->at(v.vertices[0]).y, + cloud->at(v.vertices[last]).z - cloud->at(v.vertices[0]).z); + Eigen::Vector3f normal = v0.cross(v1); + normal.normalize(); + // flat normal (per face) + for(unsigned int j=0; jat(v.vertices[j]).normal_x = normal[0]; + cloud->at(v.vertices[j]).normal_y = normal[1]; + cloud->at(v.vertices[j]).normal_z = normal[2]; + } + } + pcl::toPCLPointCloud2 (*cloud, textureMesh->cloud); + } + else + { + pcl::PointCloud::Ptr cloud (new pcl::PointCloud); + pcl::fromPCLPointCloud2(mesh->cloud, *cloud); + + for(unsigned int i=0; ipolygons.size(); ++i) + { + pcl::Vertices & v = mesh->polygons[i]; + UASSERT(v.vertices.size()>2); + Eigen::Vector3f v0( + cloud->at(v.vertices[1]).x - cloud->at(v.vertices[0]).x, + cloud->at(v.vertices[1]).y - cloud->at(v.vertices[0]).y, + cloud->at(v.vertices[1]).z - cloud->at(v.vertices[0]).z); + int last = v.vertices.size()-1; + Eigen::Vector3f v1( + cloud->at(v.vertices[last]).x - cloud->at(v.vertices[0]).x, + cloud->at(v.vertices[last]).y - cloud->at(v.vertices[0]).y, + cloud->at(v.vertices[last]).z - cloud->at(v.vertices[0]).z); + Eigen::Vector3f normal = v0.cross(v1); + normal.normalize(); + // flat normal (per face) + for(unsigned int j=0; jat(v.vertices[j]).normal_x = normal[0]; + cloud->at(v.vertices[j]).normal_y = normal[1]; + cloud->at(v.vertices[j]).normal_z = normal[2]; + } + } + pcl::toPCLPointCloud2 (*cloud, textureMesh->cloud); + } } } - if(!hasNormals) - { - // use polygons - if(hasColors) - { - pcl::PointCloud::Ptr cloud (new pcl::PointCloud); - pcl::fromPCLPointCloud2(mesh->cloud, *cloud); - - for(unsigned int i=0; ipolygons.size(); ++i) - { - pcl::Vertices & v = mesh->polygons[i]; - UASSERT(v.vertices.size()>2); - Eigen::Vector3f v0( - cloud->at(v.vertices[1]).x - cloud->at(v.vertices[0]).x, - cloud->at(v.vertices[1]).y - cloud->at(v.vertices[0]).y, - cloud->at(v.vertices[1]).z - cloud->at(v.vertices[0]).z); - int last = v.vertices.size()-1; - Eigen::Vector3f v1( - cloud->at(v.vertices[last]).x - cloud->at(v.vertices[0]).x, - cloud->at(v.vertices[last]).y - cloud->at(v.vertices[0]).y, - cloud->at(v.vertices[last]).z - cloud->at(v.vertices[0]).z); - Eigen::Vector3f normal = v0.cross(v1); - normal.normalize(); - // flat normal (per face) - for(unsigned int j=0; jat(v.vertices[j]).normal_x = normal[0]; - cloud->at(v.vertices[j]).normal_y = normal[1]; - cloud->at(v.vertices[j]).normal_z = normal[2]; - } - } - pcl::toPCLPointCloud2 (*cloud, textureMesh->cloud); - } - else - { - pcl::PointCloud::Ptr cloud (new pcl::PointCloud); - pcl::fromPCLPointCloud2(mesh->cloud, *cloud); - - for(unsigned int i=0; ipolygons.size(); ++i) - { - pcl::Vertices & v = mesh->polygons[i]; - UASSERT(v.vertices.size()>2); - Eigen::Vector3f v0( - cloud->at(v.vertices[1]).x - cloud->at(v.vertices[0]).x, - cloud->at(v.vertices[1]).y - cloud->at(v.vertices[0]).y, - cloud->at(v.vertices[1]).z - cloud->at(v.vertices[0]).z); - int last = v.vertices.size()-1; - Eigen::Vector3f v1( - cloud->at(v.vertices[last]).x - cloud->at(v.vertices[0]).x, - cloud->at(v.vertices[last]).y - cloud->at(v.vertices[0]).y, - cloud->at(v.vertices[last]).z - cloud->at(v.vertices[0]).z); - Eigen::Vector3f normal = v0.cross(v1); - normal.normalize(); - // flat normal (per face) - for(unsigned int j=0; jat(v.vertices[j]).normal_x = normal[0]; - cloud->at(v.vertices[j]).normal_y = normal[1]; - cloud->at(v.vertices[j]).normal_z = normal[2]; - } - } - pcl::toPCLPointCloud2 (*cloud, textureMesh->cloud); - } - } - return textureMesh; } diff --git a/guilib/src/CMakeLists.txt b/guilib/src/CMakeLists.txt index 426de672..9dd1f40b 100644 --- a/guilib/src/CMakeLists.txt +++ b/guilib/src/CMakeLists.txt @@ -29,6 +29,7 @@ SET(headers_ui ./ParametersToolBox.h ./DepthCalibrationDialog.h ./3rdParty/QMultiComboBox.h + ./TexturingState.h ) SET(uis diff --git a/guilib/src/ExportCloudsDialog.cpp b/guilib/src/ExportCloudsDialog.cpp index 362e8a8c..42913e21 100644 --- a/guilib/src/ExportCloudsDialog.cpp +++ b/guilib/src/ExportCloudsDialog.cpp @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ExportCloudsDialog.h" #include "ui_exportCloudsDialog.h" -#include "rtabmap/gui/ProgressDialog.h" #include "rtabmap/gui/CloudViewer.h" +#include "TexturingState.h" #include "rtabmap/utilite/ULogger.h" #include "rtabmap/utilite/UConversion.h" #include "rtabmap/utilite/UThread.h" @@ -82,7 +82,8 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) : connect(_ui->comboBox_meshingApproach, SIGNAL(currentIndexChanged(int)), this, SIGNAL(configChanged())); connect(_ui->comboBox_meshingApproach, SIGNAL(currentIndexChanged(int)), this, SLOT(updateReconstructionFlavor())); - connect(_ui->groupBox_regenerate, SIGNAL(clicked(bool)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_regenerate, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_regenerate, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor())); connect(_ui->spinBox_decimation, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged())); connect(_ui->doubleSpinBox_maxDepth, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->doubleSpinBox_minDepth, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); @@ -92,11 +93,13 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) : connect(_ui->lineEdit_distortionModel, SIGNAL(textChanged(const QString &)), this, SIGNAL(configChanged())); connect(_ui->toolButton_distortionModel, SIGNAL(clicked()), this, SLOT(selectDistortionModel())); - connect(_ui->groupBox_bilateral, SIGNAL(clicked(bool)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_bilateral, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_bilateral, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor())); connect(_ui->doubleSpinBox_bilateral_sigmaS, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->doubleSpinBox_bilateral_sigmaR, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); - connect(_ui->groupBox_filtering, SIGNAL(clicked(bool)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_filtering, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_filtering, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor())); connect(_ui->doubleSpinBox_filteringRadius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->spinBox_filteringMinNeighbors, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged())); @@ -104,12 +107,14 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) : connect(_ui->checkBox_assemble, SIGNAL(clicked(bool)), this, SLOT(updateReconstructionFlavor())); connect(_ui->doubleSpinBox_voxelSize_assembled, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); - connect(_ui->groupBox_subtraction, SIGNAL(clicked(bool)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_subtraction, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_subtraction, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor())); connect(_ui->doubleSpinBox_subtractPointFilteringRadius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->doubleSpinBox_subtractPointFilteringAngle, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->spinBox_subtractFilteringMinPts, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged())); - connect(_ui->groupBox_mls, SIGNAL(clicked(bool)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_smoothing, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_smoothing, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor())); connect(_ui->doubleSpinBox_mlsRadius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->spinBox_polygonialOrder, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged())); connect(_ui->comboBox_upsamplingMethod, SIGNAL(currentIndexChanged(int)), this, SIGNAL(configChanged())); @@ -121,15 +126,17 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) : connect(_ui->comboBox_upsamplingMethod, SIGNAL(currentIndexChanged(int)), _ui->stackedWidget_upsampling, SLOT(setCurrentIndex(int))); connect(_ui->comboBox_upsamplingMethod, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMLSGrpVisibility())); - connect(_ui->groupBox_gain, SIGNAL(clicked(bool)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_gainCompensation, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_gainCompensation, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor())); connect(_ui->doubleSpinBox_gainRadius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->doubleSpinBox_gainOverlap, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->doubleSpinBox_gainAlpha, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->doubleSpinBox_gainBeta, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->checkBox_gainLinkedLocationsOnly, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); - connect(_ui->groupBox_meshing, SIGNAL(clicked(bool)), this, SIGNAL(configChanged())); - connect(_ui->groupBox_meshing, SIGNAL(toggled(bool)), this, SLOT(updateReconstructionFlavor())); + connect(_ui->checkBox_meshing, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_meshing, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor())); + connect(_ui->checkBox_meshing, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor())); connect(_ui->doubleSpinBox_gp3Radius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->doubleSpinBox_gp3Mu, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->doubleSpinBox_meshDecimationFactor, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); @@ -142,6 +149,10 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) : connect(_ui->comboBox_meshingTextureFormat, SIGNAL(currentIndexChanged(int)), this, SIGNAL(configChanged())); connect(_ui->comboBox_meshingTextureSize, SIGNAL(currentIndexChanged(int)), this, SIGNAL(configChanged())); connect(_ui->doubleSpinBox_meshingTextureMaxDistance, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_cameraFilter, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); + connect(_ui->checkBox_cameraFilter, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor())); + connect(_ui->doubleSpinBox_cameraFilterRadius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); + connect(_ui->doubleSpinBox_cameraFilterAngle, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(_ui->checkBox_poisson_outputPolygons, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); connect(_ui->checkBox_poisson_manifold, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); @@ -199,7 +210,7 @@ void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & grou settings.setValue("binary", _ui->checkBox_binary->isChecked()); settings.setValue("normals_k", _ui->spinBox_normalKSearch->value()); - settings.setValue("regenerate", _ui->groupBox_regenerate->isChecked()); + settings.setValue("regenerate", _ui->checkBox_regenerate->isChecked()); settings.setValue("regenerate_decimation", _ui->spinBox_decimation->value()); settings.setValue("regenerate_max_depth", _ui->doubleSpinBox_maxDepth->value()); settings.setValue("regenerate_min_depth", _ui->doubleSpinBox_minDepth->value()); @@ -208,23 +219,23 @@ void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & grou settings.setValue("regenerate_roi", _ui->lineEdit_roiRatios->text()); settings.setValue("regenerate_distortion_model", _ui->lineEdit_distortionModel->text()); - settings.setValue("bilateral", _ui->groupBox_bilateral->isChecked()); + settings.setValue("bilateral", _ui->checkBox_bilateral->isChecked()); settings.setValue("bilateral_sigma_s", _ui->doubleSpinBox_bilateral_sigmaS->value()); settings.setValue("bilateral_sigma_r", _ui->doubleSpinBox_bilateral_sigmaR->value()); - settings.setValue("filtering", _ui->groupBox_filtering->isChecked()); + settings.setValue("filtering", _ui->checkBox_filtering->isChecked()); settings.setValue("filtering_radius", _ui->doubleSpinBox_filteringRadius->value()); settings.setValue("filtering_min_neighbors", _ui->spinBox_filteringMinNeighbors->value()); settings.setValue("assemble", _ui->checkBox_assemble->isChecked()); settings.setValue("assemble_voxel",_ui->doubleSpinBox_voxelSize_assembled->value()); - settings.setValue("subtract",_ui->groupBox_subtraction->isChecked()); + settings.setValue("subtract",_ui->checkBox_subtraction->isChecked()); settings.setValue("subtract_point_radius",_ui->doubleSpinBox_subtractPointFilteringRadius->value()); settings.setValue("subtract_point_angle",_ui->doubleSpinBox_subtractPointFilteringAngle->value()); settings.setValue("subtract_min_neighbors",_ui->spinBox_subtractFilteringMinPts->value()); - settings.setValue("mls", _ui->groupBox_mls->isChecked()); + settings.setValue("mls", _ui->checkBox_smoothing->isChecked()); settings.setValue("mls_radius", _ui->doubleSpinBox_mlsRadius->value()); settings.setValue("mls_polygonial_order", _ui->spinBox_polygonialOrder->value()); settings.setValue("mls_upsampling_method", _ui->comboBox_upsamplingMethod->currentIndex()); @@ -234,14 +245,14 @@ void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & grou settings.setValue("mls_dilation_voxel_size", _ui->doubleSpinBox_dilationVoxelSize->value()); settings.setValue("mls_dilation_iterations", _ui->spinBox_dilationSteps->value()); - settings.setValue("gain", _ui->groupBox_gain->isChecked()); + settings.setValue("gain", _ui->checkBox_gainCompensation->isChecked()); settings.setValue("gain_radius", _ui->doubleSpinBox_gainRadius->value()); settings.setValue("gain_overlap", _ui->doubleSpinBox_gainOverlap->value()); settings.setValue("gain_alpha", _ui->doubleSpinBox_gainAlpha->value()); settings.setValue("gain_beta", _ui->doubleSpinBox_gainBeta->value()); settings.setValue("gain_linked_locations", _ui->checkBox_gainLinkedLocationsOnly->isChecked()); - settings.setValue("mesh", _ui->groupBox_meshing->isChecked()); + settings.setValue("mesh", _ui->checkBox_meshing->isChecked()); settings.setValue("mesh_radius", _ui->doubleSpinBox_gp3Radius->value()); settings.setValue("mesh_mu", _ui->doubleSpinBox_gp3Mu->value()); settings.setValue("mesh_decimation_factor", _ui->doubleSpinBox_meshDecimationFactor->value()); @@ -255,6 +266,9 @@ void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & grou settings.setValue("mesh_textureFormat", _ui->comboBox_meshingTextureFormat->currentIndex()); settings.setValue("mesh_textureSize", _ui->comboBox_meshingTextureSize->currentIndex()); settings.setValue("mesh_textureMaxDistance", _ui->doubleSpinBox_meshingTextureMaxDistance->value()); + settings.setValue("mesh_textureCameraFiltering", _ui->checkBox_cameraFilter->isChecked()); + settings.setValue("mesh_textureCameraFilteringRadius", _ui->doubleSpinBox_cameraFilterRadius->value()); + settings.setValue("mesh_textureCameraFilteringAngle", _ui->doubleSpinBox_cameraFilterAngle->value()); settings.setValue("mesh_angle_tolerance", _ui->doubleSpinBox_mesh_angleTolerance->value()); @@ -288,7 +302,7 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou _ui->checkBox_binary->setChecked(settings.value("binary", _ui->checkBox_binary->isChecked()).toBool()); _ui->spinBox_normalKSearch->setValue(settings.value("normals_k", _ui->spinBox_normalKSearch->value()).toInt()); - _ui->groupBox_regenerate->setChecked(settings.value("regenerate", _ui->groupBox_regenerate->isChecked()).toBool()); + _ui->checkBox_regenerate->setChecked(settings.value("regenerate", _ui->checkBox_regenerate->isChecked()).toBool()); _ui->spinBox_decimation->setValue(settings.value("regenerate_decimation", _ui->spinBox_decimation->value()).toInt()); _ui->doubleSpinBox_maxDepth->setValue(settings.value("regenerate_max_depth", _ui->doubleSpinBox_maxDepth->value()).toDouble()); _ui->doubleSpinBox_minDepth->setValue(settings.value("regenerate_min_depth", _ui->doubleSpinBox_minDepth->value()).toDouble()); @@ -297,23 +311,23 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou _ui->lineEdit_roiRatios->setText(settings.value("regenerate_roi", _ui->lineEdit_roiRatios->text()).toString()); _ui->lineEdit_distortionModel->setText(settings.value("regenerate_distortion_model", _ui->lineEdit_distortionModel->text()).toString()); - _ui->groupBox_bilateral->setChecked(settings.value("bilateral", _ui->groupBox_bilateral->isChecked()).toBool()); + _ui->checkBox_bilateral->setChecked(settings.value("bilateral", _ui->checkBox_bilateral->isChecked()).toBool()); _ui->doubleSpinBox_bilateral_sigmaS->setValue(settings.value("bilateral_sigma_s", _ui->doubleSpinBox_bilateral_sigmaS->value()).toDouble()); _ui->doubleSpinBox_bilateral_sigmaR->setValue(settings.value("bilateral_sigma_r", _ui->doubleSpinBox_bilateral_sigmaR->value()).toDouble()); - _ui->groupBox_filtering->setChecked(settings.value("filtering", _ui->groupBox_filtering->isChecked()).toBool()); + _ui->checkBox_filtering->setChecked(settings.value("filtering", _ui->checkBox_filtering->isChecked()).toBool()); _ui->doubleSpinBox_filteringRadius->setValue(settings.value("filtering_radius", _ui->doubleSpinBox_filteringRadius->value()).toDouble()); _ui->spinBox_filteringMinNeighbors->setValue(settings.value("filtering_min_neighbors", _ui->spinBox_filteringMinNeighbors->value()).toInt()); _ui->checkBox_assemble->setChecked(settings.value("assemble", _ui->checkBox_assemble->isChecked()).toBool()); _ui->doubleSpinBox_voxelSize_assembled->setValue(settings.value("assemble_voxel", _ui->doubleSpinBox_voxelSize_assembled->value()).toDouble()); - _ui->groupBox_subtraction->setChecked(settings.value("subtract",_ui->groupBox_subtraction->isChecked()).toBool()); + _ui->checkBox_subtraction->setChecked(settings.value("subtract",_ui->checkBox_subtraction->isChecked()).toBool()); _ui->doubleSpinBox_subtractPointFilteringRadius->setValue(settings.value("subtract_point_radius",_ui->doubleSpinBox_subtractPointFilteringRadius->value()).toDouble()); _ui->doubleSpinBox_subtractPointFilteringAngle->setValue(settings.value("subtract_point_angle",_ui->doubleSpinBox_subtractPointFilteringAngle->value()).toDouble()); _ui->spinBox_subtractFilteringMinPts->setValue(settings.value("subtract_min_neighbors",_ui->spinBox_subtractFilteringMinPts->value()).toInt()); - _ui->groupBox_mls->setChecked(settings.value("mls", _ui->groupBox_mls->isChecked()).toBool()); + _ui->checkBox_smoothing->setChecked(settings.value("mls", _ui->checkBox_smoothing->isChecked()).toBool()); _ui->doubleSpinBox_mlsRadius->setValue(settings.value("mls_radius", _ui->doubleSpinBox_mlsRadius->value()).toDouble()); _ui->spinBox_polygonialOrder->setValue(settings.value("mls_polygonial_order", _ui->spinBox_polygonialOrder->value()).toInt()); _ui->comboBox_upsamplingMethod->setCurrentIndex(settings.value("mls_upsampling_method", _ui->comboBox_upsamplingMethod->currentIndex()).toInt()); @@ -323,14 +337,14 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou _ui->doubleSpinBox_dilationVoxelSize->setValue(settings.value("mls_dilation_voxel_size", _ui->doubleSpinBox_dilationVoxelSize->value()).toDouble()); _ui->spinBox_dilationSteps->setValue(settings.value("mls_dilation_iterations", _ui->spinBox_dilationSteps->value()).toInt()); - _ui->groupBox_gain->setChecked(settings.value("gain", _ui->groupBox_gain->isChecked()).toBool()); + _ui->checkBox_gainCompensation->setChecked(settings.value("gain", _ui->checkBox_gainCompensation->isChecked()).toBool()); _ui->doubleSpinBox_gainRadius->setValue(settings.value("gain_radius", _ui->doubleSpinBox_gainRadius->value()).toDouble()); _ui->doubleSpinBox_gainOverlap->setValue(settings.value("gain_overlap", _ui->doubleSpinBox_gainOverlap->value()).toDouble()); _ui->doubleSpinBox_gainAlpha->setValue(settings.value("gain_alpha", _ui->doubleSpinBox_gainAlpha->value()).toDouble()); _ui->doubleSpinBox_gainBeta->setValue(settings.value("gain_beta", _ui->doubleSpinBox_gainBeta->value()).toDouble()); _ui->checkBox_gainLinkedLocationsOnly->setChecked(settings.value("gain_linked_locations", _ui->checkBox_gainLinkedLocationsOnly->isChecked()).toBool()); - _ui->groupBox_meshing->setChecked(settings.value("mesh", _ui->groupBox_meshing->isChecked()).toBool()); + _ui->checkBox_meshing->setChecked(settings.value("mesh", _ui->checkBox_meshing->isChecked()).toBool()); _ui->doubleSpinBox_gp3Radius->setValue(settings.value("mesh_radius", _ui->doubleSpinBox_gp3Radius->value()).toDouble()); _ui->doubleSpinBox_gp3Mu->setValue(settings.value("mesh_mu", _ui->doubleSpinBox_gp3Mu->value()).toDouble()); _ui->doubleSpinBox_meshDecimationFactor->setValue(settings.value("mesh_decimation_factor",_ui->doubleSpinBox_meshDecimationFactor->value()).toDouble()); @@ -344,6 +358,9 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou _ui->comboBox_meshingTextureFormat->setCurrentIndex(settings.value("mesh_textureFormat", _ui->comboBox_meshingTextureFormat->currentIndex()).toInt()); _ui->comboBox_meshingTextureSize->setCurrentIndex(settings.value("mesh_textureSize", _ui->comboBox_meshingTextureSize->currentIndex()).toInt()); _ui->doubleSpinBox_meshingTextureMaxDistance->setValue(settings.value("mesh_textureMaxDistance", _ui->doubleSpinBox_meshingTextureMaxDistance->value()).toDouble()); + _ui->checkBox_cameraFilter->setChecked(settings.value("mesh_textureCameraFiltering", _ui->checkBox_cameraFilter->isChecked()).toBool()); + _ui->doubleSpinBox_cameraFilterRadius->setValue(settings.value("mesh_textureCameraFilteringRadius", _ui->doubleSpinBox_cameraFilterRadius->value()).toDouble()); + _ui->doubleSpinBox_cameraFilterAngle->setValue(settings.value("mesh_textureCameraFilteringAngle", _ui->doubleSpinBox_cameraFilterAngle->value()).toDouble()); _ui->doubleSpinBox_mesh_angleTolerance->setValue(settings.value("mesh_angle_tolerance", _ui->doubleSpinBox_mesh_angleTolerance->value()).toDouble()); _ui->checkBox_mesh_quad->setChecked(settings.value("mesh_quad", _ui->checkBox_mesh_quad->isChecked()).toBool()); @@ -374,7 +391,7 @@ void ExportCloudsDialog::restoreDefaults() _ui->checkBox_binary->setChecked(true); _ui->spinBox_normalKSearch->setValue(10); - _ui->groupBox_regenerate->setChecked(false); + _ui->checkBox_regenerate->setChecked(false); _ui->spinBox_decimation->setValue(1); _ui->doubleSpinBox_maxDepth->setValue(4); _ui->doubleSpinBox_minDepth->setValue(0); @@ -383,23 +400,23 @@ void ExportCloudsDialog::restoreDefaults() _ui->lineEdit_roiRatios->setText("0.0 0.0 0.0 0.0"); _ui->lineEdit_distortionModel->setText(""); - _ui->groupBox_bilateral->setChecked(false); + _ui->checkBox_bilateral->setChecked(false); _ui->doubleSpinBox_bilateral_sigmaS->setValue(10.0); _ui->doubleSpinBox_bilateral_sigmaR->setValue(0.1); - _ui->groupBox_filtering->setChecked(false); + _ui->checkBox_filtering->setChecked(false); _ui->doubleSpinBox_filteringRadius->setValue(0.02); _ui->spinBox_filteringMinNeighbors->setValue(2); _ui->checkBox_assemble->setChecked(true); _ui->doubleSpinBox_voxelSize_assembled->setValue(0.0); - _ui->groupBox_subtraction->setChecked(false); + _ui->checkBox_subtraction->setChecked(false); _ui->doubleSpinBox_subtractPointFilteringRadius->setValue(0.02); _ui->doubleSpinBox_subtractPointFilteringAngle->setValue(0); _ui->spinBox_subtractFilteringMinPts->setValue(5); - _ui->groupBox_mls->setChecked(false); + _ui->checkBox_smoothing->setChecked(false); _ui->doubleSpinBox_mlsRadius->setValue(0.04); _ui->spinBox_polygonialOrder->setValue(2); _ui->comboBox_upsamplingMethod->setCurrentIndex(0); @@ -409,14 +426,14 @@ void ExportCloudsDialog::restoreDefaults() _ui->doubleSpinBox_dilationVoxelSize->setValue(0.01); _ui->spinBox_dilationSteps->setValue(0); - _ui->groupBox_gain->setChecked(false); + _ui->checkBox_gainCompensation->setChecked(false); _ui->doubleSpinBox_gainRadius->setValue(0.02); _ui->doubleSpinBox_gainOverlap->setValue(0.05); _ui->doubleSpinBox_gainAlpha->setValue(0.01); _ui->doubleSpinBox_gainBeta->setValue(10); _ui->checkBox_gainLinkedLocationsOnly->setChecked(true); - _ui->groupBox_meshing->setChecked(false); + _ui->checkBox_meshing->setChecked(false); _ui->doubleSpinBox_gp3Radius->setValue(0.2); _ui->doubleSpinBox_gp3Mu->setValue(2.5); _ui->doubleSpinBox_meshDecimationFactor->setValue(0.0); @@ -430,6 +447,9 @@ void ExportCloudsDialog::restoreDefaults() _ui->comboBox_meshingTextureFormat->setCurrentIndex(0); _ui->comboBox_meshingTextureSize->setCurrentIndex(5); // 4096 _ui->doubleSpinBox_meshingTextureMaxDistance->setValue(3.0); + _ui->checkBox_cameraFilter->setChecked(false); + _ui->doubleSpinBox_cameraFilterRadius->setValue(0.1); + _ui->doubleSpinBox_cameraFilterAngle->setValue(30); _ui->doubleSpinBox_mesh_angleTolerance->setValue(15.0); _ui->checkBox_mesh_quad->setChecked(false); @@ -453,21 +473,34 @@ void ExportCloudsDialog::restoreDefaults() void ExportCloudsDialog::updateReconstructionFlavor() { - _ui->groupBox_mls->setVisible(_ui->comboBox_pipeline->currentIndex() == 1); - _ui->groupBox_mls->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1); + _ui->checkBox_smoothing->setVisible(_ui->comboBox_pipeline->currentIndex() == 1); + _ui->checkBox_smoothing->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1); _ui->label_denseReconstruction->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1); _ui->doubleSpinBox_meshDecimationFactor->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1); _ui->label_meshDecimation->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1); _ui->groupBox_organized->setVisible(_ui->comboBox_pipeline->currentIndex() == 0); + _ui->groupBox_regenerate->setVisible(_ui->checkBox_regenerate->isChecked()); + _ui->groupBox_bilateral->setVisible(_ui->checkBox_bilateral->isChecked()); + _ui->groupBox_filtering->setVisible(_ui->checkBox_filtering->isChecked()); + _ui->groupBox_gain->setVisible(_ui->checkBox_gainCompensation->isChecked()); + _ui->groupBox_mls->setVisible(_ui->checkBox_smoothing->isEnabled() && _ui->checkBox_smoothing->isChecked()); + _ui->groupBox_meshing->setVisible(_ui->checkBox_meshing->isChecked()); + _ui->groupBox_subtraction->setVisible(_ui->checkBox_subtraction->isChecked()); + _ui->groupBox_textureMapping->setVisible(_ui->checkBox_textureMapping->isChecked()); + _ui->groupBox_cameraFilter->setVisible(_ui->checkBox_cameraFilter->isChecked()); + // dense texturing options _ui->groupBox_gp3->setVisible(_ui->comboBox_pipeline->currentIndex() == 1 && _ui->comboBox_meshingApproach->currentIndex()==0); _ui->groupBox_poisson->setVisible(_ui->comboBox_pipeline->currentIndex() == 1 && _ui->comboBox_meshingApproach->currentIndex()==1); - if(_ui->groupBox_meshing->isChecked()) + if(_ui->checkBox_meshing->isChecked()) { _ui->comboBox_meshingApproach->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1); - _ui->comboBox_meshingApproach->setCurrentIndex(_ui->checkBox_assemble->isChecked()?1:0); _ui->comboBox_meshingApproach->setItemData(1, _ui->checkBox_assemble->isChecked()?1 | 32:0,Qt::UserRole - 1); + if(!_ui->checkBox_assemble->isChecked()) + { + _ui->comboBox_meshingApproach->setCurrentIndex(0); + } _ui->checkBox_poisson_outputPolygons->setDisabled( _ui->checkBox_binary->isEnabled() || @@ -523,9 +556,9 @@ void ExportCloudsDialog::enableRegeneration(bool enabled) { if(!enabled) { - _ui->groupBox_regenerate->setChecked(false); + _ui->checkBox_regenerate->setChecked(false); } - _ui->groupBox_regenerate->setEnabled(enabled); + _ui->checkBox_regenerate->setEnabled(enabled); } void ExportCloudsDialog::exportClouds( @@ -715,7 +748,7 @@ void ExportCloudsDialog::viewClouds( UASSERT(cachedSignatures.contains(textureId) && !cachedSignatures.value(textureId).sensorData().imageCompressed().empty()); cachedSignatures.value(textureId).sensorData().uncompressDataConst(&globalTexture, 0); UASSERT(!globalTexture.empty()); - if (_ui->groupBox_gain->isChecked() && _compensator && _compensator->getIndex(textureId) >= 0) + if (_ui->checkBox_gainCompensation->isChecked() && _compensator && _compensator->getIndex(textureId) >= 0) { _compensator->apply(textureId, globalTexture); } @@ -837,7 +870,7 @@ bool ExportCloudsDialog::getExportedClouds( _progressDialog->resetProgress(); _progressDialog->show(); int mul = 1; - if(_ui->groupBox_meshing->isChecked()) + if(_ui->checkBox_meshing->isChecked()) { mul+=1; } @@ -846,7 +879,7 @@ bool ExportCloudsDialog::getExportedClouds( mul+=1; } - if(_ui->groupBox_subtraction->isChecked()) + if(_ui->checkBox_subtraction->isChecked()) { mul+=1; } @@ -855,7 +888,7 @@ bool ExportCloudsDialog::getExportedClouds( { mul+=1; } - if(_ui->groupBox_gain->isChecked()) + if(_ui->checkBox_gainCompensation->isChecked()) { mul+=1; } @@ -879,7 +912,7 @@ bool ExportCloudsDialog::getExportedClouds( if(clouds.empty()) { _progressDialog->setAutoClose(false); - if(_ui->groupBox_regenerate->isEnabled() && !_ui->groupBox_regenerate->isChecked()) + if(_ui->checkBox_regenerate->isEnabled() && !_ui->checkBox_regenerate->isChecked()) { QMessageBox::warning(this, tr("Creating clouds..."), tr("Could create clouds for %1 node(s). You " "may want to activate clouds regeneration option.").arg(poses.size())); @@ -892,7 +925,7 @@ bool ExportCloudsDialog::getExportedClouds( return false; } - if(_ui->groupBox_gain->isChecked() && clouds.size() > 1) + if(_ui->checkBox_gainCompensation->isChecked() && clouds.size() > 1) { UASSERT(_compensator == 0); _compensator = new GainCompensator(_ui->doubleSpinBox_gainRadius->value(), _ui->doubleSpinBox_gainOverlap->value(), _ui->doubleSpinBox_gainAlpha->value(), _ui->doubleSpinBox_gainBeta->value()); @@ -931,7 +964,7 @@ bool ExportCloudsDialog::getExportedClouds( _compensator->feed(clouds, links); } - if(!(_ui->groupBox_meshing->isChecked() && + if(!(_ui->checkBox_meshing->isChecked() && _ui->checkBox_textureMapping->isEnabled() && _ui->checkBox_textureMapping->isChecked())) { @@ -958,7 +991,7 @@ bool ExportCloudsDialog::getExportedClouds( pcl::PointCloud::Ptr rawAssembledCloud(new pcl::PointCloud); std::vector rawCameraIndices; if(_ui->checkBox_assemble->isChecked() && - !(_ui->comboBox_pipeline->currentIndex()==0 && _ui->groupBox_meshing->isChecked())) + !(_ui->comboBox_pipeline->currentIndex()==0 && _ui->checkBox_meshing->isChecked())) { _progressDialog->appendText(tr("Assembling %1 clouds...").arg(clouds.size())); QApplication::processEvents(); @@ -1020,7 +1053,7 @@ bool ExportCloudsDialog::getExportedClouds( } std::map viewPoints = poses; - if(_ui->groupBox_mls->isEnabled() && _ui->groupBox_mls->isChecked()) + if(_ui->checkBox_smoothing->isEnabled() && _ui->checkBox_smoothing->isChecked()) { _progressDialog->appendText(tr("Smoothing the surface using Moving Least Squares (MLS) algorithm... " "[search radius=%1m voxel=%2m]").arg(_ui->doubleSpinBox_mlsRadius->value()).arg(_ui->doubleSpinBox_voxelSize_assembled->value())); @@ -1053,7 +1086,7 @@ bool ExportCloudsDialog::getExportedClouds( { pcl::PointCloud::Ptr cloudWithNormals = iter->second.first; - if(_ui->groupBox_mls->isEnabled() && _ui->groupBox_mls->isChecked()) + if(_ui->checkBox_smoothing->isEnabled() && _ui->checkBox_smoothing->isChecked()) { pcl::PointCloud::Ptr cloudWithoutNormals(new pcl::PointCloud); if(iter->second.second->size()) @@ -1109,7 +1142,7 @@ bool ExportCloudsDialog::getExportedClouds( cloudWithNormals); } } - else if(iter->second.first->isOrganized() && _ui->groupBox_filtering->isChecked()) + else if(iter->second.first->isOrganized() && _ui->checkBox_filtering->isChecked()) { cloudWithNormals = util3d::extractIndices(iter->second.first, iter->second.second, false, true); } @@ -1129,8 +1162,8 @@ bool ExportCloudsDialog::getExportedClouds( std::map organizedCloudSizes; //mesh - UDEBUG("Meshing=%d", _ui->groupBox_meshing->isChecked()?1:0); - if(_ui->groupBox_meshing->isChecked()) + UDEBUG("Meshing=%d", _ui->checkBox_meshing->isChecked()?1:0); + if(_ui->checkBox_meshing->isChecked()) { if(_ui->comboBox_pipeline->currentIndex() == 0) { @@ -1720,11 +1753,47 @@ bool ExportCloudsDialog::getExportedClouds( else { UDEBUG("Texture by projection"); + + if(cameraPoses.size() && _ui->checkBox_cameraFilter->isChecked()) + { + int before = (int)cameraPoses.size(); + cameraPoses = graph::radiusPosesFiltering(cameraPoses, + _ui->doubleSpinBox_cameraFilterRadius->value(), + _ui->doubleSpinBox_cameraFilterAngle->value()); + for(std::map::iterator modelIter = cameraModels.begin(); modelIter!=cameraModels.end();) + { + if(cameraPoses.find(modelIter->first)==cameraPoses.end()) + { + cameraModels.erase(modelIter++); + } + else + { + ++modelIter; + } + } + _progressDialog->appendText(tr("Camera filtering: keeping %1/%2 cameras for texturing.").arg(cameraPoses.size()).arg(before)); + QApplication::processEvents(); + uSleep(100); + QApplication::processEvents(); + } + + if(_canceled) + { + return false; + } + + TexturingState texturingState(_progressDialog); textureMesh = util3d::createTextureMesh( iter->second, cameraPoses, cameraModels, - _ui->doubleSpinBox_meshingTextureMaxDistance->value()); + _ui->doubleSpinBox_meshingTextureMaxDistance->value(), + &texturingState); + + if(_canceled) + { + return false; + } // Remove occluded polygons (polygons with no texture) if(_ui->checkBox_cleanMesh->isChecked() && @@ -1922,7 +1991,7 @@ std::map::Ptr, pcl::Indic { pcl::PointCloud::Ptr cloud(new pcl::PointCloud); pcl::IndicesPtr indices(new std::vector); - if(_ui->groupBox_regenerate->isChecked()) + if(_ui->checkBox_regenerate->isChecked()) { if(cachedSignatures.contains(iter->first)) { @@ -1948,7 +2017,7 @@ std::map::Ptr, pcl::Indic } // bilateral filtering - if(_ui->groupBox_bilateral->isChecked()) + if(_ui->checkBox_bilateral->isChecked()) { depth = util2d::fastBilateralFiltering(depth, _ui->doubleSpinBox_bilateral_sigmaS->value(), @@ -1983,7 +2052,7 @@ std::map::Ptr, pcl::Indic if(cloudWithoutNormals->size()) { // Don't voxelize if we create organized mesh - if(!(_ui->comboBox_pipeline->currentIndex()==0 && _ui->groupBox_meshing->isChecked()) && _ui->doubleSpinBox_voxelSize_assembled->value()>0.0) + if(!(_ui->comboBox_pipeline->currentIndex()==0 && _ui->checkBox_meshing->isChecked()) && _ui->doubleSpinBox_voxelSize_assembled->value()>0.0) { cloudWithoutNormals = util3d::voxelize(cloudWithoutNormals, indices, _ui->doubleSpinBox_voxelSize_assembled->value()); indices->resize(cloudWithoutNormals->size()); @@ -2011,7 +2080,7 @@ std::map::Ptr, pcl::Indic pcl::PointCloud::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), viewPoint); pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud); - if(_ui->groupBox_subtraction->isChecked() && + if(_ui->checkBox_subtraction->isChecked() && _ui->doubleSpinBox_subtractPointFilteringRadius->value() > 0.0) { pcl::IndicesPtr beforeSubtractionIndices = indices; @@ -2047,7 +2116,7 @@ std::map::Ptr, pcl::Indic else if(uContains(cachedClouds, iter->first)) { pcl::PointCloud::Ptr cloudWithoutNormals; - if(!_ui->groupBox_meshing->isChecked() && + if(!_ui->checkBox_meshing->isChecked() && _ui->doubleSpinBox_voxelSize_assembled->value() > 0.0) { cloudWithoutNormals = util3d::voxelize( @@ -2102,7 +2171,7 @@ std::map::Ptr, pcl::Indic if(indices->size()) { - if(_ui->groupBox_filtering->isChecked() && + if(_ui->checkBox_filtering->isChecked() && _ui->doubleSpinBox_filteringRadius->value() > 0.0f && _ui->spinBox_filteringMinNeighbors->value() > 0) { @@ -2121,7 +2190,7 @@ std::map::Ptr, pcl::Indic if(points>0) { - if(_ui->groupBox_regenerate->isChecked()) + if(_ui->checkBox_regenerate->isChecked()) { _progressDialog->appendText(tr("Generated cloud %1 with %2 points and %3 indices (%4/%5).") .arg(iter->first).arg(points).arg(totalIndices).arg(index).arg(poses.size())); @@ -2511,7 +2580,7 @@ cv::Mat ExportCloudsDialog::mergeTextures(pcl::TextureMesh & mesh, const QMapgroupBox_gain->isChecked() && _compensator && _compensator->getIndex(textures[t]) >= 0) + if(_ui->checkBox_gainCompensation->isChecked() && _compensator && _compensator->getIndex(textures[t]) >= 0) { _compensator->apply(textures[t], resizedImage); } @@ -2595,7 +2664,7 @@ void ExportCloudsDialog::saveTextureMeshes( cachedSignatures.value(textureId).sensorData().uncompressDataConst(&image, 0); UASSERT(!image.empty()); imageSize = image.size(); - if(_ui->groupBox_gain->isChecked() && _compensator && _compensator->getIndex(textureId) >= 0) + if(_ui->checkBox_gainCompensation->isChecked() && _compensator && _compensator->getIndex(textureId) >= 0) { _compensator->apply(textureId, image); } @@ -2715,7 +2784,7 @@ void ExportCloudsDialog::saveTextureMeshes( cachedSignatures.value(textureId).sensorData().uncompressDataConst(&image, 0); UASSERT(!image.empty()); imageSize = image.size(); - if(_ui->groupBox_gain->isChecked() && _compensator && _compensator->getIndex(textureId) >= 0) + if(_ui->checkBox_gainCompensation->isChecked() && _compensator && _compensator->getIndex(textureId) >= 0) { _compensator->apply(textureId, image); } diff --git a/guilib/src/MainWindow.cpp b/guilib/src/MainWindow.cpp index a6662dbc..c41e5d19 100644 --- a/guilib/src/MainWindow.cpp +++ b/guilib/src/MainWindow.cpp @@ -285,7 +285,6 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) : _ui->rawLikelihoodPlot->showLegend(false); _initProgressDialog = new ProgressDialog(this); - _initProgressDialog->setWindowTitle(tr("Progress dialog")); _initProgressDialog->setMinimumWidth(800); connect(_initProgressDialog, SIGNAL(canceled()), this, SLOT(cancelProgress())); diff --git a/guilib/src/TexturingState.h b/guilib/src/TexturingState.h new file mode 100644 index 00000000..ab58d992 --- /dev/null +++ b/guilib/src/TexturingState.h @@ -0,0 +1,71 @@ +/* +Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Universite de Sherbrooke nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef GUILIB_SRC_TEXTURINGSTATE_H_ +#define GUILIB_SRC_TEXTURINGSTATE_H_ + +#include "rtabmap/gui/ProgressDialog.h" +#include "rtabmap/core/ProgressState.h" +#include + +namespace rtabmap { + +class TexturingState : public QObject, public ProgressState +{ + Q_OBJECT + +public: + TexturingState(ProgressDialog * dialog): dialog_(dialog), canceled_(false) + { + connect(dialog_, SIGNAL(canceled()), this, SLOT(cancel())); + } + virtual ~TexturingState() {} + virtual bool callback(const std::string & msg) const + { + if(!msg.empty()) + { + dialog_->appendText(msg.c_str()); + } + QApplication::processEvents(); + return !canceled_; + } + +public slots: + void cancel() + { + canceled_ = true; + } + +private: + ProgressDialog * dialog_; + bool canceled_; +}; + +} + +#endif /* GUILIB_SRC_TEXTURINGSTATE_H_ */ diff --git a/guilib/src/ui/exportCloudsDialog.ui b/guilib/src/ui/exportCloudsDialog.ui index a68138db..e0250bcf 100644 --- a/guilib/src/ui/exportCloudsDialog.ui +++ b/guilib/src/ui/exportCloudsDialog.ui @@ -23,24 +23,14 @@ 0 - -1643 + -1879 773 - 2810 + 3158 - - - - 3 - - - 20 - - - @@ -68,6 +58,94 @@ + + + + Set the number of k nearest neighbors to use for the normal estimation. + + + true + + + + + + + + + + + + + + Regenerate clouds. This can be used to regenerate the point clouds at higher density than those used for online visualization. + + + true + + + + + + + Gain compensation. Normalize brightness of images. + + + true + + + + + + + 3 + + + 20 + + + + + + + Voxel size. Set 0 to disable. When organized meshes are assembled, this is the radius in which the vertices of the polygons are merged. + + + true + + + + + + + Binary file. + + + true + + + + + + + + Organized Point Cloud + + + + + Dense Point Cloud + + + + + + + + Reconstruction flavor. + + + @@ -87,57 +165,64 @@ - - + + - Set the number of k nearest neighbors to use for the normal estimation. + Cloud smoothing using Moving Least Squares algorithm (MLS). true - - + + - Reconstruction flavor. + - - - - - Organized Point Cloud - - - - - Dense Point Cloud - - + + + + + - - + + - Binary file. + + + + + + + + Cloud filtering. Remove sparse points that are far from surfaces. true - - + + - Voxel size. Set 0 to disable. When organized meshes are assembled, this is the radius in which the vertices of the polygons are merged. + Meshing. true + + + + + + + @@ -146,18 +231,35 @@ Regenerate Clouds - true + false - - + + - 3D cloud decimation (1-2-4-8-...). Negative decimation is done from RGB size instead of depth size (if depth is smaller than RGB, it may be interpolated depending of the decimation value). + ... - - true + + + + + + pixels + + + + + + + -32 + + + 32 + + + 1 @@ -180,23 +282,19 @@ + + + + 3D cloud decimation (1-2-4-8-...). Negative decimation is done from RGB size instead of depth size (if depth is smaller than RGB, it may be interpolated depending of the decimation value). + + + true + + + - - - - ... - - - - - - - pixels - - - @@ -256,19 +354,6 @@ - - - - -32 - - - 32 - - - 1 - - - @@ -305,6 +390,40 @@ + + + + + + + + + + + Bilateral filtering of the depth image. Reduce noise in depth images. + + + true + + + + + + + Cloud subtraction. Superposed points from different nodes are filtered. + + + true + + + + + + + + + + @@ -313,7 +432,7 @@ Bilateral Filtering of the Depth Image - true + false @@ -395,7 +514,7 @@ Cloud Subtraction - true + false @@ -488,10 +607,10 @@ - Cloud Filtering (remove noisy points) + Cloud Filtering - true + false @@ -555,13 +674,13 @@ - Cloud Smoothing using Moving Least Squares algorithm (MLS) + Cloud Smoothing - true + false - true + false @@ -943,7 +1062,7 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0. Gain Compensation - true + false @@ -1100,32 +1219,12 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0. Meshing - true + false - - - - -1 - - - 99999 - - - - - - - Mesh quadric decimation factor (0=no decimation). Used to reduce the number of polygons. Higher the factor, lower the output resolution (less polygons). Can be used when dense reconstruction flavor is selected. - - - true - - - - + Texture mapping. Images of the cameras will be projected on the mesh(es). Output is a *.obj format. Available on Export or when clouds are not assembled. @@ -1149,7 +1248,14 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0. - + + + + + + + + m @@ -1171,84 +1277,38 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0. - - + + - - - - - - - - - .jpg - - - - - .png - - - - - - - - Output texture size. If not set or when clouds are not assembled, all textures are saved separately. Warning: values higher than 2048 may not be compatible with all GPUs. + Clean mesh from polygons without color or texture. true - - - - - Disabled - - - - - 256x256 - - - - - 512x512 - - - - - 1024x1024 - - - - - 2048x2048 - - - - - 4096x4096 - - - - - 8192x8192 - - - - - 16384x16384 - - - - - 32768x32768 - - + + + + -1 + + + 99999 + + + + + + + + + + + + + + Minimum polygon cluster size (-1 means that only the biggest cluster is kept). + @@ -1261,24 +1321,7 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0. - - - - Transferring color radius. Radius used to transfer color from original cloud to resampled reconstructed surface (e.g., Poisson or mesh decimation). Negative means disabled, 0 means take the nearest point. - - - true - - - - - - - - - - 2 @@ -1297,67 +1340,243 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0. - - - - Clean mesh from polygons without color or texture. - - - true - - - - + - Texture format. + Transferring color radius. Radius used to transfer color from original cloud to resampled reconstructed surface (e.g., Poisson or mesh decimation). Negative means disabled, 0 means take the nearest point. true - - + + - Minimum polygon cluster size (-1 means that only the biggest cluster is kept). - - - - - - - Maximum distance from the camera for polygons to be textured by this camera (0 means infinite). Only used with dense reconstruction flavor. + Mesh quadric decimation factor (0=no decimation). Used to reduce the number of polygons. Higher the factor, lower the output resolution (less polygons). Can be used when dense reconstruction flavor is selected. Can reduce a lot texturing time. true - - - - m - - - 1 - - - 0.000000000000000 - - - 99.000000000000000 - - - 1.000000000000000 - - - 3.000000000000000 - - - + + + + Texturing + + + false + + + false + + + + + + + + + .jpg + + + + + .png + + + + + + + + Texture format. + + + true + + + + + + + + Disabled + + + + + 256x256 + + + + + 512x512 + + + + + 1024x1024 + + + + + 2048x2048 + + + + + 4096x4096 + + + + + 8192x8192 + + + + + 16384x16384 + + + + + 32768x32768 + + + + + + + + Output texture size. If not set or when clouds are not assembled, all textures are saved separately. Warning: values higher than 2048 may not be compatible with all GPUs. + + + true + + + + + + + m + + + 1 + + + 0.000000000000000 + + + 99.000000000000000 + + + 1.000000000000000 + + + 3.000000000000000 + + + + + + + Maximum distance from the camera for polygons to be textured by this camera (0 means infinite). Only used with dense reconstruction flavor. + + + true + + + + + + + + + + + + + + Camera filtering. By comparing poses in the same area, only one camera in a fixed radius and angle is used for texturing. + + + true + + + + + + + + + Camera Filtering + + + + + + m + + + 0.010000000000000 + + + 0.100000000000000 + + + + + + + Radius. + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + deg + + + 0 + + + 180.000000000000000 + + + 30.000000000000000 + + + + + + + Angle. + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + +