mirror of
https://github.com/introlab/rtabmap.git
synced 2026-10-03 16:47:47 +08:00
Export: CPU-TSDF mesh reconstruction integration
This commit is contained in:
@@ -151,6 +151,7 @@ option(WITH_ZED "Include ZED sdk support" ON)
|
||||
option(WITH_REALSENSE "Include RealSense support" ON)
|
||||
option(WITH_REALSENSE_SLAM "Include RealSenseSlam support" ON)
|
||||
option(WITH_OCTOMAP "Include Octomap support" ON)
|
||||
option(WITH_CPUTSDF "Include CPUTSDF support" ON)
|
||||
option(PCL_OMP "With PCL OMP implementations" ON)
|
||||
|
||||
FIND_PACKAGE(OpenCV REQUIRED QUIET)
|
||||
@@ -336,6 +337,13 @@ IF(WITH_OCTOMAP)
|
||||
ENDIF(OCTOMAP_FOUND)
|
||||
ENDIF(WITH_OCTOMAP)
|
||||
|
||||
IF(WITH_CPUTSDF)
|
||||
FIND_PACKAGE(CPUTSDF QUIET)
|
||||
IF(CPUTSDF_FOUND)
|
||||
MESSAGE(STATUS "Found CPUTSDF: ${CPUTSDF_INCLUDE_DIRS}")
|
||||
ENDIF(CPUTSDF_FOUND)
|
||||
ENDIF(WITH_CPUTSDF)
|
||||
|
||||
IF(G2O_FOUND OR GTSAM_FOUND OR ZED_FOUND OR ANDROID OR RealSense_FOUND)
|
||||
#Newest versions require std11
|
||||
IF(NOT MSVC)
|
||||
@@ -453,6 +461,11 @@ IF(NOT OCTOMAP_FOUND)
|
||||
ELSE()
|
||||
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${OCTOMAP_LIBRARIES})
|
||||
ENDIF()
|
||||
IF(NOT CPUTSDF_FOUND)
|
||||
SET(CPUTSDF "//")
|
||||
ELSE()
|
||||
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${CPUTSDF_LIBRARIES})
|
||||
ENDIF()
|
||||
IF(ADD_VTK_GUI_SUPPORT_QT_TO_CONF)
|
||||
SET(CONF_VTK_QT true)
|
||||
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} vtkGUISupportQt)
|
||||
@@ -768,6 +781,14 @@ ELSE()
|
||||
MESSAGE(STATUS " With OCTOMAP = NO (octomap not found)")
|
||||
ENDIF()
|
||||
|
||||
IF(CPUTSDF_FOUND)
|
||||
MESSAGE(STATUS " With CPUTSDF = YES (License: BSD)")
|
||||
ELSEIF(NOT WITH_CPUTSDF)
|
||||
MESSAGE(STATUS " With CPUTSDF = NO (WITH_CPUTSDF=OFF)")
|
||||
ELSE()
|
||||
MESSAGE(STATUS " With CPUTSDF = NO (CPUTSDF not found)")
|
||||
ENDIF()
|
||||
|
||||
IF(QT4_FOUND)
|
||||
MESSAGE(STATUS " With Qt4 = YES (License: Open Source or Commercial)")
|
||||
ELSEIF(Qt5_FOUND)
|
||||
|
||||
@@ -53,6 +53,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@REALSENSE@#define RTABMAP_REALSENSE
|
||||
@REALSENSESLAM@#define RTABMAP_REALSENSE_SLAM
|
||||
@OCTOMAP@#define RTABMAP_OCTOMAP
|
||||
@CPUTSDF@#define RTABMAP_CPUTSDF
|
||||
|
||||
#endif /* VERSION_H_ */
|
||||
|
||||
|
||||
@@ -60,6 +60,11 @@ AboutDialog::AboutDialog(QWidget * parent) :
|
||||
_ui->label_octomap->setText("Yes");
|
||||
#else
|
||||
_ui->label_octomap->setText("No");
|
||||
#endif
|
||||
#ifdef RTABMAP_CPUTSDF
|
||||
_ui->label_cputsdf->setText("Yes");
|
||||
#else
|
||||
_ui->label_cputsdf->setText("No");
|
||||
#endif
|
||||
_ui->label_freenect->setText(CameraFreenect::available()?"Yes":"No");
|
||||
_ui->label_openni2->setText(CameraOpenNI2::available()?"Yes":"No");
|
||||
|
||||
@@ -137,6 +137,17 @@ IF(OCTOMAP_FOUND)
|
||||
)
|
||||
ENDIF(OCTOMAP_FOUND)
|
||||
|
||||
IF(CPUTSDF_FOUND)
|
||||
SET(INCLUDE_DIRS
|
||||
${INCLUDE_DIRS}
|
||||
${CPUTSDF_INCLUDE_DIRS}
|
||||
)
|
||||
SET(LIBRARIES
|
||||
${LIBRARIES}
|
||||
${CPUTSDF_LIBRARIES}
|
||||
)
|
||||
ENDIF(CPUTSDF_FOUND)
|
||||
|
||||
IF(VTK_USE_QVTK)
|
||||
SET(INCLUDE_DIRS ${INCLUDE_DIRS} ${QVTK_INCLUDE_DIR})
|
||||
SET(LIBRARIES ${LIBRARIES} ${QVTK_LIBRARY})
|
||||
|
||||
+467
-248
@@ -45,6 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "rtabmap/core/GainCompensator.h"
|
||||
#include "rtabmap/core/clams/discrete_depth_distortion_model.h"
|
||||
#include "rtabmap/core/DBDriver.h"
|
||||
#include "rtabmap/core/Version.h"
|
||||
|
||||
#include <pcl/conversions.h>
|
||||
#include <pcl/io/pcd_io.h>
|
||||
@@ -62,6 +63,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <QInputDialog>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#ifdef RTABMAP_CPUTSDF
|
||||
#include <cpu_tsdf/tsdf_volume_octree.h>
|
||||
#include <cpu_tsdf/marching_cubes_tsdf_octree.h>
|
||||
#endif
|
||||
|
||||
namespace rtabmap {
|
||||
|
||||
ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
|
||||
@@ -175,6 +181,14 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
|
||||
connect(_ui->doubleSpinBox_poisson_pointWeight, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_poisson_scale, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
|
||||
connect(_ui->doubleSpinBox_cputsdf_size, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_cputsdf_resolution, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_cputsdf_tuncPos, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_cputsdf_tuncNeg, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_cputsdf_minWeight, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_cputsdf_flattenRadius, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->spinBox_cputsdf_randomSplit, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
|
||||
|
||||
_progressDialog = new ProgressDialog(this);
|
||||
_progressDialog->setVisible(false);
|
||||
_progressDialog->setAutoClose(true, 2);
|
||||
@@ -312,6 +326,14 @@ void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & grou
|
||||
settings.setValue("poisson_pointWeight", _ui->doubleSpinBox_poisson_pointWeight->value());
|
||||
settings.setValue("poisson_scale", _ui->doubleSpinBox_poisson_scale->value());
|
||||
|
||||
settings.setValue("cputsdf_size", _ui->doubleSpinBox_cputsdf_size->value());
|
||||
settings.setValue("cputsdf_resolution", _ui->doubleSpinBox_cputsdf_resolution->value());
|
||||
settings.setValue("cputsdf_truncPos", _ui->doubleSpinBox_cputsdf_tuncPos->value());
|
||||
settings.setValue("cputsdf_truncNeg", _ui->doubleSpinBox_cputsdf_tuncNeg->value());
|
||||
settings.setValue("cputsdf_minWeight", _ui->doubleSpinBox_cputsdf_minWeight->value());
|
||||
settings.setValue("cputsdf_flattenRadius", _ui->doubleSpinBox_cputsdf_flattenRadius->value());
|
||||
settings.setValue("cputsdf_randomSplit", _ui->spinBox_cputsdf_randomSplit->value());
|
||||
|
||||
if(!group.isEmpty())
|
||||
{
|
||||
settings.endGroup();
|
||||
@@ -413,6 +435,14 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou
|
||||
_ui->doubleSpinBox_poisson_pointWeight->setValue(settings.value("poisson_pointWeight", _ui->doubleSpinBox_poisson_pointWeight->value()).toDouble());
|
||||
_ui->doubleSpinBox_poisson_scale->setValue(settings.value("poisson_scale", _ui->doubleSpinBox_poisson_scale->value()).toDouble());
|
||||
|
||||
_ui->doubleSpinBox_cputsdf_size->setValue(settings.value("cputsdf_size", _ui->doubleSpinBox_cputsdf_size->value()).toDouble());
|
||||
_ui->doubleSpinBox_cputsdf_resolution->setValue(settings.value("cputsdf_resolution", _ui->doubleSpinBox_cputsdf_resolution->value()).toDouble());
|
||||
_ui->doubleSpinBox_cputsdf_tuncPos->setValue(settings.value("cputsdf_truncPos", _ui->doubleSpinBox_cputsdf_tuncPos->value()).toDouble());
|
||||
_ui->doubleSpinBox_cputsdf_tuncNeg->setValue(settings.value("cputsdf_truncNeg", _ui->doubleSpinBox_cputsdf_tuncNeg->value()).toDouble());
|
||||
_ui->doubleSpinBox_cputsdf_minWeight->setValue(settings.value("cputsdf_minWeight", _ui->doubleSpinBox_cputsdf_minWeight->value()).toDouble());
|
||||
_ui->doubleSpinBox_cputsdf_flattenRadius->setValue(settings.value("cputsdf_flattenRadius", _ui->doubleSpinBox_cputsdf_flattenRadius->value()).toDouble());
|
||||
_ui->spinBox_cputsdf_randomSplit->setValue(settings.value("cputsdf_randomSplit", _ui->spinBox_cputsdf_randomSplit->value()).toInt());
|
||||
|
||||
updateReconstructionFlavor();
|
||||
updateMLSGrpVisibility();
|
||||
|
||||
@@ -509,6 +539,14 @@ void ExportCloudsDialog::restoreDefaults()
|
||||
_ui->doubleSpinBox_poisson_pointWeight->setValue(4.0);
|
||||
_ui->doubleSpinBox_poisson_scale->setValue(1.1);
|
||||
|
||||
_ui->doubleSpinBox_cputsdf_size->setValue(12.0);
|
||||
_ui->doubleSpinBox_cputsdf_resolution->setValue(0.01);
|
||||
_ui->doubleSpinBox_cputsdf_tuncPos->setValue(0.03);
|
||||
_ui->doubleSpinBox_cputsdf_tuncNeg->setValue(0.03);
|
||||
_ui->doubleSpinBox_cputsdf_minWeight->setValue(0);
|
||||
_ui->doubleSpinBox_cputsdf_flattenRadius->setValue(0.005);
|
||||
_ui->spinBox_cputsdf_randomSplit->setValue(1);
|
||||
|
||||
updateReconstructionFlavor();
|
||||
updateMLSGrpVisibility();
|
||||
|
||||
@@ -519,14 +557,6 @@ void ExportCloudsDialog::updateReconstructionFlavor()
|
||||
{
|
||||
_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);
|
||||
#ifndef DISABLE_VTK
|
||||
_ui->doubleSpinBox_meshDecimationFactor->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1);
|
||||
_ui->label_meshDecimation->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1);
|
||||
_ui->spinBox_meshMaxPolygons->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1);
|
||||
_ui->label_meshMaxPolygons->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1);
|
||||
#endif
|
||||
_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());
|
||||
@@ -539,15 +569,28 @@ void ExportCloudsDialog::updateReconstructionFlavor()
|
||||
_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->checkBox_meshing->isChecked())
|
||||
{
|
||||
_ui->comboBox_meshingApproach->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1);
|
||||
_ui->comboBox_meshingApproach->setItemData(1, _ui->checkBox_assemble->isChecked()?1 | 32:0,Qt::UserRole - 1);
|
||||
_ui->comboBox_meshingApproach->setItemData(0, _ui->comboBox_pipeline->currentIndex() == 1?1 | 32:0,Qt::UserRole - 1);
|
||||
_ui->comboBox_meshingApproach->setItemData(1, _ui->comboBox_pipeline->currentIndex() == 1 && _ui->checkBox_assemble->isChecked()?1 | 32:0,Qt::UserRole - 1);
|
||||
#ifdef RTABMAP_CPUTSDF
|
||||
_ui->comboBox_meshingApproach->setItemData(2, _ui->comboBox_pipeline->currentIndex() == 0 && _ui->checkBox_assemble->isChecked()?1 | 32:0,Qt::UserRole - 1);
|
||||
#else
|
||||
_ui->comboBox_meshingApproach->setItemData(2, Qt::UserRole - 1);
|
||||
#endif
|
||||
_ui->comboBox_meshingApproach->setItemData(3, _ui->comboBox_pipeline->currentIndex() == 0?1 | 32:0,Qt::UserRole - 1);
|
||||
|
||||
if(_ui->comboBox_pipeline->currentIndex() == 0 && _ui->comboBox_meshingApproach->currentIndex()<2)
|
||||
{
|
||||
_ui->comboBox_meshingApproach->setCurrentIndex(3);
|
||||
}
|
||||
if(_ui->comboBox_pipeline->currentIndex() == 1 && _ui->comboBox_meshingApproach->currentIndex()>1)
|
||||
{
|
||||
_ui->comboBox_meshingApproach->setCurrentIndex(1);
|
||||
}
|
||||
if(!_ui->checkBox_assemble->isChecked())
|
||||
{
|
||||
_ui->comboBox_meshingApproach->setCurrentIndex(0);
|
||||
_ui->comboBox_meshingApproach->setCurrentIndex(_ui->comboBox_pipeline->currentIndex() == 1?0:3);
|
||||
}
|
||||
|
||||
_ui->checkBox_poisson_outputPolygons->setDisabled(
|
||||
@@ -558,6 +601,18 @@ void ExportCloudsDialog::updateReconstructionFlavor()
|
||||
|
||||
_ui->checkBox_cleanMesh->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1);
|
||||
_ui->label_meshClean->setEnabled(_ui->comboBox_pipeline->currentIndex() == 1);
|
||||
|
||||
_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);
|
||||
_ui->groupBox_cputsdf->setVisible(_ui->comboBox_pipeline->currentIndex() == 0 && _ui->comboBox_meshingApproach->currentIndex()==2);
|
||||
_ui->groupBox_organized->setVisible(_ui->comboBox_pipeline->currentIndex() == 0 && _ui->comboBox_meshingApproach->currentIndex()==3);
|
||||
|
||||
#ifndef DISABLE_VTK
|
||||
_ui->doubleSpinBox_meshDecimationFactor->setEnabled(_ui->comboBox_meshingApproach->currentIndex()!=3);
|
||||
_ui->label_meshDecimation->setEnabled(_ui->comboBox_meshingApproach->currentIndex()!=3);
|
||||
_ui->spinBox_meshMaxPolygons->setEnabled(_ui->comboBox_meshingApproach->currentIndex()!=3);
|
||||
_ui->label_meshMaxPolygons->setEnabled(_ui->comboBox_meshingApproach->currentIndex()!=3);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1255,6 +1310,10 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RTABMAP_CPUTSDF
|
||||
cpu_tsdf::TSDFVolumeOctree::Ptr tsdf;
|
||||
#endif
|
||||
|
||||
//used for organized texturing below
|
||||
std::map<int, std::vector<int> > organizedIndices;
|
||||
std::map<int, cv::Size> organizedCloudSizes;
|
||||
@@ -1264,8 +1323,15 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
if(_ui->checkBox_meshing->isChecked())
|
||||
{
|
||||
if(_ui->comboBox_pipeline->currentIndex() == 0)
|
||||
{
|
||||
if(_ui->comboBox_meshingApproach->currentIndex()==2)
|
||||
{
|
||||
_progressDialog->appendText(tr("Creating TSDF volume... "));
|
||||
}
|
||||
else
|
||||
{
|
||||
_progressDialog->appendText(tr("Organized fast mesh... "));
|
||||
}
|
||||
QApplication::processEvents();
|
||||
uSleep(100);
|
||||
QApplication::processEvents();
|
||||
@@ -1297,6 +1363,65 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
_dbDriver->getCalibration(iter->first, models, stereoModel);
|
||||
}
|
||||
|
||||
#ifdef RTABMAP_CPUTSDF
|
||||
if(_ui->comboBox_meshingApproach->currentIndex()==2 && _ui->checkBox_assemble->isChecked())
|
||||
{
|
||||
if(tsdf.get() == 0)
|
||||
{
|
||||
if(models.size()==1 && models[0].isValidForProjection() && models[0].imageHeight()>0 && models[0].imageWidth()>0)
|
||||
{
|
||||
float tsdf_size = _ui->doubleSpinBox_cputsdf_size->value();
|
||||
float cell_size = _ui->doubleSpinBox_cputsdf_resolution->value();
|
||||
int num_random_splits = _ui->spinBox_cputsdf_randomSplit->value();
|
||||
int tsdf_res;
|
||||
int desired_res = tsdf_size / cell_size;
|
||||
// Snap to nearest power of 2;
|
||||
int n = 1;
|
||||
while (desired_res > n)
|
||||
{
|
||||
n *= 2;
|
||||
}
|
||||
tsdf_res = n;
|
||||
_progressDialog->appendText(tr("CPU-TSDF: Setting resolution: %1 with grid size %2").arg(tsdf_res).arg(tsdf_size));
|
||||
tsdf.reset (new cpu_tsdf::TSDFVolumeOctree);
|
||||
tsdf->setGridSize (tsdf_size, tsdf_size, tsdf_size);
|
||||
tsdf->setResolution (tsdf_res, tsdf_res, tsdf_res);
|
||||
float decimation = float(models[0].imageWidth()) / float(iter->second->width);
|
||||
tsdf->setImageSize (models[0].imageWidth()/decimation, models[0].imageHeight()/decimation);
|
||||
tsdf->setCameraIntrinsics (models[0].fx()/decimation, models[0].fy()/decimation, models[0].cx()/decimation, models[0].cy()/decimation);
|
||||
tsdf->setNumRandomSplts (num_random_splits);
|
||||
tsdf->setSensorDistanceBounds (0, 9999);
|
||||
tsdf->setIntegrateColor(true);
|
||||
tsdf->setDepthTruncationLimits (_ui->doubleSpinBox_cputsdf_tuncPos->value(), _ui->doubleSpinBox_cputsdf_tuncNeg->value());
|
||||
tsdf->reset ();
|
||||
}
|
||||
else
|
||||
{
|
||||
_progressDialog->appendText(tr("CPU-TSDF: Invalid camera model! Only single RGB-D camera supported."), Qt::darkYellow);
|
||||
_progressDialog->setAutoClose(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(tsdf.get())
|
||||
{
|
||||
if(tsdf.get() && models.size() == 1 && !models[0].localTransform().isNull())
|
||||
{
|
||||
Eigen::Affine3d pose_rel_to_first_frame = ((poses.begin()->second.inverse() * poses.at(iter->first))*models[0].localTransform()).toEigen3d();
|
||||
if(!tsdf->integrateCloud(*util3d::transformPointCloud(iter->second, models[0].localTransform().inverse()), pcl::PointCloud<pcl::Normal>(), pose_rel_to_first_frame))
|
||||
{
|
||||
_progressDialog->appendText(tr("CPU-TSDF: Failed integrating cloud %1 to TSDF volume").arg(iter->first));
|
||||
}
|
||||
else
|
||||
{
|
||||
_progressDialog->appendText(tr("CPU-TSDF: Integrated cloud %1 to TSDF volume").arg(iter->first));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if(models.size() && !models[0].localTransform().isNull())
|
||||
{
|
||||
viewpoint[0] = models[0].localTransform().x();
|
||||
@@ -1422,6 +1547,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_progressDialog->appendText(tr("Mesh %1 not created (no valid points) (%2/%3).").arg(iter->first).arg(++i).arg(clouds.size()));
|
||||
@@ -1529,241 +1655,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
|
||||
if(mesh->polygons.size()>0)
|
||||
{
|
||||
double meshDecimationFactor = 0.0;
|
||||
if(_ui->doubleSpinBox_meshDecimationFactor->isEnabled() &&
|
||||
_ui->doubleSpinBox_meshDecimationFactor->value() > 0.0)
|
||||
{
|
||||
meshDecimationFactor = _ui->doubleSpinBox_meshDecimationFactor->value();
|
||||
}
|
||||
if(_ui->spinBox_meshMaxPolygons->isEnabled() &&
|
||||
_ui->spinBox_meshMaxPolygons->value() > 0)
|
||||
{
|
||||
double factor = 1.0-double(_ui->spinBox_meshMaxPolygons->value())/double(mesh->polygons.size());
|
||||
if(factor > meshDecimationFactor)
|
||||
{
|
||||
meshDecimationFactor = factor;
|
||||
}
|
||||
}
|
||||
if(meshDecimationFactor > 0.0)
|
||||
{
|
||||
unsigned int count = mesh->polygons.size();
|
||||
_progressDialog->appendText(tr("Mesh decimation (factor=%1) from %2 polygons...").arg(meshDecimationFactor).arg(count));
|
||||
QApplication::processEvents();
|
||||
uSleep(100);
|
||||
QApplication::processEvents();
|
||||
|
||||
mesh = util3d::meshDecimation(mesh, (float)meshDecimationFactor);
|
||||
_progressDialog->appendText(tr("Mesh decimated (factor=%1) from %2 to %3 polygons").arg(meshDecimationFactor).arg(count).arg(mesh->polygons.size()));
|
||||
if(count < mesh->polygons.size())
|
||||
{
|
||||
_progressDialog->appendText(tr("Decimated mesh %1 has more polygons than before!").arg(iter->first), Qt::darkYellow);
|
||||
_progressDialog->setAutoClose(false);
|
||||
}
|
||||
QApplication::processEvents();
|
||||
lostColors = true;
|
||||
}
|
||||
|
||||
if(lostColors &&
|
||||
_ui->doubleSpinBox_transferColorRadius->value() >= 0.0 &&
|
||||
(!_ui->checkBox_textureMapping->isEnabled() || !_ui->checkBox_textureMapping->isChecked()))
|
||||
{
|
||||
_progressDialog->appendText(tr("Transferring color from point cloud to mesh..."));
|
||||
QApplication::processEvents();
|
||||
|
||||
// transfer color from point cloud to mesh
|
||||
pcl::search::KdTree<pcl::PointXYZRGBNormal>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGBNormal>(true));
|
||||
tree->setInputCloud(iter->second);
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr coloredCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
|
||||
pcl::fromPCLPointCloud2(mesh->cloud, *coloredCloud);
|
||||
std::vector<bool> coloredPts(coloredCloud->size());
|
||||
for(unsigned int i=0; i<coloredCloud->size(); ++i)
|
||||
{
|
||||
std::vector<int> kIndices;
|
||||
std::vector<float> kDistances;
|
||||
pcl::PointXYZRGBNormal pt;
|
||||
pt.x = coloredCloud->at(i).x;
|
||||
pt.y = coloredCloud->at(i).y;
|
||||
pt.z = coloredCloud->at(i).z;
|
||||
if(_ui->doubleSpinBox_transferColorRadius->value() > 0.0)
|
||||
{
|
||||
tree->radiusSearch(pt, _ui->doubleSpinBox_transferColorRadius->value(), kIndices, kDistances);
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->nearestKSearch(pt, 1, kIndices, kDistances);
|
||||
}
|
||||
if(kIndices.size())
|
||||
{
|
||||
//compute average color
|
||||
int r=0;
|
||||
int g=0;
|
||||
int b=0;
|
||||
int a=0;
|
||||
for(unsigned int j=0; j<kIndices.size(); ++j)
|
||||
{
|
||||
r+=(int)iter->second->at(kIndices[j]).r;
|
||||
g+=(int)iter->second->at(kIndices[j]).g;
|
||||
b+=(int)iter->second->at(kIndices[j]).b;
|
||||
a+=(int)iter->second->at(kIndices[j]).a;
|
||||
}
|
||||
coloredCloud->at(i).r = r/kIndices.size();
|
||||
coloredCloud->at(i).g = g/kIndices.size();
|
||||
coloredCloud->at(i).b = b/kIndices.size();
|
||||
coloredCloud->at(i).a = a/kIndices.size();
|
||||
coloredPts.at(i) = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//white
|
||||
coloredCloud->at(i).r = coloredCloud->at(i).g = coloredCloud->at(i).b = 255;
|
||||
coloredPts.at(i) = false;
|
||||
}
|
||||
}
|
||||
pcl::toPCLPointCloud2(*coloredCloud, mesh->cloud);
|
||||
|
||||
// remove polygons with no color
|
||||
if(_ui->checkBox_cleanMesh->isChecked())
|
||||
{
|
||||
std::vector<pcl::Vertices> filteredPolygons(mesh->polygons.size());
|
||||
int oi=0;
|
||||
for(unsigned int i=0; i<mesh->polygons.size(); ++i)
|
||||
{
|
||||
bool coloredPolygon = true;
|
||||
for(unsigned int j=0; j<mesh->polygons[i].vertices.size(); ++j)
|
||||
{
|
||||
if(!coloredPts.at(mesh->polygons[i].vertices[j]))
|
||||
{
|
||||
coloredPolygon = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(coloredPolygon)
|
||||
{
|
||||
filteredPolygons[oi++] = mesh->polygons[i];
|
||||
}
|
||||
}
|
||||
filteredPolygons.resize(oi);
|
||||
mesh->polygons = filteredPolygons;
|
||||
}
|
||||
}
|
||||
else if(lostColors &&
|
||||
_ui->doubleSpinBox_transferColorRadius->value() > 0.0 &&
|
||||
_ui->checkBox_cleanMesh->isChecked() &&
|
||||
(_ui->checkBox_textureMapping->isEnabled() && _ui->checkBox_textureMapping->isChecked()))
|
||||
{
|
||||
_progressDialog->appendText(tr("Removing polygons too far from the cloud..."));
|
||||
QApplication::processEvents();
|
||||
|
||||
// transfer color from point cloud to mesh
|
||||
pcl::search::KdTree<pcl::PointXYZRGBNormal>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGBNormal>(true));
|
||||
tree->setInputCloud(iter->second);
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr optimizedCloud(new pcl::PointCloud<pcl::PointXYZ>);
|
||||
pcl::fromPCLPointCloud2(mesh->cloud, *optimizedCloud);
|
||||
std::vector<bool> closePts(optimizedCloud->size());
|
||||
for(unsigned int i=0; i<optimizedCloud->size(); ++i)
|
||||
{
|
||||
std::vector<int> kIndices;
|
||||
std::vector<float> kDistances;
|
||||
pcl::PointXYZRGBNormal pt;
|
||||
pt.x = optimizedCloud->at(i).x;
|
||||
pt.y = optimizedCloud->at(i).y;
|
||||
pt.z = optimizedCloud->at(i).z;
|
||||
tree->radiusSearch(pt, _ui->doubleSpinBox_transferColorRadius->value(), kIndices, kDistances);
|
||||
if(kIndices.size())
|
||||
{
|
||||
closePts.at(i) = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
closePts.at(i) = false;
|
||||
}
|
||||
}
|
||||
|
||||
// remove far polygons
|
||||
std::vector<pcl::Vertices> filteredPolygons(mesh->polygons.size());
|
||||
int oi=0;
|
||||
for(unsigned int i=0; i<mesh->polygons.size(); ++i)
|
||||
{
|
||||
bool keepPolygon = true;
|
||||
for(unsigned int j=0; j<mesh->polygons[i].vertices.size(); ++j)
|
||||
{
|
||||
if(!closePts.at(mesh->polygons[i].vertices[j]))
|
||||
{
|
||||
keepPolygon = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(keepPolygon)
|
||||
{
|
||||
filteredPolygons[oi++] = mesh->polygons[i];
|
||||
}
|
||||
}
|
||||
filteredPolygons.resize(oi);
|
||||
mesh->polygons = filteredPolygons;
|
||||
}
|
||||
|
||||
if(_ui->spinBox_mesh_minClusterSize->value() &&
|
||||
!(_ui->checkBox_textureMapping->isEnabled() &&
|
||||
_ui->checkBox_textureMapping->isChecked() &&
|
||||
_ui->checkBox_cleanMesh->isChecked()))
|
||||
{
|
||||
_progressDialog->appendText(tr("Filter small polygon clusters..."));
|
||||
QApplication::processEvents();
|
||||
|
||||
// filter polygons
|
||||
std::vector<std::set<int> > neighbors;
|
||||
std::vector<std::set<int> > vertexToPolygons;
|
||||
util3d::createPolygonIndexes(mesh->polygons,
|
||||
mesh->cloud.height*mesh->cloud.width,
|
||||
neighbors,
|
||||
vertexToPolygons);
|
||||
std::list<std::list<int> > clusters = util3d::clusterPolygons(
|
||||
neighbors,
|
||||
_ui->spinBox_mesh_minClusterSize->value()<0?0:_ui->spinBox_mesh_minClusterSize->value());
|
||||
|
||||
std::vector<pcl::Vertices> filteredPolygons(mesh->polygons.size());
|
||||
if(_ui->spinBox_mesh_minClusterSize->value() < 0)
|
||||
{
|
||||
// only keep the biggest cluster
|
||||
std::list<std::list<int> >::iterator biggestClusterIndex = clusters.end();
|
||||
unsigned int biggestClusterSize = 0;
|
||||
for(std::list<std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
|
||||
{
|
||||
if(iter->size() > biggestClusterSize)
|
||||
{
|
||||
biggestClusterIndex = iter;
|
||||
biggestClusterSize = iter->size();
|
||||
}
|
||||
}
|
||||
if(biggestClusterIndex != clusters.end())
|
||||
{
|
||||
int oi=0;
|
||||
for(std::list<int>::iterator jter=biggestClusterIndex->begin(); jter!=biggestClusterIndex->end(); ++jter)
|
||||
{
|
||||
filteredPolygons[oi++] = mesh->polygons.at(*jter);
|
||||
}
|
||||
filteredPolygons.resize(oi);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int oi=0;
|
||||
for(std::list<std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
|
||||
{
|
||||
for(std::list<int>::iterator jter=iter->begin(); jter!=iter->end(); ++jter)
|
||||
{
|
||||
filteredPolygons[oi++] = mesh->polygons.at(*jter);
|
||||
}
|
||||
}
|
||||
filteredPolygons.resize(oi);
|
||||
}
|
||||
|
||||
int before = (int)mesh->polygons.size();
|
||||
mesh->polygons = filteredPolygons;
|
||||
|
||||
_progressDialog->appendText(tr("Filtered %1 polygons.").arg(before-(int)mesh->polygons.size()));
|
||||
}
|
||||
|
||||
denseMeshPostProcessing(iter->first, mesh, lostColors, iter->second);
|
||||
meshes.insert(std::make_pair(iter->first, mesh));
|
||||
}
|
||||
else
|
||||
@@ -1782,6 +1674,91 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RTABMAP_CPUTSDF
|
||||
if(tsdf.get())
|
||||
{
|
||||
_progressDialog->appendText(tr("CPU-TSDF: Creating mesh from TSDF volume..."));
|
||||
QApplication::processEvents();
|
||||
uSleep(100);
|
||||
QApplication::processEvents();
|
||||
|
||||
cpu_tsdf::MarchingCubesTSDFOctree mc;
|
||||
mc.setMinWeight (_ui->doubleSpinBox_cputsdf_minWeight->value());
|
||||
mc.setInputTSDF (tsdf);
|
||||
mc.setColorByRGB (true);
|
||||
pcl::PolygonMesh::Ptr mesh (new pcl::PolygonMesh);
|
||||
mc.reconstruct (*mesh);
|
||||
_progressDialog->appendText(tr("CPU-TSDF: Creating mesh from TSDF volume...done!"));
|
||||
meshes.clear();
|
||||
|
||||
if(mesh->polygons.size()>0)
|
||||
{
|
||||
|
||||
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr vertices (new pcl::PointCloud<pcl::PointXYZRGBNormal>);
|
||||
pcl::fromPCLPointCloud2 (mesh->cloud, *vertices);
|
||||
|
||||
if(_ui->doubleSpinBox_cputsdf_flattenRadius->value()>0.0)
|
||||
{
|
||||
_progressDialog->appendText(tr("CPU-TSDF: Flattening mesh (radius=%1)...").arg(_ui->doubleSpinBox_cputsdf_flattenRadius->value()));
|
||||
QApplication::processEvents();
|
||||
uSleep(100);
|
||||
QApplication::processEvents();
|
||||
|
||||
float min_dist = _ui->doubleSpinBox_cputsdf_flattenRadius->value();
|
||||
pcl::search::KdTree<pcl::PointXYZRGBNormal> vert_tree (true);
|
||||
vert_tree.setInputCloud (vertices);
|
||||
// Find duplicates
|
||||
std::vector<int> vertex_remap (vertices->size (), -1);
|
||||
int idx = 0;
|
||||
std::vector<int> neighbors;
|
||||
std::vector<float> dists;
|
||||
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr vertices_new(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
|
||||
vertices_new->resize(vertices->size ());
|
||||
for (size_t i = 0; i < vertices->size (); i++)
|
||||
{
|
||||
if (vertex_remap[i] >= 0)
|
||||
continue;
|
||||
vertex_remap[i] = idx;
|
||||
vert_tree.radiusSearch (i, min_dist, neighbors, dists);
|
||||
for (size_t j = 1; j < neighbors.size (); j++)
|
||||
{
|
||||
if (dists[j] < min_dist)
|
||||
vertex_remap[neighbors[j]] = idx;
|
||||
}
|
||||
vertices_new->at(idx++) = vertices->at (i);
|
||||
}
|
||||
vertices_new->resize(idx);
|
||||
std::vector<size_t> faces_to_remove;
|
||||
size_t face_idx = 0;
|
||||
for (size_t i = 0; i < mesh->polygons.size (); i++)
|
||||
{
|
||||
pcl::Vertices &v = mesh->polygons[i];
|
||||
for (size_t j = 0; j < v.vertices.size (); j++)
|
||||
{
|
||||
v.vertices[j] = vertex_remap[v.vertices[j]];
|
||||
}
|
||||
if (!(v.vertices[0] == v.vertices[1] || v.vertices[1] == v.vertices[2] || v.vertices[2] == v.vertices[0]))
|
||||
{
|
||||
mesh->polygons[face_idx++] = mesh->polygons[i];
|
||||
}
|
||||
}
|
||||
mesh->polygons.resize (face_idx);
|
||||
pcl::toPCLPointCloud2 (*vertices_new, mesh->cloud);
|
||||
vertices = vertices_new;
|
||||
}
|
||||
|
||||
pcl::fromPCLPointCloud2(mesh->cloud, *vertices);
|
||||
denseMeshPostProcessing(0, mesh, false, vertices);
|
||||
meshes.insert(std::make_pair(0, mesh));
|
||||
}
|
||||
else
|
||||
{
|
||||
_progressDialog->appendText(tr("No polygons created TSDF volume!"), Qt::darkYellow);
|
||||
_progressDialog->setAutoClose(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(_canceled)
|
||||
{
|
||||
return false;
|
||||
@@ -3628,4 +3605,246 @@ void ExportCloudsDialog::saveTextureMeshes(
|
||||
}
|
||||
}
|
||||
|
||||
void ExportCloudsDialog::denseMeshPostProcessing(
|
||||
int id,
|
||||
pcl::PolygonMeshPtr & mesh,
|
||||
bool lostColors,
|
||||
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud)
|
||||
{
|
||||
double meshDecimationFactor = 0.0;
|
||||
if(_ui->doubleSpinBox_meshDecimationFactor->isEnabled() &&
|
||||
_ui->doubleSpinBox_meshDecimationFactor->value() > 0.0)
|
||||
{
|
||||
meshDecimationFactor = _ui->doubleSpinBox_meshDecimationFactor->value();
|
||||
}
|
||||
if(_ui->spinBox_meshMaxPolygons->isEnabled() &&
|
||||
_ui->spinBox_meshMaxPolygons->value() > 0)
|
||||
{
|
||||
double factor = 1.0-double(_ui->spinBox_meshMaxPolygons->value())/double(mesh->polygons.size());
|
||||
if(factor > meshDecimationFactor)
|
||||
{
|
||||
meshDecimationFactor = factor;
|
||||
}
|
||||
}
|
||||
if(meshDecimationFactor > 0.0)
|
||||
{
|
||||
unsigned int count = mesh->polygons.size();
|
||||
_progressDialog->appendText(tr("Mesh decimation (factor=%1) from %2 polygons...").arg(meshDecimationFactor).arg(count));
|
||||
QApplication::processEvents();
|
||||
uSleep(100);
|
||||
QApplication::processEvents();
|
||||
|
||||
mesh = util3d::meshDecimation(mesh, (float)meshDecimationFactor);
|
||||
_progressDialog->appendText(tr("Mesh decimated (factor=%1) from %2 to %3 polygons").arg(meshDecimationFactor).arg(count).arg(mesh->polygons.size()));
|
||||
if(count < mesh->polygons.size())
|
||||
{
|
||||
_progressDialog->appendText(tr("Decimated mesh %1 has more polygons than before!").arg(id), Qt::darkYellow);
|
||||
_progressDialog->setAutoClose(false);
|
||||
}
|
||||
QApplication::processEvents();
|
||||
lostColors = true;
|
||||
}
|
||||
|
||||
if(lostColors &&
|
||||
_ui->doubleSpinBox_transferColorRadius->value() >= 0.0 &&
|
||||
(!_ui->checkBox_textureMapping->isEnabled() || !_ui->checkBox_textureMapping->isChecked()))
|
||||
{
|
||||
_progressDialog->appendText(tr("Transferring color from point cloud to mesh..."));
|
||||
QApplication::processEvents();
|
||||
|
||||
// transfer color from point cloud to mesh
|
||||
pcl::search::KdTree<pcl::PointXYZRGBNormal>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGBNormal>(true));
|
||||
tree->setInputCloud(cloud);
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr coloredCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
|
||||
pcl::fromPCLPointCloud2(mesh->cloud, *coloredCloud);
|
||||
std::vector<bool> coloredPts(coloredCloud->size());
|
||||
for(unsigned int i=0; i<coloredCloud->size(); ++i)
|
||||
{
|
||||
std::vector<int> kIndices;
|
||||
std::vector<float> kDistances;
|
||||
pcl::PointXYZRGBNormal pt;
|
||||
pt.x = coloredCloud->at(i).x;
|
||||
pt.y = coloredCloud->at(i).y;
|
||||
pt.z = coloredCloud->at(i).z;
|
||||
if(_ui->doubleSpinBox_transferColorRadius->value() > 0.0)
|
||||
{
|
||||
tree->radiusSearch(pt, _ui->doubleSpinBox_transferColorRadius->value(), kIndices, kDistances);
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->nearestKSearch(pt, 1, kIndices, kDistances);
|
||||
}
|
||||
if(kIndices.size())
|
||||
{
|
||||
//compute average color
|
||||
int r=0;
|
||||
int g=0;
|
||||
int b=0;
|
||||
int a=0;
|
||||
for(unsigned int j=0; j<kIndices.size(); ++j)
|
||||
{
|
||||
r+=(int)cloud->at(kIndices[j]).r;
|
||||
g+=(int)cloud->at(kIndices[j]).g;
|
||||
b+=(int)cloud->at(kIndices[j]).b;
|
||||
a+=(int)cloud->at(kIndices[j]).a;
|
||||
}
|
||||
coloredCloud->at(i).r = r/kIndices.size();
|
||||
coloredCloud->at(i).g = g/kIndices.size();
|
||||
coloredCloud->at(i).b = b/kIndices.size();
|
||||
coloredCloud->at(i).a = a/kIndices.size();
|
||||
coloredPts.at(i) = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//white
|
||||
coloredCloud->at(i).r = coloredCloud->at(i).g = coloredCloud->at(i).b = 255;
|
||||
coloredPts.at(i) = false;
|
||||
}
|
||||
}
|
||||
pcl::toPCLPointCloud2(*coloredCloud, mesh->cloud);
|
||||
|
||||
// remove polygons with no color
|
||||
if(_ui->checkBox_cleanMesh->isChecked())
|
||||
{
|
||||
std::vector<pcl::Vertices> filteredPolygons(mesh->polygons.size());
|
||||
int oi=0;
|
||||
for(unsigned int i=0; i<mesh->polygons.size(); ++i)
|
||||
{
|
||||
bool coloredPolygon = true;
|
||||
for(unsigned int j=0; j<mesh->polygons[i].vertices.size(); ++j)
|
||||
{
|
||||
if(!coloredPts.at(mesh->polygons[i].vertices[j]))
|
||||
{
|
||||
coloredPolygon = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(coloredPolygon)
|
||||
{
|
||||
filteredPolygons[oi++] = mesh->polygons[i];
|
||||
}
|
||||
}
|
||||
filteredPolygons.resize(oi);
|
||||
mesh->polygons = filteredPolygons;
|
||||
}
|
||||
}
|
||||
else if(lostColors &&
|
||||
_ui->doubleSpinBox_transferColorRadius->value() > 0.0 &&
|
||||
_ui->checkBox_cleanMesh->isChecked() &&
|
||||
(_ui->checkBox_textureMapping->isEnabled() && _ui->checkBox_textureMapping->isChecked()))
|
||||
{
|
||||
_progressDialog->appendText(tr("Removing polygons too far from the cloud..."));
|
||||
QApplication::processEvents();
|
||||
|
||||
// transfer color from point cloud to mesh
|
||||
pcl::search::KdTree<pcl::PointXYZRGBNormal>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGBNormal>(true));
|
||||
tree->setInputCloud(cloud);
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr optimizedCloud(new pcl::PointCloud<pcl::PointXYZ>);
|
||||
pcl::fromPCLPointCloud2(mesh->cloud, *optimizedCloud);
|
||||
std::vector<bool> closePts(optimizedCloud->size());
|
||||
for(unsigned int i=0; i<optimizedCloud->size(); ++i)
|
||||
{
|
||||
std::vector<int> kIndices;
|
||||
std::vector<float> kDistances;
|
||||
pcl::PointXYZRGBNormal pt;
|
||||
pt.x = optimizedCloud->at(i).x;
|
||||
pt.y = optimizedCloud->at(i).y;
|
||||
pt.z = optimizedCloud->at(i).z;
|
||||
tree->radiusSearch(pt, _ui->doubleSpinBox_transferColorRadius->value(), kIndices, kDistances);
|
||||
if(kIndices.size())
|
||||
{
|
||||
closePts.at(i) = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
closePts.at(i) = false;
|
||||
}
|
||||
}
|
||||
|
||||
// remove far polygons
|
||||
std::vector<pcl::Vertices> filteredPolygons(mesh->polygons.size());
|
||||
int oi=0;
|
||||
for(unsigned int i=0; i<mesh->polygons.size(); ++i)
|
||||
{
|
||||
bool keepPolygon = true;
|
||||
for(unsigned int j=0; j<mesh->polygons[i].vertices.size(); ++j)
|
||||
{
|
||||
if(!closePts.at(mesh->polygons[i].vertices[j]))
|
||||
{
|
||||
keepPolygon = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(keepPolygon)
|
||||
{
|
||||
filteredPolygons[oi++] = mesh->polygons[i];
|
||||
}
|
||||
}
|
||||
filteredPolygons.resize(oi);
|
||||
mesh->polygons = filteredPolygons;
|
||||
}
|
||||
|
||||
if(_ui->spinBox_mesh_minClusterSize->value() &&
|
||||
!(_ui->checkBox_textureMapping->isEnabled() &&
|
||||
_ui->checkBox_textureMapping->isChecked() &&
|
||||
_ui->checkBox_cleanMesh->isChecked()))
|
||||
{
|
||||
_progressDialog->appendText(tr("Filter small polygon clusters..."));
|
||||
QApplication::processEvents();
|
||||
|
||||
// filter polygons
|
||||
std::vector<std::set<int> > neighbors;
|
||||
std::vector<std::set<int> > vertexToPolygons;
|
||||
util3d::createPolygonIndexes(mesh->polygons,
|
||||
mesh->cloud.height*mesh->cloud.width,
|
||||
neighbors,
|
||||
vertexToPolygons);
|
||||
std::list<std::list<int> > clusters = util3d::clusterPolygons(
|
||||
neighbors,
|
||||
_ui->spinBox_mesh_minClusterSize->value()<0?0:_ui->spinBox_mesh_minClusterSize->value());
|
||||
|
||||
std::vector<pcl::Vertices> filteredPolygons(mesh->polygons.size());
|
||||
if(_ui->spinBox_mesh_minClusterSize->value() < 0)
|
||||
{
|
||||
// only keep the biggest cluster
|
||||
std::list<std::list<int> >::iterator biggestClusterIndex = clusters.end();
|
||||
unsigned int biggestClusterSize = 0;
|
||||
for(std::list<std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
|
||||
{
|
||||
if(iter->size() > biggestClusterSize)
|
||||
{
|
||||
biggestClusterIndex = iter;
|
||||
biggestClusterSize = iter->size();
|
||||
}
|
||||
}
|
||||
if(biggestClusterIndex != clusters.end())
|
||||
{
|
||||
int oi=0;
|
||||
for(std::list<int>::iterator jter=biggestClusterIndex->begin(); jter!=biggestClusterIndex->end(); ++jter)
|
||||
{
|
||||
filteredPolygons[oi++] = mesh->polygons.at(*jter);
|
||||
}
|
||||
filteredPolygons.resize(oi);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int oi=0;
|
||||
for(std::list<std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
|
||||
{
|
||||
for(std::list<int>::iterator jter=iter->begin(); jter!=iter->end(); ++jter)
|
||||
{
|
||||
filteredPolygons[oi++] = mesh->polygons.at(*jter);
|
||||
}
|
||||
}
|
||||
filteredPolygons.resize(oi);
|
||||
}
|
||||
|
||||
int before = (int)mesh->polygons.size();
|
||||
mesh->polygons = filteredPolygons;
|
||||
|
||||
_progressDialog->appendText(tr("Filtered %1 polygons.").arg(before-(int)mesh->polygons.size()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -122,6 +122,12 @@ private:
|
||||
void setOkButton();
|
||||
void enableRegeneration(bool enabled);
|
||||
|
||||
void denseMeshPostProcessing(
|
||||
int id,
|
||||
pcl::PolygonMeshPtr & mesh,
|
||||
bool lostColors,
|
||||
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud);
|
||||
|
||||
private:
|
||||
Ui_ExportCloudsDialog * _ui;
|
||||
ProgressDialog * _progressDialog;
|
||||
|
||||
+180
-163
@@ -82,30 +82,6 @@ p, li { white-space: pre-wrap; }
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
|
||||
<item row="9" column="1">
|
||||
<widget class="QLabel" name="label_pcl_version">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Author :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>With Freenect :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
@@ -113,8 +89,8 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QLabel" name="label_freenect">
|
||||
<item row="9" column="1">
|
||||
<widget class="QLabel" name="label_pcl_version">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
@@ -123,44 +99,6 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QLabel" name="label_openni2">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>With Freenect2 :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>With stereo FlyCapture2 :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>PCL version :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Version :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="20" column="1">
|
||||
<widget class="QLabel" name="label_cvsba">
|
||||
<property name="text">
|
||||
@@ -171,15 +109,8 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="19" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>With GTSAM :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="21" column="1">
|
||||
<widget class="QLabel" name="label_octomap">
|
||||
<item row="11" column="1">
|
||||
<widget class="QLabel" name="label_freenect">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
@@ -188,25 +119,8 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="1">
|
||||
<widget class="QLabel" name="label_zed">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="21" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>With Octomap :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QLabel" name="label_dc1394">
|
||||
<item row="19" column="1">
|
||||
<widget class="QLabel" name="label_gtsam">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
@@ -225,8 +139,8 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLabel" name="label_version">
|
||||
<item row="21" column="1">
|
||||
<widget class="QLabel" name="label_octomap">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
@@ -235,41 +149,51 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_HomePage_3">
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://introlab.github.io/rtabmap"><span style=" text-decoration: underline; color:#0000ff;">Home page</span></a></p></body></html></string>
|
||||
<string>With Freenect2 :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>With OpenNI2 :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QLabel" name="label_vtk_version">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QLabel" name="label_openni2">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>OpenCV version :</string>
|
||||
<string>PCL version :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<item row="17" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>With g2o :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>With stereo dc1394 :</string>
|
||||
<string>With stereo Zed :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -283,42 +207,46 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<item row="18" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Mathieu Labbé, [email protected]</string>
|
||||
<string>With g2o :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="1">
|
||||
<widget class="QLabel" name="label_zed">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<item row="20" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>With OpenNI2 :</string>
|
||||
<string>With cvsba :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_HomePage_2">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://github.com/introlab/rtabmap"><span style=" text-decoration: underline; color:#0000ff;">Source page</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
<string>OpenCV version :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLabel" name="label_opencv_version">
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>With stereo dc1394 :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLabel" name="label_version">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
@@ -337,30 +265,6 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>With stereo Zed :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="19" column="1">
|
||||
<widget class="QLabel" name="label_gtsam">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="20" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>With cvsba :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
@@ -378,6 +282,64 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Mathieu Labbé, [email protected]</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Version :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLabel" name="label_opencv_version">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>With Freenect :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="21" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>With Octomap :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QLabel" name="label_dc1394">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Author :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
@@ -385,8 +347,63 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QLabel" name="label_vtk_version">
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>With stereo FlyCapture2 :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_HomePage_2">
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://github.com/introlab/rtabmap"><span style=" text-decoration: underline; color:#0000ff;">Source page</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_HomePage_3">
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://introlab.github.io/rtabmap"><span style=" text-decoration: underline; color:#0000ff;">Home page</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="19" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>With GTSAM :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="22" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>With CPU-TSDF :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="22" column="1">
|
||||
<widget class="QLabel" name="label_cputsdf">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-1802</y>
|
||||
<y>-3080</y>
|
||||
<width>778</width>
|
||||
<height>3385</height>
|
||||
<height>3701</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
@@ -1205,7 +1205,7 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_denseReconstruction">
|
||||
<property name="text">
|
||||
<string>Surface reconstruction approach. Can be used only when dense reconstruction flavor is selected. Poisson is available when clouds are assembled.</string>
|
||||
<string>Surface reconstruction approach. Poisson is available when clouds are assembled and dense reconstruction flavor is selected. CPU-TSDF is available when clouds are assembled, organized reconstruction flavor is selected and RTAB-Map is built with CPU-TSDF support.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -1244,7 +1244,7 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_meshDecimation">
|
||||
<property name="text">
|
||||
<string>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.</string>
|
||||
<string>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 organized mesh approach is not selected. Can reduce a lot texturing time.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -1273,6 +1273,16 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
|
||||
<string>Poisson</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>CPU-TSDF</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Organized</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
@@ -1998,6 +2008,247 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_cputsdf">
|
||||
<property name="title">
|
||||
<string>CPU-TSDF Reconstruction</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_17">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="https://github.com/sdmiller/cpu_tsdf"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/sdmiller/cpu_tsdf</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_17" columnstretch="0,1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_cputsdf_size">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>9999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>12.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Volume size.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_cputsdf_resolution">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Resolution.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_cputsdf_tuncPos">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.030000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Depth truncation positive limit. Maximum distance a voxel will be set to positive.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_cputsdf_tuncNeg">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.030000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Depth truncation negative limit. Maximum distance a voxel will be set to negative.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QSpinBox" name="spinBox_cputsdf_randomSplit">
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>Set the number of random samples per surface point the octree should split on. If you don't know what this does, it's almost certainly best to leave it at 1.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_cputsdf_minWeight">
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.500000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Minimum weight of a voxel to be added in the mesh.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_cputsdf_flattenRadius">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>9.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.005000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.005000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Flatten radius (0=disabled).</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_organized">
|
||||
<property name="title">
|
||||
@@ -2009,6 +2260,9 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
|
||||
<property name="text">
|
||||
<string>Triangle size</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@@ -2016,6 +2270,9 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
|
||||
<property name="text">
|
||||
<string>Quad</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
@@ -2052,6 +2309,9 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
|
||||
<property name="text">
|
||||
<string>Angle tolerance</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
|
||||
Reference in New Issue
Block a user