mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 01:20:25 +08:00
Export: supporting texturing with multi-camera
This commit is contained in:
@@ -74,6 +74,7 @@ protected:
|
||||
virtual void showEvent(QShowEvent* anEvent);
|
||||
virtual void moveEvent(QMoveEvent* anEvent);
|
||||
virtual void resizeEvent(QResizeEvent* anEvent);
|
||||
virtual void keyPressEvent(QKeyEvent *event);
|
||||
virtual void closeEvent(QCloseEvent* event);
|
||||
virtual bool eventFilter(QObject *obj, QEvent *event);
|
||||
|
||||
@@ -134,7 +135,6 @@ private:
|
||||
QLabel * label,
|
||||
QLabel * stamp,
|
||||
rtabmap::ImageView * view,
|
||||
rtabmap::CloudViewer * view3D,
|
||||
QLabel * labelId,
|
||||
QLabel * labelMapId,
|
||||
QLabel * labelPose,
|
||||
@@ -164,8 +164,7 @@ private:
|
||||
private:
|
||||
Ui_DatabaseViewer * ui_;
|
||||
CloudViewer * constraintsViewer_;
|
||||
CloudViewer * cloudViewerA_;
|
||||
CloudViewer * cloudViewerB_;
|
||||
CloudViewer * cloudViewer_;
|
||||
CloudViewer * stereoViewer_;
|
||||
CloudViewer * occupancyGridViewer_;
|
||||
QList<int> ids_;
|
||||
|
||||
@@ -118,6 +118,7 @@ protected:
|
||||
virtual void showEvent(QShowEvent* anEvent);
|
||||
virtual void moveEvent(QMoveEvent* anEvent);
|
||||
virtual void resizeEvent(QResizeEvent* anEvent);
|
||||
virtual void keyPressEvent(QKeyEvent *event);
|
||||
virtual bool eventFilter(QObject *obj, QEvent *event);
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -144,18 +144,15 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
|
||||
|
||||
// Create cloud viewers
|
||||
constraintsViewer_ = new CloudViewer(ui_->dockWidgetContents);
|
||||
cloudViewerA_ = new CloudViewer(ui_->dockWidgetContents_3dviews);
|
||||
cloudViewerB_ = new CloudViewer(ui_->dockWidgetContents_3dviews);
|
||||
cloudViewer_ = new CloudViewer(ui_->dockWidgetContents_3dviews);
|
||||
stereoViewer_ = new CloudViewer(ui_->dockWidgetContents_stereo);
|
||||
occupancyGridViewer_ = new CloudViewer(ui_->dockWidgetContents_occupancyGrid);
|
||||
constraintsViewer_->setObjectName("constraintsViewer");
|
||||
cloudViewerA_->setObjectName("cloudViewerA");
|
||||
cloudViewerB_->setObjectName("cloudViewerB");
|
||||
cloudViewer_->setObjectName("cloudViewerA");
|
||||
stereoViewer_->setObjectName("stereoViewer");
|
||||
occupancyGridViewer_->setObjectName("occupancyGridView");
|
||||
ui_->layout_constraintsViewer->addWidget(constraintsViewer_);
|
||||
ui_->horizontalLayout_3dviews->addWidget(cloudViewerA_, 1);
|
||||
ui_->horizontalLayout_3dviews->addWidget(cloudViewerB_, 1);
|
||||
ui_->horizontalLayout_3dviews->addWidget(cloudViewer_, 1);
|
||||
ui_->horizontalLayout_stereo->addWidget(stereoViewer_, 1);
|
||||
ui_->layout_occupancyGridView->addWidget(occupancyGridViewer_, 1);
|
||||
|
||||
@@ -268,6 +265,7 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
|
||||
connect(ui_->spinBox_mesh_depthError, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
|
||||
connect(ui_->checkBox_mesh_quad, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
|
||||
connect(ui_->spinBox_mesh_triangleSize, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
|
||||
connect(ui_->checkBox_showWords, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
|
||||
connect(ui_->checkBox_showCloud, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
|
||||
connect(ui_->checkBox_showMesh, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
|
||||
connect(ui_->checkBox_showScan, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
|
||||
@@ -311,6 +309,8 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
|
||||
connect(ui_->spinBox_grid_depth, SIGNAL(valueChanged(int)), this, SLOT(updateOctomapView()));
|
||||
connect(ui_->checkBox_grid_empty, SIGNAL(stateChanged(int)), this, SLOT(updateOctomapView()));
|
||||
connect(ui_->doubleSpinBox_gainCompensationRadius, SIGNAL(valueChanged(double)), this, SLOT(updateConstraintView()));
|
||||
connect(ui_->doubleSpinBox_voxelSize, SIGNAL(valueChanged(double)), this, SLOT(updateConstraintView()));
|
||||
connect(ui_->doubleSpinBox_voxelSize, SIGNAL(valueChanged(double)), this, SLOT(update3dView()));
|
||||
connect(ui_->groupBox_posefiltering, SIGNAL(clicked(bool)), this, SLOT(updateGraphView()));
|
||||
connect(ui_->doubleSpinBox_posefilteringRadius, SIGNAL(editingFinished()), this, SLOT(updateGraphView()));
|
||||
connect(ui_->doubleSpinBox_posefilteringAngle, SIGNAL(editingFinished()), this, SLOT(updateGraphView()));
|
||||
@@ -342,6 +342,7 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
|
||||
connect(ui_->checkBox_gridErode, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||
connect(ui_->checkBox_octomap, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||
connect(ui_->doubleSpinBox_gainCompensationRadius, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||
connect(ui_->doubleSpinBox_voxelSize, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||
connect(ui_->doubleSpinBox_gridCellSize, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||
connect(ui_->groupBox_posefiltering, SIGNAL(clicked(bool)), this, SLOT(configModified()));
|
||||
connect(ui_->doubleSpinBox_posefilteringRadius, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||
@@ -396,12 +397,10 @@ void DatabaseViewer::setupMainLayout(bool vertical)
|
||||
if(vertical)
|
||||
{
|
||||
qobject_cast<QHBoxLayout *>(ui_->horizontalLayout_imageViews->layout())->setDirection(QBoxLayout::TopToBottom);
|
||||
qobject_cast<QHBoxLayout *>(ui_->horizontalLayout_3dviews->layout())->setDirection(QBoxLayout::TopToBottom);
|
||||
}
|
||||
else if(!vertical)
|
||||
{
|
||||
qobject_cast<QHBoxLayout *>(ui_->horizontalLayout_imageViews->layout())->setDirection(QBoxLayout::LeftToRight);
|
||||
qobject_cast<QHBoxLayout *>(ui_->horizontalLayout_3dviews->layout())->setDirection(QBoxLayout::LeftToRight);
|
||||
}
|
||||
if(ids_.size())
|
||||
{
|
||||
@@ -469,6 +468,8 @@ void DatabaseViewer::readSettings()
|
||||
ui_->checkBox_ignoreUserLoop->setChecked(settings.value("ignoreUserLoop", ui_->checkBox_ignoreUserLoop->isChecked()).toBool());
|
||||
ui_->spinBox_optimizationDepth->setValue(settings.value("depth", ui_->spinBox_optimizationDepth->value()).toInt());
|
||||
ui_->doubleSpinBox_gainCompensationRadius->setValue(settings.value("gainCompensationRadius", ui_->doubleSpinBox_gainCompensationRadius->value()).toDouble());
|
||||
ui_->doubleSpinBox_voxelSize->setValue(settings.value("voxelSize", ui_->doubleSpinBox_voxelSize->value()).toDouble());
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("grid");
|
||||
@@ -561,6 +562,7 @@ void DatabaseViewer::writeSettings()
|
||||
//settings.setValue("slam2d", ui_->checkBox_2dslam->isChecked());
|
||||
settings.setValue("depth", ui_->spinBox_optimizationDepth->value());
|
||||
settings.setValue("gainCompensationRadius", ui_->doubleSpinBox_gainCompensationRadius->value());
|
||||
settings.setValue("voxelSize", ui_->doubleSpinBox_voxelSize->value());
|
||||
settings.endGroup();
|
||||
|
||||
// save Grid settings
|
||||
@@ -637,6 +639,7 @@ void DatabaseViewer::restoreDefaultSettings()
|
||||
ui_->checkBox_ignoreUserLoop->setChecked(false);
|
||||
ui_->spinBox_optimizationDepth->setValue(0);
|
||||
ui_->doubleSpinBox_gainCompensationRadius->setValue(0.0);
|
||||
ui_->doubleSpinBox_voxelSize->setValue(0.0);
|
||||
|
||||
ui_->doubleSpinBox_gridCellSize->setValue(0.05);
|
||||
ui_->groupBox_posefiltering->setChecked(false);
|
||||
@@ -955,6 +958,15 @@ void DatabaseViewer::resizeEvent(QResizeEvent* anEvent)
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseViewer::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
//catch ctrl-s to save settings
|
||||
if((event->modifiers() & Qt::ControlModifier) && event->key() == Qt::Key_S)
|
||||
{
|
||||
this->writeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabaseViewer::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::Resize && qobject_cast<QDockWidget*>(obj))
|
||||
@@ -2370,7 +2382,6 @@ void DatabaseViewer::sliderAValueChanged(int value)
|
||||
ui_->label_labelA,
|
||||
ui_->label_stampA,
|
||||
ui_->graphicsView_A,
|
||||
cloudViewerA_,
|
||||
ui_->label_idA,
|
||||
ui_->label_mapA,
|
||||
ui_->label_poseA,
|
||||
@@ -2388,7 +2399,6 @@ void DatabaseViewer::sliderBValueChanged(int value)
|
||||
ui_->label_labelB,
|
||||
ui_->label_stampB,
|
||||
ui_->graphicsView_B,
|
||||
cloudViewerB_,
|
||||
ui_->label_idB,
|
||||
ui_->label_mapB,
|
||||
ui_->label_poseB,
|
||||
@@ -2404,7 +2414,6 @@ void DatabaseViewer::update(int value,
|
||||
QLabel * label,
|
||||
QLabel * stamp,
|
||||
rtabmap::ImageView * view,
|
||||
rtabmap::CloudViewer * view3D,
|
||||
QLabel * labelId,
|
||||
QLabel * labelMapId,
|
||||
QLabel * labelPose,
|
||||
@@ -2543,7 +2552,7 @@ void DatabaseViewer::update(int value,
|
||||
}
|
||||
|
||||
// 3d view
|
||||
if(view3D->isVisible())
|
||||
if(cloudViewer_->isVisible())
|
||||
{
|
||||
Transform pose = Transform::getIdentity();
|
||||
if(signatures.size() && ui_->checkBox_odomFrame_3dview->isChecked())
|
||||
@@ -2553,14 +2562,15 @@ void DatabaseViewer::update(int value,
|
||||
pose = Transform(0,0,z,roll,pitch,0);
|
||||
}
|
||||
|
||||
view3D->removeAllFrustums();
|
||||
view3D->removeCloud("mesh");
|
||||
view3D->removeCloud("cloud");
|
||||
view3D->removeCloud("scan");
|
||||
view3D->removeCloud("map");
|
||||
view3D->removeCloud("ground");
|
||||
view3D->removeCloud("obstacles");
|
||||
view3D->removeOctomap();
|
||||
cloudViewer_->removeAllFrustums();
|
||||
cloudViewer_->removeCloud("mesh");
|
||||
cloudViewer_->removeCloud("cloud");
|
||||
cloudViewer_->removeCloud("scan");
|
||||
cloudViewer_->removeCloud("map");
|
||||
cloudViewer_->removeCloud("ground");
|
||||
cloudViewer_->removeCloud("obstacles");
|
||||
cloudViewer_->removeCloud("words");
|
||||
cloudViewer_->removeOctomap();
|
||||
if(ui_->checkBox_showCloud->isChecked() || ui_->checkBox_showMesh->isChecked())
|
||||
{
|
||||
if(!data.depthOrRightRaw().empty())
|
||||
@@ -2591,6 +2601,11 @@ void DatabaseViewer::update(int value,
|
||||
}
|
||||
if(cloud->size())
|
||||
{
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
cloud = util3d::voxelize(cloud, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
|
||||
if(ui_->checkBox_showMesh->isChecked() && !cloud->is_dense)
|
||||
{
|
||||
Eigen::Vector3f viewpoint(0.0f,0.0f,0.0f);
|
||||
@@ -2638,14 +2653,13 @@ void DatabaseViewer::update(int value,
|
||||
polygons = filteredPolygons;
|
||||
}
|
||||
|
||||
view3D->addCloudMesh("mesh", cloud, polygons, pose);
|
||||
cloudViewer_->addCloudMesh("mesh", cloud, polygons, pose);
|
||||
}
|
||||
if(ui_->checkBox_showCloud->isChecked())
|
||||
{
|
||||
view3D->addCloud("cloud", cloud, pose);
|
||||
cloudViewer_->addCloud("cloud", cloud, pose);
|
||||
}
|
||||
}
|
||||
view3D->updateCameraFrustums(pose, data.cameraModels());
|
||||
}
|
||||
else if(ui_->checkBox_showCloud->isChecked())
|
||||
{
|
||||
@@ -2653,25 +2667,68 @@ void DatabaseViewer::update(int value,
|
||||
cloud = util3d::cloudFromSensorData(data, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters());
|
||||
if(cloud->size())
|
||||
{
|
||||
view3D->addCloud("cloud", cloud, pose);
|
||||
view3D->updateCameraFrustum(pose, data.stereoCameraModel());
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
cloud = util3d::voxelize(cloud, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
|
||||
cloudViewer_->addCloud("cloud", cloud, pose);
|
||||
cloudViewer_->updateCameraFrustum(pose, data.stereoCameraModel());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//frustums
|
||||
if(cloudViewer_->isFrustumShown())
|
||||
{
|
||||
cloudViewer_->updateCameraFrustums(pose, data.cameraModels());
|
||||
}
|
||||
|
||||
//words
|
||||
if(ui_->checkBox_showWords->isChecked() && signatures.size())
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
|
||||
cloud->resize((*signatures.begin())->getWords3().size());
|
||||
int i=0;
|
||||
for(std::multimap<int, cv::Point3f>::const_iterator iter=(*signatures.begin())->getWords3().begin();
|
||||
iter!=(*signatures.begin())->getWords3().end();
|
||||
++iter)
|
||||
{
|
||||
cloud->at(i++) = pcl::PointXYZ(iter->second.x, iter->second.y, iter->second.z);
|
||||
}
|
||||
|
||||
if(cloud->size())
|
||||
{
|
||||
cloud = rtabmap::util3d::removeNaNFromPointCloud(cloud);
|
||||
}
|
||||
|
||||
if(cloud->size())
|
||||
{
|
||||
cloudViewer_->addCloud("words", cloud, pose, Qt::red);
|
||||
}
|
||||
}
|
||||
|
||||
//add scan
|
||||
if(ui_->checkBox_showScan->isChecked() && data.laserScanRaw().cols)
|
||||
{
|
||||
if(data.laserScanRaw().channels() == 6)
|
||||
{
|
||||
pcl::PointCloud<pcl::PointNormal>::Ptr scan = util3d::laserScanToPointCloudNormal(data.laserScanRaw(), data.laserScanInfo().localTransform());
|
||||
view3D->addCloud("scan", scan, pose, Qt::yellow);
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
cloudViewer_->addCloud("scan", scan, pose, Qt::yellow);
|
||||
}
|
||||
else
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr scan = util3d::laserScanToPointCloud(data.laserScanRaw(), data.laserScanInfo().localTransform());
|
||||
view3D->addCloud("scan", scan, pose, Qt::yellow);
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
cloudViewer_->addCloud("scan", scan, pose, Qt::yellow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2735,7 +2792,7 @@ void DatabaseViewer::update(int value,
|
||||
if(!map8S.empty())
|
||||
{
|
||||
//convert to gray scaled map
|
||||
view3D->addOccupancyGridMap(util3d::convertMap2Image8U(map8S), gridCellSize, xMin, yMin, 1);
|
||||
cloudViewer_->addOccupancyGridMap(util3d::convertMap2Image8U(map8S), gridCellSize, xMin, yMin, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2751,36 +2808,36 @@ void DatabaseViewer::update(int value,
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud = octomap->createCloud(0, obstacles.get(), empty.get());
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr obstaclesCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
|
||||
pcl::copyPointCloud(*cloud, *obstacles, *obstaclesCloud);
|
||||
view3D->addCloud("obstacles", obstaclesCloud);
|
||||
view3D->setCloudPointSize("obstacles", 5);
|
||||
cloudViewer_->addCloud("obstacles", obstaclesCloud);
|
||||
cloudViewer_->setCloudPointSize("obstacles", 5);
|
||||
if(ui_->checkBox_grid_empty->isChecked())
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr emptyCloud(new pcl::PointCloud<pcl::PointXYZ>);
|
||||
pcl::copyPointCloud(*cloud, *empty, *emptyCloud);
|
||||
view3D->addCloud("ground", emptyCloud, Transform::getIdentity(), Qt::white);
|
||||
view3D->setCloudOpacity("ground", 0.5);
|
||||
view3D->setCloudPointSize("ground", 5);
|
||||
cloudViewer_->addCloud("ground", emptyCloud, Transform::getIdentity(), Qt::white);
|
||||
cloudViewer_->setCloudOpacity("ground", 0.5);
|
||||
cloudViewer_->setCloudPointSize("ground", 5);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
view3D->addOctomap(octomap);
|
||||
cloudViewer_->addOctomap(octomap);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// occupancy cloud
|
||||
view3D->addCloud("ground",
|
||||
cloudViewer_->addCloud("ground",
|
||||
util3d::laserScanToPointCloud(localMaps.begin()->second.first),
|
||||
Transform::getIdentity(),
|
||||
Qt::green);
|
||||
view3D->addCloud("obstacles",
|
||||
cloudViewer_->addCloud("obstacles",
|
||||
util3d::laserScanToPointCloud(localMaps.begin()->second.second),
|
||||
Transform::getIdentity(),
|
||||
Qt::red);
|
||||
view3D->setCloudPointSize("ground", 5);
|
||||
view3D->setCloudPointSize("obstacles", 5);
|
||||
cloudViewer_->setCloudPointSize("ground", 5);
|
||||
cloudViewer_->setCloudPointSize("obstacles", 5);
|
||||
}
|
||||
}
|
||||
#ifdef RTABMAP_OCTOMAP
|
||||
@@ -2791,7 +2848,7 @@ void DatabaseViewer::update(int value,
|
||||
#endif
|
||||
}
|
||||
}
|
||||
view3D->update();
|
||||
cloudViewer_->update();
|
||||
}
|
||||
|
||||
if(signatures.size())
|
||||
@@ -3381,7 +3438,6 @@ void DatabaseViewer::updateConstraintView(
|
||||
ui_->label_labelA,
|
||||
ui_->label_stampA,
|
||||
ui_->graphicsView_A,
|
||||
cloudViewerA_,
|
||||
ui_->label_idA,
|
||||
ui_->label_mapA,
|
||||
ui_->label_poseA,
|
||||
@@ -3395,7 +3451,6 @@ void DatabaseViewer::updateConstraintView(
|
||||
ui_->label_labelB,
|
||||
ui_->label_stampB,
|
||||
ui_->graphicsView_B,
|
||||
cloudViewerB_,
|
||||
ui_->label_idB,
|
||||
ui_->label_mapB,
|
||||
ui_->label_poseB,
|
||||
@@ -3472,10 +3527,18 @@ void DatabaseViewer::updateConstraintView(
|
||||
|
||||
if(cloudFrom.get() && cloudFrom->size())
|
||||
{
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
cloudFrom = util3d::voxelize(cloudFrom, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
constraintsViewer_->addCloud("cloud0", cloudFrom, pose, Qt::red);
|
||||
}
|
||||
if(cloudTo.get() && cloudTo->size())
|
||||
{
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
cloudTo = util3d::voxelize(cloudTo, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
constraintsViewer_->addCloud("cloud1", cloudTo, pose, Qt::cyan);
|
||||
}
|
||||
}
|
||||
@@ -3699,6 +3762,10 @@ void DatabaseViewer::updateConstraintView(
|
||||
|
||||
if(assembledScans->size())
|
||||
{
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
assembledScans = util3d::voxelize(assembledScans, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
constraintsViewer_->addCloud("scan2", assembledScans, pose, Qt::cyan);
|
||||
}
|
||||
if(graph->size())
|
||||
@@ -3716,24 +3783,40 @@ void DatabaseViewer::updateConstraintView(
|
||||
{
|
||||
pcl::PointCloud<pcl::PointNormal>::Ptr scan;
|
||||
scan = rtabmap::util3d::laserScanToPointCloudNormal(dataFrom.laserScanRaw(), dataFrom.laserScanInfo().localTransform());
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
constraintsViewer_->addCloud("scan0", scan, pose, Qt::yellow);
|
||||
}
|
||||
else
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr scan;
|
||||
scan = rtabmap::util3d::laserScanToPointCloud(dataFrom.laserScanRaw(), dataFrom.laserScanInfo().localTransform());
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
constraintsViewer_->addCloud("scan0", scan, pose, Qt::yellow);
|
||||
}
|
||||
if(dataTo.laserScanRaw().channels() == 6)
|
||||
{
|
||||
pcl::PointCloud<pcl::PointNormal>::Ptr scan;
|
||||
scan = rtabmap::util3d::laserScanToPointCloudNormal(dataTo.laserScanRaw(), t*dataTo.laserScanInfo().localTransform());
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
constraintsViewer_->addCloud("scan1", scan, pose, Qt::magenta);
|
||||
}
|
||||
else
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr scan;
|
||||
scan = rtabmap::util3d::laserScanToPointCloud(dataTo.laserScanRaw(), t*dataTo.laserScanInfo().localTransform());
|
||||
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
|
||||
{
|
||||
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
|
||||
}
|
||||
constraintsViewer_->addCloud("scan1", scan, pose, Qt::magenta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -777,7 +777,7 @@ void ExportCloudsDialog::viewClouds(
|
||||
for(unsigned int j=0; j<vertices.vertices.size(); ++j)
|
||||
{
|
||||
UASSERT(oi < cloud->size());
|
||||
UASSERT(vertices.vertices[j] < originalCloud->size());
|
||||
UASSERT_MSG(vertices.vertices[j] < originalCloud->size(), uFormat("%d vs %d", vertices.vertices[j], (int)originalCloud->size()).c_str());
|
||||
cloud->at(oi) = originalCloud->at(vertices.vertices[j]);
|
||||
vertices.vertices[j] = oi; // new vertice index
|
||||
++oi;
|
||||
@@ -1090,7 +1090,10 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
}
|
||||
else
|
||||
{
|
||||
transformed = util3d::transformPointCloud(iter->second.first, poses.at(iter->first));
|
||||
// it looks like that using only transformPointCloud with indices
|
||||
// flushes the colors, so we should extract points before... maybe a too old PCL version
|
||||
pcl::copyPointCloud(*iter->second.first, *iter->second.second, *transformed);
|
||||
transformed = rtabmap::util3d::transformPointCloud(transformed, poses.at(iter->first));
|
||||
}
|
||||
|
||||
*assembledCloud += *transformed;
|
||||
@@ -1124,7 +1127,13 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
}
|
||||
|
||||
clouds.clear();
|
||||
clouds.insert(std::make_pair(0, std::make_pair(assembledCloud, pcl::IndicesPtr(new std::vector<int>))));
|
||||
pcl::IndicesPtr indices(new std::vector<int>);
|
||||
indices->resize(assembledCloud->size());
|
||||
for(unsigned int i=0; i<indices->size(); ++i)
|
||||
{
|
||||
indices->at(i) = i;
|
||||
}
|
||||
clouds.insert(std::make_pair(0, std::make_pair(assembledCloud, indices)));
|
||||
}
|
||||
|
||||
if(_canceled)
|
||||
@@ -1803,7 +1812,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
cameras.insert(std::make_pair(iter->first, _ui->checkBox_assemble->isChecked()?poses.at(iter->first):Transform::getIdentity()));
|
||||
}
|
||||
std::map<int, Transform> cameraPoses;
|
||||
std::map<int, CameraModel> cameraModels;
|
||||
std::map<int, std::vector<CameraModel> > cameraModels;
|
||||
for(std::map<int, Transform>::iterator jter=cameras.begin(); jter!=cameras.end(); ++jter)
|
||||
{
|
||||
std::vector<CameraModel> models;
|
||||
@@ -1821,18 +1830,18 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
_dbDriver->getCalibration(jter->first, models, stereoModel);
|
||||
}
|
||||
|
||||
CameraModel model;
|
||||
if(stereoModel.isValidForProjection())
|
||||
{
|
||||
model = stereoModel.left();
|
||||
models.clear();
|
||||
models.push_back(stereoModel.left());
|
||||
}
|
||||
else if(models.size() == 1 && models[0].isValidForProjection())
|
||||
else if(models.size() == 0 || !models[0].isValidForProjection())
|
||||
{
|
||||
model = models[0];
|
||||
models.clear();
|
||||
}
|
||||
if(!jter->second.isNull() && model.isValidForProjection())
|
||||
if(!jter->second.isNull() && models.size())
|
||||
{
|
||||
if(model.imageWidth() == 0 || model.imageHeight() == 0)
|
||||
if(models[0].imageWidth() == 0 || models[0].imageHeight() == 0)
|
||||
{
|
||||
// we are using an old database format (image size not saved in calibrations), we should
|
||||
// uncompress images to get their size
|
||||
@@ -1847,13 +1856,19 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
_dbDriver->getNodeData(jter->first, data, true, false, false, false);
|
||||
data.uncompressDataConst(&img, 0);
|
||||
}
|
||||
model.setImageSize(img.size());
|
||||
cv::Size imageSize = img.size();
|
||||
imageSize.width /= models.size();
|
||||
for(unsigned int i=0; i<models.size(); ++i)
|
||||
{
|
||||
models[i].setImageSize(imageSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(model.imageWidth() != 0 && model.imageHeight() != 0)
|
||||
if(models[0].imageWidth() != 0 && models[0].imageHeight() != 0)
|
||||
{
|
||||
cameraPoses.insert(std::make_pair(jter->first, jter->second));
|
||||
cameraModels.insert(std::make_pair(jter->first, model));
|
||||
cameraModels.insert(std::make_pair(jter->first, models));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1920,7 +1935,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
cameraPoses = graph::radiusPosesFiltering(cameraPoses,
|
||||
_ui->doubleSpinBox_cameraFilterRadius->value(),
|
||||
_ui->doubleSpinBox_cameraFilterAngle->value());
|
||||
for(std::map<int, CameraModel>::iterator modelIter = cameraModels.begin(); modelIter!=cameraModels.end();)
|
||||
for(std::map<int, std::vector<CameraModel> >::iterator modelIter = cameraModels.begin(); modelIter!=cameraModels.end();)
|
||||
{
|
||||
if(cameraPoses.find(modelIter->first)==cameraPoses.end())
|
||||
{
|
||||
@@ -1944,6 +1959,10 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
|
||||
TexturingState texturingState(_progressDialog);
|
||||
_progressDialog->setMaximumSteps(_progressDialog->maximumSteps()+iter->second->polygons.size()/10000+1);
|
||||
if(cameraModels.size() && cameraModels.begin()->second.size()>1)
|
||||
{
|
||||
_progressDialog->setMaximumSteps(_progressDialog->maximumSteps()+cameraModels.size()*(cameraModels.begin()->second.size()-1));
|
||||
}
|
||||
|
||||
std::vector<float> roiRatios;
|
||||
QStringList strings = _ui->lineEdit_meshingTextureRoiRatios->text().split(' ');
|
||||
@@ -2397,7 +2416,6 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
|
||||
{
|
||||
indices = util3d::radiusFiltering(cloud, indices, _ui->doubleSpinBox_filteringRadius->value(), _ui->spinBox_filteringMinNeighbors->value());
|
||||
}
|
||||
|
||||
clouds.insert(std::make_pair(iter->first, std::make_pair(cloud, indices)));
|
||||
points = (int)cloud->size();
|
||||
totalIndices = (int)indices->size();
|
||||
@@ -2728,25 +2746,32 @@ cv::Mat ExportCloudsDialog::mergeTextures(
|
||||
cv::Mat globalTexture;
|
||||
if(mesh.tex_materials.size() > 1)
|
||||
{
|
||||
std::vector<int> textures(mesh.tex_materials.size(), -1);
|
||||
std::vector<std::pair<int, int> > textures(mesh.tex_materials.size(), std::pair<int, int>(-1,-1));
|
||||
cv::Size imageSize;
|
||||
const int imageType=CV_8UC3;
|
||||
|
||||
UDEBUG("");
|
||||
for(unsigned int i=0; i<mesh.tex_materials.size(); ++i)
|
||||
{
|
||||
std::list<std::string> texFileSplit = uSplit(mesh.tex_materials[i].tex_file, '_');
|
||||
if(!mesh.tex_materials[i].tex_file.empty() &&
|
||||
mesh.tex_polygons[i].size() &&
|
||||
uIsInteger(mesh.tex_materials[i].tex_file, false))
|
||||
uIsInteger(texFileSplit.front(), false))
|
||||
{
|
||||
int textureId = uStr2Int(mesh.tex_materials[i].tex_file);
|
||||
textures[i] = textureId;
|
||||
textures[i].first = uStr2Int(texFileSplit.front());
|
||||
if(texFileSplit.size() == 2 &&
|
||||
uIsInteger(texFileSplit.back(), false) )
|
||||
{
|
||||
textures[i].second = uStr2Int(texFileSplit.back());
|
||||
}
|
||||
|
||||
int textureId = textures[i].first;
|
||||
if(imageSize.width == 0 || imageSize.height == 0)
|
||||
{
|
||||
if(cachedSignatures.find(textureId)!=cachedSignatures.end() && !cachedSignatures.find(textureId)->sensorData().imageCompressed().empty())
|
||||
{
|
||||
SensorData data = cachedSignatures.find(textureId).value().sensorData();
|
||||
if(data.cameraModels().size()==1 &&
|
||||
if(data.cameraModels().size()>=1 &&
|
||||
data.cameraModels()[0].imageHeight()>0 &&
|
||||
data.cameraModels()[0].imageWidth()>0)
|
||||
{
|
||||
@@ -2763,6 +2788,10 @@ cv::Mat ExportCloudsDialog::mergeTextures(
|
||||
data.uncompressDataConst(&image, 0);
|
||||
UASSERT(!image.empty());
|
||||
imageSize = image.size();
|
||||
if(data.cameraModels().size()>1)
|
||||
{
|
||||
imageSize.width/=data.cameraModels().size();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(_dbDriver)
|
||||
@@ -2770,7 +2799,7 @@ cv::Mat ExportCloudsDialog::mergeTextures(
|
||||
std::vector<CameraModel> models;
|
||||
StereoCameraModel stereoModel;
|
||||
_dbDriver->getCalibration(textureId, models, stereoModel);
|
||||
if(models.size()==1 &&
|
||||
if(models.size()>=1 &&
|
||||
models[0].imageHeight()>0 &&
|
||||
models[0].imageWidth()>0)
|
||||
{
|
||||
@@ -2789,11 +2818,20 @@ cv::Mat ExportCloudsDialog::mergeTextures(
|
||||
data.uncompressDataConst(&image, 0);
|
||||
UASSERT(!image.empty());
|
||||
imageSize = image.size();
|
||||
if(data.cameraModels().size()>1)
|
||||
{
|
||||
imageSize.width/=data.cameraModels().size();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UWARN("Failed parsing texture file name: %s", mesh.tex_materials[i].tex_file.c_str());
|
||||
}
|
||||
}
|
||||
UDEBUG("textures=%d imageSize=%dx%d", (int)textures.size(), imageSize.height, imageSize.width);
|
||||
if(textures.size() && imageSize.height>0 && imageSize.width>0)
|
||||
{
|
||||
float scale = 0.0f;
|
||||
@@ -2807,6 +2845,11 @@ cv::Mat ExportCloudsDialog::mergeTextures(
|
||||
globalTexture = cv::Mat(textureSize, textureSize, imageType, cv::Scalar::all(255));
|
||||
cv::Mat globalTextureMask = cv::Mat(textureSize, textureSize, CV_8UC1, cv::Scalar::all(0));
|
||||
|
||||
// used for multi camera texturing, to avoid reloading same texture for sub cameras
|
||||
cv::Mat previousImage;
|
||||
int previousTextureId = 0;
|
||||
std::vector<CameraModel> previousCameraModels;
|
||||
|
||||
// make a blank texture
|
||||
cv::Mat emptyImage(int(imageSize.height*scale), int(imageSize.width*scale), imageType, cv::Scalar::all(255));
|
||||
cv::Mat emptyImageMask(int(imageSize.height*scale), int(imageSize.width*scale), CV_8UC1, cv::Scalar::all(255));
|
||||
@@ -2824,23 +2867,47 @@ cv::Mat ExportCloudsDialog::mergeTextures(
|
||||
UASSERT(v < textureSize-emptyImage.rows);
|
||||
imageOrigin[t].x = u;
|
||||
imageOrigin[t].y = v;
|
||||
if(textures[t]>=0)
|
||||
if(textures[t].first>=0)
|
||||
{
|
||||
cv::Mat image;
|
||||
std::vector<CameraModel> models;
|
||||
|
||||
if(cachedSignatures.find(textures[t]) != cachedSignatures.end() &&
|
||||
!cachedSignatures.find(textures[t])->sensorData().imageCompressed().empty())
|
||||
if(textures[t].first == previousTextureId)
|
||||
{
|
||||
cachedSignatures.find(textures[t])->sensorData().uncompressDataConst(&image, 0);
|
||||
image = previousImage;
|
||||
models = previousCameraModels;
|
||||
}
|
||||
else if(_dbDriver)
|
||||
else
|
||||
{
|
||||
SensorData data;
|
||||
_dbDriver->getNodeData(textures[t], data, true, false, false, false);
|
||||
data.uncompressDataConst(&image, 0);
|
||||
if(cachedSignatures.find(textures[t].first) != cachedSignatures.end() &&
|
||||
!cachedSignatures.find(textures[t].first)->sensorData().imageCompressed().empty())
|
||||
{
|
||||
cachedSignatures.find(textures[t].first)->sensorData().uncompressDataConst(&image, 0);
|
||||
models = cachedSignatures.find(textures[t].first)->sensorData().cameraModels();
|
||||
}
|
||||
else if(_dbDriver)
|
||||
{
|
||||
SensorData data;
|
||||
_dbDriver->getNodeData(textures[t].first, data, true, false, false, false);
|
||||
data.uncompressDataConst(&image, 0);
|
||||
StereoCameraModel stereoModel;
|
||||
_dbDriver->getCalibration(textures[t].first, models, stereoModel);
|
||||
}
|
||||
|
||||
previousImage = image;
|
||||
previousCameraModels = models;
|
||||
previousTextureId = textures[t].first;
|
||||
}
|
||||
|
||||
UASSERT(!image.empty());
|
||||
|
||||
if(textures[t].second>=0)
|
||||
{
|
||||
UASSERT(textures[t].second < (int)models.size());
|
||||
int width = image.cols/models.size();
|
||||
image = image.colRange(width*textures[t].second, width*(textures[t].second+1));
|
||||
}
|
||||
|
||||
cv::Mat resizedImage;
|
||||
cv::resize(image, resizedImage, emptyImage.size(), 0.0f, 0.0f, cv::INTER_AREA);
|
||||
UASSERT(resizedImage.type() == CV_8UC1 || resizedImage.type() == CV_8UC3);
|
||||
@@ -2850,9 +2917,9 @@ cv::Mat ExportCloudsDialog::mergeTextures(
|
||||
cv::cvtColor(resizedImage, resizedImageColor, CV_GRAY2BGR);
|
||||
resizedImage = resizedImageColor;
|
||||
}
|
||||
if(_ui->checkBox_gainCompensation->isChecked() && _compensator && _compensator->getIndex(textures[t]) >= 0)
|
||||
if(_ui->checkBox_gainCompensation->isChecked() && _compensator && _compensator->getIndex(textures[t].first) >= 0)
|
||||
{
|
||||
_compensator->apply(textures[t], resizedImage);
|
||||
_compensator->apply(textures[t].first, resizedImage);
|
||||
}
|
||||
UASSERT(resizedImage.type() == globalTexture.type());
|
||||
resizedImage.copyTo(globalTexture(cv::Rect(u, v, resizedImage.cols, resizedImage.rows)));
|
||||
@@ -3235,6 +3302,12 @@ void ExportCloudsDialog::saveTextureMeshes(
|
||||
removeDirRecursively(QFileInfo(path).absoluteDir().absolutePath()+QDir::separator()+QFileInfo(path).baseName());
|
||||
QDir(QFileInfo(path).absoluteDir().absolutePath()).mkdir(QFileInfo(path).baseName());
|
||||
}
|
||||
|
||||
// used for multi camera texturing, to avoid reloading same texture for sub cameras
|
||||
cv::Mat previousImage;
|
||||
int previousTextureId = 0;
|
||||
std::vector<CameraModel> previousCameraModels;
|
||||
|
||||
cv::Size imageSize;
|
||||
for(unsigned int i=0; i<mesh->tex_materials.size(); ++i)
|
||||
{
|
||||
@@ -3253,22 +3326,52 @@ void ExportCloudsDialog::saveTextureMeshes(
|
||||
UDEBUG("Saving %s...", fullPath.toStdString().c_str());
|
||||
if(singleTexture || !QFileInfo(fullPath).exists())
|
||||
{
|
||||
if(uIsInteger(mesh->tex_materials[i].tex_file, false))
|
||||
std::list<std::string> texFileSplit = uSplit(mesh->tex_materials[i].tex_file, '_');
|
||||
if(texFileSplit.size() && uIsInteger(texFileSplit.front(), false))
|
||||
{
|
||||
int textureId = uStr2Int(mesh->tex_materials[i].tex_file);
|
||||
cv::Mat image;
|
||||
if(cachedSignatures.contains(textureId) && !cachedSignatures.value(textureId).sensorData().imageCompressed().empty())
|
||||
int textureId = uStr2Int(texFileSplit.front());
|
||||
int textureSubCamera = -1;
|
||||
if(texFileSplit.size() == 2 &&
|
||||
uIsInteger(texFileSplit.back(), false))
|
||||
{
|
||||
cachedSignatures.value(textureId).sensorData().uncompressDataConst(&image, 0);
|
||||
textureSubCamera = uStr2Int(texFileSplit.back());
|
||||
}
|
||||
else if(_dbDriver)
|
||||
cv::Mat image;
|
||||
std::vector<CameraModel> cameraModels;
|
||||
|
||||
if(textureId == previousTextureId)
|
||||
{
|
||||
SensorData data;
|
||||
_dbDriver->getNodeData(textureId, data, true, false, false, false);
|
||||
data.uncompressDataConst(&image, 0);
|
||||
image = previousImage;
|
||||
cameraModels = previousCameraModels;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cachedSignatures.contains(textureId) && !cachedSignatures.value(textureId).sensorData().imageCompressed().empty())
|
||||
{
|
||||
cachedSignatures.value(textureId).sensorData().uncompressDataConst(&image, 0);
|
||||
cameraModels = cachedSignatures.value(textureId).sensorData().cameraModels();
|
||||
}
|
||||
else if(_dbDriver)
|
||||
{
|
||||
SensorData data;
|
||||
_dbDriver->getNodeData(textureId, data, true, false, false, false);
|
||||
data.uncompressDataConst(&image, 0);
|
||||
StereoCameraModel stereoModel;
|
||||
_dbDriver->getCalibration(textureId, cameraModels, stereoModel);
|
||||
}
|
||||
|
||||
previousImage = image;
|
||||
previousCameraModels = cameraModels;
|
||||
previousTextureId = textureId;
|
||||
}
|
||||
UASSERT(!image.empty());
|
||||
imageSize = image.size();
|
||||
if(textureSubCamera>=0)
|
||||
{
|
||||
UASSERT(cameraModels.size());
|
||||
imageSize.width/=cameraModels.size();
|
||||
image = image.colRange(imageSize.width*textureSubCamera, imageSize.width*(textureSubCamera+1));
|
||||
}
|
||||
if(_ui->checkBox_gainCompensation->isChecked() && _compensator && _compensator->getIndex(textureId) >= 0)
|
||||
{
|
||||
_compensator->apply(textureId, image);
|
||||
@@ -3365,11 +3468,30 @@ void ExportCloudsDialog::saveTextureMeshes(
|
||||
removeDirRecursively(path+QDir::separator()+currentPrefix);
|
||||
QDir(path).mkdir(currentPrefix);
|
||||
}
|
||||
|
||||
// used for multi camera texturing, to avoid reloading same texture for sub cameras
|
||||
cv::Mat previousImage;
|
||||
int previousTextureId = 0;
|
||||
std::vector<CameraModel> previousCameraModels;
|
||||
|
||||
cv::Size imageSize;
|
||||
for(unsigned int i=0;i<mesh->tex_materials.size(); ++i)
|
||||
{
|
||||
if(!mesh->tex_materials[i].tex_file.empty())
|
||||
{
|
||||
std::list<std::string> texFileSplit = uSplit(mesh->tex_materials[i].tex_file, '_');
|
||||
int textureId = 0;
|
||||
int textureSubCamera = -1;
|
||||
if(texFileSplit.size() && uIsInteger(texFileSplit.front(), false))
|
||||
{
|
||||
textureId = uStr2Int(texFileSplit.front());
|
||||
if(texFileSplit.size() == 2 &&
|
||||
uIsInteger(texFileSplit.back(), false))
|
||||
{
|
||||
textureSubCamera = uStr2Int(texFileSplit.back());
|
||||
}
|
||||
}
|
||||
|
||||
// absolute path
|
||||
QString fullPath;
|
||||
if(singleTexture)
|
||||
@@ -3381,23 +3503,46 @@ void ExportCloudsDialog::saveTextureMeshes(
|
||||
{
|
||||
fullPath = path+QDir::separator()+currentPrefix+QDir::separator()+QString(mesh->tex_materials[i].tex_file.c_str())+_ui->comboBox_meshingTextureFormat->currentText();
|
||||
}
|
||||
if(uIsInteger(mesh->tex_materials[i].tex_file, false))
|
||||
if(textureId>0)
|
||||
{
|
||||
int textureId = uStr2Int(mesh->tex_materials[i].tex_file);
|
||||
cv::Mat image;
|
||||
if(cachedSignatures.contains(textureId) && !cachedSignatures.value(textureId).sensorData().imageCompressed().empty())
|
||||
std::vector<CameraModel> cameraModels;
|
||||
|
||||
if(textureId == previousTextureId)
|
||||
{
|
||||
cachedSignatures.value(textureId).sensorData().uncompressDataConst(&image, 0);
|
||||
image = previousImage;
|
||||
cameraModels = previousCameraModels;
|
||||
}
|
||||
else if(_dbDriver)
|
||||
else
|
||||
{
|
||||
SensorData data;
|
||||
_dbDriver->getNodeData(textureId, data, true, false, false, false);
|
||||
data.uncompressDataConst(&image, 0);
|
||||
if(cachedSignatures.contains(textureId) && !cachedSignatures.value(textureId).sensorData().imageCompressed().empty())
|
||||
{
|
||||
cachedSignatures.value(textureId).sensorData().uncompressDataConst(&image, 0);
|
||||
cameraModels = cachedSignatures.value(textureId).sensorData().cameraModels();
|
||||
}
|
||||
else if(_dbDriver)
|
||||
{
|
||||
SensorData data;
|
||||
_dbDriver->getNodeData(textureId, data, true, false, false, false);
|
||||
data.uncompressDataConst(&image, 0);
|
||||
StereoCameraModel stereoModel;
|
||||
_dbDriver->getCalibration(textureId, cameraModels, stereoModel);
|
||||
}
|
||||
|
||||
previousImage = image;
|
||||
previousCameraModels = cameraModels;
|
||||
previousTextureId = textureId;
|
||||
}
|
||||
|
||||
|
||||
UASSERT(!image.empty());
|
||||
imageSize = image.size();
|
||||
if(textureSubCamera>=0)
|
||||
{
|
||||
UASSERT(cameraModels.size());
|
||||
imageSize.width/=cameraModels.size();
|
||||
image = image.colRange(imageSize.width*textureSubCamera, imageSize.width*(textureSubCamera+1));
|
||||
}
|
||||
if(_ui->checkBox_gainCompensation->isChecked() && _compensator && _compensator->getIndex(textureId) >= 0)
|
||||
{
|
||||
_compensator->apply(textureId, image);
|
||||
|
||||
@@ -3940,6 +3940,15 @@ void MainWindow::resizeEvent(QResizeEvent* anEvent)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
//catch ctrl-s to save settings
|
||||
if((event->modifiers() & Qt::ControlModifier) && event->key() == Qt::Key_S)
|
||||
{
|
||||
this->saveConfigGUI();
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::Resize && qobject_cast<QDockWidget*>(obj))
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1465</width>
|
||||
<width>1547</width>
|
||||
<height>965</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -52,7 +52,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>353</width>
|
||||
<width>394</width>
|
||||
<height>196</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -210,7 +210,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>353</width>
|
||||
<width>394</width>
|
||||
<height>196</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -483,7 +483,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1465</width>
|
||||
<width>1547</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -1008,7 +1008,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>339</width>
|
||||
<height>186</height>
|
||||
<height>210</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -1144,7 +1144,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>282</width>
|
||||
<height>569</height>
|
||||
<height>626</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -1233,6 +1233,38 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_54">
|
||||
<property name="text">
|
||||
<string>Voxel size (for clouds and scans)</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_voxelSize">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@@ -1474,8 +1506,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>205</width>
|
||||
<height>117</height>
|
||||
<width>295</width>
|
||||
<height>223</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -1574,8 +1606,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>184</width>
|
||||
<height>487</height>
|
||||
<width>282</width>
|
||||
<height>266</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
@@ -1802,6 +1834,16 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_showWords">
|
||||
<property name="text">
|
||||
<string>Words</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_showCloud">
|
||||
<property name="text">
|
||||
|
||||
Reference in New Issue
Block a user