ExportDialog: added ground normals up option, added camera projection mask and decimation options. Export CLI: added --ground_normals_up and --cam_projection_mask options, changed --bin option by --ascii option (now binary by default). DBViewer: warn when scan from depth option is enabled but there is no depth.

This commit is contained in:
matlabbe
2022-01-27 17:57:56 -05:00
parent a8e5bbf415
commit 402afc07ed
9 changed files with 626 additions and 352 deletions

View File

@@ -106,6 +106,7 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
connect(_ui->checkBox_binary, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->spinBox_normalKSearch, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->doubleSpinBox_normalRadiusSearch, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->doubleSpinBox_groundNormalsUp, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->comboBox_pipeline, SIGNAL(currentIndexChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->comboBox_pipeline, SIGNAL(currentIndexChanged(int)), this, SLOT(updateReconstructionFlavor()));
connect(_ui->comboBox_meshingApproach, SIGNAL(currentIndexChanged(int)), this, SIGNAL(configChanged()));
@@ -192,6 +193,9 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
connect(_ui->checkBox_cameraProjection, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->checkBox_cameraProjection, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor()));
connect(_ui->lineEdit_camProjRoiRatios, SIGNAL(textChanged(const QString &)), this, SIGNAL(configChanged()));
connect(_ui->toolButton_camProjMaskFilePath, SIGNAL(clicked()), this, SLOT(selectCamProjMask()));
connect(_ui->lineEdit_camProjMaskFilePath, SIGNAL(textChanged(const QString &)), this, SIGNAL(configChanged()));
connect(_ui->spinBox_camProjDecimation, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->doubleSpinBox_camProjMaxDistance, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->doubleSpinBox_camProjMaxAngle, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
connect(_ui->checkBox_camProjDistanceToCamPolicy, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
@@ -348,6 +352,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("normals_radius", _ui->doubleSpinBox_normalRadiusSearch->value());
settings.setValue("normals_ground_normals_up", _ui->doubleSpinBox_groundNormalsUp->value());
settings.setValue("intensity_colormap", _ui->comboBox_intensityColormap->currentIndex());
settings.setValue("nodes_filtering", _ui->checkBox_nodes_filtering->isChecked());
@@ -413,6 +418,8 @@ void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & grou
settings.setValue("cam_proj", _ui->checkBox_cameraProjection->isChecked());
settings.setValue("cam_proj_roi_ratios", _ui->lineEdit_camProjRoiRatios->text());
settings.setValue("cam_proj_mask", _ui->lineEdit_camProjMaskFilePath->text());
settings.setValue("cam_proj_decimation", _ui->spinBox_camProjDecimation->value());
settings.setValue("cam_proj_max_distance", _ui->doubleSpinBox_camProjMaxDistance->value());
settings.setValue("cam_proj_max_angle", _ui->doubleSpinBox_camProjMaxAngle->value());
settings.setValue("cam_proj_distance_policy", _ui->checkBox_camProjDistanceToCamPolicy->isChecked());
@@ -518,6 +525,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->doubleSpinBox_normalRadiusSearch->setValue(settings.value("normals_radius", _ui->doubleSpinBox_normalRadiusSearch->value()).toDouble());
_ui->doubleSpinBox_groundNormalsUp->setValue(settings.value("normals_ground_normals_up", _ui->doubleSpinBox_groundNormalsUp->value()).toDouble());
_ui->comboBox_intensityColormap->setCurrentIndex(settings.value("intensity_colormap", _ui->comboBox_intensityColormap->currentIndex()).toInt());
_ui->checkBox_nodes_filtering->setChecked(settings.value("nodes_filtering", _ui->checkBox_nodes_filtering->isChecked()).toBool());
@@ -586,6 +594,8 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou
_ui->checkBox_cameraProjection->setChecked(settings.value("cam_proj", _ui->checkBox_cameraProjection->isChecked()).toBool());
_ui->lineEdit_camProjRoiRatios->setText(settings.value("cam_proj_roi_ratios", _ui->lineEdit_camProjRoiRatios->text()).toString());
_ui->lineEdit_camProjMaskFilePath->setText(settings.value("cam_proj_mask", _ui->lineEdit_camProjMaskFilePath->text()).toString());
_ui->spinBox_camProjDecimation->setValue(settings.value("cam_proj_decimation", _ui->spinBox_camProjDecimation->value()).toInt());
_ui->doubleSpinBox_camProjMaxDistance->setValue(settings.value("cam_proj_max_distance", _ui->doubleSpinBox_camProjMaxDistance->value()).toDouble());
_ui->doubleSpinBox_camProjMaxAngle->setValue(settings.value("cam_proj_max_angle", _ui->doubleSpinBox_camProjMaxAngle->value()).toDouble());
_ui->checkBox_camProjDistanceToCamPolicy->setChecked(settings.value("cam_proj_distance_policy", _ui->checkBox_camProjDistanceToCamPolicy->isChecked()).toBool());
@@ -691,6 +701,7 @@ void ExportCloudsDialog::restoreDefaults()
_ui->checkBox_binary->setChecked(true);
_ui->spinBox_normalKSearch->setValue(20);
_ui->doubleSpinBox_normalRadiusSearch->setValue(0.0);
_ui->doubleSpinBox_groundNormalsUp->setValue(0.0);
_ui->comboBox_intensityColormap->setCurrentIndex(0);
_ui->checkBox_nodes_filtering->setChecked(false);
@@ -756,6 +767,8 @@ void ExportCloudsDialog::restoreDefaults()
_ui->checkBox_cameraProjection->setChecked(false);
_ui->lineEdit_camProjRoiRatios->setText("0.0 0.0 0.0 0.0");
_ui->lineEdit_camProjMaskFilePath->setText("");
_ui->spinBox_camProjDecimation->setValue(1);
_ui->doubleSpinBox_camProjMaxDistance->setValue(0);
_ui->doubleSpinBox_camProjMaxAngle->setValue(0);
_ui->checkBox_camProjDistanceToCamPolicy->setChecked(true);
@@ -1018,6 +1031,20 @@ void ExportCloudsDialog::selectDistortionModel()
}
}
void ExportCloudsDialog::selectCamProjMask()
{
QString dir = _ui->lineEdit_camProjMaskFilePath->text();
if(dir.isEmpty())
{
dir = _workingDirectory;
}
QString path = QFileDialog::getOpenFileName(this, tr("Select file"), dir, tr("Mask (grayscale) (*.png *.pgm *bmp)"));
if(path.size())
{
_ui->lineEdit_camProjMaskFilePath->setText(path);
}
}
void ExportCloudsDialog::setSaveButton()
{
_ui->buttonBox->button(QDialogButtonBox::Ok)->setVisible(false);
@@ -1913,7 +1940,8 @@ bool ExportCloudsDialog::getExportedClouds(
normalViewpoints,
rawAssembledCloud,
rawCameraIndices,
assembledCloud);
assembledCloud,
_ui->doubleSpinBox_groundNormalsUp->value());
}
if(_ui->spinBox_randomSamples_assembled->value()>0 &&
@@ -2724,17 +2752,56 @@ bool ExportCloudsDialog::getExportedClouds(
_progressDialog->setAutoClose(false);
}
}
std::map<int, std::vector<rtabmap::CameraModel> > cameraModelsProj;
if(_ui->spinBox_camProjDecimation->value()>1)
{
for(std::map<int, std::vector<rtabmap::CameraModel> >::iterator iter=cameraModels.begin();
iter!=cameraModels.end();
++iter)
{
std::vector<rtabmap::CameraModel> models;
for(size_t i=0; i<iter->second.size(); ++i)
{
models.push_back(iter->second[i].scaled(1.0/double(_ui->spinBox_camProjDecimation->value())));
}
cameraModelsProj.insert(std::make_pair(iter->first, models));
}
}
else
{
cameraModelsProj = cameraModels;
}
cv::Mat projMask;
if(!_ui->lineEdit_camProjMaskFilePath->text().isEmpty())
{
projMask = cv::imread(_ui->lineEdit_camProjMaskFilePath->text().toStdString(), cv::IMREAD_GRAYSCALE);
if(_ui->spinBox_camProjDecimation->value()>1)
{
cv::Mat out = projMask;
cv::resize(projMask, out, cv::Size(), 1.0f/float(_ui->spinBox_camProjDecimation->value()), 1.0f/float(_ui->spinBox_camProjDecimation->value()), cv::INTER_NEAREST);
projMask = out;
}
}
std::vector<std::pair< std::pair<int, int>, pcl::PointXY> > pointToPixel;
pointToPixel = util3d::projectCloudToCameras(
*assembledCloud,
cameraPoses,
cameraModels,
cameraModelsProj,
_ui->doubleSpinBox_camProjMaxDistance->value(),
_ui->doubleSpinBox_camProjMaxAngle->value()*M_PI/180.0,
roiRatios,
projMask,
_ui->checkBox_camProjDistanceToCamPolicy->isChecked(),
&texturingState);
if(texturingState.isCanceled())
{
return false;
}
// color the cloud
UASSERT(pointToPixel.empty() || pointToPixel.size() == assembledCloud->size());
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr assembledCloudValidPoints;
@@ -2752,7 +2819,7 @@ bool ExportCloudsDialog::getExportedClouds(
if(_ui->checkBox_camProjRecolorPoints->isChecked())
{
int imagesDone = 1;
for(std::map<int, rtabmap::Transform>::iterator iter=cameraPoses.begin(); iter!=cameraPoses.end(); ++iter)
for(std::map<int, rtabmap::Transform>::iterator iter=cameraPoses.begin(); iter!=cameraPoses.end() && !_canceled; ++iter)
{
int nodeID = iter->first;
@@ -2769,15 +2836,19 @@ bool ExportCloudsDialog::getExportedClouds(
}
if(!image.empty())
{
UASSERT(cameraModels.find(nodeID) != cameraModels.end());
int modelsSize = cameraModels.at(nodeID).size();
if(_ui->spinBox_camProjDecimation->value()>1)
{
image = util2d::decimate(image, _ui->spinBox_camProjDecimation->value());
}
UASSERT(cameraModelsProj.find(nodeID) != cameraModelsProj.end());
int modelsSize = cameraModelsProj.at(nodeID).size();
for(size_t i=0; i<pointToPixel.size(); ++i)
{
int cameraIndex = pointToPixel[i].first.second;
if(nodeID == pointToPixel[i].first.first && cameraIndex>=0)
{
pcl::PointXYZRGBNormal & pt = assembledCloud->at(i);
int subImageWidth = image.cols / modelsSize;
cv::Mat subImage = image(cv::Range::all(), cv::Range(cameraIndex*subImageWidth, (cameraIndex+1)*subImageWidth));
@@ -2786,6 +2857,7 @@ bool ExportCloudsDialog::getExportedClouds(
UASSERT(x>=0 && x<subImage.cols);
UASSERT(y>=0 && y<subImage.rows);
pcl::PointXYZRGBNormal & pt = assembledCloud->at(i);
if(subImage.type()==CV_8UC3)
{
cv::Vec3b bgr = subImage.at<cv::Vec3b>(y, x);
@@ -2804,12 +2876,13 @@ bool ExportCloudsDialog::getExportedClouds(
QString msg = tr("Processed %1/%2 images").arg(imagesDone++).arg(cameraPoses.size());
UINFO(msg.toStdString().c_str());
_progressDialog->appendText(msg);
QApplication::processEvents();
}
}
pcl::IndicesPtr validIndices(new std::vector<int>(pointToPixel.size()));
size_t oi = 0;
for(size_t i=0; i<pointToPixel.size(); ++i)
for(size_t i=0; i<pointToPixel.size() && !_canceled; ++i)
{
pcl::PointXYZRGBNormal & pt = assembledCloud->at(i);
if(pointToPixel[i].first.first <=0)
@@ -3589,6 +3662,10 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
{
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), _ui->doubleSpinBox_normalRadiusSearch->value(), viewPoint);
pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud);
if(_ui->doubleSpinBox_groundNormalsUp->value() > 0.0)
{
util3d::adjustNormalsToViewPoint(cloud, viewPoint, (float)_ui->doubleSpinBox_groundNormalsUp->value());
}
}
else
{
@@ -3724,6 +3801,10 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
{
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloudWithoutNormals, indices, _ui->spinBox_normalKSearch->value(), _ui->doubleSpinBox_normalRadiusSearch->value(), viewPoint);
pcl::concatenateFields(*cloudWithoutNormals, *normals, *cloud);
if(_ui->doubleSpinBox_groundNormalsUp->value() > 0.0)
{
util3d::adjustNormalsToViewPoint(cloud, viewPoint, (float)_ui->doubleSpinBox_groundNormalsUp->value());
}
}
else
{